emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: display-buffer-alist simplifications


From: martin rudalics
Subject: Re: display-buffer-alist simplifications
Date: Fri, 05 Aug 2011 18:01:24 +0200
User-agent: Thunderbird 2.0.0.21 (Windows/20090302)

>> `display-buffer-alist' has no built-in dependencies wrt `display-buffer'
>> like the Emacs 23 buffer display options had.
>
> I don't understand what you're saying here.

That the behavior of `display-buffer' largely depends on how it is
written and not on how the user can customize it.  Take the doc-string
of `pop-up-windows':

  "Non-nil means `display-buffer' should make a new window."

But it won't do that when `pop-up-frames' is non-nil.  The only thing
that privileges `pop-up-frames' in this regard is the way
`display-buffer' is written.  So the options obey the code and this is
the orginal sin of this function.

The absurd consequence of this is that with `pop-up-frames' non-nil
`ctl-x-4-map' becomes identical to `ctl-x-5-map' and
`find-file-other-window' an alias for `find-file-other-frame'.  You
won't find any explanation of this phenomena in the doc-strings of
`pop-up-window' and `pop-up-frame' or in the documentation.

> First we need to remove the switch-to-buffer' label (and other similar
> labels, if any).

Done.

>>> - the same-frame and the same-window parameters are one needed
>>> complexity.
>> These parameters are ill-suited for a number of reasons:
>
> I'm not saying that their Emacs-23 shape and implementation is needed.
> I'm saying that the corresponding functionality is needed.

These are crutches to work around the built-in dependencies of buffer
display options and `display-buffer' as described above.  If
`display-buffer' had been only told what to do instead of what to avoid,
this extra functionality would not have been needed.

> Obviously you agree, you even provided a lot more fine-grained control
> over such things in your code.

In order to make the behavior less ambiguous, yes.

>>     If the buffer is already displayed in some window, these options
>>     are ignored by that function.
>
> That's often the right thing to do, so it's just a lack of flexibility
> in the old code.

It shouldn't be up to the code to decide whether a window shall be
reused.

>> (3) Users devising their own `special-display-function' have to ignore
>>     them or write their own code to handle them.
>
> I don't know of any such user, so I don't worry about them too much.

So apparently users are not interested in writing their own functions.

> We already have 2 ways to name particular values (via either their value
> or their function cell), so hopefully we can use one of the two as
> "macro specifier" without having to introduce this new concept and its
> attending code.

`display-buffer-alist' already accepts both - primitive method
specifiers and macro specifiers.

>>> - I don't see how you can specify "reusing a window on another frame" in
>>> special-display-buffer-names.
>> But it is done by `special-display-popup-frame' when it finds such a
>> window on a visible frame.  And you can turn that off and on by using
>> either another function via the \(BUFFER-NAME FUNCTION OTHER-ARGS) or
>> another `special-display-function'.
>
> So you're saying that the FUNCTION hook lets you specify endless things
> including "reusing a window on another frame".

No.  I said that "reusing a window on another frame" is already built
into `special-display-popup-frame'.  And that you can turn it OFF by
using the "FUNCTION hook".

> Yes, that's true.
> And the great thing about it is that it's all done by just one simple
> hook: there is no special code designed to see whether the user
> specified "reusing a window on another frame" or not.

In fact.  Users have to write their own function in order to _avoid_
that `display-buffer' does certain things.  It's precisely this behavior
I wanted to put an end to.

>> The complexity is built into the code of `special-display-popup-frame'.
>
> I don't find it particularly complex.  It just tries each one of
> the 5 different cases in turn: use FUNCTION,

No.  If it calls FUNCTION it won't try any of the others.

> already-displayed,

Usually this is a NOOP since `display-buffer' did check that case
before.  So what usually happens is a needless extra call of
`get-buffer-window'.

It is, however, much more revealing what happens in the non-usual case:

- With the default value of `display-buffer-reuse-frames',
  `display-buffer' by itself does not reuse a window on another frame.
  `special-display-popup-frame' would reuse such a window.  Hence,
  `special-display-popup-frame' does not respect the user option
  `display-buffer-reuse-frames' with the consequence that this function
  is broken on systems where reusing frames doesn't work.

- The third argument of `display-buffer' can explictly name the frames
  to consider when searching for a window showing the buffer.
  `special-display-popup-frame' deliberately ignores that argument.

- `special-display-popup-frame' does ignore the second argument of
  `display-buffer'.  As a consequence, applications must bind
  `special-display-regexps' to nil in order to guarantee that the
  selected window is not reused.

So `special-display-popup-frame' silently ignores a user option and
overrides arguments in a much more aggressive and uncontrolled form than
would be possible with `display-buffer-alist'.  If its behavior were
correctly documented in the doc-strings of `display-buffer',
`display-buffer-reuse-frames', and all involved sepcial-display options
and functions, those doc-strings alone would already exceed that of
`display-buffer-alist'.

> same-window,

Useless because overridden by `same-window-regexps' and
`same-window-buffer-names'.

> same-frame,

Necessitated by the `pop-up-frames' overrides `pop-up-windows' paradigm
explained above.

> pop-up-frame.

Which is the original and only reasonable motivation for
`special-display-popup-frame'.

>> You don't know what `special-display-buffer-names' does unless you read
>> the code of that function.
>
> I don't know what makes you think so.

The two weeks I spent with Drew trying to understand it.

>> The correct doc-string of `special-display-buffer-names' would have to
>> explain in full what the code of `special-display-popup-frame' does.
>
> What's missing?

Are the arguments above not enough?

> There's a crucial element missing: keep the design simple and modular.

Nothing about this element is particular wrt buffer display.  If you
consider Emacs 23 options more simple or modular than
`display-buffer-alist' then you are missing one aspect: Emacs 23 doesn't
bother to explain the dependencies between options.  If you say that
`pop-up-windows' non-nil means "`display-buffer' should make a new
window" and `pop-up-frames' means "whether `display-buffer' should make
a separate frame" then you don't explain anything.

>> There are five basic methods: reuse-window, pop-up-window, pop-up-frame,
>> use-side-window and specifying a function.
>
> I suggest to bring this down to 1: specifying a function.
> We can provide the other 4 as predefined functions to use there.
>
>> `same-window' is provided as a macro specifier.
>
> Using function names is just as good as a "macro specifier" I think here.

OK.

>> The difference between `new-frame-non-dedicated' and
>> `new-frame-dedicated' is not clear to me.
>
> Trivial: one marks the frame's only window as dedicated, the other
> doesn't.
>
> There's really nothing more to it, tho in the old code, those two cases
> are handled differently (one controlled by pop-up-frames, making
> non-dedicated frames with default-frame-alist, the other controlled by
> special-display-regexps making dedicated frames with
> pop-up-frame-alist).  But in your code, this is more cleanly unified by
> just giving a (dedicate . t) param.
>
>> I suppose it stems mainly from the fact that you see dedication as
>> a way to specify what to do with the window or frame when it's no
>> more used.
>
> It's also to force display-buffer (and switch-to-buffer when called
> from Lisp packages) to use some other window/frame.  I don't want any
> other buffer ever shown in my *Completions* window (which I carefully
> size and place next to my minibuffer-only frame), same for my other
> strongly-dedicated windows like *compilation*.

Why did you have to dedicate the window for this purpose?  If
`pop-up-frames' is non-nil, you get another frame before Emacs even
tries to reuse a window not showing the buffer already.

>> I specially installed the quit-restore parameter for this
>> purpose but it's currently mostly overridden by the dedicated status
>> of the window.  Couldn't you try in your private code whether you
>> could use that parameter instead and leave window dedication to what
>> it should stand for according to its name: Avoid that `display-buffer'
>> and/or `set-window-buffer' reuse a window for showing another buffer.
>
> It might be an OK replacement for the soft dedication, yes.

Then please try it by using `quit-restore-window' instead of
`quit-window'.

>>> - `reuse-window-dedicated' (AFAIK this is only used in switch-to-buffer
>>> so it's not clear why it needs to be supported in display-buffer).
>> It can (and maybe should) be used for side windows where the IDE people
>> have that idea of windows that should always show the same buffer or one
>> of the same "group".
>
> Hmmm... yeah, I guess I can see how it might be useful there.
> But then I'd rather keep it within the `side-window' (i.e. make it
> a parameter of that display function).

Can be done.

>>> - `pop-up-window-split-unsplittable'.
>> A silly leftover from the old code, IIUC.  I'd do away with it at any
>> time.
>
> You mean it's inherited from Emacs-23 or from your old code?  If it's
> from your old code, then please remove it.  If it's from Emacs-23, maybe
> as well, tho I'd first like to see where that feature was.

A frame can have the parameter unsplittable

`unsplittable'
     If non-`nil', this frame's window is never split automatically.

The specifier tells `display-buffer' to ignore that parameter.  If you
say it's useless, I'll remove it.

>>> IIUC the reason why you don't have just a single `where' parameter is so
>>> that the merge between the specifiers given in display-buffer and
>>> display-buffer-alist can be more fine-grained, right?  What were the
>>> use-cases where you thought that was important?
>> You understand correctly.  Once for compatibility with Emacs 23,
>
> Where does compatibility require fine-grained merging?

In `display-buffer-normalize-default'.

>> once for applications,
>
> Do you have concrete use-cases?

I would have to go through the sources to find that.

>> and once for people who want fine-grained control.
>
> I don't think that's a good enough justification for the complexity
> (tho of course it's good to provide it if the complexity is needed for
> other reasons anyway).
>
>> Abstractions (like near-minibuffer and same-frame) would be
>> built on top of that.
>
> But you're saying that you're not satisfied with the way same-frame is
> built on top of that, right?

Because it's too coarse-grained for my taste.

> And I don't see near-minibuffer so
> I suspect you don't have experience with it either.

`near-minibuffer' is even worse in this regard.  You can always try
splitting the root window - it will get you a window just above the
minibuffer, if there's room for it.  If you use bottom side windows you
can specify the slot for the window which gives you quite good control.
Anything else is unreliable - the window above the minibuffer might be
the window that contains the most important information for the user at
that moment - reusing it would be very strange, at least.

> I think writing
> a display-buffer-near-minibuffer function will be simpler/cleaner than
> trying to come up with some clever way to combine various specifiers.

Any such function would run into just the same problems as
`special-display-popup-frame'.  I won't deny that such functions are
useful for a small set of users.  Their usual fate is that people always
want to add just this tiny but very important functionality.

>> I can't deny that.  But that's how `display-buffer' alway worked, in a
>> hard-coded form.
>
> I don't find the two comparable because one is a piece of code which
> provides one complex behavior via a simple API, whereas
> display-buffer-alist provides a complex API.

I suppose you really intended to write "whereas display-buffer-alist
provides one simple behavior via a complex API" here ;-)

>> Even if you use a rule based system, the rules must permit to specify
>> that I want to pop up a window first and if that fails try reusing
>> another one.
>
> No.  You just have to provide one rule which reproduces the old complex
> behavior (and could use that old code to do that).

For this purpose I would have to leave in and document the old options
forever.

>  If someone wants
> something else, she can write another rule with another behavior, but we
> don't have to care about it nor about the interaction between different
> rules as long as you restrict each rule to be used in isolation.

We'd get two, three, many instances of `special-display-popup-frame'.

martin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]