unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#69993: Wrap window buffers while cycling
@ 2024-03-25  7:42 Juri Linkov
  2024-03-25  9:41 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 45+ messages in thread
From: Juri Linkov @ 2024-03-25  7:42 UTC (permalink / raw)
  To: 69993; +Cc: martin rudalics

[-- Attachment #1: Type: text/plain, Size: 611 bytes --]

Often users complain there is no way to wrap window buffers
while cycling them with 'C-x C-<left>' (previous-buffer)
and 'C-x C-<right>' (next-buffer).  One of the latest examples is
https://old.reddit.com/r/emacs/comments/1barvo2/perwindow_buffer_ordering/

This problem becomes apparent when a list of prev/next window buffers
is visualized by the tab-line.

So here is the patch that finally solves this problem
by adding a new option 'switch-to-prev-buffer-wrap'
disabled by default.

When its value is t, it wraps to the first/last buffer.
But when the value is 'stop', it stops at the first/last buffer.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: switch-to-prev-buffer-wrap.patch --]
[-- Type: text/x-diff, Size: 7194 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index df55a7ca673..4d727fb827c 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4542,6 +4542,16 @@ set-window-buffer-start-and-point
     (when point
       (set-window-point window point))))
 
+(defcustom switch-to-prev-buffer-wrap nil
+  "Wrap to the first/last window-local buffer while cycling.
+When t, wrap to the first/last buffer.
+When the value is `stop', stop at the first/last buffer."
+  :type '(choice (const :tag "Never wrap" nil)
+                 (const :tag "Stop at window-local buffers" stop)
+                 (const :tag "Wrap to window-local buffers" t))
+  :version "30.1"
+  :group 'windows)
+
 (defcustom switch-to-visible-buffer t
   "If non-nil, allow switching to an already visible buffer.
 If this variable is non-nil, `switch-to-prev-buffer' and
@@ -4676,7 +4686,7 @@ switch-to-prev-buffer
            ((or switch-to-prev-buffer-skip
                 (not switch-to-visible-buffer))
             frame)))
-         entry new-buffer killed-buffers skipped)
+         entry new-buffer killed-buffers skipped wrapped)
     (when (window-minibuffer-p window)
       ;; Don't switch in minibuffer window.
       (unless (setq window (minibuffer-selected-window))
@@ -4711,7 +4721,7 @@ switch-to-prev-buffer
       ;; buffer list in order to make sure that switching to the
       ;; previous/next buffer traverse it in opposite directions.  Skip
       ;; this step for side windows.
-      (unless window-side
+      (unless (or window-side switch-to-prev-buffer-wrap)
         (dolist (buffer (if bury-or-kill
                             (buffer-list frame)
                           (nreverse (buffer-list frame))))
@@ -4729,7 +4739,9 @@ switch-to-prev-buffer
               (set-window-buffer-start-and-point window new-buffer)
               (throw 'found t)))))
 
-      (unless bury-or-kill
+      (when (eq switch-to-prev-buffer-wrap 'stop)
+        (setq wrapped 'stop new-buffer nil))
+      (unless (or bury-or-kill (eq switch-to-prev-buffer-wrap 'stop))
 	;; Scan reverted next buffers last (must not use nreverse
 	;; here!).
 	(dolist (buffer (reverse next-buffers))
@@ -4744,6 +4756,7 @@ switch-to-prev-buffer
             (if (switch-to-prev-buffer-skip-p skip window buffer bury-or-kill)
 	        (setq skipped (or skipped buffer))
 	      (setq new-buffer buffer)
+	      (setq wrapped t)
 	      (set-window-buffer-start-and-point
 	       window new-buffer (nth 1 entry) (nth 2 entry))
 	      (throw 'found t)))))
@@ -4770,8 +4783,23 @@ switch-to-prev-buffer
 	     window (append (window-prev-buffers window) (list entry)))))
       ;; Move `old-buffer' to head of WINDOW's restored list of next
       ;; buffers.
-      (set-window-next-buffers
-       window (cons old-buffer (delq old-buffer next-buffers))))
+      (if (not (and switch-to-prev-buffer-wrap wrapped))
+          (set-window-next-buffers
+           window (cons old-buffer (delq old-buffer next-buffers)))
+        ;; Restore the right order of previous buffers.
+        (unless (eq wrapped 'stop)
+          (let ((prev-buffers (window-prev-buffers window)))
+            ;; Use the same sorting order as was in next-buffers
+            ;; with old-buffer at the bottom.
+            (setq prev-buffers
+                  (sort prev-buffers
+                        (lambda (a b)
+                          (cond
+                           ((eq (car a) old-buffer) nil)
+                           ((eq (car b) old-buffer) t)
+                           (t (< (length (memq (car a) next-buffers))
+                                 (length (memq (car b) next-buffers))))))))
+            (set-window-prev-buffers window prev-buffers)))))
 
     ;; Remove killed buffers from WINDOW's previous and next buffers.
     (when killed-buffers
@@ -4812,7 +4840,7 @@ switch-to-next-buffer
            ((or switch-to-prev-buffer-skip
                 (not switch-to-visible-buffer))
             frame)))
-	 new-buffer entry killed-buffers skipped)
+	 new-buffer entry killed-buffers skipped wrapped)
     (when (window-minibuffer-p window)
       ;; Don't switch in minibuffer window.
       (unless (setq window (minibuffer-selected-window))
@@ -4839,7 +4867,7 @@ switch-to-next-buffer
 	    (throw 'found t))))
       ;; Scan the buffer list of WINDOW's frame next, skipping previous
       ;; buffers entries.  Skip this step for side windows.
-      (unless window-side
+      (unless (or window-side switch-to-prev-buffer-wrap)
         (dolist (buffer (buffer-list frame))
           (when (and (buffer-live-p buffer)
                      (not (eq buffer old-buffer))
@@ -4856,19 +4884,22 @@ switch-to-next-buffer
               (throw 'found t)))))
       ;; Scan WINDOW's reverted previous buffers last (must not use
       ;; nreverse here!)
-      (dolist (entry (reverse (window-prev-buffers window)))
-	(when (and (not (eq new-buffer (car entry)))
-                   (not (eq old-buffer (car entry)))
-                   (setq new-buffer (car entry))
-		   (or (buffer-live-p new-buffer)
-		       (not (setq killed-buffers
-				  (cons new-buffer killed-buffers))))
-                   (or (null pred) (funcall pred new-buffer)))
-          (if (switch-to-prev-buffer-skip-p skip window new-buffer)
-	      (setq skipped (or skipped new-buffer))
-	    (set-window-buffer-start-and-point
-	     window new-buffer (nth 1 entry) (nth 2 entry))
-	    (throw 'found t))))
+      (if (eq switch-to-prev-buffer-wrap 'stop)
+          (setq wrapped 'stop new-buffer nil)
+        (dolist (entry (reverse (window-prev-buffers window)))
+          (when (and (not (eq new-buffer (car entry)))
+                     (not (eq old-buffer (car entry)))
+                     (setq new-buffer (car entry))
+                     (or (buffer-live-p new-buffer)
+                         (not (setq killed-buffers
+                                    (cons new-buffer killed-buffers))))
+                     (or (null pred) (funcall pred new-buffer)))
+            (if (switch-to-prev-buffer-skip-p skip window new-buffer)
+                (setq skipped (or skipped new-buffer))
+              (setq wrapped t)
+              (set-window-buffer-start-and-point
+               window new-buffer (nth 1 entry) (nth 2 entry))
+              (throw 'found t)))))
 
       (when (and skipped (not (functionp switch-to-prev-buffer-skip)))
         ;; Show first skipped buffer, unless skip was a function.
@@ -4876,7 +4907,13 @@ switch-to-next-buffer
 	(set-window-buffer-start-and-point window new-buffer)))
 
     ;; Remove `new-buffer' from and restore WINDOW's next buffers.
-    (set-window-next-buffers window (delq new-buffer next-buffers))
+    (if (not (and switch-to-prev-buffer-wrap wrapped))
+        (set-window-next-buffers window (delq new-buffer next-buffers))
+      (unless (eq wrapped 'stop)
+        (let ((prev-buffers (window-prev-buffers window)))
+          (setq prev-buffers
+                (nreverse (delq new-buffer (mapcar #'car prev-buffers))))
+          (set-window-next-buffers window prev-buffers))))
 
     ;; Remove killed buffers from WINDOW's previous and next buffers.
     (when killed-buffers

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

end of thread, other threads:[~2024-04-25 17:40 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-25  7:42 bug#69993: Wrap window buffers while cycling Juri Linkov
2024-03-25  9:41 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-25 17:16   ` Juri Linkov
2024-03-26  9:56     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-27  7:20       ` Juri Linkov
2024-03-27  8:48         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-28  7:54           ` Juri Linkov
2024-03-28  9:19             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-28 17:57               ` Juri Linkov
2024-03-29  8:45                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-29 16:35                   ` Juri Linkov
2024-03-30  9:37                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-30 18:24                       ` Juri Linkov
2024-03-31  8:32                         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-02  6:37                           ` Juri Linkov
2024-04-02  8:22                             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-02 16:28                               ` Juri Linkov
2024-04-03  8:24                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-03 17:45                                   ` Juri Linkov
2024-04-04  8:03                                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-05  6:45                                       ` Juri Linkov
2024-04-05  9:08                                         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-05 16:32                                           ` Juri Linkov
2024-04-06 18:43                                             ` Juri Linkov
2024-04-07  8:23                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-09  6:35                                                 ` Juri Linkov
2024-04-09  9:04                                                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-09 16:37                                                     ` Juri Linkov
2024-04-10  8:46                                                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-10 17:45                                                         ` Juri Linkov
2024-04-11  9:18                                                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-12  6:35                                                             ` Juri Linkov
2024-04-12  8:37                                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-12 16:23                                                                 ` Juri Linkov
2024-04-14 16:15                                                                   ` Juri Linkov
2024-04-16  6:38                                                                     ` Juri Linkov
2024-04-17 17:56                                                                       ` Juri Linkov
2024-04-24 16:39                                                                         ` Juri Linkov
2024-04-25  8:31                                                                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-25 17:40                                                                             ` Juri Linkov
2024-04-02 16:34                               ` Juri Linkov
2024-04-03  8:24                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-03 17:44                                   ` Juri Linkov
2024-04-04  6:22                                 ` Juri Linkov
2024-04-02 16:40                               ` Juri Linkov

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