diff options
| author | Constantine Vetoshev <vetoshev@gmail.com> | 2026-03-31 07:02:47 -0700 |
|---|---|---|
| committer | Constantine Vetoshev <vetoshev@gmail.com> | 2026-03-31 07:02:47 -0700 |
| commit | 47c083a7cee9849fe5d36759ad141a0f5df61e77 (patch) | |
| tree | 0176aaa54f9866de97a64c01dbec5f80bd3ffec2 | |
| parent | 80691af9480431cc3cbb70914d0ff0d70447a0e1 (diff) | |
Speed up persp-maybe-kill-buffer.
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | perspective.el | 43 | ||||
| -rw-r--r-- | test/test-perspective.el | 37 |
3 files changed, 65 insertions, 16 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2720880..b90c9af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Temporary `switch-to-buffer` displays with non-nil `norecord` no longer add the displayed buffer to the current perspective. This fixes `consult-buffer` preview importing previewed buffers ([#225](https://github.com/nex3/perspective-el/issues/225)). +- `persp-maybe-kill-buffer`: improve performance by avoiding switching perspectives and rebuilding buffer-name lists ([#226](https://github.com/nex3/perspective-el/issues/226)). ### Added diff --git a/perspective.el b/perspective.el index 1145dc0..8bee8d9 100644 --- a/perspective.el +++ b/perspective.el @@ -1040,42 +1040,53 @@ See also `persp-remove-buffer'." (persp-protect (let* ((buffer (current-buffer)) (bufstr (buffer-name buffer)) - candidates-for-removal candidates-for-keeping) + (current-name (persp-current-name)) + (ignore-rx (persp--make-ignore-buffer-rx)) + current-persp-removal-needed + candidates-for-removal + candidates-for-keeping) ;; XXX: For performance reasons, always allow killing off obviously ;; temporary buffers. According to Emacs convention, these buffers' names ;; start with a space. (when (string-match-p (rx string-start (one-or-more blank)) bufstr) (cl-return-from persp-maybe-kill-buffer t)) - (dolist (name (persp-names)) - (let ((buffer-names (persp-get-buffer-names name))) - (when (member bufstr buffer-names) - (if (cdr buffer-names) - (push name candidates-for-removal) - ;; We use a list for debugging purposes, a simple bool - ;; can suffice for what we are doing here. - (push name candidates-for-keeping))))) + (maphash + (lambda (name persp) + (let ((buffers (persp-buffers persp))) + (when (memq buffer buffers) + (if (cl-loop for other-buffer in buffers + thereis (and (not (eq other-buffer buffer)) + (buffer-live-p other-buffer) + (not (string-match-p ignore-rx + (buffer-name other-buffer))))) + (if (equal name current-name) + (setq current-persp-removal-needed t) + (push name candidates-for-removal)) + ;; We use a list for debugging purposes, a simple bool + ;; can suffice for what we are doing here. + (push name candidates-for-keeping))))) + (perspectives-hash)) (cond ;; When there aren't perspectives with the buffer as the only ;; buffer, it can be killed safely. Also cleanup killed ones ;; found in perspectives listing the buffer to be killed. ((not candidates-for-keeping) - ;; Switching to a perspective that isn't the current, should - ;; automatically cleanup previously killed buffers which are - ;; still in the perspective's list of buffers. Removing the - ;; buffer to be killed should also keep the list clean. (dolist (name candidates-for-removal) (with-perspective name - ;; remove the buffer that has to be killed from the list - (setf (persp-current-buffers) (remq buffer (persp-current-buffers))))) + (persp-forget-buffer buffer))) + (when current-persp-removal-needed + (setf (persp-current-buffers) (remq buffer (persp-current-buffers)))) t) ;; When a perspective have the buffer as the only buffer, the ;; buffer should not be killed, but removed from perspectives ;; that have more than one buffer. Those perspectives should ;; forget about the buffer. - (candidates-for-removal + ((or candidates-for-removal current-persp-removal-needed) (dolist (name candidates-for-removal) (with-perspective name (persp-forget-buffer buffer))) + (when current-persp-removal-needed + (persp-forget-buffer buffer)) nil))))) (defun persp-forget-buffer (buffer) diff --git a/test/test-perspective.el b/test/test-perspective.el index fbf2917..c4f1331 100644 --- a/test/test-perspective.el +++ b/test/test-perspective.el @@ -24,6 +24,7 @@ ;; Set feature flag(s): (customize-set-variable 'persp-feature-flag-prevent-killing-last-buffer-in-perspective t) +(customize-set-variable 'persp-suppress-no-prefix-key-warning t) (defun persp-test-interesting-buffer? (buf) "Return t if BUF is a non-temporary buffer (i.e., lacks @@ -2130,6 +2131,42 @@ buffers into any perspective." (should-not (persp-is-current-buffer dummy-buffer)) (should (persp-test-buffer-in-persps dummy-buffer "A"))))) +(ert-deftest basic-persp-maybe-kill-buffer-ignores-unrelated-perspectives () + "Test that unrelated perspectives do not affect `persp-maybe-kill-buffer'." + (persp-test-with-persp + (persp-test-with-temp-buffers (dummy-buffer other-buffer) + (switch-to-buffer dummy-buffer) + (should (persp-test-buffer-in-persps dummy-buffer "main")) + (persp-switch "A") + (switch-to-buffer other-buffer) + (should (persp-test-buffer-in-persps other-buffer "A")) + (should-not (persp-is-current-buffer dummy-buffer)) + (persp-switch "main") + (should (kill-buffer dummy-buffer)) + (should-not (buffer-live-p dummy-buffer)) + (should-not (persp-test-buffer-in-persps dummy-buffer)) + (should (persp-test-buffer-in-persps other-buffer "A"))))) + +(ert-deftest basic-persp-maybe-kill-buffer-preserves-last-buffer () + "Test that `persp-maybe-kill-buffer' preserves a perspective's last buffer." + (persp-test-with-persp + (let ((ido-ignore-buffers '("^\\*scratch\\*"))) + (persp-test-with-temp-buffers (dummy-buffer helper-buffer) + (switch-to-buffer dummy-buffer) + (should (persp-test-buffer-in-persps dummy-buffer "main")) + (persp-switch "A") + (switch-to-buffer dummy-buffer) + (should (persp-test-buffer-in-persps dummy-buffer "main" "A")) + (persp-switch "main") + (switch-to-buffer helper-buffer) + (should (persp-test-buffer-in-persps helper-buffer "main")) + (switch-to-buffer dummy-buffer) + (should-not (kill-buffer dummy-buffer)) + (should (buffer-live-p dummy-buffer)) + (should (persp-test-buffer-in-persps dummy-buffer "A")) + (should-not (persp-is-current-buffer dummy-buffer)) + (should (persp-test-buffer-in-persps helper-buffer "main")))))) + (ert-deftest basic-persp-switch-to-buffer*-imports-by-default () "Test that `persp-switch-to-buffer*' imports other-perspective buffers by default." (persp-test-with-persp |
