Subject: bug#7368: display-buffer a softly dedicated window

From: martin rudalics <[email-masked]>
Date: Wed, 17 Nov 2010 18:13:41 +0100

> 1) In principle, switch-to-buffer may fail.
 >
 > 2) switch-to-buffer doesn't fail in
 >
 > (let ((foo (get-buffer-create "foo"))
 >     (bar (get-buffer-create "bar"))
 >     (baz (get-buffer-create "baz")))
 >  (switch-to-buffer foo)
 >  (delete-other-windows)
 >  (let ((bar-window (display-buffer bar t)))
 >   (set-window-dedicated-p bar-window 'soft)
 >   (select-window bar-window)
 >   (switch-to-buffer baz)))
 >
 > 3) display-buffer uses switch-to-buffer as a subroutine.

That would be a very bad idea ;-)

 > 4) display-buffer checks some conditions before calling
 > switch-to-buffer, because the latter may fail.

As a matter of fact, both may fail.

 > 5) display-buffer fails in
 >
 > (let ((foo (get-buffer-create "foo"))
 >     (bar (get-buffer-create "bar"))
 >     (baz (get-buffer-create "baz")))
 >  (switch-to-buffer foo)
 >  (delete-other-windows)
 >  (let ((bar-window (display-buffer bar t)))
 >   (set-window-dedicated-p bar-window 'soft))
 >  (display-buffer baz t))
 >
 > 6) This is because checks in display-buffer before calling
 > switch-to-buffer and inside switch-to-buffer are different.

See above.

 > 7) I believe this is not logical and should be fixed.

If the window is dedicated for the sole purpose to make it disappear
when it's no more need I tend to agree.  There are better solutions.
But if an application is allowed to display another buffer _while the
completions window is shown_ it would be a bad idea to use the
completions window.

 > 8) I think there is an easy way to fix it by checking for dedicated =
 > t instead of dedicated != nil inside get-lru-window and
 > get-largest-window.

The _only_ purpose of weakly dedicated windows is to not allow
`display-buffer' to use them.  What else would they be good for after
your "fix"?  And what would you do if someone made completion windows
strongly dedicated to their buffer?

 > Do you agree with points 1-6?

If you rewrote them correctly, maybe.

 > You are right, completions buffer is not useful at the time
 > display-buffer is executed. Now completions buffer doesn't get buried
 > because no one buries it.

IIUC the sequence of events is

(1) the application issues a call for getting the name of a buffer,

(2) the user enters the name with the assistance of the completion
     routines,

(3) the completion routines return the name,

(4) the caller displays the buffer with that name.

Now why does the completion window not go away after (3) and before (4)
and what makes it go away after (4)?

 > To bury it before display-buffer is my plan B actually ;-)  The
 > problem with this solution is that it's not general: one will have to
 > modify many top-level commands capable of displaying a buffer to bury
 > *Completions* beforehand.

After returning a value the completions buffer should be buried
immediately.  So there must be something tricky in this.

 > Also such modification would most likely be rejected for upstream, as
 > properly coding when to bury *Completions* is not trivial, and that
 > nontrivial code would be in many places.

It's not the task of the application to care about the window.

 > comint.el solves this problem somehow, but so far I'm not able to
 > fully understand the code. What I see is that comint.el 's
 > *Completions* intercepts keyboard events while it's active.

That's not very nice either :-(

martin