From: "Drew Adams" <drew.adams@oracle.com>
To: "'martin rudalics'" <rudalics@gmx.at>, <4748@emacsbugs.donarmstrong.com>
Subject: bug#4748: 23.1; least recently used window - is it?
Date: Sun, 18 Oct 2009 09:30:06 -0700 [thread overview]
Message-ID: <361C5607E07445959296A72FA999D368@us.oracle.com> (raw)
In-Reply-To: <4ADAECF8.7020200@gmx.at>
> > 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.
next prev parent reply other threads:[~2009-10-18 16:30 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-18 8:41 bug#4748: 23.1; least recently used window - is it? Drew Adams
2009-10-18 10:24 ` martin rudalics
2009-10-18 16:30 ` Drew Adams [this message]
2009-10-18 17:36 ` martin rudalics
2009-10-18 18:48 ` Drew Adams
2009-10-19 7:36 ` martin rudalics
2009-10-19 1:58 ` Stefan Monnier
2009-10-19 6:28 ` Drew Adams
2009-10-19 13:57 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=361C5607E07445959296A72FA999D368@us.oracle.com \
--to=drew.adams@oracle.com \
--cc=4748@emacsbugs.donarmstrong.com \
--cc=rudalics@gmx.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).