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-devUse 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 installTry 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.dmodules- 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 eitherivyorverticofor narrowing and selection (default isvertico)sb/capf- Choose eithercompanyorcorfufor in-buffer completion at point (default iscompany)sb/tab-bar-handler- Choose eitherawesome-taborcentaur-tabsfor tabbed display (default iscentaur-tabs)sb/project-handler- Choose eitherproject.elorprojectilefor handling projects (default isprojectile)sb/lsp-provider- Choose betweenlsp-modeandeglot(default islsp-mode)sb/disable-package.el- Disablepackage.eland prefer thestraight.elpackage manager.sb/python-langserver- Choose betweenpylspandpyrightas the Python language server (default ispylsp).sb/delete-trailing-whitespace-p- Control whether trailing whitespace should be deleted
We enable LSP support for the more popular languages supported with either lsp-mode or eglot. You may need to install the necessary language servers separately to complement the packages. Use M-x lsp-install-server or check setup-emacs.sh.
npm install -save-dev @emacs-grammarly/grammarly-languageserver
LTEX_VER="16.0.0"
sudo apt-get install -y libslf4j-java liblog4j1.2-java
wget https://github.com/valentjn/ltex-ls/releases/download/${LTEX_VER}/ltex-ls-${LTEX_VER}-linux-x64.tar.gz
tar xf ltex-ls-${LTEX_VER}-linux-x64.tar.gz
JDT_VER="1.27.1"
wget https://github.com/eclipse/eclipse.jdt.ls/archive/refs/tags/v${JDT_VER}.tar.gz
tar xf v${JDT_VER}.tar.gz
cd eclipse.jdt.ls-${JDT_VER}
./mvnw clean verify -DskipTests=true
# Add "eclipse.jdt.ls-${JDT_VER}/org.eclipse.jdt.ls.product/target/repository/bin" to $PATH
# rm -rf eclipse.jdt.ls-${JDT_VER} 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 fileFILEto 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
dir3Use 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 -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-24bitUsing 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.
Stop the daemon with emacsclient --eval "(kill-emacs)".
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 modekill -s USR2 [pid]killall -s USR2 emacspkill -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-statisticsand then invokeuse-package-report - Use the package
benchmark-init - Use the script
profile-dotemacs.elas 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-modefor Elisp configuration files - Load custom snippets with
yasnippet - Disable prettifying of symbols on auto-completion in
LaTeX-mode