Transitioning to GUI'd Emacs on macOS

I went on an adventure today. I left behind the stable comforts of the terminal and compiled bleeding-edge Emacs that uses a native window system.

This is a big deal for me. As long as I can remember, I’ve used Emacs from within a terminal. I’ve decided to give the GUI’d Emacs a whirl.

My Journey

I’m running macOS Catalina (10.15.5). Originally I tried using the pre-built packages via brew (brew cask install emacs) and those available at Emacs for Mac OS X. However, all these pre-built binaries crashed on Catalina. I guess it’s a problem with Catalina. 🙄

So, I decided to try building from source. I cloned the Emacs source code directly from Savannah:

$ git clone https://git.savannah.gnu.org/git/emacs.git

I cd’d into that directory:

$ cd emacs

At this point you’ve got the bleeding-edge development Emacs. You might want to check out and pull a different branch or tag. I decided to check out the native-compilation branch:

$ git checkout feature/native-comp
$ git pull origin feature/native-comp

(I’m pretty sure those are the right commands; stuff got a little funky while I was building.)

I exported a magic1 environment variable that I got from a helpful Emacs StackExchange post:

$ export LIBXML2_CFLAGS="-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2"

After exporting that variable, I ran configure:

$ ./configure

Then I ran make:

$ make

That will create a binary at src/emacs that you can run to test to make sure that all is working as it should. If you’re satisfied with that emacs configuration, you can bundle it up into a stand-alone application:

$ make install

This will create Emacs.app inside of the nextstep/ directory. You are free to move that around:

$ mv nextstep/Emacs.app /Applications/

I also went into System Preferences > Security and gave Emacs Full Disk Access. I heard of some people having difficulty accessing iCloud files from Emacs and this cleared it up. I haven’t had any difficulty—I just wanted Emacs to have full access anyway.

Niceties

I still use the terminal a lot (though I might use it less directly if I can get comfortable with ansi-term mode) so I made a few shortcuts for myself:

  • I symlinked /usr/local/bin/emacs to /Applications/Emacs.app/Contents/MacOS/Emacs:

     $ cd /usr/local/bin
     $ ln -s /Applications/Emacs.app/Contents/MacOS/Emacs emacs
    

    /usr/local/bin is already in my PATH, so now I can just type emacs on the command line and it will fire it up just as it used to

  • I created an alias like this in my .zshrc file:

     alias 'e'='emacs -nw'
    

    That way, when I’m in a terminal and type e <filename> it will open up the file in Emacs in the terminal. I might change that behavior at some point in the future, but that will help me transition for the time being.

  • I installed the exec-path-from-shell package so that Emacs could fire off processes like elixir when using lsp-mode. Otherwise, you get errors like this inside the *lsp::stderr* buffer:

     line 66: exec: elixir: not found
    

Conclusion

Why did I do this? Because I was a little bored. I also wanted to experiment with some of the more extensive key binding opportunities that a full-bodied Emacs offers.

I’ll write updates to my blog as time goes on. I might decide to switch back to regular-old Emacs in the terminal. Right now, however, I’m enjoying the GUI’d version.

You can see my Emacs config on my GitHub. Feel free to drop me a line if you have any questions.

UPDATE 2020-07-23

After using Emacs 28.0.5 for a day, here’s what I came away with:

  • No crashes. Things did start getting a little strange when I tried selecting text with the mouse in ansi-term without switching from character-mode to line-mode; I ended up killing that ansi-term session and creating a new one.

  • I really missed having frames all in the same place and switching between them with C-x 5 o. I found a very acceptable replacement; as of Emacs 27, you can enable the built-in tab-bar-mode and switch between “tabs” with C-x t o, create new ones with C-x t 2, etc. It looks just like switching between frames does in the terminal, minus the display of which tab you’re on. I haven’t figured out how to turn that on yet.

  • Using the tab-bar stuff, I created a tab and fired up ansi-term. I was able to switch back and forth between my editor tab and the console tab as I would between iTerm tabs or if I were using C-z to suspend.

  • Inputting special characters via the keyboard has changed. No longer can I hit alt-shift-- to insert an em-dash. Instead, I turn on TeX mode input (C-\ TeX RET) and I can type the TeX character sequence (in the case of an em-dash, you just type a normal dash three times) and it will be inserted into the buffer.

In short, I’m finding this switch a decently comfortable one. I’m not giving up very much, and I’m gaining a decent amount. I’ve had some difficulty getting all the colors in the theme how I like them—I might just give up for a bit and see if I get used to them.


  1. I’m not entirely sure what it does. I know that it didn’t work before using this environment variable, and now it works after I tried using it. ↩︎