- Friday, January 05, 2007
If you followed Hack 1, you can now launch Emacs and open files from within the interface. On Windows (and in some other environments), you can also drag files to Emacs from your window manager.
But what if you want to send a file to Emacs from a console session, or via a shortcut? You could invoke Emacs using
runemacs(or create a shortcut to it), but every time you do that you end up with a whole extra instance of Emacs -- a unique operating system process which is independent from any previous instance(s).
In some cases, this might be what you want. In the rare case of an Emacs crash, for example, you would not lose any active buffers in the other instances (note that Emacs' auto-save facility would probably mitigate the damage here). Most of the time, however, you'd rather open the file in an existing instance of Emacs. This has a number of advantages:
- Memory is conserved by sharing a single process.
- Shortened start-up time since Emacs is already loaded.
- All open buffers in the shared instance can be quickly accessed from any Emacs frame.
- The buffer list can be used to see every open file across frames, and to perform actions on them.
- Dynamic abbreviations (covered in a future hack) can be sourced from a larger set of files.
- Contention issues (multiple processes accessing the same file) are avoided.
Fortunately, there is a small client / server program called gnuserv which enables us to do just this.
Installing gnuserv consists of two parts -- some platform-specific binaries (
gnuclientand, on Windows,
gnuclientw), and an Emacs Lisp file which we'll load into Emacs. The Lisp code will spawn the
gnuservprocess after Emacs has started, listening for received commands on
gnuserv's standard output stream.
On Windows, the first step is to unpack the ZIP file containing the gnuserv binaries (on Unix and derivatives, simply install the gnuserv package for your distribution). The Windows port is available at Guy Gascoigne - Piggford's site, or attached to this post if the site is unavailable. Extract the binaries to a directory in your
%PATH%(see Hack 1 for some tips on setting up your path), e.g.
Next, we need to install the Emacs Lisp portion of gnuserv. This involves placing the
gnuserv.elfile (attached to this post) somewhere in Emacs' load path. The easiest way to do this is to copy the file to the
site-lispdirectory, typically located under your base Emacs installation directory (Windows) or at
/usr/local/share/emacs/site-lisp(Unix and its derivatives). Files placed here are automatically available to Emacs.
We've installed all of the pieces necessary for gnuserv, but nothing has really changed in terms of Emacs' behavior. Even though we've added
gnuserv.elto its load path, we still need to instruct Emacs to load the file. We'll do this by adding some initialization code to our
.emacsfile (see Hack 1).
From within Emacs, type
C-x C-f(that's the control key plus x, followed by the control key plus f -- you can keep the control key pressed the whole time). This invokes Emacs'
find-filefunction, which prompts you for a file path to open using the minibuffer (the bottom line in the frame). Emacs will present you with a suggested path. Type
Tab(Emacs will remove the suggested path as part of its completion algorithm), and then press
Enterto open the file.
If you're a Windows user, this path might look strange. The tilde (
~) character is simply a handy shortcut for the folder represented by your
%HOME%environment variable, and the forward slash is Emacs' preferred path separator (that is,
C:/Usersis preferred to
C:\Users). The path syntax for the home directory is not only convenient to type, it also makes your Emacs configuration more portable. For example,
~/Desktopalways maps to your Windows desktop, regardless of your login name or other machine-specific details.
At this point, you should be staring at a blank buffer. Add the following lines to your
(require 'gnuserv) (gnuserv-start) (setq gnuserv-frame (selected-frame))
This might look somewhat strange -- it's actually just some simple Elisp which tells Emacs to load and start gnuserv. The first line calls the built-in
requirefunction, which tells Emacs to load gnuserv if it hasn't already done so (this causes Emacs to go find
gnuserv.elin our load path). The next line calls a function in
gnuserv.el, which starts (or restarts) the
gnuservprocess. The last line is an optional customization which tells Emacs that it should open new files from the clients of gnuserv in its startup frame (if you find that you prefer to have multiple Emacs frames, comment this line out by prefixing it with a
;character, or delete it entirely).
Emacs reads its
.emacsfile and evaluates these lines each time it starts up. You can either restart Emacs now, or press
M-x(M stands for meta, which is typically
eval-buffer, and press
Enter(this tells Emacs to evaluate the contents of the current buffer without requiring a restart).
At this point, you should have an Emacs instance running with
gnuservstarted. So far, so good. Now it's time to use the client programs which came with the gnuserv distribution.
gnuclient and gnuclientw
gnuclientprogram can be used to open a file in a running instance of Emacs. For example, typing
gnuclient READMEfrom a console session will open a new buffer for the file
README(even if it doesn't yet exist). If Emacs is not currently running, it will automatically be started (at which point it will evaluate its
.emacsfile, loading gnuserv).
You may notice that when a file is opened using
gnuclient, a message is displayed in Emacs' minibuffer: "When done with a buffer, type C-x #.". You may also have noticed that when you invoke
gnuclient, it does not immediately exit (that is, you can't continue using the console). What's happening is that the
gnuclientprocess is waiting for you to finish working on the file -- when you press
C-x #from within Emacs, the
gnuclientprocess exits. This is convenient in many cases -- for example, when editing a Subversion commit message. If the process returned immediately, Subversion would not be able to read the message you typed in to Emacs because there is no longer any connection between the editor and the launcher.
In other cases, however, you just want to open a file in Emacs and continue using your console session immediately. In this case, you can use
gnuclientw(Windows only -- on other platforms, use
gnuclient -q). This is a variation of
gnuclientwhich returns immediately. It's also compiled as a Windows application, so it's ideal for creating Windows shortcuts (
gnuclientopens an unneeded console window in these cases). I typically add a shortcut to
%USERPROFILE%\Desktop. In practice, I nearly always use
gnuclientw(with or without arguments) to start Emacs on Windows (because it's in your path, it can also be executed from the Run dialog). If you find yourself running
gnuclientwa lot when Emacs is already open, try adding a
-xoption to "top" the Emacs frame (make it visible if it's hidden).
The last (and in this case, the least) client program is
gnudoit, which can be used to evaluate an Elisp form. For example,
gnudoit (list-buffers)will open a window within your Emacs frame listing the currently open buffers. This command is deprecated because the same behavior can be achieved using
gnuclient-- on Windows, use
gnuclient -e (list-buffers). On other platforms, type
gnuclient -batch -eval (list-buffers). In practice, you probably won't be running these forms very often.