Subject: Re: bug#8865: 24.0.50; `display-buffer' does not respect `pop-up-frames'

From: martin rudalics <[email-masked]>
Date: Fri, 17 Jun 2011 17:46:28 +0200

> I would even expect (like to see) an entry in etc/NEWS that addresses this
 > specifically.  It is typical when some construct becomes unrecommended or
 > deprecated to provide specific info about just what to use in its stead.

The NEWS entries and the manuals will be updated next week, hopefully.

 > What
 > is the recommended replacement for a nil/non-nil test of `pop-up-frames'?

Remove it.  Such a test is not reliable.

 > In any case, that is irrelevant to my concern.  Think Emacs 22 (or 21 or 20 or
 > 19 or 18), if you prefer.  My code in a couple of places, and the Emacs 22
 > source code in many places, effects a nil/non-nil test of `pop-up-frames'.  What
 > is the proper replacement for that, i.e., to get the same behavior?
 >
 >>  > Nothing special.  So the question is how to test that user
 >>  > intention using the latest Emacs design.  From my code:
 >>  >
 >>  > ;; If non-nil `pop-up-frames' then inhibit showing annotation.
 >>  > (let ((bookmark-automatically-show-annotations
 >>  >        (and bookmark-automatically-show-annotations
 >>  >             (not pop-up-frames))))
 >>  >
 >>  > ;; Use separate frames instead of windows if `pop-up-frames'
 >>  > ;; is non-nil or if prefix arg is negative.
 >>  > (cond (...)
 >>  >       ((or pop-up-frames option)
 >>  >        (while file-list (find-file-other-frame...
 >>
 >> Code shouldn't try to guess the user's intentions in the first place:
 >
 > Huh?  What is that about?  `pop-up-frames' is a user option.  What's to guess
 > about it?

Where the user wants to display the buffer.  With Emacs 23 you would in
general have to check for (1) display-buffer-function, (2) whether the
selected window shows the buffer already and can be used, and (3)
same-window-p, before you can safely decide that the user really wants
to pop up a new frame.

What you want to do is the same thing help functions tried before I
wrote the `with-help-window' macro.  Earlier, help tried to guess from
the settings of user options where `with-output-to-temp-buffer' would
put the buffer.  And the guesses were so often wrong that users
(including you) complained continuously.  So what's good for the
functions you peruse should be good for the functions you write.

With Emacs 24 a user can specify that the buffer should go into a new
window on the selected frame if a window of the desired height can be
created and in a new frame otherwise.  Which means that the user always
gets a window of the desired size.  You can't check whether the user
wants a new frame by looking at `display-buffer-alist' alone.  You have
to look at the sizes of the windows of the selected frame before you can
decide that the user really wants to create a new frame.

 > How about forgetting for a moment what you think code should and shouldn't do,
 > and just let us know what the replacement for a nil/non-nil test of
 > `pop-up-frames' is?

You first have to normalize specifiers as with
`display-buffer-normalize-specifiers'.  If in the resulting list, you
find an entry whose car is 'pop-up-frame you know that popping up a new
frame is one possible option.  Whether it will be tried depends on the
entries preceding it and the actual window configuration.

 > What is the Emacs 24 equivalent to the intention expressed by - and the behavior
 > realized by, a nil/non-nil `pop-up-frames' test prior to Emacs 24 (i.e. prior to
 > the introduction of your feature)?
 >
 > Can you express that behavior in terms of `display-buffer-alist'?  If so,
 > presumably you can give us the test of the `display-buffer-alist' value to use
 > in place of the nil/non-nil test of the `pop-up-frames' value, that is, a test
 > that gives the same behavior.
 >
 > That's all I'm asking for here: how to do, using your new constructs, what we
 > have always done before using `pop-up-frames'.

I added a new specifier to `display-buffer-alist' called
other-window-means-other-frame.  When a user sets this it means that the
user wants `display-buffer' called with the second argument t (and most
other scalar non-nil values) to pop up a new frame instead of a new
window.  I also added a function called
`display-buffer-other-window-means-other-frame' which tells you whether
a user has set that specifier for the buffer in question.  So when this
function returns a non-nil value you can safely assume that the user "in
principle" accepts popping up a new frame.  The function is included in
the code I sent you separately.

 > That's all too vague for me, I'm afraid.  What is the answer to the question?
 > How to reproduce (e.g. by testing `display-buffer-alist') the same behavior that
 > testing `pop-up-frames' as a nil/non-nil value gave before?

With `display-buffer-alist' the user sets up a list of options that
shall be tried by `display-buffer' until one succeeds.  There's no
equivalent to this in the old code where that order was hardcoded in
`display-buffer'.

 > Please stop with the "should"s regarding programming style etc. - that's not
 > very helpful.

I received complaints that applications impose a certain method for
displaying a buffer and the users didn't have a chance to change that.
Why can't we finally let _the user_ decide what `display-buffer' should
do?

 > Emacs code has always bound some user variables.  There is
 > nothing special or sacrosanct about `pop-up-frames' in this regard.  Take a look
 > at the many bindings of `case-fold-search'...
 >
 > In general, user settings "should" prevail, but there are cases where it can
 > make sense for code to override the user's preferred default behavior
 > (customization), including by binding a user option.  Whether or not a _given_
 > binding is appropriate is another matter.  But the blanket idea that code
 > "should not" bind user options is a non-starter, at least for me.
 >
 > We can certainly agree to disagree about this.

We disagree.

 > But I will suggest that your point of view on it seems quite rigid, and it is
 > unsupported by historical experience - within either the Emacs sources or
 > third-party code.  Recognize that no one is saying that your code "should" bind
 > any given option.  It is you who is apparently declaring that _all_ code must
 > _never_ bind _any_ user option.  That is a quite rigid/doctrinaire view, no?

I think code is better off if it respects the user.

 >> Obviously, if your code is targeted only at users not customizing
 >> `display-buffer-alist', you can test `pop-up-frames' as before,
 >
 > I'm perfectly willing and wanting to have my code support whatever is the new
 > design.  That's why I'm asking the question!

But then you should simply set the second argument of `display-buffer'
appropriately _without_ thinking of the user but only thinking of what's
best for the application.  If the user doesn't want what you propose
here she can override it.

 > It does not matter in the end whether I think the new design is better or worse
 > than before, or better or worse than some possible alternative, or even whether
 > I understand it.  In any case, I want/need to support it in my code.  I'm not
 > redesigning Emacs here - you are.  I'm just trying to adapt my code to your
 > changes.
 >
 > What I'm asking is how to do so.  My code needs to support multiple Emacs
 > versions, and I would like it to DTRT for Emacs 24, which I gather means testing
 > `display-buffer-alist' appropriately.  The question is how to use/test that
 > variable to get the same behavior as before, i.e., the same behavior as for
 > other Emacs versions.  Why is this such a hard question for you to address?

Your code didn't DTRT for Emacs 23.

 >> taking care of the special values 'unset (which means the user
 >> doesn't bother) and 'graphic-only.
 >
 > Please tell me specifically what you mean - I don't follow.  Please take a given
 > nil/non-nil test of `pop-up-frames' and let me know what it would be for Emacs
 > 24 and `display-buffer-alist' instead.
 >
 > Preferably, translate Emacs 22's (if pop-up-frames...) to code that will do the
 > same thing in _both_ Emacs 22 and Emacs 24 - e.g., using `display-buffer-alist'
 > for the latter (i.e., when `boundp').  Thx.

Sigh.  Maybe the new code does what you want.

martin