I have used the Emacs for Mac OS-X distribution of Gnu Emacs for years and have been quite pleased with it. Emacs' server-mode is great in that it makes for very fast load times and it allows sharing buffer contents, kill rings, etc., between windows. However, I found it a little tricky to get it working perfectly on OS-X. These are my notes on how to install and configure it so that server-mode works correctly on OS-X.
Under server-mode, the emacsclient program is used to edit files. I have another note about how to configure emacsclient as an OS-X application. This may be worth reading as well.
Install Emacs for Mac OS-X.
Update your path:
Create a script named ec that invokes emacsclient with desired options. Note that this returns immediately; it does not wait for the edit to complete.
Create a script named ecw that invokes emacsclient with desired options. Note that this command will not exit until the edit is complete.
Many programs use the EDITOR and VISUAL environment variables to determine which editor to use. Set these up to use ecw.
Whenever you run ec or ecw, an emacs daemon in server-mode will be started, if one doesn't already exist.
This is the simplest emacs setup that I've used and it works well.
While not specific to OS-X, this is germane to server-mode emacs.
I'm used to killing buffers with C-x k. When first starting to use server-mode, I started seeing warnings about a client still using the buffer that I was killing. For my (simple) use case, the following allows me to keep using my old muscle-memory to kill the buffer yet avoid the warning:
Before I settled on the above approach, I configured OS-X to automatically start emacs in server-mode at boot time. This does work, but it isn't as clean as the above. Here's how to do it:
Create the plist ~/Library/LaunchAgents/org.fsf.gnu.emacs.plist using an editor:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>org.fsf.gnu.emacs</string> <key>ProgramArguments</key> <array> <string>/Applications/Emacs.app/Contents/MacOS/Emacs</string> <string>--daemon</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <!-- restart if it terminates --> <key>ServiceDescription</key> <string>Gnu Emacs Daemon</string> </dict> </plist>
Install the plist:
Note: I made up org.fsf.gnu.emacs. There's nothing magic about it; it could be any unique value.
Now OS-X will start emacs in daemon mode and keep it running for you. I have had weird things happen with this approach, which is why I converted to the first method presented.
'Open-with' and emacsclient
After creating an emacsclient app via Platypus, I was disappointed to notice that the app did not appear in the 'Open With' menu when a supported file was control-clicked on.
Here is how I took care of this issue.
/Applications/emacsclient.app/Contents/Info.plist contains an array of file extensions that it knows how to open; they are stored under the CFBundleDocumentTypes key. The array was empty, containing only a *.
I concluded that a suitable array could be copied from Emacs.app and set about trying to insert it into emacsclient's Info.plist. After a few hours of PlistBuddy and plutil, I was unable to get what I inserted as the array to be properly recognized.
This is why I don't like binary / non-editable configuration files. There's no reason that the plist shouldn't be editable text: YAML, XML, JSON, or whatever. A binary format for configuration files that can only be modified with dedicated tools is insane.
I finally dropped back to Python, having bypassed it initially, assuming that programming be the long road to get it done. I was surprised to see that Python includes plistlib in its standard distribution. It made things ridiculously easy.
The following code grabs the array from Emacs.app, and inserts it into a copy of Info.plist taken from emacsclient.capp. It saves the modified result as Info.plist.new in the current directory.
#!/usr/bin/env python # Run this script from the command line with the path to the Emacs.app # Info.plist as the first argument and the path to the emacsclient.app # Info.plist as the second argument. 'Info.plist.new' will be created # in current direcotory. import sys, plistlib, os (pl_from, pl_to) = sys.argv[1:] plf = plistlib.readPlist(pl_from) plt = plistlib.readPlist(pl_to) plt['CFBundleDocumentTypes'] = plf['CFBundleDocumentTypes'] plistlib.writePlist(plt, os.path.basename(pl_to) + '.new')
When this completes, copy the resulting Info.plist.new to emacsclient.app/Contents/Info.plist (after making a backup copy).
So that OS-X picks up the change, it is necessary to run lsregister, which causes Launch Services to rebuild its database. Here's how:
# Valid for OS-X 10.11.2. If the path is invalid on yours, # run 'locate lsregister' to find it. % F=/System/Library/Frameworks/CoreServices.framework % F+=/Versions/A/Frameworks/LaunchServices.framework % F+=/Versions/A/Support/lsregister % $F -lint -kill -r -domain local -domain system -domain user
This may take 15-30 seconds to run. After that, emacsclient will appear in your 'Open With' menu the next time you use it; it's worth the effort.