Weekly Emacs tip #27 — Emacs as a server/daemon and emacsclient
For roughly the first ten years of my Emacs life, I simply opened Emacs each time I wanted to edit a file. In general, this worked fine. Of course it meant that I had to keep copies of my ~/.emacs
file up to date on various machines, but as I wasn’t in the habit of editing my config very often, this was fine.
Around 2010, 2011 things started changing. I started doing more software development work, Emacs packages became a thing, which encouraged trying out new things and as a result, my ~/.emacs
init file kept growing. At the same time I was getting more into Org mode and started to experiment with using it for meeting notes, as well as documenting and tracking time spent on various projects.
The growing init file meant my Emacs startup time kept increasing. The increased Org usage, especially the time tracking, meant I kept an Emacs frame open all the time.
Emacs has been (and still is) criticised for taking a lot of time to start (generally when compared to Vim, its eternal competitor). In general there are two (non-exclusive) counterarguments to this:
- startup doesn’t need to be slow if you configure Emacs correctly by lazy-loading packages (or configure
use-package
to do that for you) - start Emacs as server or daemon so that it stays “alive” and simply don’t care about the startup time.
I use both of these, but in this post I will focus on the second and explain the how and why of running the Emacs server. The general idea is simple: start a “main” Emacs session and then use emacsclient
instead of the regular emacs
command to connect to this session and open new frames (windows for non-Emacsers) for editing files. This way, the Emacs startup time is only incurred for that first start, all subsequent calls to emacsclient
are instantaneous. Moreover, and this is actually more important to me, the complete “state” of Emacs is available all the time. My Linux desktop uses about eight virtual desktops, some dedicated to a specific task like e-mail and planning, others to different clients or projects. Having a single Emacs session means I can open one or more Emacs frames — connected to that single session — on each of these virtual desktops. If I open a buffer in one frame, I can switch to it in another — this means that, for example, the same *scratch*
buffer is available in all Emacs frames, or that I can quickly switch to one of my Org mode files to clock into or out of a project or task, or make notes. Another advantage of this is that you can point the EDITOR
environment variable to emacsclient
, which means that terminal commands like git commit
or crontab -e
open Emacs quickly, either in the console or in a new frame depending on whether you specify the --create-frame
option to emacsclient
or not.
So, are there any downsides to using Emacs in this way? In practice, I found only one that bothers me: if your Emacs sessions hangs or crashes you lose all your buffers. If you had unsaved work in any buffer in any frame, there’s a chance you have now lost it.
With all this talk about the why, what about the how? How does one set up Emacs as a server? In general there are two ways to do this, as explained in the manual.
- Start emacs as a daemon; this can be done like this:
emacs --daemon
, or by enabling thesystemd
user service provided by Emacs:systemctl --user enable emacs
. - Open Emacs the regular way and run the
server-start
command
I tried the systemd
way for some time, but ended up not liking it very much. The idea is that it starts a (headless) Emacs in the background when you log in to your computer. For reasons I don’t quite remember, I didn’t stick with it.
The way I have been working in the past few years is a variation on the server-start
method. Instead of calling that function by hand I have the following code in my ~/.emacs
:
;;; Enable the Emacs server, allows editing via emacsclient (require 'server) (when (not (server-running-p)) (server-start))
This runs the server-start
command only if there isn’t a server running already. This way, if I don’t use emacsclient
to open a new frame, but use emacs
instead, I get a fully “fresh” Emacs instance, but without the server. This makes it easier to quickly start a separate Emacs in case I want to do something that I expect might hang Emacs (e.g. loading a huge file or one with very long lines). Opening such a new non-server Emacs also makes it easy to test changes in my ~/.emacs
.
Another practical detail is that I generally don’t start Emacs or emacsclient
from the command line. Instead, I have added an Emacs application shortcut to the Gnome toolbar. By default, clicking on it opens Emacs (in a frame), which then runs server-start
if there is no server running. However, when this first Emacs frame is present I can open a new emacsclient
window by middle-clicking on the icon. This is similar to how I open a new Firefox window. And, to open a new “full” Emacs session I have added a “new instance” option to the application shortcut, which shows up when I right click on the Emacs icon in my Gnome toolbar. This is the FreeDesktop .desktop
file that does all this (it is located in ~/.local/share/applications/emacs.desktop
). It is slightly modified from the one supplied by Emacs:
- it contains the “New Instance” action
- it points to
~/.local/bin
because I compile Emacs from source and install it for my user only.
[Desktop Entry] Name=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=/home/lennart/.local/bin/emacs %F Icon=emacs Type=Application Terminal=false Categories=Development;TextEditor; StartupNotify=true StartupWMClass=Emacs Actions=new-window;new-instance [Desktop Action new-window] Name=New Window Exec=/home/lennart/.local/bin/emacsclient --alternate-editor= --create-frame %F [Desktop Action new-instance] Name=New Instance Exec=/home/lennart/.local/bin/emacs %F
Some more reading:
No Comments