Subject: Re: bug#4914: completions - remove window after use?

From: Stefan Monnier <[email-masked]>
Date: Tue, 17 Nov 2009 18:00:31 -0500

>> That would be good.  Quite generally, those windows/frames that are
>> created (e.g. via pop-to-buffer) for a specific window should be
>> removed after we're done with the interaction (see also quit-window).
>> I've had a kludge for this in Aquamacs for a long time (via an advice
>> to bury-buffer), but it's quite difficult to do consistently when
>> Emacs and 3rd-part packages aren't aware that this is happening.

> It's practically impossible to find a solution that satisfies all needs
> in this area.  Basically, `display-buffer' would set a special slot for
> any window it pops up and `quit-window' would try to delete a window if
> it has that slot set and still shows the argument of `display-buffer'.

How 'bout the patch below?

        Stefan "whose .emacs would have
                (setq display-buffer-mark-dedicated 'soft)"

Index: lisp/minibuffer.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/minibuffer.el,v
retrieving revision 1.96
diff -u -r1.96 minibuffer.el
--- lisp/minibuffer.el	12 Nov 2009 23:10:06 -0000	1.96
+++ lisp/minibuffer.el	17 Nov 2009 22:56:12 -0000
@@ -965,9 +965,14 @@
     (if (and completions
              (or (consp (cdr completions))
                  (not (equal (car completions) string))))
-        (with-output-to-temp-buffer "*Completions*"
           (let* ((last (last completions))
-                 (base-size (cdr last)))
+               (base-size (cdr last))
+               ;; If the *Completions* buffer is shown in a new
+               ;; window, mark it as softly-dedicated, so bury-buffer in
+               ;; minibuffer-hide-completions will know whether to
+               ;; delete the window or not.
+               (display-buffer-mark-dedicated 'soft))
+          (with-output-to-temp-buffer "*Completions*"
             ;; Remove the base-size tail because `sort' requires a properly
             ;; nil-terminated list.
             (when last (setcdr last nil))
Index: lisp/window.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/window.el,v
retrieving revision 1.185
diff -u -r1.185 window.el
--- lisp/window.el	13 Nov 2009 22:19:56 -0000	1.185
+++ lisp/window.el	17 Nov 2009 22:56:12 -0000
@@ -1042,6 +1042,11 @@
     (set-window-buffer window buffer)
     (window--display-buffer-1 window)))
 
+(defvar display-buffer-mark-dedicated nil
+  "If non-nil, `display-buffer' marks the windows it creates as dedicated.
+The actual non-nil value of this variable will be copied to the
+`window-dedicated-p' flag.")
+
 (defun display-buffer (buffer-or-name &optional not-this-window frame)
   "Make buffer BUFFER-OR-NAME appear in some window but don't select it.
 BUFFER-OR-NAME must be a buffer or the name of an existing
@@ -1133,8 +1133,10 @@
 			buffer (if (listp pars) pars))))))
      ((or use-pop-up-frames (not frame-to-use))
       ;; We want or need a new frame.
-      (window--display-buffer-2
-       buffer (frame-selected-window (funcall pop-up-frame-function))))
+      (let ((win (frame-selected-window (funcall pop-up-frame-function))))
+        (when display-buffer-mark-dedicated
+          (set-window-dedicated-p win display-buffer-mark-dedicated))
+        (window--display-buffer-2 buffer win)))
      ((and pop-up-windows
 	   ;; Make a new window.
 	   (or (not (frame-parameter frame-to-use 'unsplittable))
@@ -1149,8 +1149,10 @@
 		 (or (window--try-to-split-window
 		      (get-largest-window frame-to-use t))
 		     (window--try-to-split-window
-		      (get-lru-window frame-to-use t))))
-	   (window--display-buffer-2 buffer window-to-use)))
+		      (get-lru-window frame-to-use t)))))
+      (when display-buffer-mark-dedicated
+        (set-window-dedicated-p window-to-use display-buffer-mark-dedicated))
+      (window--display-buffer-2 buffer window-to-use))
      ((let ((window-to-undedicate
 	     ;; When NOT-THIS-WINDOW is non-nil, temporarily dedicate
 	     ;; the selected window to its buffer, to avoid that some of