Setup Emacs Servers in MacOS
09 Feb 2023Table of Contents
I switched to MacOS last year for editing home gym videos. I was and am still amazed by how fast the M1 chip is for exporting 4K videos. The MacOS also enriched the Emacs experience which makes it deserve another blog post.
So I have been slowly adapting my Emacs configuration and workflow to MacOS. One of the changes is the Emacs server.
The goal is to have fully loaded Emacs instances running all the time so I can use them at any time and anywhere, in Terminal or Spotlight. They are initiated upon login. In cases of Emacs crashes (it is rare but more often than I like) or I have to stop them because I messed up the configuration, they restart automatically.
Emacs Server Configuration
I have this setup in Linux using systemd
, as in my previous blog
post.
In MacOS, the launchctl is the service manager. It provides a user interface to list, start and stop services.
To build an Emacs server, create a plist file in ~/Library/LaunchAgents folder. In my case, I named it emacs_work.plist.
1: # cat ~/library/LaunchAgents/emacs_work.plist 2: <plist version="1.0"> 3: <dict> 4: <key>Label</key> 5: <string>emacs_work</string> 6: <key>ProgramArguments</key> 7: <array> 8: <string>/opt/homebrew/opt/emacs-plus@29/bin/emacs</string> 9: <string>--fg-daemon=work</string> 10: </array> 11: <key>RunAtLoad</key> 12: <true/> 13: <key>KeepAlive</key> 14: <true/> 15: <key>StandardOutPath</key> 16: <string>/tmp/emacs_work.stdout.log</string> 17: <key>StandardErrorPath</key> 18: <string>/tmp/emacs_work.stderr.log</string> 19: </dict> 20: </plist>
It is an extension of Emacs Plus' plist file. I made a few changes for running two Emacs servers: one for work (data sciences, research) and one for personal usage (GTD, books). Taking the "work" server as an example, the important attributes of the plist configuration file are:
- Line 5
- The unique service name to
launchctl
- Line 8
- The full path to the Emacs program. In my case, it is /opt/homebrew/opt/emacs-plus@29/bin/emacs
- Line 9
- The "--fg-daemon" option set the Emacs server name to
"work". Later I can connect to this server by specifying "-s=work"
option to
emacsclient
- Line 13
- The KeepAlive is set to true so it keeps trying to restart the server in case of failures
- Line 16 and 18
- The location of standard output and error files. They are used to debug. Occasionally I have to check those files to see why Emacs servers stopped working, usually because of me introducing bugs in my .emacs.d.
With the updated plist files in place, I start the Emacs servers with
The launchctl list | grep -i emacs
is a handy snippet that lists the
status of the services whose name includes "emacs". The output I have
right now is
PID | Exit Code | Server ID |
---|---|---|
1757 | 0 | emacs_org |
56696 | 0 | emacs_work |
It shows both Emacs servers are running fine with exit code 0.
Launch Emacs GUI in Terminal
I can now open a Emacs GUI and connect it to the "work" Emacs server
by running emacsclient -c -s work &
. The -c option
Launch Emacs GUI in Spotlight
In MacOS, I found it is natural to open applications using Spotlight, for example, type ⌘ + space to invoke Spotlight, put "work" in the search bar, it narrows the search down to "emacs_work" application, and hit return to finalise the search. It achieves the same thing as the command above but can be used anywhere.
I uploaded a demo video on YouTube to show it in action. You might want to watch it at 0.5x speed because I typed so fast...
To implement this shortcut, open "Automator" application, start a new "Application", select "Run Shell Script", and paste the following bash code
and save it as emacsclient_work in the ~/Application folder.
Essentially, the bash script above is wrapped up as a MacOS application, named emacsclient_work and the Spotlight searches the application folder by default.