aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2012-05-07 00:45:46 +0800
committerChong Yidong2012-05-07 00:45:46 +0800
commite5f9458fe818fd87ec99354420c3633ca928d62c (patch)
tree33f89a7828b6f63d629871f9b45f05533c0f436c
parente129292c44b6392adadb27bbd4bce94893316ff9 (diff)
downloademacs-e5f9458fe818fd87ec99354420c3633ca928d62c.tar.gz
emacs-e5f9458fe818fd87ec99354420c3633ca928d62c.zip
* lisp/buff-menu.el: Convert to Tabulated List mode.
(Buffer-menu-buffer+size-width): Make obsolete. (Buffer-menu-name-width, Buffer-menu-size-width): New variables. (Buffer-menu-mode-map): Inherit from tabulated-list-mode-map. (Buffer-menu-mode): Derive from tabulated-list-mode. Move command documentation into docstring of buffer-menu. (Buffer-menu-toggle-files-only): Add an informative message. (Buffer-menu-sort): Convert to alias for tabulated-list-sort. (Buffer-menu-buffer, Buffer-menu-beginning, Buffer-menu-mark) (Buffer-menu-unmark, Buffer-menu-backup-unmark) (Buffer-menu-delete, Buffer-menu-save, Buffer-menu-not-modified) (Buffer-menu-execute, Buffer-menu-select) (Buffer-menu-marked-buffers, Buffer-menu-toggle-read-only) (Buffer-menu-bury): Use Tabulated List machinery. (Buffer-menu-mouse-select, Buffer-menu-sort-by-column) (Buffer-menu-sort-button-map, Buffer-menu-make-sort-button): Deleted. (list-buffers--refresh): New function. (list-buffers-noselect): Use it. (tabulated-list-entry-size->, Buffer-menu--pretty-name) (Buffer-menu--pretty-file-name): New helper functions. * lisp/loadup.el: Preload tabulated-list. * lisp/emacs-lisp/tabulated-list.el (tabulated-list-sort): Rename from tabulated-list-sort-column. (tabulated-list-init-header): Add the initial aligning space even if tabulated-list-padding is zero. * src/lisp.mk (lisp): Update.
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/ChangeLog31
-rw-r--r--lisp/buff-menu.el966
-rw-r--r--lisp/emacs-lisp/cl-loaddefs.el2
-rw-r--r--lisp/emacs-lisp/tabulated-list.el11
-rw-r--r--lisp/loadup.el1
-rw-r--r--src/ChangeLog4
-rw-r--r--src/lisp.mk1
8 files changed, 373 insertions, 645 deletions
diff --git a/etc/NEWS b/etc/NEWS
index df386fa7e4f..6b59601fd81 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -163,7 +163,7 @@ server properties.
163 163
164** Tabulated List and packages derived from it 164** Tabulated List and packages derived from it
165 165
166*** New command `tabulated-list-sort-column' bound to `S' sorts column 166*** New command `tabulated-list-sort', bound to `S', sorts the column
167at point, or the Nth column if a numeric prefix argument is given. 167at point, or the Nth column if a numeric prefix argument is given.
168 168
169** Obsolete packages: 169** Obsolete packages:
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index afa4ae803f9..149c43fc9a7 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,34 @@
12012-05-06 Chong Yidong <cyd@gnu.org>
2
3 * buff-menu.el: Convert to Tabulated List mode.
4 (Buffer-menu-buffer+size-width): Make obsolete.
5 (Buffer-menu-name-width, Buffer-menu-size-width): New variables.
6 (Buffer-menu-mode-map): Inherit from tabulated-list-mode-map.
7 (Buffer-menu-mode): Derive from tabulated-list-mode. Move command
8 documentation into docstring of buffer-menu.
9 (Buffer-menu-toggle-files-only): Add an informative message.
10 (Buffer-menu-sort): Convert to alias for tabulated-list-sort.
11 (Buffer-menu-buffer, Buffer-menu-beginning, Buffer-menu-mark)
12 (Buffer-menu-unmark, Buffer-menu-backup-unmark)
13 (Buffer-menu-delete, Buffer-menu-save, Buffer-menu-not-modified)
14 (Buffer-menu-execute, Buffer-menu-select)
15 (Buffer-menu-marked-buffers, Buffer-menu-toggle-read-only)
16 (Buffer-menu-bury): Use Tabulated List machinery.
17 (Buffer-menu-mouse-select, Buffer-menu-sort-by-column)
18 (Buffer-menu-sort-button-map, Buffer-menu-make-sort-button):
19 Deleted.
20 (list-buffers--refresh): New function.
21 (list-buffers-noselect): Use it.
22 (tabulated-list-entry-size->, Buffer-menu--pretty-name)
23 (Buffer-menu--pretty-file-name): New helper functions.
24
25 * loadup.el: Preload tabulated-list.
26
27 * emacs-lisp/tabulated-list.el (tabulated-list-sort): Rename from
28 tabulated-list-sort-column.
29 (tabulated-list-init-header): Add the initial aligning space even
30 if tabulated-list-padding is zero.
31
12012-05-06 Christopher Schmidt <christopher@ch.ristopher.com> 322012-05-06 Christopher Schmidt <christopher@ch.ristopher.com>
2 33
3 * emacs-lisp/cl-macs.el (cl-expr-contains): Handle cons cells 34 * emacs-lisp/cl-macs.el (cl-expr-contains): Handle cons cells
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 105ee50958e..e28c2c0f60b 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -1,4 +1,4 @@
1;;; buff-menu.el --- buffer menu main function and support functions -*- coding:utf-8 -*- 1;;; buff-menu.el --- Interface for viewing and manipulating buffers
2 2
3;; Copyright (C) 1985-1987, 1993-1995, 2000-2012 3;; Copyright (C) 1985-1987, 1993-1995, 2000-2012
4;; Free Software Foundation, Inc. 4;; Free Software Foundation, Inc.
@@ -24,44 +24,13 @@
24 24
25;;; Commentary: 25;;; Commentary:
26 26
27;; Edit, delete, or change attributes of all currently active Emacs 27;; The Buffer Menu is used to view, edit, delete, or change attributes
28;; buffers from a list summarizing their state. A good way to browse 28;; of buffers. The entry points are C-x C-b (`list-buffers') and
29;; any special or scratch buffers you have loaded, since you can't find 29;; M-x buffer-menu.
30;; them by filename. The single entry point is `list-buffers',
31;; normally bound to C-x C-b.
32
33;;; Change Log:
34
35;; Buffer-menu-view: New function
36;; Buffer-menu-view-other-window: New function
37
38;; Merged by esr with recent mods to Emacs 19 buff-menu, 23 Mar 1993
39;;
40;; Modified by Bob Weiner, Motorola, Inc., 4/14/89
41;;
42;; Added optional backup argument to 'Buffer-menu-unmark' to make it undelete
43;; current entry and then move to previous one.
44;;
45;; Based on FSF code dating back to 1985.
46 30
47;;; Code: 31;;; Code:
48 32
49;;Trying to preserve the old window configuration works well in 33(require 'tabulated-list)
50;;simple scenarios, when you enter the buffer menu, use it, and exit it.
51;;But it does strange things when you switch back to the buffer list buffer
52;;with C-x b, later on, when the window configuration is different.
53;;The choice seems to be, either restore the window configuration
54;;in all cases, or in no cases.
55;;I decided it was better not to restore the window config at all. -- rms.
56
57;;But since then, I changed buffer-menu to use the selected window,
58;;so q now once again goes back to the previous window configuration.
59
60;;(defvar Buffer-menu-window-config nil
61;; "Window configuration saved from entry to `buffer-menu'.")
62
63;; Put buffer *Buffer List* into proper mode right away
64;; so that from now on even list-buffers is enough to get a buffer menu.
65 34
66(defgroup Buffer-menu nil 35(defgroup Buffer-menu nil
67 "Show a menu of all buffers in a buffer." 36 "Show a menu of all buffers in a buffer."
@@ -69,23 +38,41 @@
69 :group 'convenience) 38 :group 'convenience)
70 39
71(defcustom Buffer-menu-use-header-line t 40(defcustom Buffer-menu-use-header-line t
72 "Non-nil means to use an immovable header-line." 41 "If non-nil, use the header line to display Buffer Menu column titles."
73 :type 'boolean 42 :type 'boolean
74 :group 'Buffer-menu) 43 :group 'Buffer-menu)
75 44
76(defface buffer-menu-buffer 45(defface buffer-menu-buffer
77 '((t (:weight bold))) 46 '((t (:weight bold)))
78 "Face used to highlight buffer names in the buffer menu." 47 "Face for buffer names in the Buffer Menu."
79 :group 'Buffer-menu) 48 :group 'Buffer-menu)
80(put 'Buffer-menu-buffer 'face-alias 'buffer-menu-buffer) 49(put 'Buffer-menu-buffer 'face-alias 'buffer-menu-buffer)
81 50
82(defcustom Buffer-menu-buffer+size-width 26 51(defcustom Buffer-menu-buffer+size-width nil
83 "How wide to jointly make the buffer name and size columns." 52 "Combined width of buffer name and size columns in Buffer Menu.
53If nil, use `Buffer-menu-name-width' and `Buffer-menu-size-width'."
84 :type 'number 54 :type 'number
85 :group 'Buffer-menu) 55 :group 'Buffer-menu
56 :version "24.2")
57
58(make-obsolete-variable 'Buffer-menu-buffer+size-width
59 "`Buffer-menu-name-width' and `Buffer-menu-size-width'"
60 "24.2")
61
62(defcustom Buffer-menu-name-width 19
63 "Width of buffer size column in the Buffer Menu."
64 :type 'number
65 :group 'Buffer-menu
66 :version "24.2")
67
68(defcustom Buffer-menu-size-width 7
69 "Width of buffer name column in the Buffer Menu."
70 :type 'number
71 :group 'Buffer-menu
72 :version "24.2")
86 73
87(defcustom Buffer-menu-mode-width 16 74(defcustom Buffer-menu-mode-width 16
88 "How wide to make the mode name column." 75 "Width of mode name column in the Buffer Menu."
89 :type 'number 76 :type 'number
90 :group 'Buffer-menu) 77 :group 'Buffer-menu)
91 78
@@ -99,35 +86,19 @@ as it is by default."
99 :group 'Buffer-menu 86 :group 'Buffer-menu
100 :version "22.1") 87 :version "22.1")
101 88
102;; This should get updated & resorted when you click on a column heading
103(defvar Buffer-menu-sort-column nil
104 "Which column to sort the menu on.
105Use 2 to sort by buffer names, or 5 to sort by file names.
106A nil value means sort by visited order (the default).")
107
108(defconst Buffer-menu-buffer-column 4)
109
110(defvar Buffer-menu-files-only nil 89(defvar Buffer-menu-files-only nil
111 "Non-nil if the current buffer-menu lists only file buffers. 90 "Non-nil if the current Buffer Menu lists only file buffers.
112This variable determines whether reverting the buffer lists only 91This is set by the prefix argument to `buffer-menu' and related
113file buffers. It affects both manual reverting and reverting by 92commands.")
114Auto Revert Mode.")
115(make-variable-buffer-local 'Buffer-menu-files-only) 93(make-variable-buffer-local 'Buffer-menu-files-only)
116 94
117(defvar Buffer-menu--buffers nil 95(defvar Info-current-file) ; from info.el
118 "If non-nil, list of buffers shown in the current buffer-menu. 96(defvar Info-current-node) ; from info.el
119This variable determines whether reverting the buffer lists only
120these buffers. It affects both manual reverting and reverting by
121Auto Revert Mode.")
122(make-variable-buffer-local 'Buffer-menu--buffers)
123
124(defvar Info-current-file) ;; from info.el
125(defvar Info-current-node) ;; from info.el
126 97
127(defvar Buffer-menu-mode-map 98(defvar Buffer-menu-mode-map
128 (let ((map (make-keymap)) 99 (let ((map (make-sparse-keymap))
129 (menu-map (make-sparse-keymap))) 100 (menu-map (make-sparse-keymap)))
130 (suppress-keymap map t) 101 (set-keymap-parent map tabulated-list-mode-map)
131 (define-key map "v" 'Buffer-menu-select) 102 (define-key map "v" 'Buffer-menu-select)
132 (define-key map "2" 'Buffer-menu-2-window) 103 (define-key map "2" 'Buffer-menu-2-window)
133 (define-key map "1" 'Buffer-menu-1-window) 104 (define-key map "1" 'Buffer-menu-1-window)
@@ -139,12 +110,10 @@ Auto Revert Mode.")
139 (define-key map "s" 'Buffer-menu-save) 110 (define-key map "s" 'Buffer-menu-save)
140 (define-key map "d" 'Buffer-menu-delete) 111 (define-key map "d" 'Buffer-menu-delete)
141 (define-key map "k" 'Buffer-menu-delete) 112 (define-key map "k" 'Buffer-menu-delete)
142 (define-key map "\C-d" 'Buffer-menu-delete-backwards)
143 (define-key map "\C-k" 'Buffer-menu-delete) 113 (define-key map "\C-k" 'Buffer-menu-delete)
114 (define-key map "\C-d" 'Buffer-menu-delete-backwards)
144 (define-key map "x" 'Buffer-menu-execute) 115 (define-key map "x" 'Buffer-menu-execute)
145 (define-key map " " 'next-line) 116 (define-key map " " 'next-line)
146 (define-key map "n" 'next-line)
147 (define-key map "p" 'previous-line)
148 (define-key map "\177" 'Buffer-menu-backup-unmark) 117 (define-key map "\177" 'Buffer-menu-backup-unmark)
149 (define-key map "~" 'Buffer-menu-not-modified) 118 (define-key map "~" 'Buffer-menu-not-modified)
150 (define-key map "u" 'Buffer-menu-unmark) 119 (define-key map "u" 'Buffer-menu-unmark)
@@ -154,10 +123,9 @@ Auto Revert Mode.")
154 (define-key map "b" 'Buffer-menu-bury) 123 (define-key map "b" 'Buffer-menu-bury)
155 (define-key map "V" 'Buffer-menu-view) 124 (define-key map "V" 'Buffer-menu-view)
156 (define-key map "T" 'Buffer-menu-toggle-files-only) 125 (define-key map "T" 'Buffer-menu-toggle-files-only)
157 (define-key map [mouse-2] 'Buffer-menu-mouse-select)
158 (define-key map [follow-link] 'mouse-face)
159 (define-key map (kbd "M-s a C-s") 'Buffer-menu-isearch-buffers) 126 (define-key map (kbd "M-s a C-s") 'Buffer-menu-isearch-buffers)
160 (define-key map (kbd "M-s a M-C-s") 'Buffer-menu-isearch-buffers-regexp) 127 (define-key map (kbd "M-s a M-C-s") 'Buffer-menu-isearch-buffers-regexp)
128
161 (define-key map [menu-bar Buffer-menu-mode] (cons (purecopy "Buffer-Menu") menu-map)) 129 (define-key map [menu-bar Buffer-menu-mode] (cons (purecopy "Buffer-Menu") menu-map))
162 (define-key menu-map [quit] 130 (define-key menu-map [quit]
163 `(menu-item ,(purecopy "Quit") quit-window 131 `(menu-item ,(purecopy "Quit") quit-window
@@ -224,143 +192,123 @@ Auto Revert Mode.")
224 map) 192 map)
225 "Local keymap for `Buffer-menu-mode' buffers.") 193 "Local keymap for `Buffer-menu-mode' buffers.")
226 194
227;; Buffer Menu mode is suitable only for specially formatted data. 195(define-derived-mode Buffer-menu-mode tabulated-list-mode "Buffer Menu"
228(put 'Buffer-menu-mode 'mode-class 'special) 196 "Major mode for Buffer Menu buffers.
229 197The Buffer Menu is invoked by the commands \\[list-buffers], \\[buffer-menu], and
230(define-derived-mode Buffer-menu-mode special-mode "Buffer Menu" 198\\[buffer-menu-other-window]. See `buffer-menu' for details."
231 "Major mode for editing a list of buffers.
232Each line describes one of the buffers in Emacs.
233Letters do not insert themselves; instead, they are commands.
234\\<Buffer-menu-mode-map>
235\\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu.
236\\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu.
237\\[Buffer-menu-other-window] -- select that buffer in another window,
238 so the buffer menu buffer remains visible in its window.
239\\[Buffer-menu-view] -- select current line's buffer, but in view-mode.
240\\[Buffer-menu-view-other-window] -- select that buffer in
241 another window, in view-mode.
242\\[Buffer-menu-switch-other-window] -- make another window display that buffer.
243\\[Buffer-menu-mark] -- mark current line's buffer to be displayed.
244\\[Buffer-menu-select] -- select current line's buffer.
245 Also show buffers marked with m, in other windows.
246\\[Buffer-menu-1-window] -- select that buffer in full-frame window.
247\\[Buffer-menu-2-window] -- select that buffer in one window,
248 together with buffer selected before this one in another window.
249\\[Buffer-menu-isearch-buffers] -- Do incremental search in the marked buffers.
250\\[Buffer-menu-isearch-buffers-regexp] -- Isearch for regexp in the marked buffers.
251\\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer.
252\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
253\\[Buffer-menu-save] -- mark that buffer to be saved, and move down.
254\\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down.
255\\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up.
256\\[Buffer-menu-execute] -- delete or save marked buffers.
257\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
258 With prefix argument, also move up one line.
259\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
260\\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line.
261\\[revert-buffer] -- update the list of buffers.
262\\[Buffer-menu-toggle-files-only] -- toggle whether the menu displays only file buffers.
263\\[Buffer-menu-bury] -- bury the buffer listed on this line."
264 (set (make-local-variable 'revert-buffer-function)
265 'Buffer-menu-revert-function)
266 (set (make-local-variable 'buffer-stale-function) 199 (set (make-local-variable 'buffer-stale-function)
267 (lambda (&optional _noconfirm) 'fast)) 200 (lambda (&optional _noconfirm) 'fast))
268 (setq truncate-lines t) 201 (add-hook 'tabulated-list-revert-hook 'list-buffers--refresh nil t))
269 (setq buffer-read-only t)
270 ;; Force L2R direction, to avoid messing the display if the first
271 ;; buffer in the list happens to begin with a strong R2L character.
272 (setq bidi-paragraph-direction 'left-to-right))
273 202
274(define-obsolete-variable-alias 'buffer-menu-mode-hook 203(define-obsolete-variable-alias 'buffer-menu-mode-hook
275 'Buffer-menu-mode-hook "23.1") 204 'Buffer-menu-mode-hook "23.1")
276 205
277(defun Buffer-menu-revert-function (_ignore1 _ignore2) 206(defun buffer-menu (&optional arg)
278 (or (eq buffer-undo-list t) 207 "Switch to the Buffer Menu.
279 (setq buffer-undo-list nil)) 208By default, all buffers are listed except those whose names start
280 ;; We can not use save-excursion here. The buffer gets erased. 209with a space (which are for internal use). With prefix argument
281 (let ((opoint (point)) 210ARG, show only buffers that are visiting files.
282 (eobp (eobp))
283 (ocol (current-column))
284 (oline (progn (move-to-column Buffer-menu-buffer-column)
285 (get-text-property (point) 'buffer)))
286 (prop (point-min))
287 ;; do not make undo records for the reversion.
288 (buffer-undo-list t))
289 ;; We can be called by Auto Revert Mode with the "*Buffer Menu*"
290 ;; temporarily the current buffer. Make sure that the
291 ;; interactively current buffer is correctly identified with a `.'
292 ;; by `list-buffers-noselect'.
293 (with-current-buffer (window-buffer)
294 (list-buffers-noselect Buffer-menu-files-only Buffer-menu--buffers))
295 (if oline
296 (while (setq prop (next-single-property-change prop 'buffer))
297 (when (eq (get-text-property prop 'buffer) oline)
298 (goto-char prop)
299 (move-to-column ocol)))
300 (goto-char (if eobp (point-max) opoint)))))
301 211
302(defun Buffer-menu-toggle-files-only (arg) 212The first column (denoted \"C\") shows \".\" for the buffer from
303 "Toggle whether the current buffer-menu displays only file buffers. 213which you came. It shows \">\" for buffers you mark to be
304With a positive ARG display only file buffers. With zero or 214displayed, and \"D\" for those you mark for deletion.
305negative ARG, display other buffers as well."
306 (interactive "P")
307 (setq Buffer-menu-files-only
308 (cond ((not arg) (not Buffer-menu-files-only))
309 ((> (prefix-numeric-value arg) 0) t)))
310 (revert-buffer))
311 215
312 216The \"R\" column has a \"%\" if the buffer is read-only.
313(defun Buffer-menu-buffer (error-if-non-existent-p) 217The \"M\" column has a \"*\" if it is modified, or \"S\" if you
314 "Return buffer described by this line of buffer menu." 218have marked it for saving.
315 (let* ((where (+ (line-beginning-position) Buffer-menu-buffer-column)) 219
316 (name (and (not (eobp)) (get-text-property where 'buffer-name))) 220After this come the buffer name, its size in characters, its
317 (buf (and (not (eobp)) (get-text-property where 'buffer)))) 221major mode, and the visited file name (if any).
318 (if name 222
319 (or (get-buffer name) 223
320 (and buf (buffer-name buf) buf) 224In the Buffer Menu, the following commands are defined:
321 (if error-if-non-existent-p 225\\<Buffer-menu-mode-map>
322 (error "No buffer named `%s'" name) 226\\[quit-window] Remove the Buffer Menu from the display.
323 nil)) 227\\[Buffer-menu-this-window] Select current line's buffer in place of the buffer menu.
324 (or (and buf (buffer-name buf) buf) 228\\[Buffer-menu-other-window] Select that buffer in another window,
325 (if error-if-non-existent-p 229 so the Buffer Menu remains visible in its window.
326 (error "No buffer on this line") 230\\[Buffer-menu-view] Select current line's buffer, in View mode.
327 nil))))) 231\\[Buffer-menu-view-other-window] Select that buffer in
328 232 another window, in view-mode.
329(defun buffer-menu (&optional arg) 233\\[Buffer-menu-switch-other-window] Make another window display that buffer.
330 "Make a menu of buffers so you can save, delete or select them. 234\\[Buffer-menu-mark] Mark current line's buffer to be displayed.
331With argument, show only buffers that are visiting files. 235\\[Buffer-menu-select] Select current line's buffer.
332Type ? after invocation to get help on commands available. 236 Also show buffers marked with m, in other windows.
333Type q to remove the buffer menu from the display. 237\\[Buffer-menu-1-window] Select that buffer in full-frame window.
334 238\\[Buffer-menu-2-window] Select that buffer in one window, together with the
335The first column shows `>' for a buffer you have 239 buffer selected before this one in another window.
336marked to be displayed, `D' for one you have marked for 240\\[Buffer-menu-isearch-buffers] Incremental search in the marked buffers.
337deletion, and `.' for the current buffer. 241\\[Buffer-menu-isearch-buffers-regexp] Isearch for regexp in the marked buffers.
338 242\\[Buffer-menu-visit-tags-table] visit-tags-table this buffer.
339The C column has a `.' for the buffer from which you came. 243\\[Buffer-menu-not-modified] Clear modified-flag on that buffer.
340The R column has a `%' if the buffer is read-only. 244\\[Buffer-menu-save] Mark that buffer to be saved, and move down.
341The M column has a `*' if it is modified, 245\\[Buffer-menu-delete] Mark that buffer to be deleted, and move down.
342or `S' if you have marked it for saving. 246\\[Buffer-menu-delete-backwards] Mark that buffer to be deleted, and move up.
343After this come the buffer name, its size in characters, 247\\[Buffer-menu-execute] Delete or save marked buffers.
344its major mode, and the visited file name (if any)." 248\\[Buffer-menu-unmark] Remove all marks from current line.
249 With prefix argument, also move up one line.
250\\[Buffer-menu-backup-unmark] Back up a line and remove marks.
251\\[Buffer-menu-toggle-read-only] Toggle read-only status of buffer on this line.
252\\[revert-buffer] Update the list of buffers.
253\\[Buffer-menu-toggle-files-only] Toggle whether the menu displays only file buffers.
254\\[Buffer-menu-bury] Bury the buffer listed on this line."
345 (interactive "P") 255 (interactive "P")
346;;; (setq Buffer-menu-window-config (current-window-configuration))
347 (switch-to-buffer (list-buffers-noselect arg)) 256 (switch-to-buffer (list-buffers-noselect arg))
348 (message 257 (message
349 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help.")) 258 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
350 259
351(defun buffer-menu-other-window (&optional arg) 260(defun buffer-menu-other-window (&optional arg)
352 "Display a list of buffers in another window. 261 "Display the Buffer Menu in another window.
353With the buffer list buffer, you can save, delete or select the buffers. 262See `buffer-menu' for a description of the Buffer Menu.
354With argument, show only buffers that are visiting files. 263
355Type ? after invocation to get help on commands available. 264By default, all buffers are listed except those whose names start
356Type q to remove the buffer menu from the display. 265with a space (which are for internal use). With prefix argument
357For more information, see the function `buffer-menu'." 266ARG, show only buffers that are visiting files."
358 (interactive "P") 267 (interactive "P")
359;;; (setq Buffer-menu-window-config (current-window-configuration))
360 (switch-to-buffer-other-window (list-buffers-noselect arg)) 268 (switch-to-buffer-other-window (list-buffers-noselect arg))
361 (message 269 (message
362 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help.")) 270 "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
363 271
272(defun list-buffers (&optional arg)
273 "Display a list of existing buffers.
274The list is displayed in a buffer named \"*Buffer List*\".
275See `buffer-menu' for details about the Buffer Menu buffer.
276
277By default, all buffers are listed except those whose names start
278with a space (which are for internal use). With prefix argument
279ARG, show only buffers that are visiting files."
280 (interactive "P")
281 (display-buffer (list-buffers-noselect arg)))
282
283(defun Buffer-menu-toggle-files-only (arg)
284 "Toggle whether the current buffer-menu displays only file buffers.
285With a positive ARG, display only file buffers. With zero or
286negative ARG, display other buffers as well."
287 (interactive "P")
288 (setq Buffer-menu-files-only
289 (cond ((not arg) (not Buffer-menu-files-only))
290 ((> (prefix-numeric-value arg) 0) t)))
291 (message (if Buffer-menu-files-only
292 "Showing only file-visiting buffers."
293 "Showing all non-internal buffers."))
294 (revert-buffer))
295
296(defalias 'Buffer-menu-sort 'tabulated-list-sort)
297
298
299(defun Buffer-menu-buffer (&optional error-if-non-existent-p)
300 "Return the buffer described by the current Buffer Menu line.
301If there is no buffer here, return nil if ERROR-IF-NON-EXISTENT-P
302is nil or omitted, and signal an error otherwise."
303 (let ((buffer (tabulated-list-get-id)))
304 (cond ((null buffer)
305 (if error-if-non-existent-p
306 (error "No buffer on this line")))
307 ((not (buffer-live-p buffer))
308 (if error-if-non-existent-p
309 (error "This buffer has been killed")))
310 (t buffer))))
311
364(defun Buffer-menu-no-header () 312(defun Buffer-menu-no-header ()
365 (beginning-of-line) 313 (beginning-of-line)
366 (if (or Buffer-menu-use-header-line 314 (if (or Buffer-menu-use-header-line
@@ -370,166 +318,140 @@ For more information, see the function `buffer-menu'."
370 (forward-line 1) 318 (forward-line 1)
371 nil)) 319 nil))
372 320
321(defun Buffer-menu-beginning ()
322 (goto-char (point-min))
323 (unless Buffer-menu-use-header-line
324 (forward-line)))
325
326
327;;; Commands for modifying Buffer Menu entries.
328
373(defun Buffer-menu-mark () 329(defun Buffer-menu-mark ()
374 "Mark buffer on this line for being displayed by \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command." 330 "Mark the Buffer menu entry at point for later display.
331It will be displayed by the \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command."
375 (interactive) 332 (interactive)
376 (when (Buffer-menu-no-header) 333 (tabulated-list-set-col 0 ">" t)
377 (let ((inhibit-read-only t)) 334 (forward-line))
378 (delete-char 1)
379 (insert ?>)
380 (forward-line 1))))
381 335
382(defun Buffer-menu-unmark (&optional backup) 336(defun Buffer-menu-unmark (&optional backup)
383 "Cancel all requested operations on buffer on this line and move down. 337 "Cancel all requested operations on buffer on this line and move down.
384Optional prefix arg means move up." 338Optional prefix arg means move up."
385 (interactive "P") 339 (interactive "P")
386 (when (Buffer-menu-no-header) 340 (tabulated-list-set-col 0 " " t)
387 (let* ((buf (Buffer-menu-buffer t))
388 (mod (buffer-modified-p buf))
389 (readonly (with-current-buffer buf buffer-read-only))
390 (inhibit-read-only t))
391 (delete-char 3)
392 (insert (if readonly (if mod " %*" " % ") (if mod " *" " ")))))
393 (forward-line (if backup -1 1))) 341 (forward-line (if backup -1 1)))
394 342
395(defun Buffer-menu-backup-unmark () 343(defun Buffer-menu-backup-unmark ()
396 "Move up and cancel all requested operations on buffer on line above." 344 "Move up and cancel all requested operations on buffer on line above."
397 (interactive) 345 (interactive)
398 (forward-line -1) 346 (forward-line -1)
399 (Buffer-menu-unmark) 347 (tabulated-list-set-col 0 " " t))
400 (forward-line -1))
401 348
402(defun Buffer-menu-delete (&optional arg) 349(defun Buffer-menu-delete (&optional arg)
403 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command. 350 "Mark the buffer on this Buffer Menu buffer line for deletion.
404Prefix arg is how many buffers to delete. 351A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]' command
405Negative arg means delete backwards." 352will delete it.
353
354If prefix argument ARG is non-nil, it specifies the number of
355buffers to delete; a negative ARG means to delete backwards."
406 (interactive "p") 356 (interactive "p")
407 (when (Buffer-menu-no-header) 357 (if (or (null arg) (= arg 0))
408 (let ((inhibit-read-only t)) 358 (setq arg 1))
409 (if (or (null arg) (= arg 0)) 359 (while (> arg 0)
410 (setq arg 1)) 360 (when (Buffer-menu-buffer)
411 (while (> arg 0) 361 (tabulated-list-set-col 0 "D" t))
412 (delete-char 1) 362 (forward-line 1)
413 (insert ?D) 363 (setq arg (1- arg)))
414 (forward-line 1) 364 (while (< arg 0)
415 (setq arg (1- arg))) 365 (when (Buffer-menu-buffer)
416 (while (and (< arg 0) 366 (tabulated-list-set-col 0 "D" t))
417 (Buffer-menu-no-header)) 367 (forward-line -1)
418 (delete-char 1) 368 (setq arg (1+ arg))))
419 (insert ?D)
420 (forward-line -1)
421 (setq arg (1+ arg))))))
422 369
423(defun Buffer-menu-delete-backwards (&optional arg) 370(defun Buffer-menu-delete-backwards (&optional arg)
424 "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command 371 "Mark the buffer on this Buffer Menu line for deletion, and move up.
425and then move up one line. Prefix arg means move that many lines." 372Prefix ARG means move that many lines."
426 (interactive "p") 373 (interactive "p")
427 (Buffer-menu-delete (- (or arg 1)))) 374 (Buffer-menu-delete (- (or arg 1))))
428 375
429(defun Buffer-menu-save () 376(defun Buffer-menu-save ()
430 "Mark buffer on this line to be saved by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command." 377 "Mark the buffer on this Buffer Menu line for saving.
378A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]' command
379will save it."
431 (interactive) 380 (interactive)
432 (when (Buffer-menu-no-header) 381 (when (Buffer-menu-buffer)
433 (let ((inhibit-read-only t)) 382 (tabulated-list-set-col 2 "S" t)
434 (forward-char 2) 383 (forward-line 1)))
435 (delete-char 1)
436 (insert ?S)
437 (forward-line 1))))
438 384
439(defun Buffer-menu-not-modified (&optional arg) 385(defun Buffer-menu-not-modified (&optional arg)
440 "Mark buffer on this line as unmodified (no changes to save)." 386 "Mark the buffer on this line as unmodified (no changes to save).
387If ARG is non-nil (interactively, with a prefix argument), mark
388it as modified."
441 (interactive "P") 389 (interactive "P")
442 (with-current-buffer (Buffer-menu-buffer t) 390 (with-current-buffer (Buffer-menu-buffer t)
443 (set-buffer-modified-p arg)) 391 (set-buffer-modified-p arg))
444 (save-excursion 392 (tabulated-list-set-col 2 (if arg "*" " ") t))
445 (beginning-of-line)
446 (forward-char 2)
447 (if (= (char-after) (if arg ?\s ?*))
448 (let ((inhibit-read-only t))
449 (delete-char 1)
450 (insert (if arg ?* ?\s))))))
451
452(defun Buffer-menu-beginning ()
453 (goto-char (point-min))
454 (unless Buffer-menu-use-header-line
455 (forward-line)))
456 393
457(defun Buffer-menu-execute () 394(defun Buffer-menu-execute ()
458 "Save and/or delete buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] or \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands." 395 "Save and/or delete marked buffers in the Buffer Menu.
396Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-save]' are saved.
397Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-delete]' are deleted."
459 (interactive) 398 (interactive)
460 (save-excursion 399 (save-excursion
461 (Buffer-menu-beginning) 400 (Buffer-menu-beginning)
462 (while (re-search-forward "^..S" nil t) 401 (while (not (eobp))
463 (let ((modp nil)) 402 (let ((buffer (tabulated-list-get-id))
464 (with-current-buffer (Buffer-menu-buffer t) 403 (entry (tabulated-list-get-entry)))
465 (save-buffer) 404 (cond ((null entry)
466 (setq modp (buffer-modified-p))) 405 (forward-line 1))
467 (let ((inhibit-read-only t)) 406 ((not (buffer-live-p buffer))
468 (delete-char -1) 407 (tabulated-list-delete-entry))
469 (insert (if modp ?* ?\s)))))) 408 (t
470 (save-excursion 409 (let ((delete (eq (char-after) ?D)))
471 (Buffer-menu-beginning) 410 (when (equal (aref entry 2) "S")
472 (let ((buff-menu-buffer (current-buffer)) 411 (condition-case nil
473 (inhibit-read-only t)) 412 (progn
474 (while (re-search-forward "^D" nil t) 413 (with-current-buffer buffer
475 (forward-char -1) 414 (save-buffer))
476 (let ((buf (Buffer-menu-buffer nil))) 415 (tabulated-list-set-col 2 " " t))
477 (or (eq buf nil) 416 (error (warn "Error saving %s" buffer))))
478 (eq buf buff-menu-buffer) 417 (if delete
479 (save-excursion (kill-buffer buf))) 418 (unless (eq buffer (current-buffer))
480 (if (and buf (buffer-name buf)) 419 (kill-buffer buffer)
481 (progn (delete-char 1) 420 (tabulated-list-delete-entry))
482 (insert ?\s)) 421 (forward-line 1)))))))))
483 (delete-region (point) (progn (forward-line 1) (point)))
484 (unless (bobp)
485 (forward-char -1))))))))
486 422
487(defun Buffer-menu-select () 423(defun Buffer-menu-select ()
488 "Select this line's buffer; also display buffers marked with `>'. 424 "Select this line's buffer; also, display buffers marked with `>'.
489You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command. 425You can mark buffers with the \\<Buffer-menu-mode-map>`\\[Buffer-menu-mark]' command.
490This command deletes and replaces all the previously existing windows 426This command deletes and replaces all the previously existing windows
491in the selected frame." 427in the selected frame."
492 (interactive) 428 (interactive)
493 (let ((buff (Buffer-menu-buffer t)) 429 (let* ((this-buffer (Buffer-menu-buffer t))
494 (menu (current-buffer)) 430 (menu-buffer (current-buffer))
495 (others ()) 431 (others (delq this-buffer (Buffer-menu-marked-buffers t)))
496 tem) 432 (height (/ (1- (frame-height)) (1+ (length others)))))
497 (Buffer-menu-beginning)
498 (while (re-search-forward "^>" nil t)
499 (setq tem (Buffer-menu-buffer t))
500 (let ((inhibit-read-only t))
501 (delete-char -1)
502 (insert ?\s))
503 (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
504 (setq others (nreverse others)
505 tem (/ (1- (frame-height)) (1+ (length others))))
506 (delete-other-windows) 433 (delete-other-windows)
507 (switch-to-buffer buff) 434 (switch-to-buffer this-buffer)
508 (or (eq menu buff) 435 (unless (eq menu-buffer this-buffer)
509 (bury-buffer menu)) 436 (bury-buffer menu-buffer))
510 (if (equal (length others) 0) 437 (dolist (buffer others)
511 (progn 438 (split-window nil height)
512;;; ;; Restore previous window configuration before displaying 439 (other-window 1)
513;;; ;; selected buffers. 440 (switch-to-buffer buffer))
514;;; (if Buffer-menu-window-config 441 ;; Back to the beginning!
515;;; (progn 442 (other-window 1)))
516;;; (set-window-configuration Buffer-menu-window-config) 443
517;;; (setq Buffer-menu-window-config nil))) 444(defun Buffer-menu-marked-buffers (&optional unmark)
518 (switch-to-buffer buff)) 445 "Return the list of buffers marked with `Buffer-menu-mark'.
519 (while others 446If UNMARK is non-nil, unmark them."
520 (split-window nil tem)
521 (other-window 1)
522 (switch-to-buffer (car others))
523 (setq others (cdr others)))
524 (other-window 1) ;back to the beginning!
525)))
526
527(defun Buffer-menu-marked-buffers ()
528 "Return a list of buffers marked with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command."
529 (let (buffers) 447 (let (buffers)
530 (Buffer-menu-beginning) 448 (Buffer-menu-beginning)
531 (while (re-search-forward "^>" nil t) 449 (while (re-search-forward "^>" nil t)
532 (setq buffers (cons (Buffer-menu-buffer t) buffers))) 450 (let ((buffer (Buffer-menu-buffer)))
451 (if (and buffer unmark)
452 (tabulated-list-set-col 0 " " t))
453 (if (buffer-live-p buffer)
454 (push buffer buffers))))
533 (nreverse buffers))) 455 (nreverse buffers)))
534 456
535(defun Buffer-menu-isearch-buffers () 457(defun Buffer-menu-isearch-buffers ()
@@ -558,20 +480,6 @@ in the selected frame."
558 (bury-buffer (other-buffer)) 480 (bury-buffer (other-buffer))
559 (delete-other-windows)) 481 (delete-other-windows))
560 482
561(defun Buffer-menu-mouse-select (event)
562 "Select the buffer whose line you click on."
563 (interactive "e")
564 (let (buffer)
565 (with-current-buffer (window-buffer (posn-window (event-end event)))
566 (save-excursion
567 (goto-char (posn-point (event-end event)))
568 (setq buffer (Buffer-menu-buffer t))))
569 (select-window (posn-window (event-end event)))
570 (if (and (window-dedicated-p (selected-window))
571 (eq (selected-window) (frame-root-window)))
572 (switch-to-buffer-other-frame buffer)
573 (switch-to-buffer buffer))))
574
575(defun Buffer-menu-this-window () 483(defun Buffer-menu-this-window ()
576 "Select this line's buffer in this window." 484 "Select this line's buffer in this window."
577 (interactive) 485 (interactive)
@@ -599,340 +507,128 @@ The current window remains selected."
599 (bury-buffer menu))) 507 (bury-buffer menu)))
600 508
601(defun Buffer-menu-toggle-read-only () 509(defun Buffer-menu-toggle-read-only ()
602 "Toggle read-only status of buffer on this line, perhaps via version control." 510 "Toggle read-only status of buffer on this line."
603 (interactive) 511 (interactive)
604 (let (char) 512 (let (read-only)
605 (with-current-buffer (Buffer-menu-buffer t) 513 (with-current-buffer (Buffer-menu-buffer t)
606 (toggle-read-only) 514 (with-no-warnings (toggle-read-only))
607 (setq char (if buffer-read-only ?% ?\s))) 515 (setq read-only buffer-read-only))
608 (save-excursion 516 (tabulated-list-set-col 1 (if read-only "%" " ") t)))
609 (beginning-of-line)
610 (forward-char 1)
611 (if (/= (following-char) char)
612 (let ((inhibit-read-only t))
613 (delete-char 1)
614 (insert char))))))
615 517
616(defun Buffer-menu-bury () 518(defun Buffer-menu-bury ()
617 "Bury the buffer listed on this line." 519 "Bury the buffer listed on this line."
618 (interactive) 520 (interactive)
619 (when (Buffer-menu-no-header) 521 (let ((buffer (tabulated-list-get-id)))
620 (save-excursion 522 (cond ((null buffer))
621 (beginning-of-line) 523 ((buffer-live-p buffer)
622 (bury-buffer (Buffer-menu-buffer t)) 524 (bury-buffer buffer)
623 (let ((line (buffer-substring (point) (progn (forward-line 1) (point)))) 525 (save-excursion
624 (inhibit-read-only t)) 526 (let ((elt (tabulated-list-delete-entry)))
625 (delete-region (point) (progn (forward-line -1) (point))) 527 (goto-char (point-max))
626 (goto-char (point-max)) 528 (apply 'tabulated-list-print-entry elt)))
627 (insert line)) 529 (message "Buffer buried."))
628 (message "Buried buffer moved to the end")))) 530 (t
629 531 (tabulated-list-delete-entry)
532 (message "Buffer is dead; removing from list.")))))
630 533
631(defun Buffer-menu-view () 534(defun Buffer-menu-view ()
632 "View this line's buffer in View mode." 535 "View this line's buffer in View mode."
633 (interactive) 536 (interactive)
634 (view-buffer (Buffer-menu-buffer t))) 537 (view-buffer (Buffer-menu-buffer t)))
635 538
636
637(defun Buffer-menu-view-other-window () 539(defun Buffer-menu-view-other-window ()
638 "View this line's buffer in View mode in another window." 540 "View this line's buffer in View mode in another window."
639 (interactive) 541 (interactive)
640 (view-buffer-other-window (Buffer-menu-buffer t))) 542 (view-buffer-other-window (Buffer-menu-buffer t)))
641 543
642 544;;; Functions for populating the Buffer Menu.
643;;;###autoload
644(defun list-buffers (&optional files-only)
645 "Display a list of names of existing buffers.
646The list is displayed in a buffer named `*Buffer List*'.
647Note that buffers with names starting with spaces are omitted.
648Non-null optional arg FILES-ONLY means mention only file buffers.
649
650For more information, see the function `buffer-menu'."
651 (interactive "P")
652 (display-buffer (list-buffers-noselect files-only)))
653
654(defconst Buffer-menu-short-ellipsis
655 ;; This file is preloaded, so we can't use char-displayable-p here
656 ;; because we don't know yet what display we're going to connect to.
657 ":" ;; (if (char-displayable-p ?…) "…" ":")
658 )
659
660(defun Buffer-menu-buffer+size (name size &optional name-props size-props)
661 (if (> (+ (string-width name) (string-width size) 2)
662 Buffer-menu-buffer+size-width)
663 (setq name
664 (let ((tail
665 (if (string-match "<[0-9]+>$" name)
666 (match-string 0 name)
667 "")))
668 (concat (truncate-string-to-width
669 name
670 (- Buffer-menu-buffer+size-width
671 (max (string-width size) 3)
672 (string-width tail)
673 2))
674 Buffer-menu-short-ellipsis
675 tail)))
676 ;; Don't put properties on (buffer-name).
677 (setq name (copy-sequence name)))
678 (add-text-properties 0 (length name) name-props name)
679 (add-text-properties 0 (length size) size-props size)
680 (let ((name+space-width (- Buffer-menu-buffer+size-width
681 (string-width size))))
682 (concat name
683 (propertize (make-string (- name+space-width (string-width name))
684 ?\s)
685 'display `(space :align-to
686 ,(+ Buffer-menu-buffer-column
687 name+space-width)))
688 size)))
689
690(defun Buffer-menu-sort (column)
691 "Sort the buffer menu by COLUMN."
692 (interactive "P")
693 (when column
694 (setq column (prefix-numeric-value column))
695 (if (< column 2) (setq column 2))
696 (if (> column 5) (setq column 5)))
697 (setq Buffer-menu-sort-column column)
698 (let ((inhibit-read-only t) l buf m1 m2)
699 (save-excursion
700 (Buffer-menu-beginning)
701 (while (not (eobp))
702 (when (buffer-live-p
703 (setq buf (get-text-property
704 (+ (point)
705 Buffer-menu-buffer-column)
706 'buffer)))
707 (setq m1 (char-after)
708 m1 (if (memq m1 '(?> ?D)) m1)
709 m2 (char-after (+ (point) 2))
710 m2 (if (eq m2 ?S) m2))
711 (if (or m1 m2)
712 (push (list buf m1 m2) l)))
713 (forward-line)))
714 (revert-buffer)
715 (save-excursion
716 (Buffer-menu-beginning)
717 (while (not (eobp))
718 (when (setq buf (assq (get-text-property (+ (point)
719 Buffer-menu-buffer-column)
720 'buffer) l))
721 (setq m1 (cadr buf)
722 m2 (cadr (cdr buf)))
723 (when m1
724 (delete-char 1)
725 (insert m1)
726 (backward-char 1))
727 (when m2
728 (forward-char 2)
729 (delete-char 1)
730 (insert m2)))
731 (forward-line)))))
732
733(defun Buffer-menu-sort-by-column (&optional e)
734 "Sort the buffer menu by the column clicked on."
735 (interactive (list last-input-event))
736 (if e (mouse-select-window e))
737 (let* ((pos (event-start e))
738 (obj (posn-object pos))
739 (col (if obj
740 (get-text-property (cdr obj) 'column (car obj))
741 (get-text-property (posn-point pos) 'column))))
742 (Buffer-menu-sort col)))
743
744(defvar Buffer-menu-sort-button-map
745 (let ((map (make-sparse-keymap)))
746 ;; This keymap handles both nil and non-nil values for
747 ;; Buffer-menu-use-header-line.
748 (define-key map [header-line mouse-1] 'Buffer-menu-sort-by-column)
749 (define-key map [header-line mouse-2] 'Buffer-menu-sort-by-column)
750 (define-key map [mouse-2] 'Buffer-menu-sort-by-column)
751 (define-key map [follow-link] 'mouse-face)
752 (define-key map "\C-m" 'Buffer-menu-sort-by-column)
753 map)
754 "Local keymap for Buffer menu sort buttons.")
755
756(defun Buffer-menu-make-sort-button (name column)
757 (if (equal column Buffer-menu-sort-column) (setq column nil))
758 (propertize name
759 'column column
760 'help-echo (concat
761 (if Buffer-menu-use-header-line
762 "mouse-1, mouse-2: sort by "
763 "mouse-2, RET: sort by ")
764 (if column (downcase name) "visited order"))
765 'mouse-face 'highlight
766 'keymap Buffer-menu-sort-button-map))
767 545
768(defun list-buffers-noselect (&optional files-only buffer-list) 546(defun list-buffers-noselect (&optional files-only buffer-list)
769 "Create and return a buffer with a list of names of existing buffers. 547 "Create and return a Buffer Menu buffer.
770The buffer is named `*Buffer List*'. 548This is called by `buffer-menu' and others as a subroutine.
771Note that buffers with names starting with spaces are omitted. 549
772Non-null optional arg FILES-ONLY means mention only file buffers. 550If FILES-ONLY is non-nil, show only file-visiting buffers.
773 551If BUFFER-LIST is non-nil, it should be a list of buffers; it
774If BUFFER-LIST is non-nil, it should be a list of buffers; 552means list those buffers and no others."
775it means list those buffers and no others. 553 (let ((old-buffer (current-buffer))
776 554 (buffer (get-buffer-create "*Buffer List*")))
777For more information, see the function `buffer-menu'." 555 (with-current-buffer buffer
778 (let* ((old-buffer (current-buffer))
779 (standard-output standard-output)
780 (mode-end (make-string (- Buffer-menu-mode-width 2) ?\s))
781 (header (concat "CRM "
782 (Buffer-menu-buffer+size
783 (Buffer-menu-make-sort-button "Buffer" 2)
784 (Buffer-menu-make-sort-button "Size" 3))
785 " "
786 (Buffer-menu-make-sort-button "Mode" 4) mode-end
787 (Buffer-menu-make-sort-button "File" 5) "\n"))
788 list desired-point)
789 (when Buffer-menu-use-header-line
790 (let ((pos 0))
791 ;; Turn whitespace chars in the header into stretch specs so
792 ;; they work regardless of the header-line face.
793 (while (string-match "[ \t\n]+" header pos)
794 (setq pos (match-end 0))
795 (put-text-property (match-beginning 0) pos 'display
796 ;; Assume fixed-size chars in the buffer.
797 (list 'space :align-to pos)
798 header)))
799 ;; Try to better align the one-char headers.
800 (put-text-property 0 3 'face 'fixed-pitch header)
801 ;; Add a "dummy" leading space to align the beginning of the header
802 ;; line with the beginning of the text (rather than with the left
803 ;; scrollbar or the left fringe). --Stef
804 (setq header (concat (propertize " " 'display '(space :align-to 0))
805 header)))
806 (with-current-buffer (get-buffer-create "*Buffer List*")
807 (setq buffer-read-only nil)
808 (erase-buffer)
809 (setq standard-output (current-buffer))
810 ;; Force L2R direction, to avoid messing the display if the
811 ;; first buffer in the list happens to begin with a strong R2L
812 ;; character.
813 (setq bidi-paragraph-direction 'left-to-right)
814 (unless Buffer-menu-use-header-line
815 ;; Use U+2014 (EM DASH) to underline if possible, else use ASCII
816 ;; (i.e. U+002D, HYPHEN-MINUS).
817 (let ((underline (if (char-displayable-p ?\u2014) ?\u2014 ?-)))
818 (insert header
819 (apply 'string
820 (mapcar (lambda (c)
821 (if (memq c '(?\n ?\s)) c underline))
822 header)))))
823 ;; Collect info for every buffer we're interested in.
824 (dolist (buffer (or buffer-list
825 (buffer-list
826 (when Buffer-menu-use-frame-buffer-list
827 (selected-frame)))))
828 (with-current-buffer buffer
829 (let ((name (buffer-name))
830 (file buffer-file-name))
831 (unless (and (not buffer-list)
832 (or
833 ;; Don't mention internal buffers.
834 (and (string= (substring name 0 1) " ") (null file))
835 ;; Maybe don't mention buffers without files.
836 (and files-only (not file))
837 (string= name "*Buffer List*")))
838 ;; Otherwise output info.
839 (let ((mode (concat (format-mode-line mode-name nil nil buffer)
840 (if mode-line-process
841 (format-mode-line mode-line-process
842 nil nil buffer))))
843 (bits (string
844 (if (eq buffer old-buffer) ?. ?\s)
845 ;; Handle readonly status. The output buffer
846 ;; is special cased to appear readonly; it is
847 ;; actually made so at a later date.
848 (if (or (eq buffer standard-output)
849 buffer-read-only)
850 ?% ?\s)
851 ;; Identify modified buffers.
852 (if (buffer-modified-p) ?* ?\s)
853 ;; Space separator.
854 ?\s)))
855 (unless file
856 ;; No visited file. Check local value of
857 ;; list-buffers-directory and, for Info buffers,
858 ;; Info-current-file.
859 (cond ((and (boundp 'list-buffers-directory)
860 list-buffers-directory)
861 (setq file list-buffers-directory))
862 ((eq major-mode 'Info-mode)
863 (setq file Info-current-file)
864 (cond
865 ((equal file "dir")
866 (setq file "*Info Directory*"))
867 ((eq file 'apropos)
868 (setq file "*Info Apropos*"))
869 ((eq file 'history)
870 (setq file "*Info History*"))
871 ((eq file 'toc)
872 (setq file "*Info TOC*"))
873 ((not (stringp file)) ;; avoid errors
874 (setq file nil))
875 (t
876 (setq file (concat "("
877 (file-name-nondirectory file)
878 ") "
879 Info-current-node)))))))
880 (push (list buffer bits name (buffer-size) mode file)
881 list))))))
882 ;; Preserve the original buffer-list ordering, just in case.
883 (setq list (nreverse list))
884 ;; Place the buffers's info in the output buffer, sorted if necessary.
885 (dolist (buffer
886 (if Buffer-menu-sort-column
887 (sort list
888 (if (eq Buffer-menu-sort-column 3)
889 (lambda (a b)
890 (< (nth Buffer-menu-sort-column a)
891 (nth Buffer-menu-sort-column b)))
892 (lambda (a b)
893 (string< (nth Buffer-menu-sort-column a)
894 (nth Buffer-menu-sort-column b)))))
895 list))
896 (if (eq (car buffer) old-buffer)
897 (setq desired-point (point)))
898 (insert (cadr buffer)
899 ;; Put the buffer name into a text property
900 ;; so we don't have to extract it from the text.
901 ;; This way we avoid problems with unusual buffer names.
902 (let ((name (nth 2 buffer))
903 (size (int-to-string (nth 3 buffer))))
904 (Buffer-menu-buffer+size name size
905 `(buffer-name ,name
906 buffer ,(car buffer)
907 font-lock-face buffer-menu-buffer
908 mouse-face highlight
909 help-echo
910 ,(if (>= (length name)
911 (- Buffer-menu-buffer+size-width
912 (max (length size) 3)
913 2))
914 name
915 "mouse-2: select this buffer"))))
916 " "
917 (if (> (string-width (nth 4 buffer)) Buffer-menu-mode-width)
918 (truncate-string-to-width (nth 4 buffer)
919 Buffer-menu-mode-width)
920 (nth 4 buffer)))
921 (when (nth 5 buffer)
922 (indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-width
923 Buffer-menu-mode-width 4) 1)
924 (princ (abbreviate-file-name (nth 5 buffer))))
925 (princ "\n"))
926 (Buffer-menu-mode) 556 (Buffer-menu-mode)
927 (when Buffer-menu-use-header-line 557 (setq Buffer-menu-files-only (and files-only (>= files-only 0)))
928 (setq header-line-format header)) 558 (list-buffers--refresh buffer-list old-buffer)
929 ;; DESIRED-POINT doesn't have to be set; it is not when the 559 (tabulated-list-print))
930 ;; current buffer is not displayed for some reason. 560 buffer))
931 (and desired-point 561
932 (goto-char desired-point)) 562(defun list-buffers--refresh (&optional buffer-list old-buffer)
933 (setq Buffer-menu-files-only files-only) 563 ;; Set up `tabulated-list-format'.
934 (setq Buffer-menu--buffers buffer-list) 564 (let ((name-width Buffer-menu-name-width)
935 (set-buffer-modified-p nil) 565 (size-width Buffer-menu-size-width))
936 (current-buffer)))) 566 ;; Handle obsolete variable:
567 (if Buffer-menu-buffer+size-width
568 (setq name-width (- Buffer-menu-buffer+size-width size-width)))
569 (setq tabulated-list-format
570 (vector '("C" 1 t :pad-right 0)
571 '("R" 1 t :pad-right 0)
572 '("M" 1 t)
573 `("Buffer" ,name-width t)
574 `("Size" ,size-width tabulated-list-entry-size->)
575 `("Mode" ,Buffer-menu-mode-width t)
576 '("File" 1 t))))
577 ;; Collect info for each buffer we're interested in.
578 (let ((buffer-menu-buffer (current-buffer))
579 (show-non-file (not Buffer-menu-files-only))
580 entries)
581 (dolist (buffer (or buffer-list
582 (buffer-list (if Buffer-menu-use-frame-buffer-list
583 (selected-frame)))))
584 (with-current-buffer buffer
585 (let* ((name (buffer-name))
586 (file buffer-file-name))
587 (when (and (buffer-live-p buffer)
588 (or buffer-list
589 (and (not (string= (substring name 0 1) " "))
590 (not (eq buffer buffer-menu-buffer))
591 (or file show-non-file))))
592 (push (list buffer
593 (vector (if (eq buffer old-buffer) "." " ")
594 (if buffer-read-only "%" " ")
595 (if (buffer-modified-p) "*" " ")
596 (Buffer-menu--pretty-name name)
597 (number-to-string (buffer-size))
598 (concat (format-mode-line mode-name nil nil buffer)
599 (if mode-line-process
600 (format-mode-line mode-line-process
601 nil nil buffer)))
602 (Buffer-menu--pretty-file-name file)))
603 entries)))))
604 (setq tabulated-list-entries (nreverse entries)))
605 (tabulated-list-init-header))
606
607(defun tabulated-list-entry-size-> (entry1 entry2)
608 (> (string-to-number (aref (cadr entry1) 4))
609 (string-to-number (aref (cadr entry2) 4))))
610
611(defun Buffer-menu--pretty-name (name)
612 (propertize name 'font-lock-face 'buffer-menu-buffer))
613
614(defun Buffer-menu--pretty-file-name (file)
615 (cond (file
616 (abbreviate-file-name file))
617 ((and (boundp 'list-buffers-directory)
618 list-buffers-directory)
619 list-buffers-directory)
620 ((eq major-mode 'Info-mode)
621 (Buffer-menu-info-node-description Info-current-file))
622 (t "")))
623
624(defun Buffer-menu-info-node-description (file)
625 (cond
626 ((equal file "dir") "*Info Directory*")
627 ((eq file 'apropos) "*Info Apropos*")
628 ((eq file 'history) "*Info History*")
629 ((eq file 'toc) "*Info TOC*")
630 ((not (stringp file)) "") ; Avoid errors
631 (t
632 (concat "(" (file-name-nondirectory file) ") " Info-current-node))))
937 633
938;;; buff-menu.el ends here 634;;; buff-menu.el ends here
diff --git a/lisp/emacs-lisp/cl-loaddefs.el b/lisp/emacs-lisp/cl-loaddefs.el
index 48be2f72972..06c8fe8dba7 100644
--- a/lisp/emacs-lisp/cl-loaddefs.el
+++ b/lisp/emacs-lisp/cl-loaddefs.el
@@ -286,7 +286,7 @@ This also does some trivial optimizations to make the form prettier.
286;;;;;; flet progv psetq do-all-symbols do-symbols dotimes dolist 286;;;;;; flet progv psetq do-all-symbols do-symbols dotimes dolist
287;;;;;; do* do loop return-from return block etypecase typecase ecase 287;;;;;; do* do loop return-from return block etypecase typecase ecase
288;;;;;; case load-time-value eval-when destructuring-bind function* 288;;;;;; case load-time-value eval-when destructuring-bind function*
289;;;;;; defmacro* defun* gentemp gensym) "cl-macs" "cl-macs.el" "abb2e33c6f61539d69ddbe7c4046261b") 289;;;;;; defmacro* defun* gentemp gensym) "cl-macs" "cl-macs.el" "e10ebd95224fcfbe6a5edc59f40d695a")
290;;; Generated autoloads from cl-macs.el 290;;; Generated autoloads from cl-macs.el
291 291
292(autoload 'gensym "cl-macs" "\ 292(autoload 'gensym "cl-macs" "\
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index bd734a4fbe0..4291f3aacc6 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -144,7 +144,7 @@ If ADVANCE is non-nil, move forward by one line afterwards."
144 (set-keymap-parent map button-buffer-map) 144 (set-keymap-parent map button-buffer-map)
145 (define-key map "n" 'next-line) 145 (define-key map "n" 'next-line)
146 (define-key map "p" 'previous-line) 146 (define-key map "p" 'previous-line)
147 (define-key map "S" 'tabulated-list-sort-column) 147 (define-key map "S" 'tabulated-list-sort)
148 (define-key map [follow-link] 'mouse-face) 148 (define-key map [follow-link] 'mouse-face)
149 (define-key map [mouse-2] 'mouse-select-window) 149 (define-key map [mouse-2] 'mouse-select-window)
150 map) 150 map)
@@ -174,8 +174,7 @@ If ADVANCE is non-nil, move forward by one line afterwards."
174 mouse-face highlight 174 mouse-face highlight
175 keymap ,tabulated-list-sort-button-map)) 175 keymap ,tabulated-list-sort-button-map))
176 (cols nil)) 176 (cols nil))
177 (if (> tabulated-list-padding 0) 177 (push (propertize " " 'display `(space :align-to ,x)) cols)
178 (push (propertize " " 'display `(space :align-to ,x)) cols))
179 (dotimes (n (length tabulated-list-format)) 178 (dotimes (n (length tabulated-list-format))
180 (let* ((col (aref tabulated-list-format n)) 179 (let* ((col (aref tabulated-list-format n))
181 (label (nth 0 col)) 180 (label (nth 0 col))
@@ -183,9 +182,6 @@ If ADVANCE is non-nil, move forward by one line afterwards."
183 (props (nthcdr 3 col)) 182 (props (nthcdr 3 col))
184 (pad-right (or (plist-get props :pad-right) 1))) 183 (pad-right (or (plist-get props :pad-right) 1)))
185 (setq x (+ x pad-right width)) 184 (setq x (+ x pad-right width))
186 (and (<= tabulated-list-padding 0)
187 (= n 0)
188 (setq label (concat " " label)))
189 (push 185 (push
190 (cond 186 (cond
191 ;; An unsortable column 187 ;; An unsortable column
@@ -402,7 +398,7 @@ this is the vector stored within it."
402 (with-current-buffer (window-buffer (posn-window pos)) 398 (with-current-buffer (window-buffer (posn-window pos))
403 (tabulated-list--sort-by-column-name name)))) 399 (tabulated-list--sort-by-column-name name))))
404 400
405(defun tabulated-list-sort-column (&optional n) 401(defun tabulated-list-sort (&optional n)
406 "Sort Tabulated List entries by the column at point. 402 "Sort Tabulated List entries by the column at point.
407With a numeric prefix argument N, sort the Nth column." 403With a numeric prefix argument N, sort the Nth column."
408 (interactive "P") 404 (interactive "P")
@@ -424,7 +420,6 @@ With a numeric prefix argument N, sort the Nth column."
424 420
425;;; The mode definition: 421;;; The mode definition:
426 422
427;;;###autoload
428(define-derived-mode tabulated-list-mode special-mode "Tabulated" 423(define-derived-mode tabulated-list-mode special-mode "Tabulated"
429 "Generic major mode for browsing a list of items. 424 "Generic major mode for browsing a list of items.
430This mode is usually not used directly; instead, other major 425This mode is usually not used directly; instead, other major
diff --git a/lisp/loadup.el b/lisp/loadup.el
index f7ffa27a9ed..5f005a4e709 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -188,6 +188,7 @@
188(load "textmodes/fill") 188(load "textmodes/fill")
189 189
190(load "replace") 190(load "replace")
191(load "emacs-lisp/tabulated-list")
191(load "buff-menu") 192(load "buff-menu")
192 193
193(if (fboundp 'x-create-frame) 194(if (fboundp 'x-create-frame)
diff --git a/src/ChangeLog b/src/ChangeLog
index a4d7bb64919..f5811569d0d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
12012-05-06 Chong Yidong <cyd@gnu.org>
2
3 * lisp.mk (lisp): Update.
4
12012-05-05 Jim Meyering <meyering@redhat.com> 52012-05-05 Jim Meyering <meyering@redhat.com>
2 6
3 * w32font.c (fill_in_logfont): NUL-terminate a string (Bug#11372). 7 * w32font.c (fill_in_logfont): NUL-terminate a string (Bug#11372).
diff --git a/src/lisp.mk b/src/lisp.mk
index 4895ca40959..ead1abcbaae 100644
--- a/src/lisp.mk
+++ b/src/lisp.mk
@@ -129,6 +129,7 @@ lisp = \
129 $(lispsource)/textmodes/text-mode.elc \ 129 $(lispsource)/textmodes/text-mode.elc \
130 $(lispsource)/textmodes/fill.elc \ 130 $(lispsource)/textmodes/fill.elc \
131 $(lispsource)/replace.elc \ 131 $(lispsource)/replace.elc \
132 $(lispsource)/emacs-lisp/tabulated-list.elc \
132 $(lispsource)/buff-menu.elc \ 133 $(lispsource)/buff-menu.elc \
133 $(lispsource)/fringe.elc \ 134 $(lispsource)/fringe.elc \
134 $(lispsource)/emacs-lisp/regexp-opt.elc \ 135 $(lispsource)/emacs-lisp/regexp-opt.elc \