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.
exec /usr/bin/env emacsclient -c -a "" $*
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/shsays to execute the file as a shell script.
execsays to replace the shell process with what comes next, instead of creating a child process.
/usr/bin/env emacsclientsays to search the current environment, specifically the
PATHvariable, for the command
emacsclientis 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.
emacsclientto open a new window using the running Emacs server process.
emacsclientwhat 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
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:
ec -n FILENAME
-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:
(global-unset-key (kbd "C-x C-c"))
(global-unset-key (kbd "C-x C-z"))
And that’s it for today.