Reusing Emacs instances with gnuserv

Posted by Steve on Wed 28 Sep 2005 at 13:03

Tags: none.

One of the nice features of GNU Emacs is that you can "reuse" existing windows, and cause new files to be loaded there. This avoids waiting for a whole new editor to startup.

I'm not about to start a flame-war. I'm a happy user of both GNU Emacs, and Vim - so don't even think about it!

The Emacs editor is very customisable. It can be tweaked on a site-wide, or on a per-user basis.

Almost every aspect of the editor can be tweaked via the built-in scripting language, Lisp. At one point I was managing to load around 2Mb of tweaks every single time that my editor started up!

Whilst most people won't take the customisation that far it does add to the slow startup time that many people accuse Emacs of having.

One solution is to take advantage of one of the available extension packages for Emacs, gnuserv. This package allows you setup your Emacs instance as a server, which you can connect to.

If you're running XEmacs you don't need to install anything; for Emacs users you should install it with:

apt-get install gnuserv

Once installed you can modify your startup file ~/.emacs to use it by adding the following lines:

;;  Start GNUServe process when starting up.  This lets us send new files
;; to previously spawned emacs process.
(load "gnuserv-compat")
(load-library "gnuserv")

This loads the library, and starts the server. Now you can take advantage of it.

  • Firstly restart your editor "emacs &".
  • Now load a new file into it with "gnuclient /etc/passwd"

Notice in the second step you received a new window? That is actually the same Emacs process! You've avoided waiting for a new process to startup.

If you wish to cause new files to be loaded into the same "window", (this is a frame in Emacs-speak), you can add the following lines to your ~/.emacs file:

;; When loading files reuse existing frames.
(setq gnuserv-frame (car (frame-list)))

The only problem now is making sure that you remember to type gnuclient rather than emacs when you open a new file from the shell. To make this simpler you can save the following to ~/bin/emacs - assuming that your PATH is setup correctly you now don't need to change anything:

# ~/bin/emacs

# "apt-get install lsof" - if you're missing "lsof".
lsof /usr/bin/emacs | grep $USER >/dev/null 2>&1

if [ "$?" -eq "1" ]; then
    /usr/bin/emacs $* &
    /usr/bin/gnuclient $* &

This script attempts to detect if you already have an emacs process running. If so it will connect to it with gnuclient. If not it will start a new instance.

The script uses the lsof tool to test for the open process rather than running:

ps -ef |grep [e]macs

This is because we wish to call the script ~/bin/emacs, and this would always cause your list of processes to include the word emacs making the test unreliable.



Posted by Anonymous (80.144.xx.xx) on Wed 28 Sep 2005 at 13:57
I needed to change $USERNAME to $USER in order to get this working.

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Wed 28 Sep 2005 at 14:09
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Thanks, I've updated the code there.


[ Parent | Reply to this comment ]

Posted by Anonymous (193.2.xx.xx) on Wed 28 Sep 2005 at 14:02
Nice article. One can also use emacsclient, which has the same behaviour. I really do not know, which is better. Bot of them work. I also bundled up a script[1], which helps you with opening new files from various applications. One can use it from terminal, console as well as default editor via EDITOR variable. Look in script for more.



[ Parent | Reply to this comment ]

Posted by Anonymous (200.102.xx.xx) on Wed 28 Sep 2005 at 14:31
(not starting a flamewar)
You can do that in gvim also:
gvim first_file
gvim --remote +split first_file

[ Parent | Reply to this comment ]

Posted by Anonymous (195.101.xx.xx) on Thu 29 Sep 2005 at 08:23
Thanks for your tip !
I used gnuserv with Xemacs some time ago, but it was lacking
when I moved to Gnu emacs. Indeed, there is emacsserver,
but it's limited to editing files, whereas gnuserv can
let you evaluate any code, like :

gnuclient -eval '(diary)' -batch -q


[ Parent | Reply to this comment ]

Posted by cmc (71.116.xx.xx) on Thu 29 Sep 2005 at 17:13
[ Send Message ]

The emacsclient that comes with the new Emacs in CVS supports the execution of arbitrary code specified on the command line, which makes it equivalent to gnuserv.

For most everyday use, of course, you're just opening and closing files, so even the old emacsclient would do. (That said, I always used gnuserv until I switched to running the Emacs in CVS.)

I have code in my .zshrc that looks for both gnuserv and emacsclient, and sets various *EDITOR* environment variables appropriately. In the ideal situation, it will find my open command, which runs an appropriate command based on the file type (although at this point it only handles things based on what I've programmed into it -- it works well enough for me that I haven't taken the obvious next step (no pun intended) of having it figure out an appropriate application based on the MIME type of the file it's acting on.

[ Parent | Reply to this comment ]

Posted by legooolas (144.173.xx.xx) on Fri 30 Sep 2005 at 16:17
[ Send Message ]
It should be noted that GNU Emacs is limited to opening a new frame of the same type as the base one -- e.g. if you gnuserv/emacsclient a new window then if your Emacs is running in X11 then it will open another X11 window.

XEmacs with gnuserv will allow you to connect to a running XEmacs session and open a new frame of a different type -- e.g. you can open a terminal-based session connected to your X11 XEmacs.
This is pretty cool :)

[ Parent | Reply to this comment ]

Posted by Anonymous (83.249.xx.xx) on Tue 29 Nov 2005 at 17:54
This is nice, though I think this functionality should go into gnuclient/server (or rather emacsclient/server).

I also think this should handle the starting of gnuserv (emacsserver). That way you can also start Emacs without gnuserv if you want another instance of Emacs for some reason.

[ Parent | Reply to this comment ]

Posted by EricAnderson (128.138.xx.xx) on Mon 10 Apr 2006 at 17:31
[ Send Message ]
My home directory is on a network file system. Some of the machines I use have lsof and gnuclient, and some of them don't. This script degrades gracefully in those situations:
# ~/bin/emacs

# "apt-get install lsof" - if you're missing "lsof".

LSOF=`which lsof`
GNUCLIENT=`which gnuclient`

if ! [ -x ${LSOF} ] || ! [ -x ${GNUCLIENT} ]; then
    echo >&2 "Missing lsof and/or gnuclient; falling back to 'emacs'."
    ${EMACS} $* &

${LSOF} ${EMACS} 2>/dev/null | grep $USER >/dev/null 2>&1

if [ "$?" -eq "1" ]; then
    ${EMACS} $* &
    ${GNUCLIENT} $* &

[ Parent | Reply to this comment ]

Sign In







Current Poll

Which init system are you using in Debian?

( 1055 votes ~ 6 comments )