[Top][All Lists]

[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

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

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

>  > 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*"))
      (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.


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

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]