How I Use Emacs
Been meaning to write a post about my current Emacs setup for a while to explain how I work with Emacs on both Mac and Linux. I am going to call this my Emacs Workflow. I have been using this setup for over a year now with very few tweaks and it serves me well. I am currently using Emacs 24, but this setup worked fine for earlier versions.
First, let me explain how I work and what I was looking for out of an Emacs Workflow. I spend most of my time on the command line. That is either a terminal or eshell running in Emacs, with really no rhyme or reason for which. Although longer running things like tailing logs and stuff over ssh tends to crash Emacs so I typically do not do those things in eshell. Having used vim for a long time, I got used to quickly opening a file, making an edit, and then closing it. But I do find it helpful to have all the currently open files in Emacs available in buffers. Emacs daemon seemed to fit both of these, but I didn’t like starting it up in my init.el or on login.
Avdi Grimm wrote an article at
about how he launches Emacs and that got me started. I hadn’t used
emacsclient very much before this. The
-a "" trick was exactly what
I wanted to start the daemon. Avdi uses this script to launch
emacsclient and create a new frame. By default, the terminal waits
for you to close Emacs, but you can pass in -n to the ec script and
return control back to the terminal immediately.
My ‘Emacs Workflow’
My workflow is a little different. When a file is opened in the
Windowed or GUI version of Emacs, I want to work on it and leave it open.
Often times I am heading back to the terminal to run a command against the
newly edited file, like
rake test or
mvn package. That mean the
terminal launching emacsclient shouldn’t wait. When there is a GUI
version of emacs already running, I want to use that instead of
opening a new frame. When a GUI Emacs is open but minimized, I want
to maximize it and then open the file there.
For quick edits, I want to open the file quickly in Emacs in the current terminal, make my edit, and then close it. Therefore, the terminal needs to wait for me to finish.
This method for quick edits is how I did all my git commits before I took the time to learn magit. If you haven’t used magit, I highly recommend you take the time to learn it. See http://magit.github.io/magit/magit.html. This is why I
export editor=etin my ~/.bashrc.
So what I ended up with is 2 scripts, which I call ec and et,
following Avdi’s lead. The former opens emacsclient in the GUI and
returns control immediately to the shell. The latter opens emacs in
the current terminal and waits. Because both scripts are backed by the
same daemon, all open files are available as buffers in both cases.
Both script will starts the daemon if it is not
ec script has some extra code to switch focus as
described in my workflow. Here are the scripts, which what I hope are
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
These files can be found in dotfiles repo at https://github.com/mjwall/dotfiles. There are also instructions on how I install Emacs on a Mac and Linux. Also in this repo is my ~/.emac.d configuration. I keep everything together to make it as easy as possible to get setup on a new machine and keep multiple machines in sync.
If you are on a Mac, it is important to get the newer version of Emacs and emacslient on the path correctly. What has worked for me is referenced in the mac gist. Likely there are other/better ways.
Bonus, executing elisp
Another way I use these scripts is by passing in -e to execute arbitrary elisp code. For example, I have an alias setup in my bashrc to launch magit. Because it is using the same script, it takes advantage of launching the daemon if necessary and changing focus. Here is what it looks like:
So in the terminal, I run
magit and it launches Emacs and runs
magit-status on the current directory. This was inspired by a
similiar tweet somewhere, but takes advantage of the rest of the
Stopping the Daemon
The last piece of this was a shell script to stop the daemon, which is
used for example when I need to reload Emacs configs. Sometimes
shutdown on my Mac hangs while waiting for Emacs to close, so I tend
to call this
es script beforehand. The script looks like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Likely there is a good way to fix this hanging, but it doesn’t bother me so I haven’t dug deeper.
If you are still reading this, you may be thinking “This all makes me want to execute arbitrary elisp in a shell script for other things”. If so, and you looked at https://github.com/mjwall/dotfiles/blob/master/bin/ed.el, you would see the following example of how to do that
1 2 3 4
Imagine the possibilities. Go through a git repo and change all tabs to spaces. I haven’t really though of anything useful to do with this, but thought it was interesting.
If you are not still reading this, you probably stopped because you thought all this was overkill. Maybe you are right.