Subject: bug#79065: 31.0.50; [PATCH] Allow inverting the meaning of 'quit-window-kill-buffer'

From: Jim Porter <[email-masked]>
Date: Sun, 20 Jul 2025 22:22:53 -0700

X-Debbugs-Cc: [email-masked]

For a long time, I've had a bit of code in my config to invert the 
default behavior of 'quit-window', so that it normally kills the buffer, 
but buries it with the prefix arg. With bug#76248, I now have almost 
what I want in Emacs proper (thanks!), except without the prefix arg 
behavior.

Attached is a patch to do this. Hopefully the documentation is ok, but 
I'm open to other wordings. I fear my current wording might be a bit 
convoluted...

From 6280a1edde48171e73dc88eefc20a212b03d29d4 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Sun, 20 Jul 2025 22:15:46 -0700
Subject: [PATCH] Allow inverting the meaning of 'quit-window-kill-buffer'

With the prefix argument (or passing 'invert' for KILL), 'quit-window'
now does the opposite of whatever 'quit-window-kill-buffer' says,
killing when it would normally bury and vice versa.

* lisp/window.el (quit-window): Support 'invert' for KILL.

* doc/lispref/windows.texi (Quitting Windows): Describe this behavior.
---
 doc/lispref/windows.texi | 13 ++++++++++---
 lisp/window.el           | 21 +++++++++++++++------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 4535daaadf2..30c867e89b3 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -5033,10 +5033,17 @@ Quitting Windows
 will bury @var{window}'s buffer.  If this is @code{t},
 @code{quit-window} will try to kill @var{window}'s buffer.  Otherwise,
 this should be a list of major modes.  @code{quit-window} will kill the
-buffer of @var{window} regardless of the value of @var{kill} if that
+buffer of @var{window} even when @var{kill} is @code{nil} if that
 buffer's major mode is either a member of this list or is derived from a
-member of this list.  In any other case, @code{quit-window} will kill
-the buffer only if @var{kill} is non-@code{nil} and bury it otherwise.
+member of this list.
+
+If @var{kill} is the special value @code{invert}, or when calling
+interactively with the prefix argument, then @code{quit-window} inverts
+the meaning of @code{quit-window-kill-buffer}, so that when it would
+normally kill the buffer, it buries it instead, and vice versa.
+
+In any other case, @code{quit-window} will kill the buffer only if
+@var{kill} is non-@code{nil} and bury it otherwise.
 @end defopt
 
 You can get more control by calling @code{quit-restore-window} instead
diff --git a/lisp/window.el b/lisp/window.el
index 5509f36fbe9..8b7d21d8ca3 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -5532,9 +5532,13 @@ quit-window-kill-buffer
 
 (defun quit-window (&optional kill window)
   "Quit WINDOW and bury its buffer.
-WINDOW must be a live window and defaults to the selected one.
-With prefix argument KILL non-nil, kill the buffer instead of
-burying it.
+WINDOW must be a live window and defaults to the selected one.  Kill the
+buffer instead according to `quit-window-kill-buffer' (which see).
+
+If KILL is `invert' (interactively, with the prefix argument), then
+invert whether to bury or kill the buffer: if this function would
+normally bury the buffer then kill it, or vice versa.  For any other
+non-nil value of KILL, always kill the buffer instead of burying it.
 
 This calls the function `quit-restore-window' to delete WINDOW or
 show some other buffer in it.  See Info node `(elisp) Quitting
@@ -5542,8 +5546,8 @@ quit-window
 
 The functions in `quit-window-hook' will be run before doing
 anything else."
-  (interactive "P")
-  (let (kill-from-mode)
+  (interactive (list (when current-prefix-arg 'invert)))
+  (let (kill-from-mode kill-resolved)
     (with-current-buffer (window-buffer (window-normalize-window window))
       ;; Run the hook from the buffer implied to get any buffer-local
       ;; values.
@@ -5554,8 +5558,13 @@ quit-window
 		(and (listp quit-window-kill-buffer)
 		     (derived-mode-p quit-window-kill-buffer)))))
 
+    (setq kill-resolved
+          (cond
+           ((eq kill 'invert) (not kill-from-mode))
+           (kill t)
+           (t kill-from-mode)))
     (quit-restore-window
-     window (if (or kill kill-from-mode) 'kill 'bury))))
+     window (if kill-resolved 'kill 'bury))))
 
 (defun quit-windows-on (&optional buffer-or-name kill frame)
   "Quit all windows showing BUFFER-OR-NAME.
-- 
2.25.1