From fc29004fe9287ce02eb3aa52abe5a4fc54834663 Mon Sep 17 00:00:00 2001 From: dickmao Date: Tue, 9 Aug 2022 07:37:57 -0400 Subject: [PATCH] window-point is a thing We regularly split the same buffer across two windows (C-x 2) and position one window as a reference while manipulating the other. When temporarily switching out one window, say to check a definition, our flow gets wrecked by C-x b's refusal to flip back to the original buffer since it's already displayed in another window, albeit, and very importantly, at a different point (which to belabor things, is the whole reason we want the same buffer in two windows). I'm sure this has been proposed many times in the past, the preservationist society being what it is. * lisp/ido.el (ido-make-buffer-list-1): De-obfuscate. (ido-make-buffer-list): Include visible buffer when switching. (ido-get-buffers-in-frames): De-obfuscate. * lisp/window.el (read-buffer-to-switch): Include visible buffer. * test/lisp/ido-tests.el (ert-deftest): Test it. --- lisp/ido.el | 43 +++++++++++++++++++--------------------- lisp/window.el | 2 +- test/lisp/ido-tests.el | 21 ++++++++++++++++++++ test/src/buffer-tests.el | 21 ++++++++++++++++++++ 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/lisp/ido.el b/lisp/ido.el index 134081d6759..5aeb8fcec51 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -3432,32 +3432,32 @@ ido-make-buffer-list-1 (mapcar (lambda (x) (let ((name (buffer-name x))) - (if (not (or (ido-ignore-item-p name ido-ignore-buffers) (member name visible))) - name))) + (and (not (ido-ignore-item-p name ido-ignore-buffers)) + (not (member name visible)) + name))) (buffer-list frame))))) (defun ido-make-buffer-list (default) "Return the current list of buffers. -Currently visible buffers are put at the end of the list. The hook `ido-make-buffer-list-hook' is run after the list has been created to allow the user to further modify the order of the buffer names in this list. If DEFAULT is non-nil, and corresponds to an existing buffer, it is put to the start of the list." - (let* ((ido-current-buffers (ido-get-buffers-in-frames 'current)) - (ido-temp-list (ido-make-buffer-list-1 (selected-frame) ido-current-buffers))) - (if ido-temp-list - (nconc ido-temp-list ido-current-buffers) - (setq ido-temp-list ido-current-buffers)) - (if ido-predicate - (setq ido-temp-list (seq-filter - (lambda (name) - (funcall ido-predicate (cons name (get-buffer name)))) - ido-temp-list))) - (if default - (setq ido-temp-list - (cons default (delete default ido-temp-list)))) - (if (bound-and-true-p ido-enable-virtual-buffers) - (ido-add-virtual-buffers-to-list)) + (let* ((current (buffer-name (window-buffer (selected-window)))) + (ido-temp-list (ido-make-buffer-list-1 (selected-frame) (list current)))) + (when (consp ido-temp-list) + (setcdr (last ido-temp-list) (list current))) + (when ido-predicate + (setq ido-temp-list + (seq-filter + (lambda (name) + (funcall ido-predicate (cons name (get-buffer name)))) + ido-temp-list))) + (when default + (setq ido-temp-list + (cons default (delete default ido-temp-list)))) + (when (bound-and-true-p ido-enable-virtual-buffers) + (ido-add-virtual-buffers-to-list)) (run-hooks 'ido-make-buffer-list-hook) ido-temp-list)) @@ -3723,11 +3723,8 @@ ido-get-buffers-in-frames "Return the list of buffers that are visible in the current frame. If optional argument CURRENT is given, restrict searching to the current frame, rather than all frames, regardless of value of `ido-all-frames'." - (let ((ido-bufs-in-frame nil)) - (walk-windows 'ido-get-bufname nil - (if current - nil - ido-all-frames)) + (let (ido-bufs-in-frame) + (walk-windows 'ido-get-bufname nil (unless current ido-all-frames)) ido-bufs-in-frame)) (defun ido-get-bufname (win) diff --git a/lisp/window.el b/lisp/window.el index 4d88ffa9039..86996fe9730 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8673,7 +8673,7 @@ read-buffer-to-switch (setq-local icomplete-with-completion-tables (cons rbts-completion-table icomplete-with-completion-tables)))) - (read-buffer prompt (other-buffer (current-buffer)) + (read-buffer prompt (other-buffer (current-buffer) t) (confirm-nonexistent-file-or-buffer))))) (defun window-normalize-buffer-to-switch-to (buffer-or-name) diff --git a/test/lisp/ido-tests.el b/test/lisp/ido-tests.el index 56ef6cde358..034071b52b3 100644 --- a/test/lisp/ido-tests.el +++ b/test/lisp/ido-tests.el @@ -51,4 +51,25 @@ ido-directory-too-big-p (let ((ido-big-directories (cons (rx "me/di") ido-big-directories))) (should (ido-directory-too-big-p "/some/dir/")))) +(ert-deftest ido-buffer-switch-visible () + "switch-to-buffer should include already visible buffers." + (let* ((name "test-buffer-switch-visible") + (buffer (get-buffer-create name))) + (unwind-protect + (progn + (switch-to-buffer buffer) + (delete-other-windows) + (split-window-below) + (goto-char (point-min)) + (other-window 1) + (insert "foo") + (goto-char (point-max)) + (cl-letf (((symbol-function 'read-from-minibuffer) + (lambda (&rest args) (nth 5 args)))) + (call-interactively #'ido-switch-buffer) + (call-interactively #'ido-switch-buffer)) + (should (and (equal name (buffer-name)) (eq (point) (point-max))))) + (let (kill-buffer-query-functions) + (kill-buffer buffer))))) + ;;; ido-tests.el ends here diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 3c6a9208ffa..b34766c2383 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -1555,4 +1555,25 @@ test-buffer-chars-modified-ticks (if f2 (delete-file f2)) ))) +(ert-deftest test-buffer-switch-visible () + "switch-to-buffer should include already visible buffers." + (let* ((name "test-buffer-switch-visible") + (buffer (get-buffer-create name))) + (unwind-protect + (progn + (switch-to-buffer buffer) + (delete-other-windows) + (split-window-below) + (goto-char (point-min)) + (other-window 1) + (insert "foo") + (goto-char (point-max)) + (cl-letf (((symbol-function 'read-from-minibuffer) + (lambda (&rest args) (nth 5 args)))) + (call-interactively #'switch-to-buffer) + (call-interactively #'switch-to-buffer)) + (should (and (equal name (buffer-name)) (eq (point) (point-max))))) + (let (kill-buffer-query-functions) + (kill-buffer buffer))))) + ;;; buffer-tests.el ends here -- 2.36.1