unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: Steve Yegge <stevey@google.com>
Cc: Lars Magne Ingebrigtsen <larsi@gnus.org>, 4041@debbugs.gnu.org
Subject: bug#4041: 23.0.92; Emacs 23: buffer point is no longer frame-local
Date: Sat, 08 Oct 2011 15:23:29 +0200	[thread overview]
Message-ID: <4E904ED1.8090906@gmx.at> (raw)
In-Reply-To: <CAEYe22UGDZvg=y3cwU0x195o719d_EOu3gir2z8fkxxBtwaUhQ@mail.gmail.com>

 > Assume you have buffer B open on frame F in windows T, U and V,
 > respectively displaying B at positions P1, P2 and P3.  Now in window
 > W, also on F, you C-x b to switch to B.  Today it takes you to P1,
 > assuming T is next in the window-list.

Hardly.  It takes you to P1 because presumably window T is selected and
the window point of the selected window usually coincides with that
window's buffer's point.

 > If no window were currently
 > showing B, then W would display point-min.

Hopefully not.  W should display the buffer's `point' (which, if the
buffer was never shown before, would coincide with `point-min').

 > Let's call this the "existing-window" behavior, as for a new window W it
 > will choose a position from an existing window.

Not necessarily.  If another window were selected and, in B you go to
some other position, the next `switch-to-buffer' will display B around
`point' which might not coincide with any of the other windows'
positions.

 > If you were to make my
 > proposed multi-frame change, I think you could reasonably choose to
 > retain the existing-window behavior within a frame, as it preserves the
 > current intra-frame buffer-switching semantics.
 >
 > However, over the decades I have noticed that when I have two or
 > more windows open to the same buffer on the same frame, it is almost
 > always because I want to establish N > 1 persistent working locations
 > within that buffer.  In fact it is rarely useful to have two windows open
 > to the same buffer location, as they merely echo each other.  So
 > I would posit that my "multiple persistent working locations" use case
 > is likely to be the most common reason for users to have N > 1
 > windows displaying the same buffer in a given frame.

Having "two or more windows open to the same buffer" sounds like a
reasonable condition.  The problem is that you might have no window
showing the buffer and still want to restore the previous window
position.  That's why `switch-to-prev-buffer' is superior to any
`switch-to-buffer' changing solution.  Notwithstanding Lars' argument
that people are used to C-x b, tell me why `switch-to-prev-buffer'
(combined with `switch-to-next-buffer') doesn't do what you want.

 > The problem with today's "existing-window" behavior is that if you
 > have window T displaying buffer B on frame F at buffer position P,
 > then you can not sustain a *persistent* working location P' in any
 > other window U on F.  By "persistent", I specifically mean that in
 > window U, if I switch temporarily away to another buffer and then
 > back, I want to go back to P'.  Today it takes me to P:   I have lost
 > my working location in U.

Not with `switch-to-prev-buffer' ;-)

 > I have long found this behavior most unfortunate.  Ironically, the
 > best workaround is to visit B in window X on a second frame G.
 > Then no matter what happens to the window configuration in F,
 > X will retain its window point at your second working location P'.
 >
 > Trying to work around it within F requires that you disturb your
 > window configuration, or attempt to track your working locations
 > with the mark ring, or some other relatively unnatural workflow.
 > At least, I find it unnatural compared to my desired workflow:
 >
 >   - open a window T and display buffer B at position Pt
 >   - in window U switch to buffer B (it defaults to Pt, which is fine)
 >   - then in U:
 >     * move to a different position Pu in B
 >     * switch to any other buffer C (e.g. Info, shell, ...)
 >     * switch back to buffer B

This should be `switch-to-prev-buffer'.

 >     * continue working at Pu
 >
 > This workflow, which I think of as "persistent window positions",
 > would actually be closest to how Emacs works in the most
 > common use case of all:  single-frame, single-window.  If you are
 > visiting B at position P, and you switch away, then back, you will
 > return to P.  It is easy to think of this as the window remembering
 > where you last were in B.  If you think of it this way, as I do, then
 > you are constantly surprised that windows suffer from amnesia
 > whenever more than one of them is displaying the same buffer.
 > It feels to me that they should behave as if they are independent.
 >
 > Thus I would be happiest if there were an option such that every
 > window tracks the buffer positions of every buffer that it visits,

You can get these positions via `window-prev-buffers'.

 > and when switching back to a buffer B that it has already visited,
 > each window displays B at the same position it last displayed B.
 >
 > If you kill a window, its position list goes away.  New windows
 > would start with a nil position list, and the first time they visit a
 > buffer they would use the "existing-window" semantics:  use
 > the position of the next window currently displaying the buffer,
 > or else point-min.  (It might be confusing to have them choose
 > from the position-list of a window that has previously visited
 > the buffer but is not currently displaying it, so I'd not do that.)
 >
 > Similarly if you kill a buffer, then it is removed from the position
 > lists for all existing windows.  If it is recreated, e.g. by opening
 > the file again for file buffers, all windows would initially begin
 > viewing it at point-min.
 >
 > I think "per-window visited-buffer last-position lists" would solve
 > the multi-frame problem (4041).  I believe they would also
 > clean up the IMO rather unfortunate existing semantics for
 > same-buffer, same-frame, multiple windows, since the current
 > behavior (a) doesn't parallel the current single-frame, single
 > window behavior, and (b) doesn't allow for multiple temporary
 > "persistent" working locations in multiple windows in a single
 > buffer on a single frame.
 >
 > At the very least it'd be a nice global configuration option.
 > I'm sure you could probably do all this with a package, but
 > it's fairly fundamental -- it would be nice, for example, to be
 > able to enable it by setting a single variable on someone
 > else's Emacs instance while debugging something for them.
 >
 > I have done an exhaustive survey of everyone sitting near
 > me right now, and they both agreed that buffer positions
 > should be "window-local", and that they've been annoyed
 > by it forever as well.  Just wanted to cover my bases! ;)

All this has been implemented - see section 28.14 Window History in the
Elisp manual.  If you still insist on having C-x b return to the
previous position, try the definition below.

martin

(defun switch-to-buffer (buffer-or-name &optional norecord force-same-window)
   "Switch to buffer BUFFER-OR-NAME in the selected window.
If called interactively, prompt for the buffer name using the
minibuffer.  The variable `confirm-nonexistent-file-or-buffer'
determines whether to request confirmation before creating a new
buffer.

BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
nil.  If BUFFER-OR-NAME is a string that does not identify an
existing buffer, create a buffer with that name.  If
BUFFER-OR-NAME is nil, switch to the buffer returned by
`other-buffer'.

Optional argument NORECORD non-nil means do not put the buffer
specified by BUFFER-OR-NAME at the front of the buffer list and
do not make the window displaying it the most recently selected
one.

If FORCE-SAME-WINDOW is non-nil, BUFFER-OR-NAME must be displayed
in the selected window; signal an error if that is
impossible (e.g. if the selected window is minibuffer-only).  If
nil, BUFFER-OR-NAME may be displayed in another window.

Return the buffer switched to."
   (interactive
    (list (read-buffer-to-switch "Switch to buffer: ") nil t))
   (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)))
     (if (null force-same-window)
	(pop-to-buffer buffer display-buffer--same-window-action norecord)
       (cond
        ;; Don't call set-window-buffer if it's not needed since it
        ;; might signal an error (e.g. if the window is dedicated).
        ((eq buffer (window-buffer)))
        ((window-minibuffer-p)
	(error "Cannot switch buffers in minibuffer window"))
        ((eq (window-dedicated-p) t)
	(error "Cannot switch buffers in a dedicated window"))
        (t
	(let* ((entry (and (get-buffer-window buffer 0)
			   (assq buffer (window-prev-buffers))))
	       (start (and entry (nth 1 entry)))
	       (pos (and entry (nth 2 entry))))
	  (set-window-buffer nil buffer)
	  (when entry
	    ;; If BUFFER-OR-NAME (1) was shown in the selected window
	    ;; before and (2) is currently displayed in some other
	    ;; visible window, try to restore start and point of buffer
	    ;; in the selected window.
	    (set-window-start (selected-window) start t)
	    (set-window-point-1 nil pos)))))

       (unless norecord
	(select-window (selected-window)))
       (set-buffer buffer))))






  parent reply	other threads:[~2011-10-08 13:23 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-05  0:17 bug#4041: 23.0.92; Emacs 23: buffer point is no longer frame-local Steve Yegge
2009-08-06  9:33 ` martin rudalics
2011-09-17  7:04 ` Lars Magne Ingebrigtsen
2011-09-17  8:43   ` martin rudalics
2011-09-18  8:03     ` Lars Magne Ingebrigtsen
2011-10-06 22:14     ` Lars Magne Ingebrigtsen
2011-10-07  7:07       ` martin rudalics
2011-10-07 10:46         ` Lars Magne Ingebrigtsen
2011-10-07 17:00           ` martin rudalics
2011-10-07 21:09             ` Steve Yegge
2011-10-08  6:23               ` Eli Zaretskii
2011-10-08  6:32                 ` Drew Adams
2011-10-08  6:23               ` Leo
2011-10-08 13:23               ` martin rudalics [this message]
2011-10-08 14:12                 ` Eli Zaretskii
2011-10-08 15:00                   ` martin rudalics
2011-10-08 15:34                     ` Eli Zaretskii
2011-10-08 15:55                       ` martin rudalics
2011-10-08 17:07                         ` Eli Zaretskii
2011-10-08 17:53                           ` martin rudalics
2011-10-08 20:35                             ` Eli Zaretskii
2011-10-09  8:33                               ` martin rudalics
2011-10-09 17:45                                 ` Eli Zaretskii
2011-10-10 12:57                                   ` martin rudalics
2011-10-11 12:45               ` Stefan Monnier
2011-10-12  0:35                 ` Steve Yegge
2011-10-12  1:19                   ` Stefan Monnier
2011-10-12  3:52                     ` Steve Yegge
2011-10-12  9:48                     ` martin rudalics
2011-10-12 13:11                       ` Stefan Monnier
2011-10-12 13:39                         ` Stefan Monnier
2011-10-12 14:25                           ` martin rudalics
2012-10-05 10:08                         ` martin rudalics
2012-10-10 10:22                           ` martin rudalics
2011-10-12  6:52                   ` martin rudalics

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=4E904ED1.8090906@gmx.at \
    --to=rudalics@gmx.at \
    --cc=4041@debbugs.gnu.org \
    --cc=larsi@gnus.org \
    --cc=stevey@google.com \
    /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).