Skip to content

swarnendubiswas/dotemacs

Repository files navigation

My GNU Emacs Configuration

This repository lists my configuration for GNU Emacs, my primary editor. The installation instructions and customizations should work on a GNU/Linux platform and are not extensively tested on Windows. Suggestions and pull requests are welcome.

Install GNU Emacs

The Emacs version on Ubuntu is mostly outdated. There are a couple of PPAs [Emacs stable releases, Ubuntu Emacs Lisp] that we can use, but they may not include build flags I prefer. So, I suggest building Emacs from source [*Build GNU Emacs].

Build GNU Emacs

Add the following repository to install GCC v10 only if you are using Ubuntu 20.04. We do not need the following step if a more recent version version of GCC is already installed.

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 source.

wget https://ftp.gnu.org/gnu/emacs/emacs-29.4.tar.xz
tar -xf emacs-29.4.tar.xz

# Use GCC 10 or newer 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 --without-x-toolkit --with-gnutls=ifavailable --without-gconf --without-xwidgets --without-toolkit-scroll-bars --without-xaw3d --without-gsettings --without-mailutils --without-pop --without-kerberos --with-native-compilation=aot --with-json=ifavailable --with-harfbuzz --with-imagemagick --with-jpeg --with-png --with-rsvg --with-tiff=ifavailable --with-wide-int --with-xft --with-xml2 --with-xpm=ifavailable --with-gif=ifavailable --with-threads --with-included-regex --with-zlib --without-sound --with-dbus --with-tree-sitter=ifavailable CFLAGS="-O3 -mtune=native -march=native -fomit-frame-pointer -funroll-loops -floop-parallelize-all" prefix=$HOME/.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
make install

Try the following if the build fails: make bootstrap or rm lisp/loaddefs.el; make;.

Setup Emacs

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

We use straight.el as the package manager, and the setup should work on most Linux systems.

Possible build errors

Try the following resolution in case there is an error trying to connect to “raw.githubusercontent.com:443”.

git clone -b develop https://github.com/raxod502/straight.el ~/.emacs.d/straight/repos/straight.el

Comment the bootstrap code in init.el and add the following snippet.

(load "~/.emacs.d/straight/repos/straight.el/bootstrap.el" 'nomessage)
(load "~/.emacs.d/straight/repos/straight.el/straight.el" 'nomessage)

Comment the recipe for nongnu-elpa in bootstrap.el if there is an error while cloning.

Build and install texinfo if there is an error about the unavailability of makeinfo.

Directory structure

  • extras - third-party packages (may not be available from the package archives)
  • snippets - custom snippets
  • references - documentation and help files

The following are examples of a few customization options defined in init.el. Please check the file for more customization options.

  • sb/theme – Set the desired theme from a bunch of themes (default is modus-vivendi)
  • sb/modeline-theme – Set the desired modeline theme (default is powerline-nano)
  • sb/in-buffer-completion - Choose either company or corfu for in-buffer completion at point (default is company)

Support for Tags

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.

Universal Ctags

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 file FILE to use
  • M-. [TAG] <RET> – Find the first definition of TAG. The default tag is the identifier under the cursor.
  • M-* – Pop back to where you invoked M-.
  • 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 --exclude=@.ctagsignore --languages=EmacsLisp .
ctags -eR -quiet=yes --exclude=@.ctagsignore .
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

GNU Global

# Generate tags for LaTeX draft
find . -type f -iname "*.tex" -print >gtags.files
gtags -vc --gtagsconf=$HOME/.globalrc --gtagslabel=new-ctags
# Generate tags for .emacs.d directory
find . \( -path "./servers" -o -path "./etc" -o -path "./var" -o -path "./tree-sitter" -o -path "./.cache" -o -path "./eglot-java-eclipse-jdt-cache" -o -path "./eln-cache" -o -path "./straight/build" -o -path "./snippets" -o -path "./company-dict" -o -path "./**/.git" -o -path "./.git" -o -path "./share" \) -prune -o \( -type f ! -name "*.elc" ! -name "*.js" ! -name "*.png" ! -name "*.svg" ! -name "*.gif" ! -name "*.txt" ! -name "*.rst" ! -name "*.html" ! -name "*.xml" \) -print | gtags -cv --gtagsconf=$HOME/.globalrc --gtagslabel=new-ctags -f -

Configuring Emacs Daemon

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

Desktop Entry

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;

Emacs in a Terminal

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 language server.

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>.

Emacsclient

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

Debugging Emacs

  • Delete all .elc files: find $HOME/.emacs.d -name "*.elc" -delete
  • kill -s USR2 [pid]
  • killall -s USR2 emacs
  • pkill -USR2 emacs

Profile startup time

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 invoke use-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

Known Bugs

  • Disable prettifying symbols on auto-completion in LaTeX-mode

About

My GNU Emacs customizations.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published