Johan Bolmsjö's GNU Emacs Configuration
Installation instruction:
git clone github.com/johan-bolmsjo/emacs.d ~/.emacs.d
Table of Contents
1. The Init File
Requires GNU Emacs version 30.1 or greater.
The main init file is init.el.
This file loads packages that require external programs to function properly.
See chapter 3 for how to install required programs for specific packages.
1.1. Overview
Overview of enabled packages.
1.1.1. Package Management
Emacs packages are installed using the straight package manager. The advantage with this package manager is that it keeps the complete upstream Git repositories available together with lock files to pin down exact versions. This means that the Emacs configuration is reproducible. It's also possible to easily change package versions to resolve incompatibilities when the configuration is copied between hosts with different Emacs versions.
The version lock file ~/.emacs.d/straight/versions/default.el is versioned by this Git repository.
The actual upstream package source code is not managed by this Git repository.
They are downloaded by Emacs when started.
For local backup purposes it's possible to just archive the whole ~/.emacs.d directory.
It's transferable between machines.
1.1.2. Documentation Modes
1.1.4. Programming Languages Modes
1.1.5. Miscellaneous Support Functions
- Improved minibuffer completions through Vertico, Marginalia and Orderless.
- Collection of minibuffer utilities provided by Consult.
- Context aware minibuffer actions through Embark.
- Code completion through Corfu and Orderless.
- Templated auto complete assisted snippets through Yasnippet.
- Project like IDE support using Treemacs, project.el and Eglot.
- Compiler diagnostics through Flycheck or Flymake.
- Git interface through Magit.
- GDB support through GUD.
- Extraneous whitespace indications.
1.2. Keybindings
Keybindings that are specific to this configuration file.
1.2.1. User Keybindings
See https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html for user keybinding conventions. Also http://xahlee.info/emacs/emacs/keyboard_shortcuts.html for practical overrides.
C-c aalign-currentC-c ccompileC-c gfind-grepC-c iispell-regionC-c off-find-other-file(in c-mode-common)C-c ssort-linesC-c t- toggle treemacs pane
Incremental Search
C-c k- Set mark at start of current match and exit isearch (user function).
Navigation
Even though these functions are called error, they work in many contexts. E.g. moving through compilation errors, grep results, xref references.
M-_previous-errorM-+next-error
Navigate using key prefixes generated on the fly:
C-c kavy-goto-char-2C-c lavy-goto-line
Window Management
Commands useful to prevent Emacs from splitting frames and replacing buffers in windows when doing certain tasks.
C-c F- Lock current frame for automatic splitting.
C-c f- Unlock current frame for automatic splitting.
C-c W- Lock current window to its current buffer.
C-c w- Unlock current window from its current buffer.
See https://smythp.com/emacs_buffers/ for an explanation of the frames, windows and buffers terminology.
Denote
C-c n- Command prefix
The main note taking command is C-c n n.
Other keybindings are listed when entering the command prefix.
Discover all commands by entering M-x denote
Org Mode
C-c porg-agenda(planning)C-c Lorg-store-link(works in other modes to store links)
Eglot Mode
Note that eglot relies on the keybindings of other packages for most functions. E.g. xref for navigation and eldoc for documentation.
C-c e aeglot-code-actionsC-c e feglot-format(ask server to format buffer or the active region)C-c e reglot-rename(rename symbol at point)C-c e ieglot-find-implementationC-c e teglot-find-typeDefinition
Flymake Mode
Aligned with flycheck counterparts.
C-c ! lflymake-show-buffer-diagnosticsC-c ! nflymake-goto-next-errorC-c ! pflymake-goto-prev-error
Embark
Embark executes context aware actions. For example opening the URL that the cursor is placed on in a buffer. It extends some of the consult commands by making it possible to export the current selection to regular buffers for easier manipulation.
C-c v- Execute action on current context
C-c d- "Do what I mean" on current context
C-h Bembark-bindings; alternative for `describe-bindings'
GDB (debugger)
F5- Continue program being debugged.
F6- Step till next source line, do not enter subroutine (next).
F7- Step till next source line, enter subroutine (step).
F8- Execute until current stack frame returns.
S-F8- Stop debugging
1.2.2. Overridden Keybindings
Modifies standard Emacs behavior or use non-user prefix.
M-nscroll-up-commandM-pscroll-down-commandM-fforward-symbol(replaces forward-word)M-bmy/backward-symbol(replaces backward-word)C-x kmy/fast-kill-buffer(replaces kill-buffer)
1.3. User Facing Functions
Convenience functions defined by the configuration.
reload-file- Calls
revert-bufferwithout asking for confirmation
1.4. Configuration Adaptations
Configuration adaptations that may be desired when applying this Emacs configuration in a new environment.
1.4.1. Terminal Emulator
The solarized theme that is used by this Emacs configuration only works properly in graphical mode and terminals that support true color.
The website https://github.com/termstandard/colors describes how to configure terminals and associated tools to support true color.
In essence, the environment variable COLORTERM must be set to truecolor.
COLORTERM is distinct from the usual TERM environment variable that communicate terminal capabilities.
Obviously the underlying terminal must also support the true color escape codes.
My ~/.bashrc contains the following lines to set it for the suckless terminal:
# Set the COLORTERM variable to "truecolor" if the terminal supports it. # The suckless terminal (st) definitely does. # The tmux-256color can be any underlying type so is technically incorrect; # it solves the issue of SSH to remote system from within a Tmux session. if [ "$TERM" = st-256color ] || [ "$TERM" = tmux-256color ]; then export COLORTERM=truecolor fi
1.4.2. Shell Environment optional
Suggested Emacs shell integration.
Set the EDITOR environment variable to emacs in ~/.profile or other shell login environment script.
# Set preferred editor invoked by some command line tools. export EDITOR="emacs -nw"
Add a convenience command alias to e.g. ~/.bashrc to open a file in Emacs from a terminal.
# Open file in already started Emacs running in server mode (M-x server-start). # Useful to hide Emacs startup cost when editing config files from the shell. alias edit='emacsclient -n'
1.4.3. Fonts optional
A personal choice, my current favorite monospaced fonts can be found in the ~/.emacs.d/fonts/gofont directory.
Installation (Linux):
mkdir -p ~/.fonts cp ~/.emacs.d/fonts/gofont/*.ttf ~/.fonts
Update ~/.emacs.d/fonts.el with your preferred fonts and default size.
1.4.4. Custom Variables
Variables that may need customization (such as file paths) are stored in ~/.emacs.d/custom.el.
2. Quick Guides
Scattered quick guides for my own memory. It could do with more information for Emacs neophytes.
2.1. Navigation
Xref is used by many Emacs modes for navigation, including Eglot for navigating source code.
M-,- Go back
M-.- Find thing
M-?- Find references
Jump to a specific line.
M-g g- goto-line
2.2. Incremental Search
Don't forget about the occur mode when doing incremental search. It's very useful to get a navigable outline of all current matches.
All keybindings can be listed by invoking C-h b when in search mode.
Starting search:
C-s- Search forward for a literal string
C-r- Search backward for a literal string
C-M-s- Search forward for a regexp
C-M-r- Search backward for a regexp
M-s _- Search forward for a symbol
M-s .- Search forward for the symbol at point
During search:
C-s- Move to next match (
C-s C-sto resume search) C-r- Move to previous match (
C-r C-rto resume search) C-g- Abort search
M-c- Toggle case sensitive search
M-e- Edit search term
M-s o- Outline of current matches (occur)
M-s SPC- Toggle lax whitespace
RET- Terminate search, leaving cursor at the current match
2.3. Completion in Buffers
Completion is provided by Corfu together with Orderless.
Completion is triggered by C-M-i which is bound to complete-symbol.
The TAB key is also configured to either indent (if it can), else complete.
This does not work in the C/C++ mode.
The completion mechanism provided by orderless is a bit different and can take some time to get used to.
Multiple patterns (space separated words) can be entered.
Completions candidates that match all patterns regardless of order are kept.
Patterns can be regexps as well as regular words, e.g. ^desc match candidates starting with desc.
The built-in dabbrev mode can also be useful.
M-/- dabbrev-expand
C-M-/- dabbrev-completion
2.4. Minibuffer Completion
Vertico together with Marginalia and Orderless is used to enhance minibuffer completions.
For example selecting buffers, files or the function to invoke via M-x.
TAB- Navigate to selected candidate
RET- Accept selected candidate
M-RET- Submit exactly what is typed (ignore candidate completion)
C-g- Abort (as always)
Searching for previous selections is done using C-s and C-r.
Navigation is performed using the usual keybindings.
2.5. Magit
Magit is a complete text-based user interface to Git.
The magit status command is bound to C-x g.
2.6. Denote
The YouTube presentation https://www.youtube.com/watch?v=mLzFJcLpDFI by the package author gives a good overview of the note taking workflow. I recommend studying the manual for further details.
2.7. Org Mode
Org mode is a documentation and planning major mode. Some HOWTO notes are kept in docs/howto-org-mode.html.
The org-tempo package is enabled which provides some template instantiation shortcuts.
Invoke M-x describe-variable and enter org-tempo-tags to see all shortcuts.
Useful shortcuts include <s TAB for source blocks and <q TAB for quote blocks.
2.8. Text Templates
Text template support is provided by the yasnippet package. Sippets are kept under
~/.emacs.d/<MODE>/<FILE> and they are are expanded by typing their name and pressing
TAB.
2.9. Diagnostics
Diagnostics such as compiler errors are provied by either the flycheck or flymake package.
2.10. Language Server Protocol Support
Eglot works in concert with project.el to identify projects. Only version controlled directories can become projects. Eglot can only analyze files that belongs to a project.
Invoke M-x p p to add a project, select the … (choose a dir) option.
Tracked projects are stored in ~/.emacs.d/projects.
Eglot must be started manually from an opened file that belongs to a project.
This is done by invoking M-x eglot.
Eglot may ask for the language server to use if it can't find one or there are multiple choices.
After having done this once, eglot does not prompt for other files in the same project.
Eglot is well integrated with core Emacs packages.
Apart from the mentioned xref it use the eldoc package to display documentation and type information.
Invoke C-h . to show documentation at point.
2.11. Keyboard Macros
Keyboard macros are incredibly useful to apply repetitive changes in close proximity.
Press F3 to start recording key presses.
Press F4 to end the recording and bind it to the same key.
2.12. Debugging Using GDB
Activate by M-x gdb followed by M-x gdb-many-windows.
The toolbar contain debugger navigation icons so you may want to enable it using M-x tool-bar-mode.
Keybindings are listed in section GDB (debugger).
3. Setup of External Tools
Unfortunately the Emacs init file is not self contained. External tools are required to support many packages.
3.1. Terminal Mode Copy+Paste
Install xclip to make Emacs running in terminal mode copy to the X clipboard.
apt install xclip
3.2. Shell Script Mode
Install the shellcheck linter to get good advice on shell script constructs.
Ubuntu/Debian specific instruction:
apt install shellcheck
3.3. PlantUML Documentation
3.4. Go Programming Language Mode
Install the Go programming language toolchain as instructed on https://go.dev/dl/ or upgrade with the following commands:
# Select toolchain version as appropriate. # You also need to update the GOROOT and PATH environment variables for your shell. go install golang.org/dl/go1.26.0@latest go1.26.0 download
Install tools for Emacs integration:
go install golang.org/x/tools/gopls@latest go install golang.org/x/tools/cmd/goimports@latest go install golang.org/x/tools/cmd/gorename@latest go install github.com/rogpeppe/godef@latest
Install support tools (not Emacs environment related):
# Debugger for Go (versioned as the Go toolchain, e.g. v1.26). go install github.com/go-delve/delve/cmd/dlv@latest
3.5. OCaml Programming Language Mode
Install the OCaml language toolchain from https://ocaml.org/releases/
Install required tools:
opam update opam switch create 4.13.1 opam install dune utop ocaml-lsp-server merlin tuareg ocp-indent odig
The OCaml setup is a bit special in that the Emacs packages are installed by the steps above. Not by the Emacs package manager.
3.6. Python Programming Language Mode
3.6.1. Python Virtual Environments
Pyenv is used to compartmentalize python installations and make it possible to switch between them for different projects.
Install pyenv from https://github.com/pyenv/pyenv:
Clone the pyenv repo:
git clone https://github.com/pyenv/pyenv.git ~/.pyenv cd ~/.pyenv && src/configure && make -C src
Put the following in ~/.bashrc:
export PYENV_ROOT="$HOME/.pyenv"
if [ -d "$PYENV_ROOT" ]; then
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
fi
Apply the changes in the current shell (or login again):
exec "$SHELL"
Install Python build dependencies (Ubuntu specific, refer to https://github.com/pyenv/pyenv/wiki#suggested-build-environment for other OSes):
sudo apt-get update
sudo apt-get install make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev xz-utils \
tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
Install a Python version using pyenv:
pyenv install 3.10.7
Switching between Python versions:
pyenv shell VERSION- Select just for current shell session.
pyenv local VERSION- Automatically select whenever you are in the current directory (or its subdirectories).
pyenv global VERSION- Select globally for your user account.
3.6.2. Language Server
Install the language server:
pip install 'python-language-server[all]' scrapy
3.7. Zig Programming Language Mode
- Install the language toolchain from https://ziglang.org/download/
- Install the language server from https://github.com/zigtools/zls/
4. Compiling GNU Emacs
Compiling GNU Emacs from source is quite easy. Many packages see heavy development and may require a recent version.
4.1. Emacs 30.2
Install dependencies (Ubuntu 22.04, Debian 13 specific):
sudo apt install \ libcairo2-dev \ libgif-dev \ libgnutls28-dev \ libharfbuzz-dev \ libjansson-dev \ libjpeg-dev \ libncurses-dev \ librsvg2-dev \ libsqlite3-dev \ libtiff-dev \ libtree-sitter-dev \ libxaw7-dev \ libxml2-dev \ libxpm-dev
Install the libgccjit package corresponding to GCC compiler version.
Check compiler version with gcc --version.
Example: Install libgccjit corresponding to GCC version
apt install libgccjit-11-dev:amd64
Download, configure, build and install GNU Emacs on Linux:
wget https://ftp.acc.umu.se/mirror/gnu.org/gnu/emacs/emacs-30.2.tar.xz
tar xf emacs-30.2.tar.xz
cd emacs-30.2
./configure \
--with-native-compilation \
--with-mailutils \
--with-x-toolkit=lucid \
--with-tree-sitter \
--prefix=$HOME/.local
make -j16
make install
Make sure that Cairo is used for the GUI in the configure stage or some library dependency is missing.
Install tree-sitter language grammar files using M-x treesit-install-language-grammar;
example language names: python, c, cpp.
See https://www.masteringemacs.org/article/how-to-get-started-tree-sitter for an introduction to Emacs tree-sitter support and how to use it.
For now, none of the tree-sitter major modes are enabled by default.