blob: fe43575e94d7aa463be4e4e3facab5fb2dc49469 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
;;; undead-buffers.el --- Bury Rather Than Kill These Buffers -*- lexical-binding: t; coding: utf-8; -*-
;;; Commentary:
;;
;; Layer: 2 (Core UX).
;; Category: C.
;; Load shape: eager.
;; Eager reason: global kill-buffer remap and window-kill bindings wanted from
;; the first session.
;; Top-level side effects: three keymap-global-set (remaps kill-buffer; binds
;; M-S-o, M-S-m).
;; Runtime requires: none.
;; Direct test load: yes.
;;
;; This library allows for "burying" selected buffers instead of killing them.
;; Since they won't be killed, I'm calling them "undead buffers".
;; The main function cj/kill-buffer-or-bury-alive replaces kill-buffer.
;;
;; Additional helper commands and key bindings:
;; - C-; b k (=cj/kill-buffer-and-window=): delete this window and bury/kill its buffer.
;; - C-; b K (=cj/kill-other-window-buffer=): bury/kill the other window's buffer,
;; keeping that window and the split intact.
;; - M-O (=cj/kill-other-window=): delete the next window and bury/kill its buffer.
;; - M-M (=cj/kill-all-other-buffers-and-windows=): kill or bury all buffers except
;; the current one and delete all other windows.
;;
;; Add to the list of "undead buffers" by adding to the cj/buffer-bury-alive-list
;; variable.
;;
;;; Code:
(defvar cj/undead-buffer-list
'("*scratch*" "*EMMS-Playlist*" "*Messages*" "*ert*"
"*AI-Assistant*")
"Buffers to bury instead of killing.")
(defun cj/make-buffer-undead (name)
"Append NAME to `cj/undead-buffer-list' if not present.
Signal an error if NAME is not a non-empty string. Return the updated list."
(unless (and (stringp name) (> (length name) 0))
(error "cj/bury-alive-add: NAME must be a non-empty string"))
(add-to-list 'cj/undead-buffer-list name t))
(defun cj/kill-buffer-or-bury-alive (buffer)
"Kill BUFFER or bury it if it's in `cj/undead-buffer-list'."
(interactive "bBuffer to kill or bury: ")
(with-current-buffer buffer
(if current-prefix-arg
(progn
(add-to-list 'cj/undead-buffer-list (buffer-name))
(message "Added %s to bury-alive-list" (buffer-name)))
(if (member (buffer-name) cj/undead-buffer-list)
(bury-buffer)
(kill-buffer)))))
(keymap-global-set "<remap> <kill-buffer>" #'cj/kill-buffer-or-bury-alive)
(defun cj/undead-buffer-p ()
"Replacement for `save-some-buffers' skips undead-buffers.
Undead-buffers are buffers in `cj/undead-buffer-list'."
(let* ((buf (current-buffer))
(name (buffer-name buf)))
(and
(not (member name cj/undead-buffer-list))
(buffer-file-name buf)
(buffer-modified-p buf))))
(defun cj/save-some-buffers (&optional arg)
"Save some buffers, omitting those in `cj/undead-buffer-list'.
ARG is passed to `save-some-buffers'."
(interactive "P")
(save-some-buffers arg #'cj/undead-buffer-p))
(defun cj/kill-buffer-and-window ()
"Delete window and kill or bury its buffer."
(interactive)
(let ((buf (current-buffer)))
(unless (one-window-p)
(delete-window))
(cj/kill-buffer-or-bury-alive buf)))
;; Keybinding moved to custom-buffer-file.el (C-; b k)
(defun cj/kill-other-window ()
"Delete the next window and kill or bury its buffer."
(interactive)
(other-window 1)
(let ((buf (current-buffer)))
(unless (one-window-p)
(delete-window))
(cj/kill-buffer-or-bury-alive buf)))
(keymap-global-set "M-S-o" #'cj/kill-other-window)
(defun cj/kill-other-window-buffer ()
"Kill or bury the buffer shown in the other window, keeping that window
and the split intact -- the window then shows whatever bury/kill surfaces
next. With more than two windows, acts on `next-window'.
Sibling of `cj/kill-other-window', which deletes the other window; here the
split is preserved. Buffers in `cj/undead-buffer-list' are buried."
(interactive)
(if (one-window-p)
(user-error "No other window")
(with-selected-window (next-window)
(cj/kill-buffer-or-bury-alive (current-buffer)))))
;; Keybinding in custom-buffer-file.el (C-; b K)
(defun cj/kill-all-other-buffers-and-windows ()
"Kill or bury all other buffers, then delete other windows."
(interactive)
(cj/save-some-buffers)
(delete-other-windows)
(mapc #'cj/kill-buffer-or-bury-alive
(delq (current-buffer) (buffer-list))))
(keymap-global-set "M-S-m" #'cj/kill-all-other-buffers-and-windows) ;; was M-M
(provide 'undead-buffers)
;;; undead-buffers.el ends here
|