Add my/kill-some-buffers

This commit is contained in:
Alexander Rosenberg 2024-10-08 21:45:10 -07:00
parent 7d01b9791f
commit 2c08ad6436
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730

106
init.el
View File

@ -196,10 +196,112 @@ Interactively, force the recompile if called with a prefix."
"*dashboard*") "*dashboard*")
(add-to-list 'clean-buffer-list-kill-never-buffer-names (add-to-list 'clean-buffer-list-kill-never-buffer-names
"*elfeed-search*") "*elfeed-search*")
(add-to-list 'clean-buffer-list-kill-never-buffer-names
"*mu4e-last-update*")
(midnight-mode 1)) (midnight-mode 1))
(defvar my/kill-some-buffers-exclude-names
'("*mu4e-main*" "*Async-native-compile-log*" "*dashboard*" "*elfeed-search*"
"*Messages*" "*scratch*")
"List of literal buffer names that `my/kill-some-buffers' should not kill.")
(defun my/kill-some-buffers-excluded-buffer-p (buffer)
"Return non-nil if BUFFER should be excluded from `my/kill-some-buffers'."
(cl-find (buffer-name buffer) my/kill-some-buffers-exclude-names
:test 'equal))
(defun my/buffer-visible-p (buffer)
"Return non-nil if BUFFER is visible.
BUFFER can be a string or a buffer."
(cond
((stringp buffer)
(not (string-prefix-p " " buffer)))
((bufferp buffer)
(my/buffer-visible-p (buffer-name buffer)))
(t
(signal 'wrong-type-argument `((or bufferp stringp) ,buffer)))))
(defvar my/kill-some-buffers-default-pred 'my/buffer-visible-p
"Default predicate for `my/kill-some-buffers'.")
(defun my/kill-some-buffers-prompt-for (buffer)
"Generate a prompt for BUFFER."
(let* ((process (get-buffer-process buffer))
(process-p (and (process-live-p process)
(not (process-query-on-exit-flag process))))
(modified-p (and (buffer-file-name buffer)
(buffer-modified-p buffer))))
(format "Buffer \"%s\" %s. Kill? "
(buffer-name buffer)
(cond
((and process-p modified-p)
"HAS BEEN EDITED AND HAS A LIVE PROCESS")
(modified-p
"HAS BEEN EDITED")
(process-p
"HAS A LIVE PROCESS")
(t "is unmodified")))))
(cl-defun my/kill-some-buffers (&optional auto-unmod pred)
"Improved version of `kill-some-buffers'.
Ask the user weather to kill each visible buffer whose name is not in
`my/kill-some-buffers-exclude-names'.
When AUTO-UNMOD is non-nil, as it is with a prefix argument, automatically kill
unmodified buffers, and then ask about the rest.
When PRED is non-nil, it is a function that will be run in each buffer (not just
visible ones). If it returns t, that buffer will be considered for killing. If
PRED is nil, the value of `my/kill-some-buffers-default-pred' is used."
(interactive "P")
;; we already ask, no need to do it again
(let ((kill-buffer-query-functions nil)
(all-action (when auto-unmod 'unmod))
(ask-again-buffers))
(cl-flet ((ask-about (buffer allow-unmod)
(unless all-action
(read-answer
(my/kill-some-buffers-prompt-for buffer)
`(("yes" ?y "save and kill this buffer")
("no" ?n "skip this buffer")
("all" ?! "save and kill all remaining buffers")
("nosave" ?l "kill this buffer without saving")
,@(when allow-unmod
'(("unmod" ?a
"kill unmodified buffers, ask about the rest")))
("quit" ?q "exit")))))
(act-on (ans buffer allow-unmod)
(when (equal ans "all")
(setq all-action 'all))
(when (and allow-unmod
(equal ans "unmod"))
(setq all-action 'unmod))
(cond
((and (eq all-action 'unmod)
(buffer-file-name buffer)
(buffer-modified-p buffer))
(push buffer ask-again-buffers))
((or (eq all-action 'all)
(eq all-action 'unmod)
(equal ans "yes"))
(when (buffer-file-name buffer)
(with-current-buffer buffer
(save-buffer)))
(kill-buffer buffer))
((equal ans "nosave")
(with-current-buffer buffer
(set-buffer-modified-p nil))
(kill-buffer buffer))
;; Skip buffer
;; ((equal ans "no"))
((equal ans "quit")
(cl-return-from my/kill-some-buffers)))))
(dolist (buffer (buffer-list))
(when (and (not (my/kill-some-buffers-excluded-buffer-p buffer))
(funcall (or pred my/kill-some-buffers-default-pred) buffer))
(act-on (ask-about buffer t) buffer t)))
(setq all-action nil)
(dolist (buffer ask-again-buffers)
(act-on (ask-about buffer nil) buffer nil)))))
(use-package tab-bar (use-package tab-bar
:ensure nil :ensure nil
:init :init