?

Log in

No account? Create an account

fanf

Opening new emacs frames

« previous entry | next entry »
5th Jun 2007 | 08:40

One of the features I like about Firefox is when I run firefox (from the command line or from my window manager) it will start it if it isn't running, and it'll open a new window if it is. I have a lot of virtual desktops, and it is much more convenient to just run firefox than to find a desktop with an existing firefox window, create a new window, then move it to the target desktop. Sadly emacs is not so accommodating.

Emacs has a feature which allows you to tell a running emacs to start editing a file. However it does not open a new frame to display the file, so you have to go searching through your virtual desktops to find where it ended up.

I run emacs version 21, but version 22's emacsclient has a new -e (eval) option which allows you to tell emacs to run arbitrary lisp. This can solve the niggles I have described: e.g. to open a new emacs frame on the current desktop I could just run emacsclient -e '(make-frame)'. It would be nice to have this feature in version 21, so I have come up with an evil hack to do the job.

My original idea was that I could set up a file with a local variables section, including an "eval" specifier that tells emacs to open a new frame. Then opening the file would create a new frame. However emacs is sensibly paranoid and won't run lisp in arbitrary files without manual confirmation.

Plan B was to add a function to the find file hook, so that when I opened a specific file (that need not exist) the necessary magic would occur. Then running emacsclient --no-wait ~/.emacs-newframe would create a new frame. After some fiddling I made this work. The code in my .emacs is as follows. As well as creating a new frame, it kills the buffer containing the dummy file and switches the new frame to the canonical dummy buffer, to keep things tidy. It uses the server-visit-hook which is a bit more specific for my purpose than the file-find-hook.

(defun fanf-newframe ()
  (cond ((string-equal buffer-file-name "/home/fanf2/.emacs-newframe")
	 (kill-buffer nil)
	 (select-frame (make-frame))
	 (switch-to-buffer "*scratch*"))))

(add-hook 'server-visit-hook 'fanf-newframe)

A little wrapper script can start emacs or run emacsclient as necessary, to get behaviour like firefox. Instead of running bare emacsclient, it can now also create a new frame before asking emacs to visit a file, which is a bit nicer. However doing so may be racy because I can't make emacsclient ~/.emacs-newframe (without --no-wait) work sensibly: the hook runs before the buffer is registered as being visited by emacsclient, so the hook can't tell the server that the buffer is finished with after it is sure the frame exists. However emacs is not internally multi-threaded and the server handles requests in-order, so it's probably OK.

| Leave a comment | Share

Comments {13}

(Deleted comment)

Gerg

from: zkzkz
date: 5th Jun 2007 09:29 (UTC)

I do seem to recall gnudoit had an option to do precisely this in the past. I'm surprised it got lost when emacsserver levelled up to replace it.

Reply | Parent | Thread

(Deleted comment)

Gerg

from: zkzkz
date: 5th Jun 2007 09:27 (UTC)

I don't understand why you're mucking about with .emacs-newframe

For your purposes can't you just make server-visit-hook call make-frame all the time?

Reply | Thread

Tony Finch

from: fanf
date: 5th Jun 2007 10:01 (UTC)

You have to give a filename argument to emacsclient, and most of the time I just want a new frame without specifying a file to edit. I usually run the wrapper script with a key shortcut or window manager menu item, so there isn't a convenient way of specifying a file.

Reply | Parent | Thread

from: stephdairy
date: 5th Jun 2007 10:09 (UTC)

In XEmacs gnuclient and gnuserv give you the feature you want (and I use them all the time), but they might not be available in GNU Emacs.

(S)

Reply | Thread

filecoreinuse

from: filecoreinuse
date: 5th Jun 2007 10:27 (UTC)

Or you could just use vim and not care about spawning as many copies as you want because it *still* takes up less memory than one emacs session.

Reply | Thread

filecoreinuse

from: filecoreinuse
date: 5th Jun 2007 10:27 (UTC)

*sigh* - LJ ate the <troll> tags around that...

Reply | Parent | Thread

Just a random swede

from: vatine
date: 5th Jun 2007 10:58 (UTC)

I could comment on this with (some) real-world stats, but... :)

Reply | Parent | Thread

Tony Finch

from: fanf
date: 5th Jun 2007 11:05 (UTC)

I like building up an emacs session with lots of state. It's quite convenient to reserve a virtual desktop for a set of files I edit or read quite frequently. Also I dislike vim because it is not compatible with proper Berkeley vi and breaks by finger macros.

Reply | Parent | Thread

Just a random swede

from: vatine
date: 5th Jun 2007 11:20 (UTC)

That'd be why I I install nvi as soon as possible (and ideally uninstall vim, if I have a choice). I still tend towards vi for "small edits", but if I'm actively using emacs when the need for an unassociated small edit is needed, it tends to be done there. Thus the inclusion of (setq wq "Emacs, not vi!") in my .emacs file.

Reply | Parent | Thread

filecoreinuse

from: filecoreinuse
date: 5th Jun 2007 12:18 (UTC)

Funnily enough I dislike vi because is not compatible with proper vim and breaks *my* finger macros. :)

Reply | Parent | Thread

gareth_rees

from: gareth_rees
date: 5th Jun 2007 20:26 (UTC)

In Emacs 22 I reckon you can use (setq server-window #'switch-to-buffer-other-frame) (untested, but it looks plausible based on the server-window docstring).

Reply | Thread