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

From: "Drew Adams" <[email-masked]>
Date: Fri, 17 Jun 2011 11:31:44 -0700

> 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.

That doesn't help.  What is the _replacement_?  In Emacs ...20,21,22,23, code
can test `pop-up-frames'.  What is the corresponding test using
`display-buffer-alist' (or whatever)?  If there is no exact correspondence then
what is the closest correspondence.

>  >> 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 can I say?  The test of `pop-up-frames' tells me what I need to know in
Emacs 20,21,22,23, so that my code DTRT.  What is an equivalent test that I can
use in Emacs 24, so my code still DTRT?  That's all I'm asking.

If there is no exact equivalent, then let me know the closest thing.  I will try
it and see whether it is sufficient for my needs.

I'm asking to use your new features to get the same or very similar behavior -
nothing more.  Previously I could test the user's setting of `pop-up-frames' (at
least its current value) to determine what to do based on what the user wants
(at least as reflected in the current value).  How to do that now?

What's the closest mapping of `pop-up-frames' to (some part of)
`display-buffer-alist' or whatever the substitute is?

> You can't check whether the user wants a new frame by looking
> at `display-buffer-alist' alone.

Well, please give me the variables to check then.  And how to check them.

> 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.

Are you joking?  And just what must you look for?  And how do you decide based
on what you find?

Before, a user could specify that they generally wanted a separate frame (new or
existing, but separate), by just using non-nil `pop-up-frames'.  And code could
check that value and DTRT.

Now, you seem to be saying, code has to analyze a set of windows to determine
whether the user wants a separate frame?

Just how is that analysis done?  Please give us a code template that comes close
to the general case handled so simply before by just testing `pop-up-frames'.

What is the closest thing to the simple scenario we had before, of (1) a user
setting `pop-up-frames' to `t' to express wanting `display-buffer' to generally
use a separate frame and (2) code testing `pop-up-frames' to generally DTRT and
respect that user setting?

>  > 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.

Can you be please more specific?  Give an example, replacing a simple (if
pop-up-frames X Y) with recommended analysis-or-whatever code.

Please don't just send us off to read umpteen pages of code and explanation.
Let us start with a simple replacement example and see if that works well
enough.  If not, then we can dig deeper and try to understand more of your bells
and whistles.  Doing this will also help understanding.

>  > 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.

I hate to say it, but OK, I figured I'd try to guess what you mean here, so I
took a look at `display-buffer-alist' (in the code you sent me) - and I'm lost.

I expected I'd see `other-window-means-other-frame' somewhere, but its only
presence was in the most complex defcustom :type expression I have ever seen.

So, I said to myself, OK, I'll try `M-x customize-option' - maybe things will be
clearer once I'm in Customize.  Whoa!  The Customize buffer from hell!

Sorry to kid a bit, but I cannot make hide nor hair of this.  Can you please
give me an example, showing what I can try changing `(if pop-up-frames X Y)' to,
to at least test this case you're developing of a user setting (something in)
`display-buffer-alist' to `other-window-means-other-frame'?

I'm guessing that even after I understand that, it won't be sufficient - that at
least some users who might have had non-nil `pop-up-frames' in Emacs prior to 24
will change to something slightly different for `display-buffer-alist' from just
using `other-window-means-other-frame'.  But let me at least start with handling
that case.  Please let me know how to test this.

Please understand that this all seems super-complex to me, so far.  The
complexity you've added for handling windows has little bearing for me as a user
because I don't often use more than one window per frame.  I'm not typical in
that, but that might be the case of at least some other users who have used
non-nil `pop-up-frames'.  When such a user (I'll try to speak for myself) sees
that Customize buffer s?he is overwhelmed.

Even just as a user I don't know how to customize the option to get a behavior
that is as close as possible to what I had before (`display-buffer' generally
using a separate frame).  As a programmer I have even less idea how to handle
different user settings that all might trace their ancestry to use of non-nil
`pop-up-frames' in prior releases.

I'm asking for a little help here.  I think other users and programmers could
probably use some guidance also.

I find it hard to believe that things really need to be so complex, as shown by
that Customize buffer.  But I do not pretend to be an expert on Emacs windowing,
and certainly not on using multiple windows per frame.

> 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'.

That's fine.  I have no problem with that idea.  My problem is to know how to
deal with it, both as a user and a programmer.

To start with, how do I as a user customize `display-buffer-alist' to get a
behavior as close as possible to what I had in Emacs 22 or 23 by just setting
`pop-up-frames' to nil?

Do I remove all of the default `Display specifiers' and then add one that
corresponds to what I want?  If so, which one?

>  >> 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.

Huh?  What _are_ you talking about?  I'm not even calling `display-buffer'
directly.  This is about code that tests `pop-up-frames', in order to respect
what the user has specified for that option.

You said that if my code doesn't target users who customize `d-b-a' then it can
test `p-u-f' as before.  I answered that I _want_ my code to target users who
now customize `d-b-a', since users will do just that from now on.

I have been asking, with no success so far, _how_ to do that.  What is the
equivalent, or a close equivalent, for testing `d-b-a' now to testing
`pop-up-frames' in the past?

>  > 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.

How the f do you know that?  It works well enough for me and those who use it,
which is what it was designed for.

All I'm asking you is how to use your new features, to do what we've done before
using `pop-up-frames' - since you are replacing/deprecating that option.  You
have talked all around the question to no end, but you haven't answered it.

There are tests of `pop-up-frames' in the Emacs source code.  How will you
replace them?  That info would provide an example as a starting point, at least.

>  > 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.

Why "sigh"?  Why is that so hard?  You get rid of (deprecate) X, saying to use Y
instead, but you won't give an example of _how_ to use Y instead of X?

> Maybe the new code does what you want.

Do you mean the new version of window.el you sent me?  Sadly, no - the same
symptoms are there as I described originally.

But my previous test with your suggested `display-buffer-normalize-specifiers-1'
worked, as I mentioned.  You said you would install that, but it differs from
the definition that is in the window.el version you sent me.

And in fact I cannot even use the two together: If I load the window.el you sent
me and then eval the `display-buffer-normalize-specifiers-1' version you posted
in this thread (which worked, by itself), then I get this error:

Entering debugger...
let*: Wrong number of arguments: (lambda (specifiers) "Subroutine of
`display-buffer-normalize-specifiers'.
SPECIFIERS is the SPECIFIERS argument of `display-buffer'." (let (normalized
entry) (cond ((not specifiers) nil) ((listp specifiers) (dolist (specifier
specifiers) (cond ((consp specifier) (setq normalized (cons specifier
normalized))) ((symbolp specifier) (let ((entry ...)) (dolist (item ...) (setq
normalized ...)))))) (nreverse normalized)) ((and (not (eq specifiers (quote
other-window))) (setq entry (assq specifiers display-buffer-macro-specifiers)))
(cdr entry)) ((memq pop-up-frames (quote (nil unset))) (cdr (assq (quote
other-window) display-buffer-macro-specifiers))) (t (cdr (assq (quote
other-frame) display-buffer-macro-specifiers)))))), 3