[OS X Emacs] Aquamacs, emacsclient and ^X #

Jack Repenning jrepenning at collab.net
Thu Sep 15 12:56:51 EDT 2011

On Sep 15, 2011, at 1:33 AM, Roland Whitehead wrote:

> What's the "correct" solution to this (other than using the obvious -n flag in the first place)?

If "this" means "the shell prompt not coming back," then -n *is* the correct solution.

The idea is this: your editor (or your emacsclient in this case) is often used as a helper for other operations. For example, you may be using a version control system like Subversion, CVS, git, etc. and they want to show you a text editor to prepare your commit comments. Under these circumstances, the "other" code (SVN or whatever) needs to wait until you finish with the file, so it can read the data in and use it. If emacsclient quit immediately, before you were done with typing, then all your commit logs would be empty. This is actually the scenario for which emacsclient was first invented, and it's a standard, classic UNIX-ism.

But of course, conversely, there are times when you *don't* want the caller of emacsclient to wait, such as here. So emacsclient has a switch, to alter its behavior so that it returns immediately.

The only tweak in the process I use is that I rebind ^X-^C (my usual "I'm done with this file" gesture, and much easier to type than ^X-#) to a function I've defined that also notifies the waiting emacsclient (if there is one), and deletes the frame. I'll share it with you here, but I warn you it's not totally satisfactory: Emacs, and hence Aquamacs, has a deep-rooted antipathy for hanging about without at least one frame open. If you use my function (or, judging by occasional traffic here, any other solution with the same net effect) you may occasionally end up with "zombie windows": frames that look like they're visiting some file you've already closed, but when you touch them they're unresponsive, and may poof away mysteriously. 

(defun my-save-buffer-kill-frame (arg)
  "Saves buffer, if necessary (with ARG, w/o asking), and then kills it and its frame."
  (interactive "P")
  (unless (consp (server-done))
    (let ((buf (current-buffer))
	  (kill-buffer nil))
      (if (and (buffer-file-name buf)
	       (or arg (y-or-n-p (format "Save buffer %s? " (buffer-name)))))
	  (save-buffer nil))
      (setq kill-buffer (or (not (buffer-modified-p buf))
			    (not (buffer-file-name buf))
			    (yes-or-no-p (concat "Buffer "
						 (buffer-name buf)
						 " modified; kill anyway? "))))
      (when kill-buffer
	  (set-buffer buf)
	  (set-buffer-modified-p nil))
	  (kill-buffer buf)
  (when (one-window-p t t)
    (delete-frame nil 'force)))
(global-set-key [?\C-x ?\C-c] 'my-save-buffer-kill-frame)

More information about the MacOSX-Emacs mailing list