Emacs: Guide for Beginners(WIP)

Bruce Wen
14 min readJan 25, 2023

As a developer, it would a pity not to learn how to use classic development editors like Emacs and Vim. This article is to guide beginners to start use Emacs.

Emacs — Guide for Beginners — Bruce Wen

Find help for any content

Show help options

C-h ?

Then, you can see how to get help of any other content including functions, variables, keys, etc.

Search from Help by text

C-h a <any text> RET

That means you type Ctrl+h then a , it will show a prompt like below

Search for command (word list or regexp):

When you type something like fringe and then Enter key, it will open a new window to show all relevant help document text.

Help Document about Fringe

Search help for functions

M-x describe-function RET delete-selection-mode RET

Type Alt+x then type describe-function and then Enter , type function name like delete-selection-mode above.

Help Documet for Function

Try to explore all other help subcommand. Probably, you will find something which is amazing.

Magit

By default, magit read git configuration from current repository rather than global configuration. Therefore, if there is not confined user.email and user.name in current repo, then when commit by magit command, it will use default user name and email which might be different from global configured values.

In that case, the below problem might happen.

Enumerating objects: 40, done.
Counting objects: 100% (40/40), done.
Delta compression using up to 8 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (22/22), 2.30 KiB | 261.00 KiB/s, done.
Total 22 (delta 11), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (11/11)
remote: Processing changes: refs: 1, done
remote:
remote: ERROR: In commit 8f353574981447b17f8cfc73a2e3bc00850fdf70
remote: ERROR: committer email address wenijinew@codeart.com
remote: ERROR: does not match your user account.
remote: ERROR:
remote: ERROR: The following addresses are currently registered:
remote: ERROR: wenijinew@gamil.com
remote: ERROR:
remote: ERROR: To register an email address, please visit:
remote: ERROR: https://gerrit.codeart.com/#/settings/contact
remote:
remote:
To https://gerrit.codeart.com/a/auto/test
! [remote rejected] HEAD -> refs/publish/master (invalid committer)
error: failed to push some refs to 'https://gerrit.codeart.com/a/auto/autotest'

To solve, just configure user.email and user.name in current repository.

git config user.name "Bruce Wen"
git config user.email "wenijinew@gmail.com"

Customization

In Emacs, we can customize everything by the command M-x customize and then choose different customization group for target customization. By that, you can do the change interactively and apply and save the change.

Customization Groups

For example, if you want to change the display of Emacs including fonts, colors and so on. You can choose [Faces] by Enter key. Then it will bring you to [Faces] subgroups:

[Faces] Customization subgroups

There, you can change lots of things. Further, you can search anything you want to customize by the top search bar. For example, if you don’t like the search text field default background color (yellow), then you can search “field” and then you can find which face is showing background color as yellow and then do make change. In fact, it’s “[Widget Field]”. I changed it to be like below:

Customized Search Field

Now, I listed some of frequently used customization and how to do it in init file.

Font settings

To show icons in Emacs, the below faces need to change to use your favourite fonts. It’s better to run GUI mode to show kinds of different icons.

  • default
  • mode-line
  • tab-bar
  • tab-line

Run command M-x describe-face and then choose default to help buffer and then click “customize-this-face” to open Customize Face buffer. Then fill your favourite font name in “Font Family”, and click “Apply and Save”. Do the same for mode-line , tab-bar , and tab-line . I like “Hack Nerd Font”. You can also try other Nerd Fonts.

Customize Font
Icons in Mode-Line

Show line numbers

(global-display-line-numbers-mode 1)

To show relative number, add below line (Emacs 28+)

(setq display-line-numbers-type 'relative)
Relative Number in Emacs

Show cursor line number in different foreground color

(set-face-attribute 'line-number-current-line nil :background "default" :foreground "#ffb733")
Use Orange for Line Number of Current Line (Cursor Line)

Show cursor line in different background color

(global-hl-line-mode 1)

Show fill-column-indicator

Firstly, set the default value of fill-column by command:

(setq-default fill-column 79)

Then enable globally display of fill-column-indicator by command:

(global-display-fill-column-indicator-mode 1) 

It will make the fill-column-indicator visible at the position where the fill-column value is.

Then enable auto-fill-mode to enable auto-wrap when the line length extends fill-column value.

Last step, customize value of fill-column for different mode by hooks:

(add-hook 'java-mode-hook (lambda () (setq fill-column 120)))
(add-hook 'python-mode-hook (lambda () (setq fill-column 79)))

By the above code, the fill-column will be automatically changed to 120 when the Emacs enter java-mode (*.java file is opened in current buffer) and 79 for python-mode. It’s a very helpful configuration for most developers who might work on projects using different programming languages.

Different Fill-Column Indicator for Java and Python

Show help document description about the function or keyword in the cursor line

M-x toggle-debug-on-error

Show vertical-border in nicer way

(set-face-attribute 'vertical-border nil :background "default" :foreground "#4e4e7d")
(set-display-table-slot standard-display-table
'vertical-border
(make-glyph-code ?│))
Nicer Vertical-Border Dividing Windows

Show match para in customized color

(set-face-attribute 'show-paren-match-expression nil :background "yellow")

Maximize window and restore

First of all, enable winner-mode by M-x winner-mode . Then, run command M-x maximize-window to maximize the window and run command C-c < to restore the previous window layout. Then, run command C-c > to switch to the maximized window layout.

It’s highly recommended to enable winner-mode by default. It’s very helpful to switch backward and forward for window or buffers layout.

Show info about the current major mode

Command C-h m to show the major mode for current buffer.

Save customization to customized file rather than init file

Add below code to use customized file in init file

(setq custom-file "~/.config/emacs-custom.el")
(load custom-file)

Save Sessions

Session management is very important in IDE. To automatically save and restore session for Emacs, add below line in init file:

(desktop-save-mode 1)

Refer to Saving-Emacs-Sessions for more information.

Packages to install

All the packages should be available on melpa and you can install by the command likeM-x package-install RET which-key RET .

  • use-package
  • straight
  • smart-mode-line
  • doom-themes
  • emacs-which-key
  • treemacs
  • company — Modular text completion framework
  • projectile

If you cannot access melpa due to network issue in your development environment, then you can install in other machine and copy the installed packages to your development environment. Note that both the package and its dependencies should be copied to ~/.emacs.d/elpa/ folder.

Some packages could be installed manually if they don’t need to compile. For example, you can install use-package by clone it to local path and configure it in init.el file with below code:

(eval-when-compile
(add-to-list 'load-path "/repo/egugwen/github/use-package")
(require 'use-package))
(setq use-package-always-ensure t)

Elpy for Python Development in Emacs

Source code format

Before formatting by Black
After formatting by Black

Known Issues:

peculiar error: “exited abnormally with code 1”

When some dependencies were not installed, this error might happen. So, check by the command elpy-config to see which dependencies were not installed. Install them by command elpy-rpc-reinstall-virtualenv or manually activate elpy virtualenv (in terminal, go to $HOME/.emacs.d/elpy/rpc-venv/bin and run commandsource activate) and install all missed dependencies.

Error during redisplay: (jit-lock-function 24) signaled (error “Overlapping strings detected (start=24, last-end=28)”)

Configure LSP for Emacs

Refer to LSP Mode installation.

Automatical installation failure

LSP :: Server jdtls install process failed with the following error message: Could not create connection to raw.githubusercontent.com:443.

In that case, we can manage to download the jdtls server by manually and the copy to the directory A and then decompress the package there.

Completion Configuration

lsp-completion-show-detail

This variable is provided by lsp-mode.

In below snapshot, it shows some duplicated info about tooltip annotations — we can remove right side part of method signature.

Completion with details (Duplicates info)

By setting the variable lsp-completion-show-detail as off, it will become as below:

Completion without details — concise mode

company-tooltip-align-annotations

This variable is provided by company-mode frontends.

Above snapshots having this variable as on . When it’s off , it will be like below: (“Mehtod” is not right-aligned anymore)

Work with ctags

Generate tags file for your project for Emacs

Go to your project directory, and run command ctags -e -f ~/.emacs.d/TAGS $PWD and it will collect tags and write to the file ~/.emacs.d/TAGS .

Configure in init file

Add below line in init.el file:

(setq tags-file-name "~/.emacs.d/TAGS")

Use tags when edit file

By the key M-. (xref-find-definitions) shows the definition of the identifier at point. (See Looking Up Identifiers)

Show definitions of the identifier in new window

In the new window, go to the line showing the interested API reference and click Enter and it will open the file at that location in the original window and focus on the reference location in that file. To go back to the previous file, use M-, (Alt+,). (We can also use the key to switch buffer backward C-x > and forward C-x < .)

Can use keys , and . to go through all references forward and backward, the corresponding file will be open the in original window where the previous file was opened. (Note: focus is still in the xref window)

Refer to Xref-Commands for all other helpful commands.

Tircks

Edit multiple lines

  • Start rectangle mode: C-x SPC
  • Select target content area: C-p / C-n
  • To add content: Set Target area by : C-x r t then type content followed by RET key (Enter).
  • To remove content: Set target area by: C-x r k then remove highlight ares’s content.
  • To remove special char ^M generated on Windows: M-x replace-string RET C-q C-m RET RET . Note: the keys C-q C-m is to type in the char ^M.

Open multiple files

  • set the value find-file-wildcards as t
  • when do find file by C-x C-f , type * or *.[ext] to open all files or all files with the .ext in the directory.

Mark and Delete Buffers

  • Open buffers list by C-x C-b
  • Use d to mark the buffers (one by one) to delete
  • Use x to delete all marked buffers
  • Use q to close the buffers list

Multiple-Cursors (Github Link)

  • Install the package by (use-package multiple-cursors :straight t)
  • Configure the key-binding: (global-set-key (kbd “C-c m e”) ‘mc/edit-lines)

📓 Even though the key (what I used is “C-c m e”) works for the same purpose of the function (mc/edit-lines), at least in theory, if you use M-x -> mc/edit-lines, it won’t work — no multiple cursors are activated at all, at least in my own case. So, configure the key-binding, then mark (C-x space + move cursor) several lines where you want to edit by multiple-cursors, and then press the key you configured for mc/edit-lines or other multiple-cursors functions.

One very helpful feature is mc/mark-all-in-region-regexp which is used to mark the part matching the given regular expression in all lines in the region. To use it, first mark region — normally the while buffer ( C-x h ), then run the command mc/mark-all-in-region-regexp (better to define bind-key for it), then type the regular expression of the target part in each line, and click Enter to mark all matched parts in all lines. After that, normally, delete or copy the marked parts.

TODO:

Record video with https://obsproject.com/welcome

Refer to:

https://stackoverflow.com/questions/761706/edit-multiple-lines-at-once-in-emacs

Enable true color (24 bit color)

Refer to https://www.gnu.org/software/emacs/manual/html_node/efaq/Colors-on-a-TTY.html

I used the below solution for version Emacs 28.1 in Linux

$ cat terminfo-custom.src

xterm-emacs|xterm with 24-bit direct color mode for Emacs,
use=xterm-256color,
setb24=\E[48\:2\:\:%p1%{65536}%/%d\:%p1%{256}%/%{255}%&\
%d\:%p1%{255}%&%dm,
setf24=\E[38\:2\:\:%p1%{65536}%/%d\:%p1%{256}%/%{255}%&\
%d\:%p1%{255}%&%dm,

$ tic -x -o ~/.terminfo terminfo-custom.src

$ TERM=xterm-emacs emacs -nw

And it works well:

Emacs with 24bit colour

Windows Color Issue

When I start emacs -nw in Windows, it cannot show 256 colours, which is bad.

I can only see the below colours from the output of list-colors-display:

16-Color in Windows

I managed to find the source code which tell why in Windows, Emacs only support 16-color.

emacs/src/dispnew.c

1 #ifdef WINDOWSNT │
6572 terminal_type = (char *)"w32console"; │ 1 #else │
2 terminal_type = getenv ("TERM"); │
3 #endif

/* Open a display on the controlling tty. */
t = init_tty (0, terminal_type, 1); /* Errors are fatal. */

And init_tty is defined in emacs/src/term.c

   16 #ifdef WINDOWSNT                                                               │
15 { │
14 struct frame *f = XFRAME (selected_frame); │
13 int height, width; │ 12 │
11 initialize_w32_display (terminal, &width, &height); │ 10 │
9 FrameRows (tty) = height; │
8 FrameCols (tty) = width; │
7 tty->specified_window = height; │ 6 │
5 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; │ 4 FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = 0; │ 3 tty->char_ins_del_ok = 1; │ 2 baud_rate = 19200; │ 1 }

Then, by checking initialize_w32_display in emacs/src/w32console.c, we can see the relevant methods: w32con_write_glyphs, and w32_face_attributes.

Comments in w32_face_attributes

Therefore, it doesn’t support 256 colours to start Emacs in the Windows console. And, there is no support to start Emacs in Windows Terminal — it doesn’t detect it. So, if we want to use 256 colours in Windows Terminal Emacs, then we have to manage to make a change in Emacs and then rebuild it. The GitHub project emacs-w32con-vt is for this purpose. I haven’t tried it but hope it works.

Kinds of Issues

Native compiler error due to missed libraries

Most Emacs package rely on system libraries and some of them maybe not installed or not matched the version needed.

For example, when I tried o use smart-mode-line with smart-mode-line-powerline-theme, it failed to load powerline-theme due to missed gcc library:

(require 'smart-mode-line)
(require 'smart-mode-line-powerline-theme)
(setq powerline-arrow-shape 'curve)
(setq powerline-default-separator-dir '(right . left))
(setq sml/theme 'dark)
(sml/setup)
Native compiler error: (lambda (arg6 &optional) (let ((f #'handle-switch-frame)) (funcall f arg6))), "Compiling /home/egugwen/.emacs.d/eln-cache/28.1-7901736e/subr--trampoline-68616e646c652d7377697463682d6672616d65_handle_switch_frame_0.eln...
ld: cannot find crtbeginS.o: No such file or directory
ld: cannot find -lgcc
ld: cannot find -lgcc_s
libgccjit.so: error: error invoking gcc driver
Debugger entered--Lisp error: (native-ice \"failed to compile\" \"/home/egugwen/.emacs.d/eln-cache/28.1-7901736e/sub...\" \"error invoking gcc driver\")
comp--compile-ctxt-to-file(\"/home/egugwen/.emacs.d/eln-cache/28.1-7901736e/sub...\")
comp-compile-ctxt-to-file(\"/home/egugwen/.emacs.d/eln-cache/28.1-7901736e/sub...\")
comp-final1()
load-with-code-conversion(\"/proj/crbs/user/egugwen/.tmp/emacs-int-comp-subr--...\" \"/proj/crbs/user/egugwen/.tmp/emacs-int-comp-subr--...\" nil t)
command-line-1((\"-l\" \"/proj/crbs/user/egugwen/.tmp/emacs-int-comp-subr--...\"))
command-line()
normal-top-level()

To solve this issue, we need to install the libraries (E.g. download it from https://rhel.pkgs.org/8/epel-x86_64/libgccjit-8.5.0-17.el8.x86_64.rpm.html) or use alternative Emacs packages (for this case, use other theme rather than powerline).

ojectile-bookmarks.eld locked by *** (pid 21342): (s, q, p, ?)?

Find all symbolic files by tree -a -f $PWD | grep -iE '\.#.*' and then remove all of them

Re-entering top level after C stack overflow

Variable binding depth exceeds max-specpdl-size

Cannot save customizations; init file was not fully loaded

Error running timer ‘lsp — on-idle’: (wrong-type-argument stringp nil)

Frequently used commands

Windows

  • Maximize window: M-x maximize-window
  • Restore window: M-x balance-windows

Helpful keys

Note: M is Alt key in most keyboards.

  • Shift-M-, : Append comment after the current line
  • M-. : Show references of the identifier under cursor in new window
  • M-, : Go back to where you previously invoked M-. and friends (xref-pop-marker-stack).
  • M-s . : Search symbol under cursor. (Symbol Search)
  • M-u: Upper-case the word after the cursor.
  • M-l: Lower-case the word after the cursor.
  • C-x C-l: Lower-case the word in the region. This key is disabled by default, the command is downcase-region. The opposite key and command are C-x C-u and upcase-region .
  • C-M-\ : Equals to M-x indent-region to format the code.
  • C-M-b : Jump backward to matching parenthese. Could be also C-M-Left. Check by the command M-x -> backward-sexp to know the details about how the function is configured.
  • C-M-f : Jump forward to matching parenthese. Could be also C-M-Right. Check by the command M-x -> forward-sexp to know the details about how the function is configured.
  • C-x z: Run last command, and then press z to continue repeating. Very useful for toggle commands.
  • C-x C-q: enable/disable read-only mode.
  • C-x C-SPACE: return to the last position.
  • C-x p g: Find regexp — like grep -rE $PWD, do search files having text matching given regular expression in current project. This is a shortcut of the package projectile. It relies on the variable semantic-symref-filepattern-alist and grep command. If you see the message “Customize `semantic-symref-filepattern-alist’ for *** major-mode”, then you need to add a new value to semantic-symref-filepattern-alist to tell what file extensions are used to do grep for which major mode. For example, (add-to-list ‘semantic-symref-filepattern-alist ‘(scala-mode “*.scala”)). This is usually added when install package. See below snapshot.
  • C-c p c: projectile key used to call compile command for current project. I used this for Java project and the command is configured as mvn -B clean install which could be customized in Compilation group.
Configure scala for semantic-symref-filepattern-alist

The package emacs-which-key is very helpful to easily find needed key or get one overview of all keys or subkeys.

Emacs-which-key to show subkeys of C-h

For now, that’s what I want to share. More content could come later.

Thanks for reading!

Happy coding!

References

--

--