Emacs configuration

Table of Contents


Lexical binding

By default, Emacs uses dynamic binding. In order to use closures, I enable lexical binding.

;; -*- lexical-binding: t -*-

Color theme

I prefer a dark color theme. It's much easier on the eyes, and I like working in the night often in poorly lit rooms.

(load-theme 'manoj-dark)

Font size

Set the font size to something reasonable. The font size is in units of 1/10 pt. So, by setting :height to 120, I have set the font size to 12 pt. The default font face is what all other font faces base on.

(set-face-attribute 'default nil :height 120)

GNU FreeFont Tamil letters are not very clear at smaller font sizes. So, I set them to a larger size.

(set-fontset-font "fontset-default" 'tamil
                  (font-spec :name "Free Serif" :size 14.0))

Package manager and repositories

First things first, set up the package manager. Define the list of repos and initialize installed packages. More and more, I only use Emacs packages from my distro, GNU GuixSD. But, from time to time, I still need MELPA.

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))


bind-keys is a useful macro from use-package1 that makes binding keys easy. I make extensive use of it in my Emacs configuration.


Autoloading lets you speed up Emacs startup and reduce memory usage by postponing loading files until the last moment when some command requiring that file is invoked.

Wherever necessary, I have wrapped up forms in the built-in with-eval-after-load macro so that they run only after some file is loaded.

uim input method

(autoload 'uim-mode-switch "uim")
(bind-keys ("C-\\" . uim-mode-switch))

No tabs

(setq-default indent-tabs-mode nil)

Emacs as a window manager

I totally live in Emacs, so much so that I run exwm on Emacs to use it as my window manager. This is, at least at the moment, not the easiest or the most reliable approach to window management, but there are benefits. For example, with Emacs as my window manager, I can bind any key sequence on my keyboard in Emacs. Other window managers tend to block some key sequences. I can switch to and from external programs as though they were just Emacs buffers. I don't need an external program such as xbindkeys to handle keybindings to media keys, function keys, etc. I can instead use the excellent programmability of Emacs Lisp combined with clean integration to the exwm window manager. Not only does this centralize more of my system configuration in one place, it also lets me write more complex and cleanly integrated functions for my keybindings than would be possible with a bunch of shell scripts.

Display the time

In the absence of a full fledged desktop environment, it is still nice to see the current time and battery. So, let's display them on the modeline.



In order to get keybindings to work across all buffers (both external program buffers managed by exwm and other Emacs buffers), I need to bind them using exwm-input-set-key. To make this convenient, I have a macro bind-exwm-keys similar in spirit to bind-keys described earlier.

bind-exwm-keys might have to bind key sequences to not just Emacs commands, but also to external programs. For this, the external program needs to be wrapped up in an Emacs command. This wrapping is handled by make-external-command. make-external-command returns a command that invokes the external program if it isn't already running, switches to the buffer of the external program if it is already running, and switches to the last used buffer2 if the external program is already running and is the current buffer. This makes it easy to start an external program, switch to it, and switch back from it all using the same keybinding.

(require 'exwm)

(defun switch-to-last-used-buffer ()
  (switch-to-buffer (other-buffer (current-buffer) t)))

(defun make-external-command (command)
  (lambda ()
    (let ((buffer-name (car (split-string command))))
       ((equal buffer-name (buffer-name))
       ((get-buffer buffer-name)
        (switch-to-buffer (get-buffer buffer-name)))
       (t (start-process-shell-command buffer-name nil command))))))

(defmacro bind-exwm-keys (&rest keybindings)
  `(mapc (cl-function
          (lambda ((keybinding . command))
            (exwm-input-set-key (kbd keybinding)
                                (if (stringp command)
                                    (make-external-command command)

Binding function keys and media keys

I then bind a lot of external programs to the function keys.

(bind-exwm-keys ("s-1" . delete-other-windows)
                ("s-2" . "nyxt")
                ("s-3" . start-eshell)
                ("s-4" . "lxterminal")
                ("s-9" . "dino")
                ("s-0" . "mpv")
                ("s-8" . "xbacklight -dec 5")
                ("s-\\" . "xbacklight -inc 5"))

Running external programs

I might still need to run external programs not covered above with the function and media keys. For these, I have a command run-external-program that prompts for the program to run and starts it using start-process-shell-command. The prompt provides all executables in PATH as completions.

(let ((executables (seq-mapcat
                    (lambda (bin)
                      (directory-files bin nil "^[^.]"))
  (defun run-external-program (command)
    (interactive (list (completing-read "$ " executables)))
    (start-process-shell-command command nil command)))

(bind-exwm-keys ("s-r" . run-external-program))

Rename exwm buffers

I want exwm buffers to be named according to the programs they are running.

(add-hook 'exwm-update-class-hook
          (lambda ()
             (downcase exwm-class-name))))

Enable exwm

Finally, I enable exwm.


Customization of built in Emacs features

"yes or no" vs "y or n"

I can't understand why anybody would want to answer a full word "yes", instead of just "y", or "no", instead of just "n". It's certainly too long for me. Therefore, I make all prompts "y or n".

(defalias 'yes-or-no-p 'y-or-n-p)

Backup files

I don't want backup files littering my folders. I use version control systems a lot anyway.

(setq make-backup-files nil)

Menu and tool bars

Coming from a Vim background, I prefer to not have menu bars and tool bars clutter my limited screen real estate. I like all of the screen devoted to just text. Menu bars are very useful to discover new features, but I can always enable them when I need to, instead of keeping them permanently enabled.

(menu-bar-mode 0)
(tool-bar-mode 0)

Visual line mode

A lot of my work in emacs involves writing using org mode and latex. Word wrapping and the use of "visual lines" is absolutely important for this.

(global-visual-line-mode t)

Highlighting parentheses

Highlighting matching parentheses is really important when coding. I don't know why this is not enabled by default in emacs.



Splitting windows

My screen is wide. Therefore, I want split windows to be side by side (split horizontally) rather than one on top of another (split vertically).

(setq split-height-threshold nil
      split-width-threshold 75)

Moving between windows

The standard way of moving between windows using C-x o involves too many keystrokes. I prefer the more spatially intuitive s-{left,right,up,down} keybindings of the Windmove package with wrapping around the edge of the frame enabled. The Windmove default "Shift" modifier conflicts with org mode's default keybindings. So, I'm using the "Super" modifier instead.

(setq windmove-wrap-around t)
(windmove-default-keybindings 's)

Window manipulation keybindings

I bind several window and buffer manipulation commands to keybindings in the spirit of the Super key windmove keybindings. The keybindings I have set up are better than the default keybindings for these commands because they only need one keypress instead of two.

I hardly use the window enlargement/shrinking commands. Nevertheless, I keep them just in case I need them.

(bind-exwm-keys ("<s-tab>" . switch-to-last-used-buffer)
                ("s-_" . split-window-below)
                ("s-|" . split-window-right)
                ("s--" . shrink-window-horizontally)
                ("<s-kp-subtract>" . shrink-window-horizontally)
                ("s-+" . enlarge-window-horizontally)
                ("<s-kp-add>" . enlarge-window-horizontally)
                ("s-*" . enlarge-window)
                ("<s-kp-multiply>" . enlarge-window)
                ("s-/" . shrink-window)
                ("<s-kp-divide>" . shrink-window))

Evil and Evil plugins

I was using Vim for around 3 to 4 years before switching to Emacs for lisp and its superior programmability. However, I hardly want to retrain my muscle memory by learning all new keybindings. Besides, why not use the best of both worlds? So, I use Evil (the Extensible vi Layer for Emacs) on top of Emacs to emulate Vim.


Vim users have come up with nifty plugins to make life more convenient and efficient on Vim. I used to use many of these plugins when I was on Vim. Thankfully, many of these plugins have been ported to Emacs Evil, and I can stay right at home here in Emacs and enjoy their benefits.


evil-surround, a port of vim-surround, helps change surrounding text objects (such as matching parentheses) easily. How did people live without these things!



evil-commentary, a port of vim-commentary, helps quickly and easily comment out and uncomment lines. Very useful when coding. Earlier, I used to use regular expression based substitutions to do the same thing, but this is such a commonly performed operation, that it is worth having a separate plugin for it.

I unbind "s-" as it interferes with the /shrink-window keybinding I made earlier.

(unbind-key "s-/" evil-commentary-mode-map)


A common character motion in Vim/Evil is to jump to a target word by using "f". For larger sentences, this gets tedious because you are forced to scan through the text trying to decide which character to jump to. evil-quickscope, a port of vim-quickscope, highlights these characters, making it each easier to jump to words without guesswork or tedious scanning.

evil-quickscope-always-mode is distracting with too many colors changing rather rapidly. So, I prefer to use evil-quickscope-mode which highlights target characters only on pressing the "f" key.


Relative line numbering

Relative line numbering (similar to Vim's "set rnu") is very important for the "j" and "k" motions of Evil. In Emacs, relative line numbering is implemented by the Linum-Relative minor mode. While this is not an Evil plugin, I include it along with Evil plugins because it emulates a Vim-like feature.

By default, Linum-Relative operates like Vim's "set ru" displaying 0 on the current line, and the relative line number on other lines. In order to make it operate like Vim's "set rnu" – that is, display the absolute line number on the current line and the relative line number on other lines, I set linum-relative-current-symbol to the empty string "".

Some buffers, such as shell and REPL buffers, tend to have too many lines. The use of Linum-Relative mode in those buffers slows down Emacs very badly. Some other buffers, such as image and PDF buffers, open binary files and do not have a notion of lines. The use of Linum-Relative mode in such buffers makes no sense. I avoid enabling Linum-Relative mode in these buffers.

 (lambda ()
   (let ((linum-exceptions
          '(epresent-mode eshell-mode shell-mode
            term-mode geiser-repl-mode
            image-mode pdf-view-mode magit-diff-mode
            magit-status-mode notmuch-search-mode
     (unless (member major-mode linum-exceptions)
(with-eval-after-load 'linum-relative
  (setq linum-relative-current-symbol ""))

Major modes

Gnuplot mode

Gnuplot mode provides syntax highlighting, indentation and a few other convenient functions for editing gnuplot scripts. Unfortunately, by default, gnuplot mode only recognizes file extensions .gp and .gnuplot as gnuplot scripts, while Vim recognizes the .gpi extension. I don't want to have to rename all my gnuplot scripts. So, I just tell gnuplot mode to recognize the .gpi extension as well.

(add-to-list 'auto-mode-alist '("\\.gpi" . gnuplot-mode))

Octave mode

Octave mode is a major mode for editing Octave programs. I set Octave mode to recognize .m files as Octave source files. Without this, .m files are opened in Objective C mode, which I have no need for.

(require 'map)
(map-put auto-mode-alist "\\.m$" 'octave-mode)


I used to use Helm, but it proved to be a little too resource intensive and sluggish for the humble specifications of my laptop. So now, I just use Ido mode. It's lightweight and does the job.

I've added Guile's object files (.go extension) to the completion-ignored-extension list so that they are not listed in completions for find-file.

(bind-exwm-keys ("<menu>" . execute-extended-command)
                ("s-f" . ido-find-file)
                ("s-b" . ido-switch-buffer)
                ("s-k" . ido-kill-buffer))
(with-eval-after-load 'ido
  (add-to-list 'completion-ignored-extensions ".go"))


With its convenient emacsy interface and good Emacs integration, Dired is the text based file manager that finally convinced me to quit the GUI file managers I was using earlier. I spend so much time in Emacs (programming, mail, browsing, blogging, getting things done with org mode, etc.) that an Emacs based file manager is just the natural thing to have!

In Dired's file listings, I prefer seeing approximate human readable file sizes (such as 1K, 234M, 2G, etc.) instead of the number of bytes which are usually too large to be meaningfully interpreted by a human being. Hence I've added the -h switch to Dired's ls calls.

I want Dired to automatically mirror any changes to the directory caused by external programs. So, I've enabled the Auto Revert minor mode on Dired buffers.

(with-eval-after-load 'dired
  (setq dired-listing-switches "-alh")
  (add-hook 'dired-mode-hook 'auto-revert-mode)
  (add-hook 'dired-mode-hook 'dired-async-mode))


Smartparens is a minor mode for structured editing of parenthesis pairs. In plain English, smartparens automatically balances your parantheses, helps you easily navigate up and down your S-expressions, extend parentheses (slurping), shrink parentheses (barfing), etc. This is very important for writing lisp S-expressions, and I can't imagine coding without it.

I use evil-smartparens on top of smartparens to make smartparens play nice with Evil. I've rebound various smartparens commands to convenient Vim/Evil like key bindings.

(dolist (hook '(emacs-lisp-mode-hook
                lisp-mode-hook scheme-mode-hook))
  (add-hook hook 'smartparens-strict-mode))
(add-hook 'smartparens-enabled-hook 'evil-smartparens-mode)

(with-eval-after-load 'smartparens
  (evil-define-key 'normal smartparens-mode-map
    "l" 'sp-forward-sexp
    "h" 'sp-backward-sexp
    "L" 'sp-up-sexp
    "H" 'sp-backward-up-sexp
    "<" 'sp-backward-slurp-sexp
    ">" 'sp-forward-slurp-sexp
    "{" 'sp-forward-barf-sexp
    "}" 'sp-backward-barf-sexp)
  (require 'smartparens-config))


PDFView mode is much more of a full-featured PDF reader compared to the built-in DocView mode. Hence, I use it to read PDFs.

While typesetting and building LaTeX documents, it is convenient to have the opened PDF file auto-refresh from disk. Hence, I have the Auto Revert minor mode enabled in the PDFView major mode.

(add-to-list 'auto-mode-alist '("\\.pdf" . pdf-view-mode))
(with-eval-after-load 'pdf-view
  (add-hook 'pdf-view-mode-hook 'auto-revert-mode))

Emacs Multimedia System

The Emacs Multimedia System (EMMS) lets you play audio/video from Emacs. The actual playing is delegated to external players. EMMS merely holds the controls, handles the media player user interface, etc.

For the actual playing, I use mpv. The emms-player-mpv package interfaces EMMS to mpv. My common use case is to play videos from YouTube. mpv achieves this by interfacing with youtube-dl. So, I pass preferred video format parameters via the –ytdl-format command-line argument.

(with-eval-after-load 'emms
  (require 'emms-source-file)
  (require 'emms-player-mpv)
   emms-player-mpv 'regex
   (concat "\\(https\\)\\|" (emms-player-get emms-player-mpv 'regex)))
  (add-to-list 'emms-player-mpv-parameters "--ytdl-format=best[height<=480]")
  (add-to-list 'emms-player-list 'emms-player-mpv))

Obfuscating file names

I use my department printer to print a lot of documents. My department printer is one of those giant standalone printers that are actually full computers. I copy files into my pendrive, insert it directly into the printer, and print. The printer logs the names of the files I print, and I don't like it. Often, the filename leaks too much information and I don't want others to know what I've been printing. Hence, I wrote an elisp function to copy files that obscures the destination filename to some random string.

(defun obfuscated-copy (sources destination)
  (dolist (source (if (stringp sources) (list sources) sources))
    (let* ((hashed-destination
             (concat (secure-hash 'sha256 (file-name-base source))
                     (file-name-extension source t))
             (file-name-directory destination))))
      (message "%s -> %s" source hashed-destination)
      (copy-file source hashed-destination))))



use-package also provides the use-package macro that helps you organize your various customizations in a performance oriented and tidy way. While I have outgrown it, I would still recommend it to beginners trying to grok Emacs configuaration best practices.


The switch-to-last-used-buffer function that I use for this, I credit to http://emacsredux.com/blog/2013/04/28/switch-to-previous-buffer/