*** empty log message ***
[bpt/emacs.git] / lisp / buff-menu.el
CommitLineData
55535639 1;;; buff-menu.el --- buffer menu main function and support functions
c0274f38 2
d5aacb46 3;; Copyright (C) 1985, 86, 87, 93, 94, 95, 2000, 2001, 2002, 03, 2004
6d6c3f84 4;; Free Software Foundation, Inc.
2dd96f23 5
9750e079 6;; Maintainer: FSF
6d6c3f84 7;; Keywords: convenience
9750e079 8
2dd96f23
JB
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
35aaf00c 13;; the Free Software Foundation; either version 2, or (at your option)
2dd96f23
JB
14;; any later version.
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
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
2dd96f23 25
e41b2db1
ER
26;;; Commentary:
27
28;; Edit, delete, or change attributes of all currently active Emacs
eb8c3be9 29;; buffers from a list summarizing their state. A good way to browse
e41b2db1 30;; any special or scratch buffers you have loaded, since you can't find
6d6c3f84 31;; them by filename. The single entry point is `list-buffers',
86dbbfc2
ER
32;; normally bound to C-x C-b.
33
34;;; Change Log:
35
42a19c2a
RS
36;; Buffer-menu-view: New function
37;; Buffer-menu-view-other-window: New function
38
86dbbfc2
ER
39;; Merged by esr with recent mods to Emacs 19 buff-menu, 23 Mar 1993
40;;
86dbbfc2
ER
41;; Modified by Bob Weiner, Motorola, Inc., 4/14/89
42;;
43;; Added optional backup argument to 'Buffer-menu-unmark' to make it undelete
44;; current entry and then move to previous one.
45;;
46;; Based on FSF code dating back to 1985.
e41b2db1 47
5de9bdab 48;;; Code:
10e1dad9 49
d5aacb46
SM
50;;Trying to preserve the old window configuration works well in
51;;simple scenarios, when you enter the buffer menu, use it, and exit it.
52;;But it does strange things when you switch back to the buffer list buffer
53;;with C-x b, later on, when the window configuration is different.
54;;The choice seems to be, either restore the window configuration
55;;in all cases, or in no cases.
56;;I decided it was better not to restore the window config at all. -- rms.
08c82d4d 57
d5aacb46
SM
58;;But since then, I changed buffer-menu to use the selected window,
59;;so q now once again goes back to the previous window configuration.
08c82d4d 60
d5aacb46
SM
61;;(defvar Buffer-menu-window-config nil
62;; "Window configuration saved from entry to `buffer-menu'.")
2dd96f23 63
d5aacb46
SM
64;; Put buffer *Buffer List* into proper mode right away
65;; so that from now on even list-buffers is enough to get a buffer menu.
2dd96f23 66
bc7bb432
JB
67(defgroup Buffer-menu nil
68 "Show a menu of all buffers in a buffer."
69 :group 'tools
70 :group 'convenience)
71
72(defcustom Buffer-menu-use-header-line t
73 "*Non-nil means to use an immovable header-line."
74 :type 'boolean
75 :group 'Buffer-menu)
76
77(defface Buffer-menu-buffer-face
78 '((t (:weight bold)))
79 "Face used to highlight buffer name."
80 :group 'font-lock-highlighting-faces)
81
4f0992b3 82(defcustom Buffer-menu-buffer+size-width 26
bc7bb432
JB
83 "*How wide to jointly make the buffer name and size columns."
84 :type 'number
85 :group 'Buffer-menu)
86
4f0992b3 87(defcustom Buffer-menu-mode-width 16
bc7bb432
JB
88 "*How wide to make the mode name column."
89 :type 'number
90 :group 'Buffer-menu)
91
d5aacb46 92;; This should get updated & resorted when you click on a column heading
bc7bb432
JB
93(defvar Buffer-menu-sort-column nil
94 "*2 for sorting by buffer names. 5 for sorting by file names.
95nil for default sorting by visited order.")
96
97(defconst Buffer-menu-buffer-column 4)
e5ea316b 98
463a7342
JPW
99(defvar Buffer-menu-mode-map nil
100 "Local keymap for `Buffer-menu-mode' buffers.")
2dd96f23 101
7b0a86ab
LT
102(defvar Buffer-menu-files-only nil
103 "Non-nil if the current buffer-menu lists only file buffers.
104This variable determines whether reverting the buffer lists only
105file buffers. It affects both manual reverting and reverting by
106Auto Revert Mode.")
107
108(make-variable-buffer-local 'Buffer-menu-files-only)
109
2dd96f23
JB
110(if Buffer-menu-mode-map
111 ()
112 (setq Buffer-menu-mode-map (make-keymap))
113 (suppress-keymap Buffer-menu-mode-map t)
68e6f094 114 (define-key Buffer-menu-mode-map "q" 'quit-window)
3ed788ec 115 (define-key Buffer-menu-mode-map "v" 'Buffer-menu-select)
2dd96f23
JB
116 (define-key Buffer-menu-mode-map "2" 'Buffer-menu-2-window)
117 (define-key Buffer-menu-mode-map "1" 'Buffer-menu-1-window)
118 (define-key Buffer-menu-mode-map "f" 'Buffer-menu-this-window)
251680cf 119 (define-key Buffer-menu-mode-map "e" 'Buffer-menu-this-window)
8768da77 120 (define-key Buffer-menu-mode-map "\C-m" 'Buffer-menu-this-window)
2dd96f23 121 (define-key Buffer-menu-mode-map "o" 'Buffer-menu-other-window)
35aaf00c 122 (define-key Buffer-menu-mode-map "\C-o" 'Buffer-menu-switch-other-window)
2dd96f23
JB
123 (define-key Buffer-menu-mode-map "s" 'Buffer-menu-save)
124 (define-key Buffer-menu-mode-map "d" 'Buffer-menu-delete)
125 (define-key Buffer-menu-mode-map "k" 'Buffer-menu-delete)
126 (define-key Buffer-menu-mode-map "\C-d" 'Buffer-menu-delete-backwards)
127 (define-key Buffer-menu-mode-map "\C-k" 'Buffer-menu-delete)
128 (define-key Buffer-menu-mode-map "x" 'Buffer-menu-execute)
129 (define-key Buffer-menu-mode-map " " 'next-line)
130 (define-key Buffer-menu-mode-map "n" 'next-line)
131 (define-key Buffer-menu-mode-map "p" 'previous-line)
132 (define-key Buffer-menu-mode-map "\177" 'Buffer-menu-backup-unmark)
133 (define-key Buffer-menu-mode-map "~" 'Buffer-menu-not-modified)
134 (define-key Buffer-menu-mode-map "?" 'describe-mode)
135 (define-key Buffer-menu-mode-map "u" 'Buffer-menu-unmark)
136 (define-key Buffer-menu-mode-map "m" 'Buffer-menu-mark)
d91e2b1a
ER
137 (define-key Buffer-menu-mode-map "t" 'Buffer-menu-visit-tags-table)
138 (define-key Buffer-menu-mode-map "%" 'Buffer-menu-toggle-read-only)
36570c92 139 (define-key Buffer-menu-mode-map "b" 'Buffer-menu-bury)
0f88624e 140 (define-key Buffer-menu-mode-map "g" 'Buffer-menu-revert)
42a19c2a 141 (define-key Buffer-menu-mode-map "V" 'Buffer-menu-view)
7b0a86ab 142 (define-key Buffer-menu-mode-map "T" 'Buffer-menu-toggle-files-only)
2cf5fc7e 143 (define-key Buffer-menu-mode-map [mouse-2] 'Buffer-menu-mouse-select)
d91e2b1a 144)
2dd96f23
JB
145
146;; Buffer Menu mode is suitable only for specially formatted data.
147(put 'Buffer-menu-mode 'mode-class 'special)
148
149(defun Buffer-menu-mode ()
150 "Major mode for editing a list of buffers.
151Each line describes one of the buffers in Emacs.
152Letters do not insert themselves; instead, they are commands.
153\\<Buffer-menu-mode-map>
2cf5fc7e
RS
154\\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu.
155\\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu.
156\\[Buffer-menu-other-window] -- select that buffer in another window,
157 so the buffer menu buffer remains visible in its window.
42a19c2a
RS
158\\[Buffer-menu-view] -- select current line's buffer, but in view-mode.
159\\[Buffer-menu-view-other-window] -- select that buffer in
160 another window, in view-mode.
2cf5fc7e
RS
161\\[Buffer-menu-switch-other-window] -- make another window display that buffer.
162\\[Buffer-menu-mark] -- mark current line's buffer to be displayed.
163\\[Buffer-menu-select] -- select current line's buffer.
164 Also show buffers marked with m, in other windows.
dc6d9681 165\\[Buffer-menu-1-window] -- select that buffer in full-frame window.
2dd96f23
JB
166\\[Buffer-menu-2-window] -- select that buffer in one window,
167 together with buffer selected before this one in another window.
2dd96f23
JB
168\\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer.
169\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
170\\[Buffer-menu-save] -- mark that buffer to be saved, and move down.
171\\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down.
172\\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up.
173\\[Buffer-menu-execute] -- delete or save marked buffers.
174\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
86dbbfc2 175 With prefix argument, also move up one line.
d91e2b1a 176\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
0f88624e 177\\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line.
a59faabe 178\\[Buffer-menu-revert] -- update the list of buffers.
7b0a86ab 179\\[Buffer-menu-toggle-files-only] -- toggle whether the menu displays only file buffers.
a59faabe 180\\[Buffer-menu-bury] -- bury the buffer listed on this line."
2dd96f23
JB
181 (kill-all-local-variables)
182 (use-local-map Buffer-menu-mode-map)
2dd96f23
JB
183 (setq major-mode 'Buffer-menu-mode)
184 (setq mode-name "Buffer Menu")
7b0a86ab
LT
185 (set (make-local-variable 'revert-buffer-function)
186 'Buffer-menu-revert-function)
187 (set (make-local-variable 'buffer-stale-function)
012ad4a3 188 #'(lambda (&optional noconfirm) 'fast))
823316aa
KH
189 (setq truncate-lines t)
190 (setq buffer-read-only t)
2dd96f23 191 (run-hooks 'buffer-menu-mode-hook))
710e5da8 192
0f88624e
RS
193(defun Buffer-menu-revert ()
194 "Update the list of buffers."
195 (interactive)
196 (revert-buffer))
197
710e5da8 198(defun Buffer-menu-revert-function (ignore1 ignore2)
7b0a86ab
LT
199 ;; We can not use save-excursion here. The buffer gets erased.
200 (let ((old-point (point)))
201 (list-buffers-noselect Buffer-menu-files-only)
202 (goto-char old-point)))
203
204(defun Buffer-menu-toggle-files-only (arg)
205 "Toggle whether the current buffer-menu displays only file buffers.
206With a positive ARG display only file buffers. With zero or
207negative ARG, display other buffers as well."
208 (interactive "P")
209 (setq Buffer-menu-files-only
210 (cond ((not arg) (not Buffer-menu-files-only))
211 ((> (prefix-numeric-value arg) 0) t)))
212 (revert-buffer))
213
2dd96f23 214\f
2dd96f23
JB
215(defun Buffer-menu-buffer (error-if-non-existent-p)
216 "Return buffer described by this line of buffer menu."
1b40dbed
RS
217 (let* ((where (save-excursion
218 (beginning-of-line)
219 (+ (point) Buffer-menu-buffer-column)))
601ed8a0
GM
220 (name (and (not (eobp)) (get-text-property where 'buffer-name)))
221 (buf (and (not (eobp)) (get-text-property where 'buffer))))
1b40dbed
RS
222 (if name
223 (or (get-buffer name)
601ed8a0 224 (and buf (buffer-name buf) buf)
1b40dbed
RS
225 (if error-if-non-existent-p
226 (error "No buffer named `%s'" name)
227 nil))
601ed8a0 228 (or (and buf (buffer-name buf) buf)
463a7342
JPW
229 (if error-if-non-existent-p
230 (error "No buffer on this line")
601ed8a0 231 nil)))))
2dd96f23 232\f
06b1a5ef 233(defun buffer-menu (&optional arg)
2dd96f23
JB
234 "Make a menu of buffers so you can save, delete or select them.
235With argument, show only buffers that are visiting files.
236Type ? after invocation to get help on commands available.
6a0d92d3
RS
237Type q to remove the buffer menu from the display.
238
239The first column shows `>' for a buffer you have
240marked to be displayed, `D' for one you have marked for
241deletion, and `.' for the current buffer.
242
bc7bb432
JB
243The C column has a `.' for the buffer from which you came.
244The R column has a `%' if the buffer is read-only.
6a0d92d3
RS
245The M column has a `*' if it is modified,
246or `S' if you have marked it for saving.
6a0d92d3
RS
247After this come the buffer name, its size in characters,
248its major mode, and the visited file name (if any)."
08c82d4d
RS
249 (interactive "P")
250;;; (setq Buffer-menu-window-config (current-window-configuration))
251 (switch-to-buffer (list-buffers-noselect arg))
252 (message
253 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
254
255(defun buffer-menu-other-window (&optional arg)
256 "Display a list of buffers in another window.
257With the buffer list buffer, you can save, delete or select the buffers.
258With argument, show only buffers that are visiting files.
259Type ? after invocation to get help on commands available.
6a0d92d3
RS
260Type q to remove the buffer menu from the display.
261For more information, see the function `buffer-menu'."
2dd96f23 262 (interactive "P")
3ed788ec 263;;; (setq Buffer-menu-window-config (current-window-configuration))
08c82d4d 264 (switch-to-buffer-other-window (list-buffers-noselect arg))
2dd96f23 265 (message
3ed788ec
RS
266 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
267
bc7bb432
JB
268(defun Buffer-menu-no-header ()
269 (beginning-of-line)
270 (if (or Buffer-menu-use-header-line
271 (not (eq (char-after) ?C)))
272 t
273 (ding)
274 (forward-line 1)
275 nil))
276
2dd96f23
JB
277(defun Buffer-menu-mark ()
278 "Mark buffer on this line for being displayed by \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command."
279 (interactive)
bc7bb432 280 (when (Buffer-menu-no-header)
2dd96f23
JB
281 (let ((buffer-read-only nil))
282 (delete-char 1)
283 (insert ?>)
284 (forward-line 1))))
285
86dbbfc2
ER
286(defun Buffer-menu-unmark (&optional backup)
287 "Cancel all requested operations on buffer on this line and move down.
288Optional ARG means move up."
289 (interactive "P")
bc7bb432 290 (when (Buffer-menu-no-header)
2dd96f23
JB
291 (let* ((buf (Buffer-menu-buffer t))
292 (mod (buffer-modified-p buf))
293 (readonly (save-excursion (set-buffer buf) buffer-read-only))
294 (buffer-read-only nil))
295 (delete-char 3)
bc7bb432 296 (insert (if readonly (if mod " %*" " % ") (if mod " *" " ")))))
86dbbfc2 297 (forward-line (if backup -1 1)))
2dd96f23
JB
298
299(defun Buffer-menu-backup-unmark ()
300 "Move up and cancel all requested operations on buffer on line above."
301 (interactive)
302 (forward-line -1)
303 (Buffer-menu-unmark)
304 (forward-line -1))
305
77a43e01
RS
306(defun Buffer-menu-delete (&optional arg)
307 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command.
308Prefix arg is how many buffers to delete.
309Negative arg means delete backwards."
310 (interactive "p")
bc7bb432 311 (when (Buffer-menu-no-header)
2dd96f23 312 (let ((buffer-read-only nil))
77a43e01
RS
313 (if (or (null arg) (= arg 0))
314 (setq arg 1))
315 (while (> arg 0)
316 (delete-char 1)
317 (insert ?D)
318 (forward-line 1)
319 (setq arg (1- arg)))
bc7bb432
JB
320 (while (and (< arg 0)
321 (Buffer-menu-no-header))
77a43e01
RS
322 (delete-char 1)
323 (insert ?D)
324 (forward-line -1)
325 (setq arg (1+ arg))))))
326
327(defun Buffer-menu-delete-backwards (&optional arg)
2dd96f23 328 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command
77a43e01
RS
329and then move up one line. Prefix arg means move that many lines."
330 (interactive "p")
bc7bb432 331 (Buffer-menu-delete (- (or arg 1))))
2dd96f23
JB
332
333(defun Buffer-menu-save ()
334 "Mark buffer on this line to be saved by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command."
335 (interactive)
bc7bb432 336 (when (Buffer-menu-no-header)
2dd96f23 337 (let ((buffer-read-only nil))
bc7bb432 338 (forward-char 2)
2dd96f23
JB
339 (delete-char 1)
340 (insert ?S)
341 (forward-line 1))))
342
a8ce00dc 343(defun Buffer-menu-not-modified (&optional arg)
2dd96f23 344 "Mark buffer on this line as unmodified (no changes to save)."
a8ce00dc 345 (interactive "P")
2dd96f23
JB
346 (save-excursion
347 (set-buffer (Buffer-menu-buffer t))
a8ce00dc 348 (set-buffer-modified-p arg))
2dd96f23
JB
349 (save-excursion
350 (beginning-of-line)
bc7bb432
JB
351 (forward-char 2)
352 (if (= (char-after) (if arg ? ?*))
2dd96f23
JB
353 (let ((buffer-read-only nil))
354 (delete-char 1)
a8ce00dc 355 (insert (if arg ?* ? ))))))
2dd96f23
JB
356
357(defun Buffer-menu-execute ()
358 "Save and/or delete buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] or \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
359 (interactive)
360 (save-excursion
361 (goto-char (point-min))
4f1ab860
DL
362 (unless Buffer-menu-use-header-line
363 (forward-line 1))
bc7bb432 364 (while (re-search-forward "^..S" nil t)
2dd96f23
JB
365 (let ((modp nil))
366 (save-excursion
367 (set-buffer (Buffer-menu-buffer t))
368 (save-buffer)
369 (setq modp (buffer-modified-p)))
370 (let ((buffer-read-only nil))
371 (delete-char -1)
372 (insert (if modp ?* ? ))))))
373 (save-excursion
374 (goto-char (point-min))
4f1ab860
DL
375 (unless Buffer-menu-use-header-line
376 (forward-line 1))
2dd96f23
JB
377 (let ((buff-menu-buffer (current-buffer))
378 (buffer-read-only nil))
4f1ab860 379 (while (re-search-forward "^D" nil t)
2dd96f23
JB
380 (forward-char -1)
381 (let ((buf (Buffer-menu-buffer nil)))
382 (or (eq buf nil)
383 (eq buf buff-menu-buffer)
601ed8a0
GM
384 (save-excursion (kill-buffer buf)))
385 (if (and buf (buffer-name buf))
2dd96f23
JB
386 (progn (delete-char 1)
387 (insert ? ))
388 (delete-region (point) (progn (forward-line 1) (point)))
4f1ab860
DL
389 (unless (bobp)
390 (forward-char -1))))))))
2dd96f23
JB
391
392(defun Buffer-menu-select ()
393 "Select this line's buffer; also display buffers marked with `>'.
08c82d4d
RS
394You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command.
395This command deletes and replaces all the previously existing windows
396in the selected frame."
2dd96f23
JB
397 (interactive)
398 (let ((buff (Buffer-menu-buffer t))
10e1dad9 399 (menu (current-buffer))
2dd96f23
JB
400 (others ())
401 tem)
402 (goto-char (point-min))
a9fb4690
AS
403 (unless Buffer-menu-use-header-line
404 (forward-line 1))
405 (while (re-search-forward "^>" nil t)
2dd96f23
JB
406 (setq tem (Buffer-menu-buffer t))
407 (let ((buffer-read-only nil))
408 (delete-char -1)
409 (insert ?\ ))
410 (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
411 (setq others (nreverse others)
dc6d9681 412 tem (/ (1- (frame-height)) (1+ (length others))))
2dd96f23
JB
413 (delete-other-windows)
414 (switch-to-buffer buff)
415 (or (eq menu buff)
416 (bury-buffer menu))
86dbbfc2
ER
417 (if (equal (length others) 0)
418 (progn
3ed788ec
RS
419;;; ;; Restore previous window configuration before displaying
420;;; ;; selected buffers.
421;;; (if Buffer-menu-window-config
422;;; (progn
423;;; (set-window-configuration Buffer-menu-window-config)
424;;; (setq Buffer-menu-window-config nil)))
86dbbfc2
ER
425 (switch-to-buffer buff))
426 (while others
427 (split-window nil tem)
428 (other-window 1)
429 (switch-to-buffer (car others))
430 (setq others (cdr others)))
431 (other-window 1) ;back to the beginning!
432)))
433
08c82d4d 434
2dd96f23
JB
435\f
436(defun Buffer-menu-visit-tags-table ()
437 "Visit the tags table in the buffer on this line. See `visit-tags-table'."
438 (interactive)
439 (let ((file (buffer-file-name (Buffer-menu-buffer t))))
440 (if file
441 (visit-tags-table file)
442 (error "Specified buffer has no file"))))
443
444(defun Buffer-menu-1-window ()
dc6d9681 445 "Select this line's buffer, alone, in full frame."
2dd96f23
JB
446 (interactive)
447 (switch-to-buffer (Buffer-menu-buffer t))
448 (bury-buffer (other-buffer))
449 (delete-other-windows))
450
2cf5fc7e
RS
451(defun Buffer-menu-mouse-select (event)
452 "Select the buffer whose line you click on."
453 (interactive "e")
454 (let (buffer)
455 (save-excursion
456 (set-buffer (window-buffer (posn-window (event-end event))))
457 (save-excursion
458 (goto-char (posn-point (event-end event)))
459 (setq buffer (Buffer-menu-buffer t))))
460 (select-window (posn-window (event-end event)))
d953b88c
RS
461 (if (and (window-dedicated-p (selected-window))
462 (eq (selected-window) (frame-root-window)))
463 (switch-to-buffer-other-frame buffer)
464 (switch-to-buffer buffer))))
2cf5fc7e 465
2dd96f23
JB
466(defun Buffer-menu-this-window ()
467 "Select this line's buffer in this window."
468 (interactive)
469 (switch-to-buffer (Buffer-menu-buffer t)))
470
471(defun Buffer-menu-other-window ()
472 "Select this line's buffer in other window, leaving buffer menu visible."
473 (interactive)
474 (switch-to-buffer-other-window (Buffer-menu-buffer t)))
475
35aaf00c
RM
476(defun Buffer-menu-switch-other-window ()
477 "Make the other window select this line's buffer.
478The current window remains selected."
479 (interactive)
480 (display-buffer (Buffer-menu-buffer t)))
481
2dd96f23
JB
482(defun Buffer-menu-2-window ()
483 "Select this line's buffer, with previous buffer in second window."
484 (interactive)
485 (let ((buff (Buffer-menu-buffer t))
486 (menu (current-buffer))
487 (pop-up-windows t))
86dbbfc2 488 (delete-other-windows)
2dd96f23
JB
489 (switch-to-buffer (other-buffer))
490 (pop-to-buffer buff)
491 (bury-buffer menu)))
c0274f38 492
d91e2b1a 493(defun Buffer-menu-toggle-read-only ()
f450965c 494 "Toggle read-only status of buffer on this line, perhaps via version control."
d91e2b1a
ER
495 (interactive)
496 (let (char)
497 (save-excursion
498 (set-buffer (Buffer-menu-buffer t))
f450965c 499 (vc-toggle-read-only)
d91e2b1a
ER
500 (setq char (if buffer-read-only ?% ? )))
501 (save-excursion
502 (beginning-of-line)
bc7bb432 503 (forward-char 1)
d91e2b1a
ER
504 (if (/= (following-char) char)
505 (let (buffer-read-only)
506 (delete-char 1)
507 (insert char))))))
508
36570c92
RS
509(defun Buffer-menu-bury ()
510 "Bury the buffer listed on this line."
511 (interactive)
bc7bb432 512 (when (Buffer-menu-no-header)
a59faabe
RS
513 (save-excursion
514 (beginning-of-line)
515 (bury-buffer (Buffer-menu-buffer t))
516 (let ((line (buffer-substring (point) (progn (forward-line 1) (point))))
517 (buffer-read-only nil))
518 (delete-region (point) (progn (forward-line -1) (point)))
519 (goto-char (point-max))
520 (insert line))
521 (message "Buried buffer moved to the end"))))
42a19c2a
RS
522
523
524(defun Buffer-menu-view ()
525 "View this line's buffer in View mode."
526 (interactive)
527 (view-buffer (Buffer-menu-buffer t)))
528
529
530(defun Buffer-menu-view-other-window ()
531 "View this line's buffer in View mode in another window."
532 (interactive)
533 (view-buffer-other-window (Buffer-menu-buffer t)))
0b03ce3a
RS
534\f
535
536(define-key ctl-x-map "\C-b" 'list-buffers)
537
538(defun list-buffers (&optional files-only)
539 "Display a list of names of existing buffers.
540The list is displayed in a buffer named `*Buffer List*'.
541Note that buffers with names starting with spaces are omitted.
542Non-null optional arg FILES-ONLY means mention only file buffers.
543
6a0d92d3 544For more information, see the function `buffer-menu'."
0b03ce3a 545 (interactive "P")
08c82d4d
RS
546 (display-buffer (list-buffers-noselect files-only)))
547
bc7bb432
JB
548(defun Buffer-menu-buffer+size (name size &optional name-props size-props)
549 (if (> (+ (length name) (length size) 2) Buffer-menu-buffer+size-width)
550 (setq name
551 (if (string-match "<[0-9]+>$" name)
552 (concat (substring name 0
553 (- Buffer-menu-buffer+size-width
554 (max (length size) 3)
555 (match-end 0)
556 (- (match-beginning 0))
557 2))
558 ":" ; narrow ellipsis
559 (match-string 0 name))
560 (concat (substring name 0
561 (- Buffer-menu-buffer+size-width
562 (max (length size) 3)
563 2))
ee5861c8
AS
564 ":"))) ; narrow ellipsis
565 ;; Don't put properties on (buffer-name).
566 (setq name (copy-sequence name)))
bc7bb432
JB
567 (add-text-properties 0 (length name) name-props name)
568 (add-text-properties 0 (length size) size-props size)
569 (concat name
570 (make-string (- Buffer-menu-buffer+size-width
571 (length name)
572 (length size))
573 ? )
574 size))
575
d5aacb46
SM
576(defun Buffer-menu-sort (column)
577 "Sort the buffer menu by COLUMN."
578 (interactive "P")
579 (when column
580 (setq column (prefix-numeric-value column))
581 (if (< column 2) (setq column 2))
582 (if (> column 5) (setq column 5)))
583 (setq Buffer-menu-sort-column column)
584 (Buffer-menu-revert))
585
586(defun Buffer-menu-make-sort-button (name column)
587 (if (equal column Buffer-menu-sort-column) (setq column nil))
588 (propertize name
589 'help-echo (if column
590 (concat "mouse-2: sort by " (downcase name))
591 "mouse-2: sort by visited order")
592 'mouse-face 'highlight
593 'keymap (let ((map (make-sparse-keymap)))
594 (define-key map [header-line mouse-2]
595 `(lambda () (interactive)
596 (Buffer-menu-sort ,column)))
597 map)))
598
08c82d4d
RS
599(defun list-buffers-noselect (&optional files-only)
600 "Create and return a buffer with a list of names of existing buffers.
601The buffer is named `*Buffer List*'.
602Note that buffers with names starting with spaces are omitted.
603Non-null optional arg FILES-ONLY means mention only file buffers.
604
6a0d92d3 605For more information, see the function `buffer-menu'."
bc7bb432
JB
606 (let* ((old-buffer (current-buffer))
607 (standard-output standard-output)
608 (mode-end (make-string (- Buffer-menu-mode-width 2) ? ))
d5aacb46
SM
609 (header (concat " " (propertize "CRM " 'face 'fixed-pitch)
610 (Buffer-menu-buffer+size
611 (Buffer-menu-make-sort-button "Buffer" 2)
612 (Buffer-menu-make-sort-button "Size" 3))
613 " "
614 (Buffer-menu-make-sort-button "Mode" 4) mode-end
615 (Buffer-menu-make-sort-button "File" 5) "\n"))
b6fdd1ef 616 list desired-point name mode file)
748a336b 617 (when Buffer-menu-use-header-line
d5aacb46 618 (let ((pos 0))
748a336b
SM
619 ;; Turn spaces in the header into stretch specs so they work
620 ;; regardless of the header-line face.
621 (while (string-match "[ \t]+" header pos)
622 (setq pos (match-end 0))
623 (put-text-property (match-beginning 0) pos 'display
624 ;; Assume fixed-size chars
d5aacb46 625 (list 'space :align-to (1- pos))
748a336b 626 header))))
d5aacb46 627 (with-current-buffer (get-buffer-create "*Buffer List*")
08c82d4d
RS
628 (setq buffer-read-only nil)
629 (erase-buffer)
630 (setq standard-output (current-buffer))
bc7bb432 631 (unless Buffer-menu-use-header-line
638df3f7
RS
632 (insert header (propertize "---" 'face 'fixed-pitch) " ")
633 (insert (Buffer-menu-buffer+size "------" "----"))
634 (insert " ----" mode-end "----\n")
bc7bb432
JB
635 (put-text-property 1 (point) 'intangible t))
636 (setq list
637 (delq t
638 (mapcar
639 (lambda (buffer)
640 (with-current-buffer buffer
e8e8c0c7
RS
641 (setq name (buffer-name)
642 mode (concat (format-mode-line mode-name nil nil buffer)
643 (if mode-line-process
644 (format-mode-line mode-line-process nil nil buffer)))
645 file (buffer-file-name))
bc7bb432
JB
646 (cond
647 ;; Don't mention internal buffers.
648 ((and (string= (substring name 0 1) " ") (null file)))
649 ;; Maybe don't mention buffers without files.
650 ((and files-only (not file)))
651 ((string= name "*Buffer List*"))
652 ;; Otherwise output info.
653 (t
654 (unless file
655 ;; No visited file. Check local value of
656 ;; list-buffers-directory.
657 (when (and (boundp 'list-buffers-directory)
658 list-buffers-directory)
659 (setq file list-buffers-directory)))
660 (list buffer
661 (format "%c%c%c "
662 (if (eq buffer old-buffer) ?. ? )
663 ;; Handle readonly status. The output buffer is special
664 ;; cased to appear readonly; it is actually made so at a
665 ;; later date.
666 (if (or (eq buffer standard-output)
667 buffer-read-only)
668 ?% ? )
669 ;; Identify modified buffers.
670 (if (buffer-modified-p) ?* ? ))
b6fdd1ef 671 name (buffer-size) mode file)))))
bc7bb432
JB
672 (buffer-list))))
673 (dolist (buffer
674 (if Buffer-menu-sort-column
675 (sort list
676 (if (eq Buffer-menu-sort-column 3)
677 (lambda (a b)
678 (< (nth Buffer-menu-sort-column a)
679 (nth Buffer-menu-sort-column b)))
680 (lambda (a b)
681 (string< (nth Buffer-menu-sort-column a)
682 (nth Buffer-menu-sort-column b)))))
683 list))
684 (if (eq (car buffer) old-buffer)
685 (setq desired-point (point)))
686 (insert (cadr buffer)
687 ;; Put the buffer name into a text property
688 ;; so we don't have to extract it from the text.
689 ;; This way we avoid problems with unusual buffer names.
690 (Buffer-menu-buffer+size (nth 2 buffer)
691 (int-to-string (nth 3 buffer))
692 `(buffer-name ,(nth 2 buffer)
693 buffer ,(car buffer)
694 face Buffer-menu-buffer-face
695 mouse-face highlight
696 help-echo "mouse-2: select this buffer"))
697 " "
698 (if (> (length (nth 4 buffer)) Buffer-menu-mode-width)
699 (substring (nth 4 buffer) 0 Buffer-menu-mode-width)
700 (nth 4 buffer)))
701 (when (nth 5 buffer)
702 (indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-width
703 Buffer-menu-mode-width 4) 1)
704 (princ (abbreviate-file-name (nth 5 buffer))))
705 (princ "\n"))
0b03ce3a 706 (Buffer-menu-mode)
bc7bb432 707 (when Buffer-menu-use-header-line
748a336b 708 (setq header-line-format header))
08c82d4d
RS
709 ;; DESIRED-POINT doesn't have to be set; it is not when the
710 ;; current buffer is not displayed for some reason.
0b03ce3a 711 (and desired-point
08c82d4d 712 (goto-char desired-point))
7b0a86ab
LT
713 (setq Buffer-menu-files-only files-only)
714 (set-buffer-modified-p nil)
08c82d4d 715 (current-buffer))))
0b03ce3a 716
ab5796a9 717;;; arch-tag: e7dfcfc9-6cb2-46e4-bf55-8ef1936d83c6
c0274f38 718;;; buff-menu.el ends here