Some cleanups for the buffer menu and electric buffer menu.
[bpt/emacs.git] / lisp / ebuff-menu.el
CommitLineData
c0274f38
ER
1;;; ebuff-menu.el --- electric-buffer-list mode
2
acaf905b 3;; Copyright (C) 1985-1986, 1994, 2001-2012 Free Software Foundation, Inc.
2076c87c 4
3a801d0c 5;; Author: Richard Mlynarik <mly@ai.mit.edu>
54138c9d 6;; Maintainer: FSF
3465cfd7 7;; Keywords: convenience
3a801d0c 8
2076c87c
JB
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
2076c87c 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
2076c87c
JB
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
2076c87c 23
e5167999
ER
24;;; Commentary:
25
e41b2db1
ER
26;; Who says one can't have typeout windows in GNU Emacs? The entry
27;; point, `electric-buffer-list' works like ^r select buffer from the
28;; ITS Emacs lunar or tmacs libraries.
e5167999
ER
29
30;;; Code:
2076c87c
JB
31
32(require 'electric)
33
34;; this depends on the format of list-buffers (from src/buffer.c) and
35;; on stuff in lisp/buff-menu.el
36
bb0bd45a
SM
37(defvar electric-buffer-menu-mode-map
38 (let ((map (make-keymap)))
39 (fillarray (car (cdr map)) 'Electric-buffer-menu-undefined)
40 (define-key map "\e" nil)
41 (define-key map "\C-z" 'suspend-frame)
42 (define-key map "v" 'Electric-buffer-menu-mode-view-buffer)
43 (define-key map (char-to-string help-char) 'Helper-help)
44 (define-key map "?" 'Helper-describe-bindings)
45 (define-key map "\C-c" nil)
46 (define-key map "\C-c\C-c" 'Electric-buffer-menu-quit)
47 (define-key map "\C-]" 'Electric-buffer-menu-quit)
48 (define-key map "q" 'Electric-buffer-menu-quit)
49 (define-key map " " 'Electric-buffer-menu-select)
50 (define-key map "\C-m" 'Electric-buffer-menu-select)
51 (define-key map "\C-l" 'recenter)
52 (define-key map "s" 'Buffer-menu-save)
53 (define-key map "d" 'Buffer-menu-delete)
54 (define-key map "k" 'Buffer-menu-delete)
55 (define-key map "\C-d" 'Buffer-menu-delete-backwards)
56 ;; (define-key map "\C-k" 'Buffer-menu-delete)
57 (define-key map "\177" 'Buffer-menu-backup-unmark)
58 (define-key map "~" 'Buffer-menu-not-modified)
59 (define-key map "u" 'Buffer-menu-unmark)
60 (let ((i ?0))
61 (while (<= i ?9)
62 (define-key map (char-to-string i) 'digit-argument)
63 (define-key map (concat "\e" (char-to-string i)) 'digit-argument)
64 (setq i (1+ i))))
65 (define-key map "-" 'negative-argument)
66 (define-key map "\e-" 'negative-argument)
67 (define-key map "m" 'Buffer-menu-mark)
68 (define-key map "\C-u" 'universal-argument)
69 (define-key map "\C-p" 'previous-line)
70 (define-key map "\C-n" 'next-line)
71 (define-key map "p" 'previous-line)
72 (define-key map "n" 'next-line)
ce3cefcc
CY
73 (define-key map "\C-v" 'scroll-up-command)
74 (define-key map "\ev" 'scroll-down-command)
bb0bd45a
SM
75 (define-key map ">" 'scroll-right)
76 (define-key map "<" 'scroll-left)
77 (define-key map "\e\C-v" 'scroll-other-window)
78 (define-key map "\e>" 'end-of-buffer)
79 (define-key map "\e<" 'beginning-of-buffer)
80 (define-key map "\e\e" nil)
81 (define-key map "\e\e\e" 'Electric-buffer-menu-quit)
82 ;; This binding prevents the "escape => ESC" function-key-map mapping from
83 ;; kicking in!
84 ;; (define-key map [escape escape escape] 'Electric-buffer-menu-quit)
85 (define-key map [mouse-2] 'Electric-buffer-menu-mouse-select)
86 map))
2076c87c 87
3cc99f68
CY
88(put 'Electric-buffer-menu-quit :advertised-binding "\C-c\C-c")
89(put 'Electric-buffer-menu-select :advertised-binding " ")
90(put 'Helper-help :advertised-binding (char-to-string help-char))
91(put 'Helper-describe-bindings :advertised-binding "?")
92
5f20b653
TTN
93(defvar electric-buffer-menu-mode-hook nil
94 "Normal hook run by `electric-buffer-list'.")
95
2076c87c
JB
96;;;###autoload
97(defun electric-buffer-list (arg)
5f20b653 98 "Pop up a buffer describing the set of Emacs buffers.
2076c87c
JB
99Vaguely like ITS lunar select buffer; combining typeoutoid buffer
100listing with menuoid buffer selection.
101
102If the very next character typed is a space then the buffer list
103window disappears. Otherwise, one may move around in the buffer list
104window, marking buffers to be selected, saved or deleted.
105
106To exit and select a new buffer, type a space when the cursor is on
107the appropriate line of the buffer-list window. Other commands are
5f20b653 108much like those of `Buffer-menu-mode'.
2076c87c 109
5f20b653 110Run hooks in `electric-buffer-menu-mode-hook' on entry.
2076c87c 111
71296446 112\\{electric-buffer-menu-mode-map}"
2076c87c
JB
113 (interactive "P")
114 (let (select buffer)
115 (save-window-excursion
cf6ce50b
SM
116 (setq buffer (list-buffers-noselect arg))
117 (Electric-pop-up-window buffer)
2076c87c
JB
118 (unwind-protect
119 (progn
120 (set-buffer buffer)
121 (Electric-buffer-menu-mode)
ede8f2fe 122 (electric-buffer-update-highlight)
2076c87c
JB
123 (setq select
124 (catch 'electric-buffer-menu-select
fc7323e6 125 (message "<<< Press Return to bury the buffer list >>>")
d42cc509 126 (if (eq (setq unread-command-events (list (read-event)))
a8158099 127 ?\s)
dbc4e1c1 128 (progn (setq unread-command-events nil)
2076c87c 129 (throw 'electric-buffer-menu-select nil)))
69adebeb
KH
130 (let ((start-point (point))
131 (first (progn (goto-char (point-min))
a82c1267
JPW
132 (unless Buffer-menu-use-header-line
133 (forward-line 2))
2076c87c
JB
134 (point)))
135 (last (progn (goto-char (point-max))
136 (forward-line -1)
137 (point)))
138 (goal-column 0))
69adebeb
KH
139 ;; Use start-point if it is meaningful.
140 (goto-char (if (or (< start-point first)
141 (> start-point last))
142 first
143 start-point))
2076c87c
JB
144 (Electric-command-loop 'electric-buffer-menu-select
145 nil
146 t
147 'electric-buffer-menu-looper
148 (cons first last))))))
149 (set-buffer buffer)
150 (Buffer-menu-mode)
ba5bf5f0 151 (bury-buffer) ;Get rid of window, if dedicated.
2076c87c
JB
152 (message "")))
153 (if select
154 (progn (set-buffer buffer)
155 (let ((opoint (point-marker)))
156 (Buffer-menu-execute)
157 (goto-char (point-min))
158 (if (prog1 (search-forward "\n>" nil t)
159 (goto-char opoint) (set-marker opoint nil))
160 (Buffer-menu-select)
161 (switch-to-buffer (Buffer-menu-buffer t))))))))
162
163(defun electric-buffer-menu-looper (state condition)
164 (cond ((and condition
165 (not (memq (car condition) '(buffer-read-only
166 end-of-buffer
167 beginning-of-buffer))))
168 (signal (car condition) (cdr condition)))
169 ((< (point) (car state))
170 (goto-char (point-min))
a82c1267
JPW
171 (unless Buffer-menu-use-header-line
172 (forward-line 2)))
2076c87c
JB
173 ((> (point) (cdr state))
174 (goto-char (point-max))
175 (forward-line -1)
176 (if (pos-visible-in-window-p (point-max))
ede8f2fe
RS
177 (recenter -1))))
178 (electric-buffer-update-highlight))
2076c87c 179
784f8619
RS
180(defvar Helper-return-blurb)
181
2076c87c
JB
182(put 'Electric-buffer-menu-mode 'mode-class 'special)
183(defun Electric-buffer-menu-mode ()
184 "Major mode for editing a list of buffers.
185Each line describes one of the buffers in Emacs.
186Letters do not insert themselves; instead, they are commands.
187\\<electric-buffer-menu-mode-map>
188\\[keyboard-quit] or \\[Electric-buffer-menu-quit] -- exit buffer menu, returning to previous window and buffer
189 configuration. If the very first character typed is a space, it
190 also has this effect.
191\\[Electric-buffer-menu-select] -- select buffer of line point is on.
192 Also show buffers marked with m in other windows,
193 deletes buffers marked with \"D\", and saves those marked with \"S\".
194\\[Buffer-menu-mark] -- mark buffer to be displayed.
195\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
196\\[Buffer-menu-save] -- mark that buffer to be saved.
197\\[Buffer-menu-delete] or \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted.
198\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
199\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done.
200\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
201
202\\{electric-buffer-menu-mode-map}
203
5f20b653
TTN
204Entry to this mode via command `electric-buffer-list' calls the value of
205`electric-buffer-menu-mode-hook'."
e4edc5cd
TTN
206 (let ((saved header-line-format))
207 (kill-all-local-variables)
208 (setq header-line-format saved))
2076c87c
JB
209 (use-local-map electric-buffer-menu-mode-map)
210 (setq mode-name "Electric Buffer Menu")
211 (setq mode-line-buffer-identification "Electric Buffer List")
212 (make-local-variable 'Helper-return-blurb)
213 (setq Helper-return-blurb "return to buffer editing")
214 (setq truncate-lines t)
215 (setq buffer-read-only t)
216 (setq major-mode 'Electric-buffer-menu-mode)
217 (goto-char (point-min))
218 (if (search-forward "\n." nil t) (forward-char -1))
a3d9e1fa 219 (run-mode-hooks 'electric-buffer-menu-mode-hook))
2076c87c
JB
220
221;; generally the same as Buffer-menu-mode-map
222;; (except we don't indirect to global-map)
223(put 'Electric-buffer-menu-undefined 'suppress-keymap t)
bb0bd45a 224
71296446 225
2076c87c
JB
226(defun Electric-buffer-menu-exit ()
227 (interactive)
d42cc509 228 (setq unread-command-events (listify-key-sequence (this-command-keys)))
2076c87c
JB
229 ;; for robustness
230 (condition-case ()
231 (throw 'electric-buffer-menu-select nil)
232 (error (Buffer-menu-mode)
233 (other-buffer))))
234
235(defun Electric-buffer-menu-select ()
236 "Leave Electric Buffer Menu, selecting buffers and executing changes.
5f20b653
TTN
237Save buffers marked \"S\". Delete buffers marked \"K\".
238Select buffer at point and display buffers marked \">\" in other windows."
2076c87c
JB
239 (interactive)
240 (throw 'electric-buffer-menu-select (point)))
241
3c59c255
KH
242(defun Electric-buffer-menu-mouse-select (event)
243 (interactive "e")
244 (select-window (posn-window (event-end event)))
245 (set-buffer (window-buffer (selected-window)))
246 (goto-char (posn-point (event-end event)))
247 (throw 'electric-buffer-menu-select (point)))
248
2076c87c
JB
249(defun Electric-buffer-menu-quit ()
250 "Leave Electric Buffer Menu, restoring previous window configuration.
5f20b653 251Skip execution of select, save, and delete commands."
2076c87c
JB
252 (interactive)
253 (throw 'electric-buffer-menu-select nil))
254
255(defun Electric-buffer-menu-undefined ()
256 (interactive)
257 (ding)
2bb7c30c 258 (message "%s"
3cc99f68 259 (substitute-command-keys "\
2076c87c
JB
260Type \\[Electric-buffer-menu-quit] to exit, \
261\\[Electric-buffer-menu-select] to select, \
3cc99f68 262\\[Helper-help] for help, \\[Helper-describe-bindings] for commands."))
2076c87c
JB
263 (sit-for 4))
264
265(defun Electric-buffer-menu-mode-view-buffer ()
266 "View buffer on current line in Electric Buffer Menu.
5f20b653 267Return to Electric Buffer Menu when done."
2076c87c
JB
268 (interactive)
269 (let ((bufnam (Buffer-menu-buffer nil)))
270 (if bufnam
271 (view-buffer bufnam)
272 (ding)
273 (message "Buffer %s does not exist!" bufnam)
274 (sit-for 4))))
275
ede8f2fe
RS
276(defvar electric-buffer-overlay nil)
277(defun electric-buffer-update-highlight ()
080314d3
JPW
278 (when (eq major-mode 'Electric-buffer-menu-mode)
279 ;; Make sure we have an overlay to use.
280 (or electric-buffer-overlay
281 (progn
282 (make-local-variable 'electric-buffer-overlay)
283 (setq electric-buffer-overlay (make-overlay (point) (point)))))
284 (move-overlay electric-buffer-overlay
5ed619e0
GM
285 (line-beginning-position)
286 (line-end-position))
080314d3 287 (overlay-put electric-buffer-overlay 'face 'highlight)))
ede8f2fe 288
896546cd
RS
289(provide 'ebuff-menu)
290
c0274f38 291;;; ebuff-menu.el ends here