bug-gnu-emacs
[Top][All Lists]
Advanced

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

bug#4748: 23.1; least recently used window - is it?


From: Drew Adams
Subject: bug#4748: 23.1; least recently used window - is it?
Date: Sun, 18 Oct 2009 09:30:06 -0700

>  > Why shouldn't `get-lru-window' respect strictly what its 
>  > name implies, instead of having this exception that has
>  > *nothing* to do with recency of usage?
>  >
>  >   "If any full-width windows are present, it only considers these."
>  >
>  > Actually, it's not clear whether that description from the Elisp
>  > manual refers only to the behavior of function 
>  > `get-lru-window' or to the definition of "least recently used
>  > window" itself. I'm guessing it's both. (What is "it" in the
>  > sentence quoted?)
> 
> "it" usually refers to the function or variable described.  In the
> particular case "it" means `get-lru-window' and not the 
> identity of the least recently used window per se.

The name, and the description overall (especially up to that point), seem to
suggest that the function speaks for the notion: it returns the window that is
actually least recently used. The reader is thus misled (at least up to that
point).

>  > So my question is really why the "least recently used 
>  > window" isn't in fact always the least recently used window?
> 
> I suppose it's for historical reasons.  `get-lru-window' 
> should provide a window useful for displaying a buffer.
> On older displays full-width windows were probably more useful.

So rename it
`get-the-window-Emacs-cleverly-thinks-is-the-most-useful-to-display' or
something, and deprecate the name that is misleading.

Same problem for function `get-largest-window'. The behavior is such that you do
not necessarily get the largest window. (Yes, I know, that's documented.)

>  > What I would really like to be able to is to _set_ the 
>  > least recently used window - however Emacs wants to define that.
> 
> You can do that by temporarily selecting all other windows ...

Tell me how, please.

Consider this, for instance. You might think that it would cause the selected
window (`owin') to become the lru window, and then to be used by `pop-to-buffer'
for its display.

(let ((owin  (selected-window)))
  (while (not (eq (get-lru-window) owin))
   (other-window 1)))

And that works . . . except for some windows, in which case it loops forever.
IOW, there are apparently some windows that are never lru (in the sense of
`get-lru-window').

So please tell me how to do it (e.g. "by temporarily selecting all other
windows").

>  > I would do that so
>  > that code that then uses the least recently used window 
>  > would use the window I specified (by having set it as the
>  > least recently used).
> 
> ... and you can't do that unless that window is full-width ...

That seems to be the bottom line here. True lru won't get you there.

Which means you cannot use `pop-up-buffer' in any reasonable way to get the
window-selection behavior of `switch-to-buffer'. Or else please show me how.

`switch-to-buffer', which Stefan says repeatedly (and it sounds right to me)
should not be used in Lisp code (i.e. should be used pretty much only
interactively), does not respect `special-display-regexps',
`special-display-buffer-names', or `pop-up-frames'.

And yet `switch-to-buffer' _is_ used in Lisp code, including in the Emacs
sources. It is called from commonly used commands, such as `bookmark-bmenu-list'
and `view-buffer'/`view-file' (which means, e.g., `view-emacs-news').

Presumably, there is a common use case there that should be respected: someone
wants to substitute for the current buffer preferably in the same window,
instead of opening a new window and moving focus there. Dunno if that's a
reasonable use case - I never need that behavior myself, but it seems to be
fairly common.

Assuming we should be able to meet that use case, what's the right replacement
for `switch-to-buffer' for that case? What code will do the same thing wrt which
window gets used and which buffer will be put in place after using, say,
`quit-window' in the newly displayed buffer?

The above code loops forever in some cases (e.g. C-x 2 C-x 3; put 3 diff buffers
in the windows; then the small, right-hand window will never be used by
`pop-to-buffer'. That is, this will not work:

(cond ((one-window-p) ; This part works.
       (pop-to-buffer (get-buffer-create "*foo*"))
       (delete-other-windows))
      (t ; This part works except for some windows.
       (let ((owin  (selected-window)))
         (while (not (eq (get-lru-window) owin))
           (other-window 1)))
       (pop-to-buffer (get-buffer-create "*foo*"))))

(You'll recommend comparing with the root window, instead of calling
`one-window-p', but that doesn't change the point in question.)

Here's another attempt, which at least doesn't loop forever: Replace the `let'
sexp above by this:

(dotimes (i (1- (count-windows))) (other-window 1))

That suffers from more or less the same problem: the newly displayed buffer is
never shown in the right-hand window - the full-width window is always used
whenever the right-hand window is selected. (But of course this preference for
full-width is inconsistent - the just-as-small left-hand window _is_ used to
display the buffer. IOW, this dwim does not dwim.)

[You cannot just use (other-window (1- (count-window)) instead of a loop,
because that doesn't cycle the window-selection (lru) order.]

And if you have the same buffer in more than one window, then such "solutions"
also behave differently from `switch-to-buffer' when you use `quit-window'. E.g.
C-x 2 C-x 3, without using 3 different buffers, etc.

Reminder:

1. The reason for avoiding `switch-to-buffer' here, and using `pop-to-buffer'
instead, is so that variables such as `special-display-*' and `pop-up-frames'
will be respected. E.g., if `special-display-regexps' is ("[ ]?[*][^*]+[*]"),
then *foo* will be opened in its own, special frame.

2. The reason for trying to simulate `switch-to-buffer's which-window-gets-used
behavior and its `quit-window' behavior is that such behavior is apparently a
common use case. If replacing `switch-to-buffer' in, say, `view-buffer', we
would presumably want to keep the same behavior as now for users who do not use
`special-display-*' and `pop-up-frames'.

Again, dunno about #2. Maybe we should just forget about that use case and
replace `switch-to-buffer' willy nilly by `pop-to-buffer'/`display-buffer'?

Or maybe we should redefine `switch-to-buffer' so that it respects the variables
in question (and possibly other relevant variables, if any). IOW, make it use
`display-buffer'. (Why doesn't it?)

And perhaps add a parameter to `display-buffer' to let you use the same window
or specify the window to use? Or perhaps allow you to more easily set the least
recently used window and specify that the full-width stuff be ignored?

Or (more likely) maybe I'm missing something, and there is already a reasonable
way to get both (a) the `switch-to-buffer' behavior wrt window selection and
`quit-window' and (b) the `display-buffer' behavior wrt the use-another-frame
variables?

In which case, please enlighten me. How should we replace `switch-to-buffer' in,
say, `view-buffer' or `bookmark-bmenu-list' (or...)?

>  > That might even be the selected window in some cases.
> 
> ... in particular if there is only one window ;-)

Yes, but the only-window case is easy. It's the other cases that are not.

>  > Currently, it doesn't seem easy to predict or control 
>  > which window is used by things such as `pop-to-buffer'
>  > that try to use another window. Being able to set the
>  > so-called lruw that such functions use would
>  > make things a lot more straightforward.
> 
> We can easily remove the FULL-WIDTH feature.  But _who_ would be
> responsible for "touching" windows in order to make them LRU?

I would do it in my code - if it worked.

But the main question is posed above. Given the aim of, in effect, making
`pop-to-buffer' use a particular window, I tried to somehow set a window to be
the lru. But that doesn't work because of the full-width criterion.

When there is no substitute for a clever, behind-the-scenes dwim behavior, users
(including Elisp users) lose control. Even if the under-cover magic DTRT 99% of
the time (which is not certain), there should be some reasonable way for
programmers to control the behavior (get beyond the dwim).

I was hoping that simply making a window be the least recently used one would
cause `pop-to-buffer' to use that window. But things are apparently far from so
simple. I'm hoping you or someone else (e.g. Stefan) has a simple solution that
I've been blind to.






reply via email to

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