Working with EmacsClient

3 minute read

Previously, I showed how I set $EDITOR. On my laptop, I actually do something different to take advantage of my favorite Emacs feature EmacsClient. EmacsClient is command line accessory that commands existing Emacs sessions to open files. That way you can have Emacs open with your windows arranged the way you like and push in files that you want to work as you go.

In addition, EmacsClient can be used as $EDITOR to cause programs, say a ‘git commit’ to open a window instead of starting a new editor session. On Unix-like systems EmacsClient is typically in /usr/bin/emacsclient or /usr/local/bin/emacsclient. On the Mac, at least when built from source, lives in the application bundle /Applications/Emacs.app/Contents/MacOS/bin/emacsclient.

Setup

Before you can use EmacsClient, Emacs needs to be running in “server mode”, there are pleny of ways to do this.

One time - run ‘M-x server-start’ or ‘M-x server-mode’ or, from the command line, start Emacs with the --daemon option.

emacs --daemon

Every time - put:

(server-start)
;; or
(server-mode 1)

in (depending on how you roll) your .emacs. .emacs.el, or .emacs.d/init.el.

Once the daemon process is started, running emacsclient file will open that file in the current Emacs window (or “frame” in Emacs-speak) and wait until you hit C-x #.

What if Emacs isn’t already running? The default behavior is for emacsclient to raise an error. However, if you set the environmental variable “ALTERNATE_EDITOR” to an empty string:

export ALTERNATE_EDITOR=""

then emacsclient will launch Emacs in daemon mode and wait for it to start up. ALTERNATE_EDITOR can also be set to a different, fallback editor however, I’ve never found a use case for this.

How I work

Personally, I don’t like the default emacsclient behavior as it ties up a shell window and buries the buffer I was last in. Instead, I add two command-line options, -c which creates a new frame for the file and -n which tells emacsclient to exit immediately instead of waiting for me to finish editing. As a bonus, when you use -n, closing the window EmacsClient opened has the same effect as C-x #.

Now when I fire up emacsclient -n -c file, or ec file as I like to alias it, a new frame opens with the file and I’m back at my prompt.

Setting $EDITOR

The EDITOR (and it’s strange, historical friend, VISUAL) environmental variable can be set to emacsclient -c. Doing this causes programs that launch an external editor, for example running git commit, two open it’s edits in a new frame in your current Emacs session.

When setting $EDITOR you do not want to using the -n flag. If emacsclient doesn’t wait, the program that open the editor will think you exited it. In the case of our git commit, we would end up with a blank commit message.

Putting it all together.

My complete configuration looks like this:

if [ -z "$SSH_CONNECTION" ]; then
   case $OSTYPE in
   darwin*)
       export EMACSCLIENT=/Applications/Emacs.app/Contents/MacOS/bin/emacsclient
       alias emacsclient=$EMACSCLIENT
       ;;
   *)
       export EMACSCLIENT=emacsclient
       ;;
   esac
   alias ec="$EMACSCLIENT -c -n"
   export EDITOR="$EMACSCLIENT -c"
   export ALTERNATE_EDITOR=""
else
    export EDITOR=$(type -P emacs || type -P vim || type -P vi)
fi
export VISUAL=$EDITOR

As I only want to use EmacsClient when I am on my desktop, -z "$SSH_CONNECTION" is a simple way to check for remote vs local sessions. I use $OSTYPE to detect if I am on a Mac and setup it’s unusual path. The case statement is overkill, but allows for further per OS customization.

That is a bit of upfront configuration, but I find one editor to rule them all solves my problem of having half a dozen editors open and not being able to find the one I was just working on.

Tags: ,

Updated:

Comments