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