Prereqs for this hack being useful to you: (1) you use GNU Emacs; (2) you keep a single Emacs running in your session and use
emacsclient to open files for editing in it; (3) you have Linux computers that use
systemd on which you keep multiple concurrent login sessions open; and (4) you want
emacsclient on those computers to automatically send your edits to the Emacs running in your currently active session.
My use case: I log into my computer while sitting in front of it (GNOME). I log into the same computer remotely over SSH and connect to a persistent Screen session. I keep Emacs running persistently in both contexts (GNOME, Screen). I want
emacsclient to instantly and invisibly do the right thing regardless of which session (GNOME, Screen) I happen to be in at the moment.
Solution: Have Emacs launch the server on startup. After that, check every few seconds to see if the current
systemd session has transitioned from idle to active. When that happens, restart the server in this Emacs process if it doesn’t already own it.
To use it: download
server-sucker.el (gist below), save it somewhere in your Emacs lisp search path, and put
(require 'server-sucker) in your
Note: read on below the code for an alternative solution which does most of what mine does without requiring any custom lisp code.
(Mostly) solving this problem with
emacsclient -t and
After I posted this, Christian Lynbech, pointed me at emacsclient’s
-c command-line options. In a nutshell, if you have an Emacs running in any session on the computer with the Emacs server started inside it, then you can use
emacsclient -t to open a file for editing inside that Emacs process but with Emacs using your current terminal as its display for the purpose of editing the file, or (if you’re in a graphical session)
emacsclient -c to open a new graphical Emacs frame to edit a file in.
Furthermore, you can launch Emacs in the background with
emacs --daemon and it’ll respond to these
emacsclient -c and
emacsclient -t requests.
This is nearly good enough to solve the problem I was trying to solve when I wrote the lisp code above, and it may be good enough for you, but here are the reasons why I prefer my solution and you might as well:
- I don’t want to have to remember to specify
-t. I just want
emacsclientto do the right thing.
- I can’t specify
emacsclientis called by another program via
I could potentially fix both of the above by writing a smart wrapper around
emacsclient which knows how to do what I want, but there are other problems…
- Something has to “own” the master Emacs process for this to work, but I want a solution that works even whether or not I’m logged in on the console.
- You can’t use
emacsclient -tinside an Emacs shell buffer, and you can’t use
emacsclient -cinside the shell buffer if you’re not currently on a graphical desktop, and if you don’t specify
-cyou have no control over which window/frame Emacs decides to open the file for editing in.
emacsclient -tdoesn’t work properly for me in a GNOME terminal window; there’s something wrong with the screen drawing.
- There’s currently a bug in GNOME which causes new Emacs frames to sometimes open with the wrong geometry. Very annoying.
My solution above avoids all of these problems.