This repository lists my configuration for GNU Emacs, my primary editor. The install instructions and customizations should work on a GNU/Linux platform and are not extensively tested on Windows. Suggestions and pull requests are welcome.
The Emacs version on Ubuntu is outdated. There are a couple of PPAs [Emacs stable releases, Ubuntu Emacs Lisp] that we can use, but they do not include build flags that I need. So, I prefer to build from source [*Build GNU Emacs].
Add the following repository only if you are using Ubuntu 20.04.
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
# Install gcc-10 packages with the required support for libgccjit
sudo apt install -y gcc-10 g++-10 libgccjit0 libgccjit-10-dev libjansson4 libjansson-dev
Use the following instructions to configure and build GNU Emacs from the source (Ubuntu 20.04 or 22.04).
wget https://ftp.gnu.org/gnu/emacs/emacs-29.1.tar.xz
tar -xf emacs-29.1.tar.xz
# Use GCC 10 if you are on Ubuntu 20.04
export CC=/usr/bin/gcc-11 CXX=/usr/bin/g++-11
make distclean
./autogen.sh
./configure --with-cairo --with-modules --without-compress-install --with-x-toolkit=no --with-gnutls=ifavailable --without-gconf --without-xwidgets --without-toolkit-scroll-bars --without-xaw3d --without-gsettings --with-mailutils --with-native-compilation=aot --with-json=ifavailable --with-harfbuzz --with-imagemagick --with-jpeg --with-png --with-rsvg --with-tiff --with-wide-int --with-xft --with-xml2 --with-xpm --with-gif --with-threads --with-included-regex --with-zlib --without-sound --with-dbus --without-pop --with-dbus --with-tree-sitter=ifavailable CFLAGS="-O3 -mtune=native -march=native -fomit-frame-pointer -funroll-loops -floop-parallelize-all" prefix=/usr/local
# Use NATIVE_FULL_AOT=1 to native compile ahead-of-time all the elisp files included in the Emacs
# distribution instead of after startup
make -j"$(nproc)" NATIVE_FULL_AOT=1
sudo make install
Try the following if the build fails: make bootstrap
or rm lisp/loaddefs.el; make;
.
You can check whether “NATIVE__COMP” is part of the system-configuration-features
variable. Run the following to native compile all Elisp files under a directory (e.g., ~/.emacs.d
):
(native-compile-async "//home/swarnendu//.emacs.d/elpa" 'recursively)
Back up the contents of your .emacs.d
directory if it is not empty, and then check out the source.
git clone https://github.com/swarnendubiswas/dotemacs.git .emacs.d
modules
- Emacs modules divided across featuresextras
- third-party packages (may not be available from the package archives)snippets
- custom snippetsreferences
- documentation and help filesdir-locals-examples
- examples to show how to use directory-local variablesprojectile-examples
- projectile configuration files
The following are examples of a few customization options defined in init-config.el. Please check the file for more customization options.
sb/theme
– Set the desired theme from a bunch of themes (default ismodus-vivendi
)sb/modeline-theme
– Set the desired modeline theme (default ispowerline-nano
)sb/fill-column
– Column beyond which lines should not extend (default is 100)sb/minibuffer-completion
- Choose eitherivy
orvertico
for narrowing and selection (default isvertico
)sb/capf
- Choose eithercompany
orcorfu
for in-buffer completion at point (default iscompany
)sb/tab-bar-handler
- Choose eitherawesome-tab
orcentaur-tabs
for tabbed display (default iscentaur-tabs
)sb/project-handler
- Choose eitherproject.el
orprojectile
for handling projects (default isprojectile
)sb/lsp-provider
- Choose betweenlsp-mode
andeglot
(default islsp-mode
)sb/disable-package.el
- Disablepackage.el
and prefer thestraight.el
package manager.sb/python-langserver
- Choose betweenpylsp
andpyright
as the Python language server (default ispylsp
).sb/delete-trailing-whitespace-p
- Control whether trailing whitespace should be deleted
Support for LSP in GNU Emacs means you will usually not need to create tags separately. However, tags are still useful for languages that are not yet supported by lsp-mode
and to understand complicated project structures that a language server may not understand. I prefer Universal Ctags over GNU Global.
GNU Global has better database search support while Universal Ctags supports more languages. GNU Global can be built with support for Universal Ctags.
- https://github.com/rdbeni0/emacs.d/tree/main/ggtags
- Compiling GNU Global with universal-ctags support
- Tags for Emacs: Relationship between etags, ebrowse, cscope, GNU Global and exuberant ctags
- GTags for Python in Emacs
Use Universal Ctags (u-ctags
) with Citre
.
-R
– recursively scan for files-e
– use Emacs-compatible syntax--list-excludes
– check which patterns are excluded from processing--list-languages
– list supported languages--languages=Python
– include Python files
By default, Emacs expects a tag file by the name TAGS
in the current directory. Once the tag file is built, the following commands exercise the tag indexing feature.
M-x visit-tags-table <RET> FILE <RET>
– Select the tag fileFILE
to useM-. [TAG] <RET>
– Find the first definition ofTAG
. The default tag is the identifier under the cursor.M-*
– Pop back to where you invokedM-.
C-u M-.
– Find the next definition for the last tag
For more commands, see the Tags topic in the Emacs info document.
ctags -eR --exclude=*.py --exclude=*.json --exclude=*.js --exclude=build* --exclude=*.sh --exclude=*.xml --exclude=*.java --exclude=*.html --exclude=*.md --exclude=*.pbtxt --exclude=*.png --exclude=*.css --exclude=*.rst --exclude=bazel-* --exclude=doc --exclude=node_modules --exclude=.meteor --exclude='packages/*/.build/'
ctags -e -R [email protected] --languages=EmacsLisp .
ctags -eR -quiet=yes [email protected] .
ctags -eR --languages=Python
find . -name "*.tex" | ctags -e -quiet -L -
find src -name "*.py" | ctags -e -L -
find -L . -type f -iname "*.cpp" -o -iname "*.c" -o -iname "*.cc" -o -iname "*.h" -o -iname "*.hpp" -o -iname "*.cu" | ctags -e -L -
$ cat .ctagsignore
dir1
dir2
dir3
Use GNU Global with counsel-gtags
: gtags -cv --gtagslabel=new-ctags
find -L . -type f -iname "*.cpp" -o -iname "*.c" -o -iname "*.cc" -o -iname "*.h" -o -iname "*.hpp" -o -iname "*.py" ! -iname "*.cu" -o -iname "*.proto" | gtags -cv --gtagslabel=new-ctags -f -
find ./src -type f -iname "*.py" ! -iname "__init__.py" | gtags -cv --gtagslabel=new-ctags -f -
find . -type f -iname "*.tex" | gtags -vc --gtagslabel=new-ctags -f -
find . -type d \( -path ./etc -o -path ./var -o -path ./eln-cache -o -path ./.cache \) -prune | gtags -cv --gtagslabel=new-ctags -f -
Enable server support either through init.el
or as a systemd
service. I prefer the systemd
approach. Create a file $HOME/.config/systemd/user/emacs.service
with the following content.
[Unit]
Description=GNU Emacs Daemon
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))"
Restart=always
[Install]
WantedBy=default.target
- Enable the unit to start at login:
systemctl --user enable emacs.service
- Disable the unit to start at login:
systemctl --user disable emacs.service
- Start the service for the current session:
systemctl --user start emacs.service
- Stop the service for the current session:
systemctl --user stop emacs.service
- Restart the service for the current session:
systemctl --user restart emacs.service
Create emacs.desktop
and emacsclient.desktop
files in $HOME/.local/share/applications
with the following content.
[Desktop Entry]
Name=GNU Emacs
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=/usr/local/bin/emacs
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;Utility;
StartupWMClass=Emacs
Keywords=Text;Editor;
[Desktop Entry]
Name=GNU Emacsclient
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=emacsclient -c -a "" -n -F "'(fullscreen . maximized)" %f
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;Utility;
StartupWMClass=Emacs
Keywords=Text;Editor;
I use LSP over Tramp intensively, and LSP+Tramp is sluggish and fails often. It seems difficult to properly set up language servers with Tramp support. Therefore, I prefer to use Emacs in a terminal that has a much better performance. It is important to set up support for 24-bit colors and proper keybindings in the terminal for a good experience. I use Alacritty which is easy to customize.
Using Terminal Emacs over Tramp for editing remote files obviates the need for a remote langsever.
Use the steps mentioned in the link Spacemacs Terminal to enable support for 24bit colors in the terminal.
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export TERM=xterm-24bit
Using export TERM=xterm-24bit
may lead to failures when accessing remote systems. In such cases, we can fall back to TERM=xterm-256color ssh -X <remote-path>
.
Start the Emacs daemon with emacs --daemon
. To run Emacsclient with a GUI, use emacsclient -c -a ""
, where -a ""
starts Emacs daemon and reattaches. To run Emacsclient in a terminal, use emacsclient -nw -q
or emacsclient -t -q -a ""
, where -t
starts the client in the terminal.
Add the following to your .bashrc
to use Emacsclient as your editor.
export ALTERNATE_EDITOR=""
export EDITOR="emacsclient -t" # $EDITOR opens in terminal
export VISUAL="emacsclient -c -a emacs" # $VISUAL opens in GUI mode
kill -s USR2 [pid]
killall -s USR2 emacs
pkill -USR2 emacs
Estimate the best possible startup time with emacs -q --eval
‘(message “%s” (emacs-init-time))’=.
There are a few choices to evaluate the performance of the configuration.
- Set
use-package-compute-statistics
and then invokeuse-package-report
- Use the package
benchmark-init
- Use the script
profile-dotemacs.el
as follows:emacs -Q -l $HOME/.emacs.d/extras/profile-dotemacs.el -f profile-dotemacs
- Advanced Techniques for Reducing Emacs Startup Time
- Flickering with
corfu-terminal-mode
- Disable pairing = before at the beginning of a word in
smartparens
- Enable
flycheck-mode
for Elisp configuration files - Load custom snippets with
yasnippet
- Disable prettifying of symbols on auto-completion in
LaTeX-mode