Emacs (Application)

From campisano.org
Jump to navigation Jump to search

Emacs

Install

  • from Debian-like O.S.:
# for terminal version
apt-get install emacs-nox
# or for X version
apt-get install emacs
# shared/opt install schema v1.5.6

#### as common user ####
# define applications vars
export SOFTWARE_PATH="/home/shared/opt/software"
export NAME="emacs"
export VERSION="29.3"
export URL="ftp://ftp.gnu.org/pub/gnu/emacs/emacs-${VERSION}.tar.gz"
su - -w SOFTWARE_PATH,NAME,VERSION

#### as root ####
# install generic dependencies
apt-get -q -y install wget coreutils findutils < /dev/null
# dependencies for MINIMAL terminal version
apt-get -q -y install tar gzip gcc make libtinfo-dev libgccjit-10-dev libssl-dev libgnutls28-dev gnutls-bin pkg-config < /dev/null
# OR dependencies for terminal version
apt-get -q -y install tar gzip gcc make libtinfo-dev libgccjit-10-dev libssl-dev libgnutls28-dev gnutls-bin pkg-config libgccjit-10-dev libjansson-dev libtinfo-dev zlib1g-dev < /dev/null
# OR dependencies for X version
apt-get -q -y install tar gzip gcc make libtinfo-dev libgccjit-10-dev libssl-dev libgnutls28-dev gnutls-bin pkg-config libgccjit-10-dev libjansson-dev libtinfo-dev zlib1g-dev libtool texinfo build-essential xorg-dev libgtk-3-dev libjpeg-dev libncurses5-dev libdbus-1-dev libgif-dev libtiff-dev libm17n-dev libpng-dev librsvg2-dev libotf-dev libxml2-dev libxpm-dev libnotify-dev < /dev/null
# paths
mkdir -m 777 "${SOFTWARE_PATH}/tmp_install/" "${SOFTWARE_PATH}/${NAME}_${VERSION}/"
exit

#### as common user ####
umask 0027
cd "${SOFTWARE_PATH}/tmp_install"
wget -c --no-check-certificate "${URL}"
tar -xzf "emacs-${VERSION}.tar.gz"
cd "emacs-${VERSION}"
# define compiler flags optimizations (from debian dpkg-buildflags command)
export CFLAGS="-g0 -O2 -fstack-protector-strong -Wformat -Werror=format-security -mtune=native -pipe"
export LDFLAGS="-s -Wl,-z,relro"
# configure for MINIMAL terminal version
./configure --prefix="${SOFTWARE_PATH}/${NAME}_${VERSION}" --without-all --with-native-compilation=aot --with-gnutls --without-compress-install --without-x --with-x-toolkit=no --without-sound
# OR configure for terminal version
./configure --prefix="${SOFTWARE_PATH}/${NAME}_${VERSION}" --without-all --with-native-compilation=aot --with-gnutls --with-mailutils --without-compress-install --without-x --with-x-toolkit=no --without-sound --with-file-notification=no --with-native-compilation --with-modules --with-threads --with-zlib --with-json
# OR configure for X version
./configure --prefix="${SOFTWARE_PATH}/${NAME}_${VERSION}" --without-all --with-native-compilation=aot --with-gnutls --with-mailutils --without-compress-install --with-x --with-x-toolkit=gtk3 --without-gsettings --without-gconf --without-dbus --without-makeinfo --with-file-notification=inotify --with-native-compilation --with-modules --with-threads --with-zlib --with-json
make -s
make install
cd
su - -w SOFTWARE_PATH,NAME,VERSION

#### as root ####
# ensure permissions to destination path
cd "${SOFTWARE_PATH}"
chown -R root:users "${NAME}_${VERSION}"
find "${NAME}_${VERSION}" -type d -exec chmod a-s,u+rwx,g+rx,g-w,o-rwx {} \;
find "${NAME}_${VERSION}" -type f -exec chmod a-s,u+rw,g+r,g-w,o-rwx {} \;
rm -rf tmp_install
ln -s -f -T "${NAME}_${VERSION}" "${NAME}"
exit

#### as common user ####
# test the application
"${SOFTWARE_PATH}/${NAME}/bin/emacs"

Configure

Emacs as default git difftool

git config --global diff.tool emacs
git config --global difftool.prompt false
# the result of the following command is: cmd = emacs -nw --eval \"(progn (setq vc-handled-backends ()) (ediff-files \\\"$LOCAL\\\" \\\"$REMOTE\\\"))\"
git config --global difftool.emacs.cmd 'emacs -nw --eval "(progn (setq vc-handled-backends ()) (ediff-files \"$LOCAL\" \"$REMOTE\"))"'

Emacs as default git mergetool

git config --global merge.tool emacs
git config --global mergetool.prompt false
# the result of the following command is: cmd =  emacs -nw --eval \"(progn (setq vc-handled-backends ()) (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\" \\\"$BASE\\\" nil \\\"$MERGED\\\"))\"
git config --global mergetool.emacs.cmd 'emacs -nw --eval "(progn (setq vc-handled-backends ()) (ediff-merge-files-with-ancestor \"$LOCAL\" \"$REMOTE\" \"$BASE\" nil \"$MERGED\"))"'

Improve GDB print of STL containers

  • Install libstdc++6
sudo apt-get install libstdc++6
  • libstdc++6 provide a version of python prettyprinter like function

to be used with gdb, however if you got errors like

"Python Exception <type 'exceptions.ValueError'> Cannot find type"

you may want to install a more recent version:

# download
svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python ~/gdb/python
# configure
cat >> ~/.gdbinit << EOF
python
import os
import sys
sys.path.insert(0, os.environ['HOME'] + '/gdb/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
EOF
  • Configure GDB print behaviour
cat >> ~/.gdbinit << EOF

#
# C++ related beautifiers (optional)
#
set print pretty on
set print object on
set print static-members on
set print vtbl on
set print demangle on
set demangle-style gnu-v3
set print sevenbit-strings off
EOF

C++ navigation and completation with language server

First install one of such language servers:

Then, config a language server package for emacs like eglot or lsp-mode, the follow is a config sample for lsp-mode:


(use-package lsp-mode
  :ensure t
  :config
  (add-hook 'prog-mode-hook #'lsp)
  )

(use-package lsp-ui
  :ensure t
  :config
  (add-hook 'lsp-mode-hook #'lsp-ui-mode)
  )

(use-package company
  :ensure t
  :config
  (global-company-mode))
  
(use-package company-lsp
  :ensure t
  :config
  (setq company-lsp-enable-recompletion t)
  (add-to-list 'company-backends 'company-lsp)
  )

Java navigation and completation with Eclipse JDT Language Server

# dependencies
su -c "apt-get install curl tar gzip" # NOTE: jdk and maven are required too
# binary
DESTINATION="/home/shared/opt/software"                 # Edit when needed
VERSION="d30acc4c7cf961a2234b19b5b9e8dfe3d7402987"      # Edit when needed
URL="https://github.com/eclipse/eclipse.jdt.ls/archive/d30acc4c7cf961a2234b19b5b9e8dfe3d7402987.zip"
umask 0027
mkdir tmp
cd tmp
curl -C - -kLO "${URL}"
unzip "${VERSION}.zip"
cd "eclipse.jdt.ls-${VERSION}"
./mvnw clean verify
cd ../..
su -c "chown -R root:users tmp;\
 find tmp -type d -exec chmod a-s,u+rwx,g+rx,g-w,o-rwx {} \;;\
 find tmp -type f -exec chmod a-s,u+rw,g+r,g-w,o-rwx {} \;;\
 mv tmp/eclipse.jdt.ls-${VERSION} ${DESTINATION};\
 rm -f ${DESTINATION}/eclipse.jdt.ls;\
 ln -s eclipse.jdt.ls-${VERSION} ${DESTINATION}/eclipse.jdt.ls;\
 chmod 2777 ${DESTINATION}/eclipse.jdt.ls/org.eclipse.jdt.ls.product/target/repository/config_linux"
  • configure
(use-package lsp-java
  :ensure t
  :after lsp
  :config
  (setq-default lsp-java-server-install-dir "/home/shared/opt/software/eclipse.jdt.ls/org.eclipse.jdt.ls.product/target/repository/")

  (require 'dap-java)

  ;; (require 'lsp-java-boot)
  ;; ;; to enable the lenses
  ;; (add-hook 'lsp-mode-hook #'lsp-lens-mode)
  ;; (add-hook 'java-mode-hook #'lsp-java-boot-lens-mode)

  (add-hook 'java-mode-hook #'lsp)
  (add-hook 'java-mode-hook 'flycheck-mode)
  (add-hook 'java-mode-hook 'company-mode)
  )

Emacs commands

Modifier keys

Defaults:

  • C stands for the <Control> modifier, key [Ctrl]
  • M stands for the <Meta> modifier, key [Alt] usually
  • S stands for the <Shift> modifier, ket [Shift]

Basic Emacs commands

Files

Stop current command            C-g
Open file                       C-x C-f
Save file                       C-x C-s
Save file as new                C-x C-w
Close file                      C-x k

Editing

Select all                      C-x h
Auto-indent selected code       TAB
Copy                            M-w
Cut                             C-w
Paste (Yank)                    C-y
Undo                            C-/
Redo (unexistent: undo of undo) C-g C-/
Search                          C-s
Replace                         M-%
Replace with newlines           M-% <string to replace> RET C-q C-j RET  # where C-q C-j is the newline character
Go to line (emacs >= 23.2)      M-g g
  • rectangle
Put a marker                                        C-SPACE
# OR
Visual rectangle selection                          C-x SPACE
# then
Delete text rectangle (from marker)                 C-x r d
Cut text rectangle (from marker)                    C-x r k
Copy text rectangle (from marker)                   C-x r M-w
Paste (Yank) text rectangle (from first line)       C-x r y
Insert text in each line of rectangle (from marker) C-x r t <string> RET

Navigation

Buffer navigation (i.e. open file)

Previous buffer                 C-x Left
Next buffer                     C-x Right
List buffers                    C-x C-b

Window navigation

It is not default. You can enable default keybinds (see (windmove-default-keybindings)) or you can explicit define yours like follows:

;; set keybindings to move focus to near windows
(global-set-key (kbd "C-c C-<up>") 'windmove-up)
(global-set-key (kbd "C-c C-<down>") 'windmove-down)
(global-set-key (kbd "C-c C-<right>") 'windmove-right)
(global-set-key (kbd "C-c C-<left>") 'windmove-left)

;; set keybindings to manage splitted windows size
(global-set-key (kbd "M-S-<up>") 'shrink-window)
(global-set-key (kbd "M-S-<down>") 'enlarge-window)
(global-set-key (kbd "M-S-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "M-S-<right>") 'enlarge-window-horizontally)

Source navigation

When available (when some package (like cquery above) allows emacs to understand the source code), you can go:

Find definitions                M-.
Find references                 M-?

Windows

Split window horizontally       C-x 2
Split window vertically         C-x 3
Focus to next window            C-x o
Enlarge window                  C-x ^
Close window                    C-x 0

Projectile commands

Alternate header source         C-c p a
Search file in project          C-c p f

Magit

Open Magit interface            C-x g
 quit                           q
 git add                        s
 git commit message             c c
  git completing commit         C-c C-c
 diffing with ediff             e

Debugging

Start debugger                  M-x gdb (select the binary file)
Set a breakpoint                C-x C-a C-b
Delete a breakpoint             C-x C-a C-d
Step into next statement        C-x C-a C-s
Step out until previous stack   C-x C-a C-f
Step next current stack stat.   C-x C-a C-n
Continue                        C-x C-a C-r
Go to inner stack               C-x C-a >
Go to parent stack              C-x C-a <

Bug

open a terminal (e.g. Terminal.app, size 160x40)
press enter until the end of terminal
mkdir -p tmp; cd tmp; for i in {1..100}; do touch $i; done
execute emacs -q --eval '(progn (menu-bar-mode 0) (tab-bar-mode) (setq
scroll-conservatively 101) (setq scroll-margin 0))'
C-x C-f tab tab
C-x C-c

References