(cvs-tree-use-jisx0208): Use char-displayable-p.
[bpt/emacs.git] / lisp / buff-menu.el
CommitLineData
55535639 1;;; buff-menu.el --- buffer menu main function and support functions
c0274f38 2
ee5861c8 3;; Copyright (C) 1985, 86, 87, 93, 94, 95, 2000, 2001, 2002, 2003
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
08c82d4d
RS
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.
57
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.
60
3ed788ec
RS
61;;;(defvar Buffer-menu-window-config nil
62;;; "Window configuration saved from entry to `buffer-menu'.")
2dd96f23
JB
63
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.
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
92; This should get updated & resorted when you click on a column heading
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
JB
101
102(if Buffer-menu-mode-map
103 ()
104 (setq Buffer-menu-mode-map (make-keymap))
105 (suppress-keymap Buffer-menu-mode-map t)
68e6f094 106 (define-key Buffer-menu-mode-map "q" 'quit-window)
3ed788ec 107 (define-key Buffer-menu-mode-map "v" 'Buffer-menu-select)
2dd96f23
JB
108 (define-key Buffer-menu-mode-map "2" 'Buffer-menu-2-window)
109 (define-key Buffer-menu-mode-map "1" 'Buffer-menu-1-window)
110 (define-key Buffer-menu-mode-map "f" 'Buffer-menu-this-window)
251680cf 111 (define-key Buffer-menu-mode-map "e" 'Buffer-menu-this-window)
8768da77 112 (define-key Buffer-menu-mode-map "\C-m" 'Buffer-menu-this-window)
2dd96f23 113 (define-key Buffer-menu-mode-map "o" 'Buffer-menu-other-window)
35aaf00c 114 (define-key Buffer-menu-mode-map "\C-o" 'Buffer-menu-switch-other-window)
2dd96f23
JB
115 (define-key Buffer-menu-mode-map "s" 'Buffer-menu-save)
116 (define-key Buffer-menu-mode-map "d" 'Buffer-menu-delete)
117 (define-key Buffer-menu-mode-map "k" 'Buffer-menu-delete)
118 (define-key Buffer-menu-mode-map "\C-d" 'Buffer-menu-delete-backwards)
119 (define-key Buffer-menu-mode-map "\C-k" 'Buffer-menu-delete)
120 (define-key Buffer-menu-mode-map "x" 'Buffer-menu-execute)
121 (define-key Buffer-menu-mode-map " " 'next-line)
122 (define-key Buffer-menu-mode-map "n" 'next-line)
123 (define-key Buffer-menu-mode-map "p" 'previous-line)
124 (define-key Buffer-menu-mode-map "\177" 'Buffer-menu-backup-unmark)
125 (define-key Buffer-menu-mode-map "~" 'Buffer-menu-not-modified)
126 (define-key Buffer-menu-mode-map "?" 'describe-mode)
127 (define-key Buffer-menu-mode-map "u" 'Buffer-menu-unmark)
128 (define-key Buffer-menu-mode-map "m" 'Buffer-menu-mark)
d91e2b1a
ER
129 (define-key Buffer-menu-mode-map "t" 'Buffer-menu-visit-tags-table)
130 (define-key Buffer-menu-mode-map "%" 'Buffer-menu-toggle-read-only)
36570c92 131 (define-key Buffer-menu-mode-map "b" 'Buffer-menu-bury)
0f88624e 132 (define-key Buffer-menu-mode-map "g" 'Buffer-menu-revert)
42a19c2a 133 (define-key Buffer-menu-mode-map "V" 'Buffer-menu-view)
2cf5fc7e 134 (define-key Buffer-menu-mode-map [mouse-2] 'Buffer-menu-mouse-select)
d91e2b1a 135)
2dd96f23
JB
136
137;; Buffer Menu mode is suitable only for specially formatted data.
138(put 'Buffer-menu-mode 'mode-class 'special)
139
140(defun Buffer-menu-mode ()
141 "Major mode for editing a list of buffers.
142Each line describes one of the buffers in Emacs.
143Letters do not insert themselves; instead, they are commands.
144\\<Buffer-menu-mode-map>
2cf5fc7e
RS
145\\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu.
146\\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu.
147\\[Buffer-menu-other-window] -- select that buffer in another window,
148 so the buffer menu buffer remains visible in its window.
42a19c2a
RS
149\\[Buffer-menu-view] -- select current line's buffer, but in view-mode.
150\\[Buffer-menu-view-other-window] -- select that buffer in
151 another window, in view-mode.
2cf5fc7e
RS
152\\[Buffer-menu-switch-other-window] -- make another window display that buffer.
153\\[Buffer-menu-mark] -- mark current line's buffer to be displayed.
154\\[Buffer-menu-select] -- select current line's buffer.
155 Also show buffers marked with m, in other windows.
dc6d9681 156\\[Buffer-menu-1-window] -- select that buffer in full-frame window.
2dd96f23
JB
157\\[Buffer-menu-2-window] -- select that buffer in one window,
158 together with buffer selected before this one in another window.
2dd96f23
JB
159\\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer.
160\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
161\\[Buffer-menu-save] -- mark that buffer to be saved, and move down.
162\\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down.
163\\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up.
164\\[Buffer-menu-execute] -- delete or save marked buffers.
165\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
86dbbfc2 166 With prefix argument, also move up one line.
d91e2b1a 167\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
0f88624e 168\\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line.
a59faabe
RS
169\\[Buffer-menu-revert] -- update the list of buffers.
170\\[Buffer-menu-bury] -- bury the buffer listed on this line."
2dd96f23
JB
171 (kill-all-local-variables)
172 (use-local-map Buffer-menu-mode-map)
2dd96f23
JB
173 (setq major-mode 'Buffer-menu-mode)
174 (setq mode-name "Buffer Menu")
710e5da8
RS
175 (make-local-variable 'revert-buffer-function)
176 (setq revert-buffer-function 'Buffer-menu-revert-function)
823316aa
KH
177 (setq truncate-lines t)
178 (setq buffer-read-only t)
2dd96f23 179 (run-hooks 'buffer-menu-mode-hook))
710e5da8 180
0f88624e
RS
181(defun Buffer-menu-revert ()
182 "Update the list of buffers."
183 (interactive)
184 (revert-buffer))
185
710e5da8
RS
186(defun Buffer-menu-revert-function (ignore1 ignore2)
187 (list-buffers))
2dd96f23 188\f
2dd96f23
JB
189(defun Buffer-menu-buffer (error-if-non-existent-p)
190 "Return buffer described by this line of buffer menu."
1b40dbed
RS
191 (let* ((where (save-excursion
192 (beginning-of-line)
193 (+ (point) Buffer-menu-buffer-column)))
601ed8a0
GM
194 (name (and (not (eobp)) (get-text-property where 'buffer-name)))
195 (buf (and (not (eobp)) (get-text-property where 'buffer))))
1b40dbed
RS
196 (if name
197 (or (get-buffer name)
601ed8a0 198 (and buf (buffer-name buf) buf)
1b40dbed
RS
199 (if error-if-non-existent-p
200 (error "No buffer named `%s'" name)
201 nil))
601ed8a0 202 (or (and buf (buffer-name buf) buf)
463a7342
JPW
203 (if error-if-non-existent-p
204 (error "No buffer on this line")
601ed8a0 205 nil)))))
2dd96f23 206\f
06b1a5ef 207(defun buffer-menu (&optional arg)
2dd96f23
JB
208 "Make a menu of buffers so you can save, delete or select them.
209With argument, show only buffers that are visiting files.
210Type ? after invocation to get help on commands available.
6a0d92d3
RS
211Type q to remove the buffer menu from the display.
212
213The first column shows `>' for a buffer you have
214marked to be displayed, `D' for one you have marked for
215deletion, and `.' for the current buffer.
216
bc7bb432
JB
217The C column has a `.' for the buffer from which you came.
218The R column has a `%' if the buffer is read-only.
6a0d92d3
RS
219The M column has a `*' if it is modified,
220or `S' if you have marked it for saving.
6a0d92d3
RS
221After this come the buffer name, its size in characters,
222its major mode, and the visited file name (if any)."
08c82d4d
RS
223 (interactive "P")
224;;; (setq Buffer-menu-window-config (current-window-configuration))
225 (switch-to-buffer (list-buffers-noselect arg))
226 (message
227 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
228
229(defun buffer-menu-other-window (&optional arg)
230 "Display a list of buffers in another window.
231With the buffer list buffer, you can save, delete or select the buffers.
232With argument, show only buffers that are visiting files.
233Type ? after invocation to get help on commands available.
6a0d92d3
RS
234Type q to remove the buffer menu from the display.
235For more information, see the function `buffer-menu'."
2dd96f23 236 (interactive "P")
3ed788ec 237;;; (setq Buffer-menu-window-config (current-window-configuration))
08c82d4d 238 (switch-to-buffer-other-window (list-buffers-noselect arg))
2dd96f23 239 (message
3ed788ec
RS
240 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
241
bc7bb432
JB
242(defun Buffer-menu-no-header ()
243 (beginning-of-line)
244 (if (or Buffer-menu-use-header-line
245 (not (eq (char-after) ?C)))
246 t
247 (ding)
248 (forward-line 1)
249 nil))
250
2dd96f23
JB
251(defun Buffer-menu-mark ()
252 "Mark buffer on this line for being displayed by \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command."
253 (interactive)
bc7bb432 254 (when (Buffer-menu-no-header)
2dd96f23
JB
255 (let ((buffer-read-only nil))
256 (delete-char 1)
257 (insert ?>)
258 (forward-line 1))))
259
86dbbfc2
ER
260(defun Buffer-menu-unmark (&optional backup)
261 "Cancel all requested operations on buffer on this line and move down.
262Optional ARG means move up."
263 (interactive "P")
bc7bb432 264 (when (Buffer-menu-no-header)
2dd96f23
JB
265 (let* ((buf (Buffer-menu-buffer t))
266 (mod (buffer-modified-p buf))
267 (readonly (save-excursion (set-buffer buf) buffer-read-only))
268 (buffer-read-only nil))
269 (delete-char 3)
bc7bb432 270 (insert (if readonly (if mod " %*" " % ") (if mod " *" " ")))))
86dbbfc2 271 (forward-line (if backup -1 1)))
2dd96f23
JB
272
273(defun Buffer-menu-backup-unmark ()
274 "Move up and cancel all requested operations on buffer on line above."
275 (interactive)
276 (forward-line -1)
277 (Buffer-menu-unmark)
278 (forward-line -1))
279
77a43e01
RS
280(defun Buffer-menu-delete (&optional arg)
281 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command.
282Prefix arg is how many buffers to delete.
283Negative arg means delete backwards."
284 (interactive "p")
bc7bb432 285 (when (Buffer-menu-no-header)
2dd96f23 286 (let ((buffer-read-only nil))
77a43e01
RS
287 (if (or (null arg) (= arg 0))
288 (setq arg 1))
289 (while (> arg 0)
290 (delete-char 1)
291 (insert ?D)
292 (forward-line 1)
293 (setq arg (1- arg)))
bc7bb432
JB
294 (while (and (< arg 0)
295 (Buffer-menu-no-header))
77a43e01
RS
296 (delete-char 1)
297 (insert ?D)
298 (forward-line -1)
299 (setq arg (1+ arg))))))
300
301(defun Buffer-menu-delete-backwards (&optional arg)
2dd96f23 302 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command
77a43e01
RS
303and then move up one line. Prefix arg means move that many lines."
304 (interactive "p")
bc7bb432 305 (Buffer-menu-delete (- (or arg 1))))
2dd96f23
JB
306
307(defun Buffer-menu-save ()
308 "Mark buffer on this line to be saved by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command."
309 (interactive)
bc7bb432 310 (when (Buffer-menu-no-header)
2dd96f23 311 (let ((buffer-read-only nil))
bc7bb432 312 (forward-char 2)
2dd96f23
JB
313 (delete-char 1)
314 (insert ?S)
315 (forward-line 1))))
316
a8ce00dc 317(defun Buffer-menu-not-modified (&optional arg)
2dd96f23 318 "Mark buffer on this line as unmodified (no changes to save)."
a8ce00dc 319 (interactive "P")
2dd96f23
JB
320 (save-excursion
321 (set-buffer (Buffer-menu-buffer t))
a8ce00dc 322 (set-buffer-modified-p arg))
2dd96f23
JB
323 (save-excursion
324 (beginning-of-line)
bc7bb432
JB
325 (forward-char 2)
326 (if (= (char-after) (if arg ? ?*))
2dd96f23
JB
327 (let ((buffer-read-only nil))
328 (delete-char 1)
a8ce00dc 329 (insert (if arg ?* ? ))))))
2dd96f23
JB
330
331(defun Buffer-menu-execute ()
332 "Save and/or delete buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] or \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
333 (interactive)
334 (save-excursion
335 (goto-char (point-min))
4f1ab860
DL
336 (unless Buffer-menu-use-header-line
337 (forward-line 1))
bc7bb432 338 (while (re-search-forward "^..S" nil t)
2dd96f23
JB
339 (let ((modp nil))
340 (save-excursion
341 (set-buffer (Buffer-menu-buffer t))
342 (save-buffer)
343 (setq modp (buffer-modified-p)))
344 (let ((buffer-read-only nil))
345 (delete-char -1)
346 (insert (if modp ?* ? ))))))
347 (save-excursion
348 (goto-char (point-min))
4f1ab860
DL
349 (unless Buffer-menu-use-header-line
350 (forward-line 1))
2dd96f23
JB
351 (let ((buff-menu-buffer (current-buffer))
352 (buffer-read-only nil))
4f1ab860 353 (while (re-search-forward "^D" nil t)
2dd96f23
JB
354 (forward-char -1)
355 (let ((buf (Buffer-menu-buffer nil)))
356 (or (eq buf nil)
357 (eq buf buff-menu-buffer)
601ed8a0
GM
358 (save-excursion (kill-buffer buf)))
359 (if (and buf (buffer-name buf))
2dd96f23
JB
360 (progn (delete-char 1)
361 (insert ? ))
362 (delete-region (point) (progn (forward-line 1) (point)))
4f1ab860
DL
363 (unless (bobp)
364 (forward-char -1))))))))
2dd96f23
JB
365
366(defun Buffer-menu-select ()
367 "Select this line's buffer; also display buffers marked with `>'.
08c82d4d
RS
368You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command.
369This command deletes and replaces all the previously existing windows
370in the selected frame."
2dd96f23
JB
371 (interactive)
372 (let ((buff (Buffer-menu-buffer t))
10e1dad9 373 (menu (current-buffer))
2dd96f23
JB
374 (others ())
375 tem)
376 (goto-char (point-min))
a9fb4690
AS
377 (unless Buffer-menu-use-header-line
378 (forward-line 1))
379 (while (re-search-forward "^>" nil t)
2dd96f23
JB
380 (setq tem (Buffer-menu-buffer t))
381 (let ((buffer-read-only nil))
382 (delete-char -1)
383 (insert ?\ ))
384 (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
385 (setq others (nreverse others)
dc6d9681 386 tem (/ (1- (frame-height)) (1+ (length others))))
2dd96f23
JB
387 (delete-other-windows)
388 (switch-to-buffer buff)
389 (or (eq menu buff)
390 (bury-buffer menu))
86dbbfc2
ER
391 (if (equal (length others) 0)
392 (progn
3ed788ec
RS
393;;; ;; Restore previous window configuration before displaying
394;;; ;; selected buffers.
395;;; (if Buffer-menu-window-config
396;;; (progn
397;;; (set-window-configuration Buffer-menu-window-config)
398;;; (setq Buffer-menu-window-config nil)))
86dbbfc2
ER
399 (switch-to-buffer buff))
400 (while others
401 (split-window nil tem)
402 (other-window 1)
403 (switch-to-buffer (car others))
404 (setq others (cdr others)))
405 (other-window 1) ;back to the beginning!
406)))
407
08c82d4d 408
2dd96f23
JB
409\f
410(defun Buffer-menu-visit-tags-table ()
411 "Visit the tags table in the buffer on this line. See `visit-tags-table'."
412 (interactive)
413 (let ((file (buffer-file-name (Buffer-menu-buffer t))))
414 (if file
415 (visit-tags-table file)
416 (error "Specified buffer has no file"))))
417
418(defun Buffer-menu-1-window ()
dc6d9681 419 "Select this line's buffer, alone, in full frame."
2dd96f23
JB
420 (interactive)
421 (switch-to-buffer (Buffer-menu-buffer t))
422 (bury-buffer (other-buffer))
423 (delete-other-windows))
424
2cf5fc7e
RS
425(defun Buffer-menu-mouse-select (event)
426 "Select the buffer whose line you click on."
427 (interactive "e")
428 (let (buffer)
429 (save-excursion
430 (set-buffer (window-buffer (posn-window (event-end event))))
431 (save-excursion
432 (goto-char (posn-point (event-end event)))
433 (setq buffer (Buffer-menu-buffer t))))
434 (select-window (posn-window (event-end event)))
d953b88c
RS
435 (if (and (window-dedicated-p (selected-window))
436 (eq (selected-window) (frame-root-window)))
437 (switch-to-buffer-other-frame buffer)
438 (switch-to-buffer buffer))))
2cf5fc7e 439
2dd96f23
JB
440(defun Buffer-menu-this-window ()
441 "Select this line's buffer in this window."
442 (interactive)
443 (switch-to-buffer (Buffer-menu-buffer t)))
444
445(defun Buffer-menu-other-window ()
446 "Select this line's buffer in other window, leaving buffer menu visible."
447 (interactive)
448 (switch-to-buffer-other-window (Buffer-menu-buffer t)))
449
35aaf00c
RM
450(defun Buffer-menu-switch-other-window ()
451 "Make the other window select this line's buffer.
452The current window remains selected."
453 (interactive)
454 (display-buffer (Buffer-menu-buffer t)))
455
2dd96f23
JB
456(defun Buffer-menu-2-window ()
457 "Select this line's buffer, with previous buffer in second window."
458 (interactive)
459 (let ((buff (Buffer-menu-buffer t))
460 (menu (current-buffer))
461 (pop-up-windows t))
86dbbfc2 462 (delete-other-windows)
2dd96f23
JB
463 (switch-to-buffer (other-buffer))
464 (pop-to-buffer buff)
465 (bury-buffer menu)))
c0274f38 466
d91e2b1a 467(defun Buffer-menu-toggle-read-only ()
f450965c 468 "Toggle read-only status of buffer on this line, perhaps via version control."
d91e2b1a
ER
469 (interactive)
470 (let (char)
471 (save-excursion
472 (set-buffer (Buffer-menu-buffer t))
f450965c 473 (vc-toggle-read-only)
d91e2b1a
ER
474 (setq char (if buffer-read-only ?% ? )))
475 (save-excursion
476 (beginning-of-line)
bc7bb432 477 (forward-char 1)
d91e2b1a
ER
478 (if (/= (following-char) char)
479 (let (buffer-read-only)
480 (delete-char 1)
481 (insert char))))))
482
36570c92
RS
483(defun Buffer-menu-bury ()
484 "Bury the buffer listed on this line."
485 (interactive)
bc7bb432 486 (when (Buffer-menu-no-header)
a59faabe
RS
487 (save-excursion
488 (beginning-of-line)
489 (bury-buffer (Buffer-menu-buffer t))
490 (let ((line (buffer-substring (point) (progn (forward-line 1) (point))))
491 (buffer-read-only nil))
492 (delete-region (point) (progn (forward-line -1) (point)))
493 (goto-char (point-max))
494 (insert line))
495 (message "Buried buffer moved to the end"))))
42a19c2a
RS
496
497
498(defun Buffer-menu-view ()
499 "View this line's buffer in View mode."
500 (interactive)
501 (view-buffer (Buffer-menu-buffer t)))
502
503
504(defun Buffer-menu-view-other-window ()
505 "View this line's buffer in View mode in another window."
506 (interactive)
507 (view-buffer-other-window (Buffer-menu-buffer t)))
0b03ce3a
RS
508\f
509
510(define-key ctl-x-map "\C-b" 'list-buffers)
511
512(defun list-buffers (&optional files-only)
513 "Display a list of names of existing buffers.
514The list is displayed in a buffer named `*Buffer List*'.
515Note that buffers with names starting with spaces are omitted.
516Non-null optional arg FILES-ONLY means mention only file buffers.
517
6a0d92d3 518For more information, see the function `buffer-menu'."
0b03ce3a 519 (interactive "P")
08c82d4d
RS
520 (display-buffer (list-buffers-noselect files-only)))
521
bc7bb432
JB
522(defun Buffer-menu-buffer+size (name size &optional name-props size-props)
523 (if (> (+ (length name) (length size) 2) Buffer-menu-buffer+size-width)
524 (setq name
525 (if (string-match "<[0-9]+>$" name)
526 (concat (substring name 0
527 (- Buffer-menu-buffer+size-width
528 (max (length size) 3)
529 (match-end 0)
530 (- (match-beginning 0))
531 2))
532 ":" ; narrow ellipsis
533 (match-string 0 name))
534 (concat (substring name 0
535 (- Buffer-menu-buffer+size-width
536 (max (length size) 3)
537 2))
ee5861c8
AS
538 ":"))) ; narrow ellipsis
539 ;; Don't put properties on (buffer-name).
540 (setq name (copy-sequence name)))
bc7bb432
JB
541 (add-text-properties 0 (length name) name-props name)
542 (add-text-properties 0 (length size) size-props size)
543 (concat name
544 (make-string (- Buffer-menu-buffer+size-width
545 (length name)
546 (length size))
547 ? )
548 size))
549
08c82d4d
RS
550(defun list-buffers-noselect (&optional files-only)
551 "Create and return a buffer with a list of names of existing buffers.
552The buffer is named `*Buffer List*'.
553Note that buffers with names starting with spaces are omitted.
554Non-null optional arg FILES-ONLY means mention only file buffers.
555
6a0d92d3 556For more information, see the function `buffer-menu'."
bc7bb432
JB
557 (let* ((old-buffer (current-buffer))
558 (standard-output standard-output)
559 (mode-end (make-string (- Buffer-menu-mode-width 2) ? ))
748a336b
SM
560 (header (concat (propertize "CRM " 'face 'fixed-pitch)
561 (Buffer-menu-buffer+size "Buffer" "Size")
bc7bb432
JB
562 " Mode" mode-end "File\n"))
563 list desired-point name file mode)
748a336b
SM
564 (when Buffer-menu-use-header-line
565 (let ((spaces
638df3f7
RS
566 (- (car (window-inside-edges))
567 (car (window-edges))))
748a336b
SM
568 (pos 0))
569 ;; Turn spaces in the header into stretch specs so they work
570 ;; regardless of the header-line face.
571 (while (string-match "[ \t]+" header pos)
572 (setq pos (match-end 0))
573 (put-text-property (match-beginning 0) pos 'display
574 ;; Assume fixed-size chars
575 (list 'space :align-to (+ spaces pos))
576 header))
577 ;; Add the leading space
578 (setq header (concat (propertize (make-string (floor spaces) ? )
579 'display (list 'space :width spaces))
580 header))))
08c82d4d
RS
581 (save-excursion
582 (set-buffer (get-buffer-create "*Buffer List*"))
583 (setq buffer-read-only nil)
584 (erase-buffer)
585 (setq standard-output (current-buffer))
bc7bb432 586 (unless Buffer-menu-use-header-line
638df3f7
RS
587 (insert header (propertize "---" 'face 'fixed-pitch) " ")
588 (insert (Buffer-menu-buffer+size "------" "----"))
589 (insert " ----" mode-end "----\n")
bc7bb432
JB
590 (put-text-property 1 (point) 'intangible t))
591 (setq list
592 (delq t
593 (mapcar
594 (lambda (buffer)
595 (with-current-buffer buffer
596 (setq name (buffer-name)
597 file (buffer-file-name))
598 (cond
599 ;; Don't mention internal buffers.
600 ((and (string= (substring name 0 1) " ") (null file)))
601 ;; Maybe don't mention buffers without files.
602 ((and files-only (not file)))
603 ((string= name "*Buffer List*"))
604 ;; Otherwise output info.
605 (t
606 (unless file
607 ;; No visited file. Check local value of
608 ;; list-buffers-directory.
609 (when (and (boundp 'list-buffers-directory)
610 list-buffers-directory)
611 (setq file list-buffers-directory)))
612 (list buffer
613 (format "%c%c%c "
614 (if (eq buffer old-buffer) ?. ? )
615 ;; Handle readonly status. The output buffer is special
616 ;; cased to appear readonly; it is actually made so at a
617 ;; later date.
618 (if (or (eq buffer standard-output)
619 buffer-read-only)
620 ?% ? )
621 ;; Identify modified buffers.
622 (if (buffer-modified-p) ?* ? ))
623 name (buffer-size) mode-name file)))))
624 (buffer-list))))
625 (dolist (buffer
626 (if Buffer-menu-sort-column
627 (sort list
628 (if (eq Buffer-menu-sort-column 3)
629 (lambda (a b)
630 (< (nth Buffer-menu-sort-column a)
631 (nth Buffer-menu-sort-column b)))
632 (lambda (a b)
633 (string< (nth Buffer-menu-sort-column a)
634 (nth Buffer-menu-sort-column b)))))
635 list))
636 (if (eq (car buffer) old-buffer)
637 (setq desired-point (point)))
638 (insert (cadr buffer)
639 ;; Put the buffer name into a text property
640 ;; so we don't have to extract it from the text.
641 ;; This way we avoid problems with unusual buffer names.
642 (Buffer-menu-buffer+size (nth 2 buffer)
643 (int-to-string (nth 3 buffer))
644 `(buffer-name ,(nth 2 buffer)
645 buffer ,(car buffer)
646 face Buffer-menu-buffer-face
647 mouse-face highlight
648 help-echo "mouse-2: select this buffer"))
649 " "
650 (if (> (length (nth 4 buffer)) Buffer-menu-mode-width)
651 (substring (nth 4 buffer) 0 Buffer-menu-mode-width)
652 (nth 4 buffer)))
653 (when (nth 5 buffer)
654 (indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-width
655 Buffer-menu-mode-width 4) 1)
656 (princ (abbreviate-file-name (nth 5 buffer))))
657 (princ "\n"))
0b03ce3a 658 (Buffer-menu-mode)
bc7bb432 659 (when Buffer-menu-use-header-line
748a336b 660 (setq header-line-format header))
08c82d4d
RS
661 ;; DESIRED-POINT doesn't have to be set; it is not when the
662 ;; current buffer is not displayed for some reason.
0b03ce3a 663 (and desired-point
08c82d4d
RS
664 (goto-char desired-point))
665 (current-buffer))))
0b03ce3a 666
ab5796a9 667;;; arch-tag: e7dfcfc9-6cb2-46e4-bf55-8ef1936d83c6
c0274f38 668;;; buff-menu.el ends here