From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.bugs Subject: bug#4041: 23.0.92; Emacs 23: buffer point is no longer frame-local Date: Sat, 08 Oct 2011 15:23:29 +0200 Message-ID: <4E904ED1.8090906@gmx.at> References: <20090805001735.1CC041E844E@localhost> <4E745DAE.5040808@gmx.at> <4E8EA522.9090300@gmx.at> <4E8F3040.1060409@gmx.at> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1318080232 31765 80.91.229.12 (8 Oct 2011 13:23:52 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sat, 8 Oct 2011 13:23:52 +0000 (UTC) Cc: Lars Magne Ingebrigtsen , 4041@debbugs.gnu.org To: Steve Yegge Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Oct 08 15:23:48 2011 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RCWsV-0003oW-3V for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Oct 2011 15:23:47 +0200 Original-Received: from localhost ([::1]:44718 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCWsU-0006kh-9J for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Oct 2011 09:23:46 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:45116) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCWsR-0006kb-QA for bug-gnu-emacs@gnu.org; Sat, 08 Oct 2011 09:23:45 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RCWsQ-0002wC-A5 for bug-gnu-emacs@gnu.org; Sat, 08 Oct 2011 09:23:43 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:40089) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCWsQ-0002vC-5W for bug-gnu-emacs@gnu.org; Sat, 08 Oct 2011 09:23:42 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.69) (envelope-from ) id 1RCWsk-0002kb-1e for bug-gnu-emacs@gnu.org; Sat, 08 Oct 2011 09:24:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: martin rudalics Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 08 Oct 2011 13:24:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 4041 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: confirmed Original-Received: via spool by 4041-submit@debbugs.gnu.org id=B4041.131808024110565 (code B ref 4041); Sat, 08 Oct 2011 13:24:02 +0000 Original-Received: (at 4041) by debbugs.gnu.org; 8 Oct 2011 13:24:01 +0000 Original-Received: from localhost ([127.0.0.1] helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1RCWsi-0002kM-AT for submit@debbugs.gnu.org; Sat, 08 Oct 2011 09:24:01 -0400 Original-Received: from mailout-de.gmx.net ([213.165.64.23]) by debbugs.gnu.org with smtp (Exim 4.69) (envelope-from ) id 1RCWsf-0002k6-74 for 4041@debbugs.gnu.org; Sat, 08 Oct 2011 09:23:59 -0400 Original-Received: (qmail invoked by alias); 08 Oct 2011 13:23:30 -0000 Original-Received: from 62-47-47-212.adsl.highway.telekom.at (EHLO [62.47.47.212]) [62.47.47.212] by mail.gmx.net (mp037) with SMTP; 08 Oct 2011 15:23:30 +0200 X-Authenticated: #14592706 X-Provags-ID: V01U2FsdGVkX194aRU+WRp4qYpPUrVJOQF4CObULSjKbl3xuBYpgv J3lH9i+qFvBODb User-Agent: Thunderbird 2.0.0.21 (Windows/20090302) In-Reply-To: X-Y-GMX-Trusted: 0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.11 Precedence: list Resent-Date: Sat, 08 Oct 2011 09:24:02 -0400 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 1) X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:52417 Archived-At: > 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))))