diff --git a/core/autoload/buffers.el b/core/autoload/buffers.el index 1c474cd94..238ba2e7c 100644 --- a/core/autoload/buffers.el +++ b/core/autoload/buffers.el @@ -155,30 +155,35 @@ popup window/buffer and b) isn't a special buffer." buffer, but only bury the buffer if it is present in another window. See `doom-real-buffer-p' for what 'real' means." - (let* ((buffer (or buffer (current-buffer))) - (buffer-win (get-buffer-window buffer)) - (only-buffer-window-p (= 1 (length (get-buffer-window-list buffer nil t))))) - ;; deal with unsaved buffers - (when (and only-buffer-window-p - (buffer-file-name buffer) - (buffer-modified-p buffer)) - (with-current-buffer buffer - (if (and (not dont-save) - (yes-or-no-p "Buffer is unsaved, save it?")) - (save-buffer) - (set-buffer-modified-p nil)))) - ;; deal with dedicated windows - (if (window-dedicated-p buffer-win) - (unless (window--delete buffer-win t t) - (split-window buffer-win) - (window--delete buffer-win t t)) - ;; cycle to a real buffer - (doom--cycle-real-buffers -1) - (when buffer-win - (unrecord-window-buffer buffer-win buffer)) - (when only-buffer-window-p - (kill-buffer buffer))) - (eq (current-buffer) buffer))) + (setq buffer (or buffer (current-buffer))) + (when (and (bufferp buffer) (buffer-live-p buffer)) + (let ((buffer-win (get-buffer-window buffer)) + (only-buffer-window-p (= 1 (length (get-buffer-window-list buffer nil t))))) + ;; deal with unsaved buffers + (when (and only-buffer-window-p + (buffer-file-name buffer) + (buffer-modified-p buffer)) + (with-current-buffer buffer + (if (and (not dont-save) + (yes-or-no-p "Buffer is unsaved, save it?")) + (save-buffer) + (set-buffer-modified-p nil)))) + ;; deal with dedicated windows + (if buffer-win + (if (window-dedicated-p buffer-win) + (unless (window--delete buffer-win t t) + (split-window buffer-win) + (window--delete buffer-win t t)) + ;; cycle to a real buffer + (with-selected-window buffer-win + (doom--cycle-real-buffers -1) + (when buffer-win + (unrecord-window-buffer buffer-win buffer)) + (when only-buffer-window-p + (kill-buffer buffer))) + (not (eq (current-buffer) buffer))) + (kill-buffer buffer) + (not (buffer-live-p buffer)))))) ;;;###autoload (defun doom-force-kill-buffer (&optional buffer dont-save) @@ -187,7 +192,7 @@ switched to a real buffer." (interactive) (let* ((buffer (or buffer (current-buffer))) (windows (get-buffer-window-list buffer nil t))) - (kill-buffer buffer) + (doom-kill-buffer buffer dont-save) (dolist (win windows) (with-selected-window win (unless (doom-real-buffer-p) diff --git a/test/core/autoload/test-buffers.el b/test/core/autoload/test-buffers.el index 10efdc77e..73b235f55 100644 --- a/test/core/autoload/test-buffers.el +++ b/test/core/autoload/test-buffers.el @@ -1,36 +1,91 @@ ;;; test/core/autoload/test-buffers.el +(defmacro with-temp-buffers! (buffer-args &rest body) + (declare (indent defun)) + (let (buffers) + (dolist (bsym buffer-args) + (push `(,bsym (get-buffer-create ,(symbol-name bsym))) + buffers)) + `(let* (,@buffers + (buffer-list (list ,@(reverse (mapcar #'car buffers))))) + ,@body + (mapc #'kill-buffer buffer-list)))) + (def-test-group! core/autoload/buffers (ert-deftest get-buffers () - (let ((a (get-buffer-create "*a*")) - (b (get-buffer-create "*b*")) - (c (get-buffer-create "*c*")) - (buffers (doom-buffer-list))) - (should buffers) - (should (cl-every 'bufferp buffers)) - (should (cl-every (lambda (b) (memq b buffers)) (list a b c))))) + (with-temp-buffers! (a b c) + (should (cl-every #'buffer-live-p buffer-list)) + (should (equal buffer-list (list a b c))) + (dolist (buf (list (cons a doom-emacs-dir) + (cons b doom-emacs-dir) + (cons c "/tmp/"))) + (with-current-buffer (car buf) + (setq-local default-directory (cdr buf)))) + (with-current-buffer a + ;; should produce all buffers + (let ((buffers (doom-buffer-list))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b c)))) + ;; should produce only project buffers + (let ((buffers (doom-buffer-list t))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b))) + (should-not (memq c buffers)))) + ;; If no project is available, just get all buffers + (with-current-buffer c + (let ((buffers (doom-buffer-list t))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b c))))))) + + (ert-deftest get-real-buffers () + (with-temp-buffers! (a b c d) + (with-current-buffer c + (rename-buffer "*C*")) + (with-current-buffer d + (doom-popup-mode +1)) + (let ((buffers (doom-real-buffers-list buffer-list))) + (should (= (length buffers) 2)) + (should (cl-every (lambda (x) (memq x buffers)) (list a b))) + (should (cl-notany (lambda (x) (memq x buffers)) (list c d)))))) + + (ert-deftest kill-buffers () + (with-temp-buffers! (a b) + (doom-kill-buffer a) + (should-not (buffer-live-p a)) + ;; modified buffer + (with-current-buffer b + (set-buffer-modified-p t)) + (doom-kill-buffer b t) + (should-not (buffer-live-p a)))) + + (ert-deftest kill-buffer-then-show-real-buffer () + (with-temp-buffers! (a b c) + (should (cl-every #'buffer-live-p buffer-list)) + (switch-to-buffer a) + (should (eq (current-buffer) a)) + (should (eq (selected-window) (get-buffer-window a))) + (should (doom-kill-buffer a)) + (should (eq (current-buffer) b)) + (should (doom-kill-buffer)) + (should (eq (current-buffer) c)) + (doom/kill-this-buffer) + (should (eq (current-buffer) (doom-fallback-buffer))))) (ert-deftest matching-buffers () - (let ((a (get-buffer-create "*a*")) - (b (get-buffer-create "*b*")) - (c (get-buffer-create "*c*")) - (buffers (doom-matching-buffers "^\\*[ac]\\*$"))) - (should (= 2 (length buffers))) - (should (cl-every 'bufferp buffers)) - (should (cl-every (lambda (b) (memq b buffers)) (list a c))))) + (with-temp-buffers! (a b c) + (let ((buffers (doom-matching-buffers "^[ac]$"))) + (should (= 2 (length buffers))) + (should (cl-every #'bufferp buffers)) + (should (cl-every (lambda (x) (memq x buffers)) (list a c))) + (should (equal (reverse buffers) (doom-matching-buffers "^[ac]$" buffer-list)))))) (ert-deftest buffers-in-mode () - (dolist (name (list "*a*" "*b*")) - (with-current-buffer (get-buffer-create name) - (emacs-lisp-mode))) - (dolist (name (list "*c*" "*d*" "*e*")) - (with-current-buffer (get-buffer-create name) - (text-mode))) - (let ((el-buffers (doom-buffers-in-mode 'emacs-lisp-mode)) - (txt-buffers (doom-buffers-in-mode 'text-mode))) - (should (cl-every 'bufferp (append el-buffers txt-buffers))) - (should (= 2 (length el-buffers))) - (should (= 3 (length txt-buffers))))) - - ;; TODO - ) + (with-temp-buffers! (a b c d e) + (dolist (buf (list a b)) + (with-current-buffer buf + (emacs-lisp-mode))) + (dolist (buf (list c d e)) + (with-current-buffer buf + (text-mode))) + (let ((el-buffers (doom-buffers-in-mode 'emacs-lisp-mode)) + (txt-buffers (doom-buffers-in-mode 'text-mode))) + (should (cl-every #'buffer-live-p (append el-buffers txt-buffers))) + (should (= 2 (length el-buffers))) + (should (= 3 (length txt-buffers)))))))