unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#4748: 23.1; least recently used window - is it?
@ 2009-10-18  8:41 Drew Adams
  2009-10-18 10:24 ` martin rudalics
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2009-10-18  8:41 UTC (permalink / raw)
  To: bug-gnu-emacs

Consider it a question rather than a bug, if you prefer.
 
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?)
 
So my question is really why the "least recently used window" isn't in
fact always the least recently used window?
 
It seems clear that code cannot depend on this lru concept behaving
according to the chronology of window access. To control which window
is the lru means you must consider not only window-access chronology
but whether there are full-width windows etc.
 
What I would really like to be able to is to _set_ the least recently
used window - however Emacs wants to define that. 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). That
might even be the selected window in some cases.
 
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.
 

In GNU Emacs 23.1.1 (i386-mingw-nt5.1.2600)
 of 2009-07-29 on SOFT-MJASON
Windowing system distributor `Microsoft Corp.', version 5.1.2600
configured using `configure --with-gcc (4.4)'
 







^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  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
  0 siblings, 1 reply; 9+ messages in thread
From: martin rudalics @ 2009-10-18 10:24 UTC (permalink / raw)
  To: Drew Adams, 4748

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

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

 > It seems clear that code cannot depend on this lru concept behaving
 > according to the chronology of window access. To control which window
 > is the lru means you must consider not only window-access chronology
 > but whether there are full-width windows etc.

Yes.

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

 > 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
 > might even be the selected window in some cases.

... in particular if there is only one window ;-)

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

martin





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-18 10:24 ` martin rudalics
@ 2009-10-18 16:30   ` Drew Adams
  2009-10-18 17:36     ` martin rudalics
  2009-10-19  1:58     ` Stefan Monnier
  0 siblings, 2 replies; 9+ messages in thread
From: Drew Adams @ 2009-10-18 16:30 UTC (permalink / raw)
  To: 'martin rudalics', 4748

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






^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-18 16:30   ` Drew Adams
@ 2009-10-18 17:36     ` martin rudalics
  2009-10-18 18:48       ` Drew Adams
  2009-10-19  1:58     ` Stefan Monnier
  1 sibling, 1 reply; 9+ messages in thread
From: martin rudalics @ 2009-10-18 17:36 UTC (permalink / raw)
  To: Drew Adams; +Cc: 4748

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

Maybe.  I'll leave this to people more literate.

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

The behavior was introduced nearly 25 years ago by this change

1985-09-07  Richard M. Stallman  (rms@mit-prep)

	...
	* window.c (Fget_lru_window):
	Give preference to full-width windows.

so I think we should leave that alone.

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

Where do you see a difference in the documentation of `get-lru-window'?

 >>  > 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').

Well, we know that there are such windows.

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

Something like

(let ((owin (selected-window)))
   (dolist (window (window-list))
     (unless (eq window owin)
       (select-window window)))
   (get-lru-window))

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

Maybe.  My `switch-to-buffer' is in Elisp for quite some time.  It goes
like

(defun switch-to-buffer (buffer-or-name &optional norecord)
   "Switch to buffer BUFFER-OR-NAME in the selected window.
If BUFFER-OR-NAME does not identify an existing buffer, then this
function creates a buffer with that name.

When called from Lisp, BUFFER-OR-NAME may be a buffer, a string
\(a buffer name), or nil.  If BUFFER-OR-NAME is nil, then this
function chooses a buffer using `other-buffer'.  Optional second
arg NORECORD non-nil means do not put this buffer at the front of
the list of recently selected ones.  This function returns the
buffer it switched to.

WARNING: This is NOT the way to work on another buffer
temporarily within a Lisp program!  Use `set-buffer' instead.
That avoids messing with the window-buffer correspondences."
   (interactive "BSwitch to buffer:\nP")
   (cond
    ((eq buffer-or-name (window-buffer))
     ;; Basically a NOP.  Avoid signalling an error in the case where
     ;; the selected window is dedicated, or a minibuffer.

     ;; But do put this buffer at the front of the buffer list, unless
     ;; that has been inhibited.  Note that even if BUFFER is at the
     ;; front of the main buffer-list already, we still want to move it
     ;; to the front of the frame's buffer list.
     (unless norecord
       (record-buffer buffer-or-name)
       (set-buffer buffer-or-name)))
    ((or (window-minibuffer-p) (eq (window-dedicated-p) t))
     (pop-to-buffer buffer-or-name nil norecord))
    (t
     (let (buffer)
       (if buffer-or-name
	  (progn
	    (setq buffer (get-buffer buffer-or-name))
	    (unless buffer
	      (setq buffer (get-buffer-create buffer-or-name))
	      (set-buffer-major-mode buffer)))
	(setq buffer (other-buffer (current-buffer))))
       (set-buffer buffer)
       (unless norecord
	(record-buffer buffer))
       (set-window-buffer nil buffer)
       buffer))))

but you can't try that on your system because you don't have
`record-buffer' (you could comment out the call though).

 > `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'.

Because it wouldn't make much sense to respect these ;-)

 > 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').

We'd have to look at each of these cases to tell whether they can use
`pop-to-buffer' directly.

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

I can't tell.  Obviously `same-window-buffer-names' and friends
implicitly provide the same service.

 > Assuming we should be able to meet that use case, what's the right replacement
 > for `switch-to-buffer' for that case?

If and when we enhance `display-buffer' with a same-window argument
`switch-to-buffer' could become obsolete (for Elisp calls).  OTOH this
might lead programmers to call `display-buffer' with the same-window
argument in these and other cases.

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

Does `quit-window' behave differently wrt whether `switch-to-buffer' was
called or `pop-to-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.)

You shouldn't use `other-window' because it doesn't bury the window as
you expect.  Loop over `window-list' instead.

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

I still don't understand why and how you want to control the setting of
the LRU window in practice.

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

In what sense do they behave differently?

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

Good.

 > 2. The reason for trying to simulate `switch-to-buffer's which-window-gets-used
 > behavior and its `quit-window' behavior

I still don't understand - what is `switch-to-buffer's `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'.

So try to experiment with the following: Have `display-buffer' interpret
a 'same-window value for the NOT-THIS-WINDOW argument and replace calls
like (switch-to-buffer buffer) with (pop-to-buffer buffer 'same-window).

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

It does (if the selected window is dedicated).

 > And perhaps add a parameter to `display-buffer' to let you use the same window
 > or specify the window to use?

See above.

 > Or perhaps allow you to more easily set the least
 > recently used window and specify that the full-width stuff be ignored?

I wouldn't object that.

 > 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...)?

First you have to enlighten me wrt the quit-window behavior.

 >>  > 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 it's the _user_ who should touch the windows, not the application
programmer.

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

Stefan has proposed to enhance the NOT-THIS-WINDOW argument of
`display-buffer' for this purpose and I'm all for it.

martin







^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-18 17:36     ` martin rudalics
@ 2009-10-18 18:48       ` Drew Adams
  2009-10-19  7:36         ` martin rudalics
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2009-10-18 18:48 UTC (permalink / raw)
  To: 'martin rudalics'; +Cc: 4748

> (let ((owin (selected-window)))
>    (dolist (window (window-list))
>      (unless (eq window owin)
>        (select-window window)))
>    (get-lru-window))

That doesn't work either. For the same reason: `get-lru-window' will never
return certain windows.

>  > 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.
> 
> Maybe.  My `switch-to-buffer' is in Elisp for quite some 
> time.  It goes like
...
>     ((or (window-minibuffer-p) (eq (window-dedicated-p) t))
>      (pop-to-buffer buffer-or-name nil norecord))

(I'm curious: Why not call `pop-to-buffer' if the window is dedicated or a
minibuffer? What's the reason for that conditional?)

If you feel that your version of `switch-to-buffer' makes it respect the
use-other-frame variables but otherwise have the same behavior as the current
`switch-to-buffer', then why don't you install it?

But do you in fact claim that? If not, I don't see it as a solution to the
question.

>  > `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'.
> 
> Because it wouldn't make much sense to respect these ;-)

Huh? Why not? Why shouldn't it use the current window (as now) except when those
variables say not to (a la `switch-to-buffer-other-window' and `pop-to-buffer')?

IOW, have it do just what you claim it already does for dedicated windows. Just
as a dedicated window says "don't use me", so the use-other-frame variables also
say "don't use me". You say that we listen to the former - but we unfortunately
still do not listen to the latter.

>  > 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').
> 
> We'd have to look at each of these cases to tell whether they can use
> `pop-to-buffer' directly.

They cannot, by definition, if we intend to keep the current behavior of using
the same window (except when the use-other-frame vars say not to) and having the
same `quit-window' behavior.

The problem is not just looking at each occurrence individually. The problem is
how to get the intended behavior (current window unless frame vars say
otherwise; same `quit-window' behavior).

>  > 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.
> 
> I can't tell.  Obviously `same-window-buffer-names' and friends
> implicitly provide the same service.

How so? If you have a solution to the question I raised, please post it, by all
means.

>  > Assuming we should be able to meet that use case, what's 
>  > the right replacement for `switch-to-buffer' for that case?
> 
> If and when we enhance `display-buffer' with a same-window argument
> `switch-to-buffer' could become obsolete (for Elisp calls).  OTOH this
> might lead programmers to call `display-buffer' with the same-window
> argument in these and other cases.

Is that a discussion topic for emacs-devel? If you're proposing such a change to
`display-buffer', then it should be discussed there. Such a change shouldn't
"just happen".
 
>  > 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?
> 
> Does `quit-window' behave differently wrt whether 
> `switch-to-buffer' was called or `pop-to-buffer'?

Try it. I gave the recipe. Use the code I sent that uses `pop-to-buffer' and
compare, using the C-x 2 C-x 3 situation, with different buffers and with the
same buffer in all 3 windows.

>  > 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.)
> 
> You shouldn't use `other-window' because it doesn't bury the window as
> you expect.  Loop over `window-list' instead.

Please show me what you mean. You can see what I'm trying to do. How to do it?

And please explain why `other-window' should not be used - in what way doesn't
it "bury the window as you expect"? Is it also a dwim function? What about
`next-window' - would that work better?

>  > 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.]
> 
> I still don't understand why and how you want to control the 
> setting of the LRU window in practice.

I don't really care about the lru window. I was trying to get `pop-to-buffer' to
use the selected window (whatever that window is, no exceptions). And also to
keep the same `quit-window' behavior that you get when you use
`switch-to-buffer'.

>  > 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.
> 
> In what sense do they behave differently?

When you quit the window, you get a different buffer from what you get when you
use `switch-to-buffer'. At least that's what I saw. Try the examples I mentioned
- C-x 2 C-x 3.

>  > 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.
> 
> Good.
> 
>  > 2. The reason for trying to simulate `switch-to-buffer's 
>  >    which-window-gets-used behavior and its `quit-window' behavior
> 
> I still don't understand - what is `switch-to-buffer's `quit-window'
> behavior?

God only knows. I don't try to characterize any of the behavior in a meaningful
way. It does what it does - why and how I do not know.

The point is that if you use `switch-to-buffer' and then quit the window, the
buffer that is displayed is different than what you see if you use
`pop-to-buffer' (successfully forcing it to use the same window, at least for
most windows) and then you quit the window. Try the examples I gave, and see for
yourself.

Again, personally I don't care about preserving the same behavior that
`switch-to-buffer' gives (wrt using the same window and quitting). But I imagine
that someone does, or we wouldn't still be using it.

>  > 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'.
> 
> So try to experiment with the following: Have `display-buffer'
> interpret a 'same-window value for the NOT-THIS-WINDOW argument
> and replace calls like (switch-to-buffer buffer) with
> (pop-to-buffer buffer 'same-window).

I don't have any time for that, sorry.

But if that makes `pop-to-buffer' use the same window, and users are happy with
it, then that's the way to go.

However, that won't help with older Emacs versions, which is a concern I also
have. IOW, even if the main concern (for me too) is to fix Emacs in this regard
going forward, I would also like to know what code I can use in older versions
to get a solution (act like `switch-to-buffer' except when the use-other-frame
vars say to use another frame). Maybe the answer is that there is no such
solution. But I'd like to know.

>  > 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?)
> 
> It does (if the selected window is dedicated).

That's not a solution. `special-display-*' and `pop-up-frames' do not affect
only dedicated windows.

Have it respect _all_ such don't-use-this-window stuff, not just dedicated
windows.
 
>  > 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...)?
> 
> First you have to enlighten me wrt the quit-window behavior.

Just try it. I saw a difference, when you: (a) use `quit-window' after using
`switch-to-buffer' versus (b) use `quit-window' after using `pop-to-buffer' in
such a way that it reuses the same window (not possible for some windows, but
possible for most - see the code I sent). The buffer that is displayed in the
window after `quit-window' is not the same.

If I'm wrong about that, fine - one less thing to worry about when trying to
keep the current `switch-to-buffer' behavior (except when proscribed by
use-other-frame vars).

>  >>  > 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 it's the _user_ who should touch the windows, not the application
> programmer.

Agreed. So show me how to do it without fiddling with lru. I tried that fiddling
only to try to get `pop-to-buffer' to reuse the same window. The aim was to keep
the `switch-to-buffer' behavior for people who do not use `special-display-*' or
`pop-to-frames', but otherwise have the behavior that `pop-to-buffer' has when
those vars are used.

>  > 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.
...
>  > 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.
> 
> Stefan has proposed to enhance the NOT-THIS-WINDOW argument of
> `display-buffer' for this purpose and I'm all for it.

I haven't seen such a proposal discussed in emacs-devel. What is the thread?

And what is a solution for older Emacs versions (is there one)?







^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-18 16:30   ` Drew Adams
  2009-10-18 17:36     ` martin rudalics
@ 2009-10-19  1:58     ` Stefan Monnier
  2009-10-19  6:28       ` Drew Adams
  1 sibling, 1 reply; 9+ messages in thread
From: Stefan Monnier @ 2009-10-19  1:58 UTC (permalink / raw)
  To: Drew Adams; +Cc: 4748

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

IIUC you tried to control which window pop-to-buffer was going to use,
by selecting windows, hoping to control what get-lru-window returns?
If you need that kind of control, you should either not use
pop-to-buffer and change pop-to-buffer to do what you want.

> I was hoping that simply making a window be the least recently used
> one would cause `pop-to-buffer' to use that window.

The window used by pop-to-buffer depends on so many different factors
that it's illusory to think you can control it from the outside.


        Stefan





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-19  1:58     ` Stefan Monnier
@ 2009-10-19  6:28       ` Drew Adams
  2009-10-19 13:57         ` Stefan Monnier
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2009-10-19  6:28 UTC (permalink / raw)
  To: 'Stefan Monnier'; +Cc: 4748

> The window used by pop-to-buffer depends on so many different factors
> that it's illusory to think you can control it from the outside.

You didn't respond to the question, which was how to replace `switch-to-buffer',
to both (a) keep the same-window and `quit-window' behavior that people are used
to (and presumably want) and (b) respect `special-display-*' and
`pop-up-frames'. Those vars would take precedence, but if their values don't
require using another frame, then the behavior should be to do what
`switch-to-buffer' does now (use the same window).

I don't need this for myself (other than curiosity), but I understood that an
aim was to move away from using `switch-to-buffer' in Emacs code and encourage
the same for 3rd-party code. And I understood that one reason for that was that
`switch-to-buffer' does not respect those use-other-frame variables (that's what
bothers me about it, at least).

If that's not the case, then don't worry about the question. I use
`pop-to-buffer', myself.

FWIW, this came up because I was replacing some code in `bookmark-bmenu-list',
and I wanted to preserve the `switch-to-buffer' that users are used to (and
might prefer), while at the same time making it sane wrt
`special-display-regexps' (for users like me). So far, I'm just using this to
replace the `switch-to-buffer' call - it at least DTRT for one-window frames:

(let ((one-win-p  (one-window-p)))
  (pop-to-buffer (get-buffer-create "*Bookmark List*"))
  (when one-win-p (delete-other-windows)))






^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-18 18:48       ` Drew Adams
@ 2009-10-19  7:36         ` martin rudalics
  0 siblings, 0 replies; 9+ messages in thread
From: martin rudalics @ 2009-10-19  7:36 UTC (permalink / raw)
  To: Drew Adams; +Cc: 4748

 >> (let ((owin (selected-window)))
 >>    (dolist (window (window-list))
 >>      (unless (eq window owin)
 >>        (select-window window)))
 >>    (get-lru-window))
 >
 > That doesn't work either. For the same reason: `get-lru-window' will never
 > return certain windows.

But it correctly sets the LRU window internally without looping.

 >>     ((or (window-minibuffer-p) (eq (window-dedicated-p) t))
 >>      (pop-to-buffer buffer-or-name nil norecord))
 >
 > (I'm curious: Why not call `pop-to-buffer' if the window is dedicated or a
 > minibuffer? What's the reason for that conditional?)

Why "Why not" ... ?

 > If you feel that your version of `switch-to-buffer' makes it respect the
 > use-other-frame variables but otherwise have the same behavior as the current
 > `switch-to-buffer', then why don't you install it?
 >
 > But do you in fact claim that? If not, I don't see it as a solution to the
 > question.

My version tried to be faithful to the one written in C.

 >>  > `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'.
 >>
 >> Because it wouldn't make much sense to respect these ;-)
 >
 > Huh? Why not? Why shouldn't it use the current window (as now) except when those
 > variables say not to (a la `switch-to-buffer-other-window' and `pop-to-buffer')?

Presently a `not-this-window' argument to `display-buffer' overrides
these variables.  Any `same-window' argument would override them too.

 > IOW, have it do just what you claim it already does for dedicated windows. Just
 > as a dedicated window says "don't use me", so the use-other-frame variables also
 > say "don't use me". You say that we listen to the former - but we unfortunately
 > still do not listen to the latter.

The idea of `switch-to-buffer' is to switch to a buffer in the selected
window.  This won't change ever.  The only thing we can (and probably
should) change is whether an application like bookmarks does call
`switch-to-buffer' in the first place.

 >> We'd have to look at each of these cases to tell whether they can use
 >> `pop-to-buffer' directly.
 >
 > They cannot, by definition, if we intend to keep the current behavior of using
 > the same window (except when the use-other-frame vars say not to) and having the
 > same `quit-window' behavior.

If using the same window is intentional (and I think in the case of
`view-buffer' this is at least discussable) it will have to use the same
window.

 > The problem is not just looking at each occurrence individually. The problem is
 > how to get the intended behavior (current window unless frame vars say
 > otherwise; same `quit-window' behavior).

Nevertheless we have to look at each occurrence individually.

 >> I can't tell.  Obviously `same-window-buffer-names' and friends
 >> implicitly provide the same service.
 >
 > How so? If you have a solution to the question I raised, please post it, by all
 > means.

By default `same-window-buffer-names' has `display-buffer' emulate the
behavior of `switch-to-buffer' for buffers like *shell* or *mail*.  I
don't know whether bookmark buffers would fit that category as well.
Buffers handled by `view-buffer' certainly won't.

 >> If and when we enhance `display-buffer' with a same-window argument
 >> `switch-to-buffer' could become obsolete (for Elisp calls).  OTOH this
 >> might lead programmers to call `display-buffer' with the same-window
 >> argument in these and other cases.
 >
 > Is that a discussion topic for emacs-devel? If you're proposing such a change to
 > `display-buffer', then it should be discussed there. Such a change shouldn't
 > "just happen".

It's discussed in the "dired-pop-to-buffer in wrong place" thread.

 >> Does `quit-window' behave differently wrt whether
 >> `switch-to-buffer' was called or `pop-to-buffer'?
 >
 > Try it. I gave the recipe. Use the code I sent that uses `pop-to-buffer' and
 > compare, using the C-x 2 C-x 3 situation, with different buffers and with the
 > same buffer in all 3 windows.

What do you want me to try?  Replace the `switch-to-buffer' call in
`quit-window' with `pop-to-buffer'?  That would be dead wrong.

 >>  > 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.)
 >>
 >> You shouldn't use `other-window' because it doesn't bury the window as
 >> you expect.  Loop over `window-list' instead.
 >
 > Please show me what you mean. You can see what I'm trying to do. How to do it?

I do _not_ know what you're trying.  If you want to reconstruct how
`display-buffer' finds its window without using the underlying C
primitives then I can only refer you to Stefan's remark on this: You
won't be able to do that.

 > And please explain why `other-window' should not be used - in what way doesn't
 > it "bury the window as you expect"? Is it also a dwim function? What about
 > `next-window' - would that work better?

You said you got an endless loop here.  Obviously that happens because
you use `other-window'.

 >> I still don't understand why and how you want to control the
 >> setting of the LRU window in practice.
 >
 > I don't really care about the lru window. I was trying to get `pop-to-buffer' to
 > use the selected window (whatever that window is, no exceptions).

Above you wanted `pop-to-buffer' follow user customizations.  Unless you
settle on either

- respect user customizations thus getting a behavior different from
   `switch-to-buffer', or

- implement the `switch-to-buffer' behavior thus not respecting user
   customizations,

this won't get us anywhere.

 > And also to
 > keep the same `quit-window' behavior that you get when you use
 > `switch-to-buffer'.

Can you please describe in a few words what a "`quit-window' behavior"
is?

 >>  > 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.
 >>
 >> In what sense do they behave differently?
 >
 > When you quit the window, you get a different buffer from what you get when you
 > use `switch-to-buffer'.

... use `switch-to-buffer' _where_?  In the code of `quit-window'?

 > At least that's what I saw. Try the examples I mentioned
 > - C-x 2 C-x 3.

Do you mean that the `other-buffer' call in `switch-to-buffer' when
called by `quit-window' chooses another buffer to display?  Are you sure
you have set all NORECORD arguments correctly?

 > The point is that if you use `switch-to-buffer' and then quit the window, the
 > buffer that is displayed is different than what you see if you use
 > `pop-to-buffer' (successfully forcing it to use the same window, at least for
 > most windows) and then you quit the window. Try the examples I gave, and see for
 > yourself.
 >
 > Again, personally I don't care about preserving the same behavior that
 > `switch-to-buffer' gives (wrt using the same window and quitting). But I imagine
 > that someone does, or we wouldn't still be using it.

Do you mean the examples where you call `other-window'?  `other-window'
calls `select-window' which calls record_buffer so you obviously get a
completely stochastic 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'.
 >>
 >> So try to experiment with the following: Have `display-buffer'
 >> interpret a 'same-window value for the NOT-THIS-WINDOW argument
 >> and replace calls like (switch-to-buffer buffer) with
 >> (pop-to-buffer buffer 'same-window).
 >
 > I don't have any time for that, sorry.

Then I won't be able to help you at the moment.

martin





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#4748: 23.1; least recently used window - is it?
  2009-10-19  6:28       ` Drew Adams
@ 2009-10-19 13:57         ` Stefan Monnier
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Monnier @ 2009-10-19 13:57 UTC (permalink / raw)
  To: Drew Adams; +Cc: 4748

>> The window used by pop-to-buffer depends on so many different factors
>> that it's illusory to think you can control it from the outside.

> You didn't respond to the question, which was how to replace
> `switch-to-buffer', to both (a) keep the same-window and `quit-window'
> behavior that people are used to (and presumably want) and (b) respect
> `special-display-*' and `pop-up-frames'. Those vars would take
> precedence, but if their values don't require using another frame,
> then the behavior should be to do what `switch-to-buffer' does now
> (use the same window).

There is currently no way to do that (and changing get-lru-window won't
help in this respect).
That's part of the motivation for the idea of extending the
`other-window' argument to pop-to-buffer so it can specify things like
`same-window'.


        Stefan





^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-10-19 13:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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