Running Emacs as a Server (Emacs Reboot #15)

Unlike more lightweight editors, it doesn’t really make sense to run a new instance of Emacs whenever editing a file. Emacs is at its best when managing many buffers, frames, and windows from a single master process. That way you can easily copy and paste betweem buffers, search across buffers, pull auto-completions from all open buffers, and much more. Not to mention that a fully configured Emacs often takes a few seconds to startup, something you don’t want to wait for every time you open a file.

To ensure I run Emacs as a single central process, I create a new shell script for starting Emacs.

I save this script as /usr/local/bin/ec and make it executable with chmod +x /usr/local/bin/ec.

There’s a lot going on in this script:

  • #!/bin/sh says to execute the file as a shell script.
  • exec says to replace the shell process with what comes next, instead of creating a child process.
  • /usr/bin/env emacsclient says to search the current environment, specifically the PATH variable, for the command emacsclient.
  • emacsclient is part of the Emacs distribution. It communicates with a running Emacs server process to tell it to open new buffers or execute arbitrary ELisp code.
  • -c tells emacsclient to open a new window using the running Emacs server process.
  • -a tells emacsclient what command to use as an alternate if it can’t find a running Emacs server process. Giving it the empty string (“”) as an argument is a special flag which means “start a new Emacs process as a daemon in the background, and then try again to connect”.
  • $* passes any command-line arguments supplied to ec to the emacsclient executable.

Now I can just type ec FILENAME to open a file in a new Emacs window. If Emacs is already running, the window will pop open immediately. If it isn’t, a new Emacs server process is started and daemonized, and then the window pops open. The Emacs process that is started is a true daemon, so even if I close all Emacs windows or close the terminal from which I started it, it will still be running in the background, waiting for emacsclient to tell it to do something.

After sending its message to the Emacs server, the call to ec will pause until I signal I’m done editing the file using C-x # in the new window. Only then will the emacsclient process return control to the terminal. This behavior works well with programs like Git, which sometimes open an editor in order to get feedback from the user. These programs wait for the exiting of the editor process to signal that the user has finished making edits. I can set my EDITOR environment variable to ec, and it will play well with Git and other utilities.

If I just want to open a file in a new window and immediately get back to what I was doing in the terminal, I can call ec like this:

The -n flag tells emacsclient not to wait for the associated window to be closed with C-x #, but to exit immediately instead. Remember, it’s just the emacsclient process that exits, not the Emacs process itself.

One last thing: I’m running emacs as a daemon process in a graphical desktop environment. There are two keybindings which just don’t serve much purpose in this context: killing Emacs (I don’t want to do that often enough to warrant a keybinding), and minimizing a window (my window manager has its own keys for that). It just so happens that the default keybindings for these actions are close enough to C-x C-s (save-buffer) that I accidentally hit them way too often, so it’s high time I got rid of them.

I edit my keybindings file to unbind both:

And that’s it for today.

This post is part of the Emacs Reboot series. Check out the rest of the series for more Emacs goodness. You can also subscribe to a podcast feed of just the videos.