6

I have a daemonized emacs, and I'm able to close any emacs frame, even the last one, using the window manager or old good C-x C-c, just to be able to retrieve all my buffers when i ask the daemon for a new frame.

Instead if I try to close the last displayed frame using C-x 0 I'm told

Attempt to delete minibuffer or sole ordinary window

I understand that a window is not a frame, I know that the command bound to C-x 0 is delete-window, nevertheless I would like to have the window/frame closed rather than the error message.

Binding C-x 0 to delete-frame is not what I want, I want to kill windows with C-x 0 but the last one, in which case only I want to have Emacs close the frame.

gboffi
  • 594
  • 2
  • 19

1 Answers1

5

You can check to see what command a keybinding runs with C-h k KEYBINDING (where C-h k runs describe-key). If you do that with C-x 0, you get the following docstring:

C-x 0 runs the command delete-window (found in global-map), which is an interactive compiled Lisp function in ‘window.el’.

It is bound to C-x 0.

(delete-window &optional WINDOW)

Delete WINDOW. WINDOW must be a valid window and defaults to the selected one. Return nil.

If the variable ignore-window-parameters is non-nil or the delete-window parameter of WINDOW equals t, do not process any parameters of WINDOW. Otherwise, if the delete-window parameter of WINDOW specifies a function, call that function with WINDOW as its sole argument and return the value returned by that function.

Otherwise, if WINDOW is part of an atomic window, call delete-window with the root of the atomic window as its argument. Signal an error if WINDOW is either the only window on its frame, the last non-side window, or part of an atomic window that is its frame’s root window.

delete-window is for deleting windows and NOT frames. The docstring lets you know why it is signaling the errors you're seeing.

If you want to delete a frame, you need to use the command delete-frame, which, by default, is bound to C-x 5 0.

If you really want one command to do it all, below is a simple option (lightly tested) that deletes a window and, if it's the last one, deletes the frame it's in:

(defun delete-window-or-frame (&optional window frame force)
  (interactive)
  (if (= 1 (length (window-list frame)))
      (delete-frame frame force)
    (delete-window window)))
Dan
  • 32,584
  • 6
  • 98
  • 168