Mention checking autotools when testing tarfile.
[bpt/emacs.git] / lisp / ibuffer.el
CommitLineData
25d2f683
CW
1;;; ibuffer.el --- operate on buffers like dired
2
ab422c4d 3;; Copyright (C) 2000-2013 Free Software Foundation, Inc.
25d2f683
CW
4
5;; Author: Colin Walters <walters@verbum.org>
4e4a724c 6;; Maintainer: John Paul Wallington <jpw@gnu.org>
25d2f683 7;; Created: 8 Sep 2000
25d2f683 8;; Keywords: buffer, convenience
25d2f683 9
b5cd37ea 10;; This file is part of GNU Emacs.
25d2f683 11
eb3fa2cf
GM
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
25d2f683 16
eb3fa2cf
GM
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
25d2f683
CW
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25d2f683
CW
24
25;;; Commentary:
26
27;; ibuffer.el is an advanced replacement for the `buffer-menu' which
28;; is normally distributed with Emacs. Its interface is intended to
29;; be analogous to that of Dired.
30
31;;; Code:
32
33(eval-when-compile
a464a6c7 34 (require 'cl-lib)
25d2f683
CW
35 (require 'ibuf-macs)
36 (require 'dired))
37
730da5b2 38(require 'font-core)
fd225d80 39
735d7026
JB
40;; These come from ibuf-ext.el, which can not be require'd at compile time
41;; because it has a recursive dependency on ibuffer.el
42(defvar ibuffer-auto-mode)
43(defvar ibuffer-cached-filter-formats)
44(defvar ibuffer-compiled-filter-formats)
45(defvar ibuffer-filter-format-alist)
46(defvar ibuffer-filter-group-kill-ring)
47(defvar ibuffer-filter-groups)
48(defvar ibuffer-filtering-qualifiers)
6d11a78b 49(defvar ibuffer-header-line-format)
735d7026
JB
50(defvar ibuffer-hidden-filter-groups)
51(defvar ibuffer-inline-columns)
52(defvar ibuffer-show-empty-filter-groups)
53(defvar ibuffer-tmp-hide-regexps)
54(defvar ibuffer-tmp-show-regexps)
63f0a166 55
2ead9289 56(declare-function ibuffer-mark-on-buffer "ibuf-ext"
004a00f4 57 (func &optional ibuffer-mark-on-buffer-mark group))
2ead9289 58(declare-function ibuffer-generate-filter-groups "ibuf-ext"
004a00f4
DN
59 (bmarklist &optional noempty nodefault))
60(declare-function ibuffer-format-filter-group-data "ibuf-ext" (filter))
61
25d2f683 62(defgroup ibuffer nil
cf20dee0
CY
63 "Advanced replacement for `buffer-menu'.
64Ibuffer lets you operate on buffers in a Dired-like way,
65with the ability to sort, mark by regular expression,
66and filter displayed buffers by various criteria."
bf247b6e 67 :version "22.1"
25d2f683
CW
68 :group 'convenience)
69
ac3c7293
JPW
70(defcustom ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide)
71 " " (size 9 -1 :right)
b9debd54 72 " " (mode 16 16 :left :elide) " " filename-and-process)
25d2f683
CW
73 (mark " " (name 16 -1) " " filename))
74 "A list of ways to display buffer lines.
75
76With Ibuffer, you are not limited to displaying just certain
77attributes of a buffer such as size, name, and mode in a particular
cba63a2d 78order. Through this variable, you can completely customize and
25d2f683
CW
79control the appearance of an Ibuffer buffer. See also
80`define-ibuffer-column', which allows you to define your own columns
81for display.
82
83This variable has the form
2e4fae7d 84 ((COLUMN COLUMN ...) (COLUMN COLUMN ...) ...)
25d2f683
CW
85Each element in `ibuffer-formats' should be a list containing COLUMN
86specifiers. A COLUMN can be any of the following:
87
88 SYMBOL - A symbol naming the column. Predefined columns are:
89 mark modified read-only name size mode process filename
90 When you define your own columns using `define-ibuffer-column', just
91 use their name like the predefined columns here. This entry can
92 also be a function of two arguments, which should return a string.
93 The first argument is the buffer object, and the second is the mark
94 on that buffer.
95 or
96 \"STRING\" - A literal string to display.
97 or
98 (SYMBOL MIN-SIZE MAX-SIZE &optional ALIGN ELIDE) - SYMBOL is a
99 symbol naming the column, and MIN-SIZE and MAX-SIZE are integers (or
100 functions of no arguments returning an integer) which constrict the
101 size of a column. If MAX-SIZE is -1, there is no upper bound. The
102 default values are 0 and -1, respectively. If MIN-SIZE is negative,
103 use the end of the string. The optional element ALIGN describes the
104 alignment of the column; it can be :left, :center or :right. The
105 optional element ELIDE describes whether or not to elide the column
106 if it is too long; valid values are :elide and nil. The default is
107 nil (don't elide).
108
109Some example of valid entries in `ibuffer-formats', with
110description (also, feel free to try them out, and experiment with your
111own!):
112
113 (mark \" \" name)
114 This format just displays the current mark (if any) and the name of
115 the buffer, separated by a space.
116 (mark modified read-only \" \" (name 16 16 :left) \" \" (size 6 -1 :right))
117 This format displays the current mark (if any), its modification and
118 read-only status, as well as the name of the buffer and its size. In
119 this format, the name is restricted to 16 characters (longer names
523304ed 120 will be truncated, and shorter names will be padded with spaces), and
cba63a2d 121 the name is also aligned to the left. The size of the buffer will
25d2f683
CW
122 be padded with spaces up to a minimum of six characters, but there is
123 no upper limit on its size. The size will also be aligned to the
124 right.
125
865fe16f
CY
126Thus, if you wanted to use these two formats, the appropriate
127value for this variable would be
25d2f683 128
865fe16f
CY
129 '((mark \" \" name)
130 (mark modified read-only
131 (name 16 16 :left)
132 (size 6 -1 :right)))
25d2f683
CW
133
134Using \\[ibuffer-switch-format], you can rotate the display between
135the specified formats in the list."
136 :type '(repeat sexp)
137 :group 'ibuffer)
138
139(defcustom ibuffer-always-compile-formats (featurep 'bytecomp)
140 "If non-nil, then use the byte-compiler to optimize `ibuffer-formats'.
141This will increase the redisplay speed, at the cost of loading the
142elisp byte-compiler."
143 :type 'boolean
144 :group 'ibuffer)
145
146(defcustom ibuffer-fontification-alist
40c10465 147 `((10 buffer-read-only font-lock-constant-face)
9fe14abe
JPW
148 (15 (and buffer-file-name
149 (string-match ibuffer-compressed-file-name-regexp
150 buffer-file-name))
151 font-lock-doc-face)
152 (20 (string-match "^*" (buffer-name)) font-lock-keyword-face)
153 (25 (and (string-match "^ " (buffer-name))
da337a28
JPW
154 (null buffer-file-name))
155 italic)
9fe14abe
JPW
156 (30 (memq major-mode ibuffer-help-buffer-modes) font-lock-comment-face)
157 (35 (eq major-mode 'dired-mode) font-lock-function-name-face))
25d2f683
CW
158 "An alist describing how to fontify buffers.
159Each element should be of the form (PRIORITY FORM FACE), where
160PRIORITY is an integer, FORM is an arbitrary form to evaluate in the
161buffer, and FACE is the face to use for fontification. If the FORM
162evaluates to non-nil, then FACE will be put on the buffer name. The
fd225d80
CW
163element with the highest PRIORITY takes precedence.
164
4e4a724c 165If you change this variable, you must kill the Ibuffer buffer and
fd225d80 166recreate it for the change to take effect."
25d2f683
CW
167 :type '(repeat
168 (list (integer :tag "Priority")
169 (sexp :tag "Test Form")
170 face))
171 :group 'ibuffer)
172
173(defcustom ibuffer-use-other-window nil
7ad5b902 174 "If non-nil, display Ibuffer in another window by default."
25d2f683
CW
175 :type 'boolean
176 :group 'ibuffer)
177
178(defcustom ibuffer-default-shrink-to-minimum-size nil
179 "If non-nil, minimize the size of the Ibuffer window by default."
180 :type 'boolean
181 :group 'ibuffer)
182(defvar ibuffer-shrink-to-minimum-size nil)
183
0740098c
JPW
184(defcustom ibuffer-display-summary t
185 "If non-nil, summarize Ibuffer columns."
186 :type 'boolean
187 :group 'ibuffer)
188
3eda3649
CW
189(defcustom ibuffer-truncate-lines t
190 "If non-nil, do not display continuation lines."
191 :type 'boolean
192 :group 'ibuffer)
193
25d2f683
CW
194(defcustom ibuffer-case-fold-search case-fold-search
195 "If non-nil, ignore case when searching."
196 :type 'boolean
197 :group 'ibuffer)
198
199(defcustom ibuffer-default-sorting-mode 'recency
200 "The criteria by which to sort the buffers.
201
4e4a724c
JPW
202Note that this variable is local to each Ibuffer buffer. Thus, you
203can have multiple Ibuffer buffers open, each with a different sorted
25d2f683
CW
204view of the buffers."
205 :type '(choice (const :tag "Last view time" :value recency)
206 (const :tag "Lexicographic" :value alphabetic)
207 (const :tag "Buffer size" :value size)
d5794180 208 (const :tag "File name" :value filename/process)
25d2f683
CW
209 (const :tag "Major mode" :value major-mode))
210 :group 'ibuffer)
211(defvar ibuffer-sorting-mode nil)
e7820654 212(defvar ibuffer-last-sorting-mode nil)
25d2f683
CW
213
214(defcustom ibuffer-default-sorting-reversep nil
215 "If non-nil, reverse the default sorting order."
216 :type 'boolean
217 :group 'ibuffer)
218(defvar ibuffer-sorting-reversep nil)
219
220(defcustom ibuffer-elide-long-columns nil
972b8f82 221 "If non-nil, then elide column entries which exceed their max length."
25d2f683
CW
222 :type 'boolean
223 :group 'ibuffer)
972b8f82
JB
224(make-obsolete-variable 'ibuffer-elide-long-columns
225 "use the :elide argument of `ibuffer-formats'."
226 "22.1")
25d2f683
CW
227
228(defcustom ibuffer-eliding-string "..."
229 "The string to use for eliding long columns."
230 :type 'string
231 :group 'ibuffer)
232
233(defcustom ibuffer-maybe-show-predicates `(,(lambda (buf)
234 (and (string-match "^ " (buffer-name buf))
235 (null buffer-file-name))))
4e4a724c
JPW
236 "A list of predicates for buffers to display conditionally.
237
238A predicate can be a regexp or a function.
25d2f683
CW
239If a regexp, then it will be matched against the buffer's name.
240If a function, it will be called with the buffer as an argument, and
241should return non-nil if this buffer should be shown.
242
957237cb 243Viewing of buffers hidden because of these predicates may be customized
bf247b6e 244via `ibuffer-default-display-maybe-show-predicates' and is toggled by
957237cb
JPW
245giving a non-nil prefix argument to `ibuffer-update'.
246Note that this specialized filtering occurs before real filtering."
25d2f683
CW
247 :type '(repeat (choice regexp function))
248 :group 'ibuffer)
249
957237cb
JPW
250(defcustom ibuffer-default-display-maybe-show-predicates nil
251 "Non-nil means show buffers that match `ibuffer-maybe-show-predicates'."
252 :type 'boolean
253 :group 'ibuffer)
254
255(defvar ibuffer-display-maybe-show-predicates nil)
256
25d2f683
CW
257(defvar ibuffer-current-format nil)
258
0ce780e1
CW
259(defcustom ibuffer-movement-cycle t
260 "If non-nil, then forward and backwards movement commands cycle."
261 :type 'boolean
262 :group 'ibuffer)
263
25d2f683
CW
264(defcustom ibuffer-modified-char ?*
265 "The character to display for modified buffers."
266 :type 'character
267 :group 'ibuffer)
268
269(defcustom ibuffer-read-only-char ?%
270 "The character to display for read-only buffers."
271 :type 'character
272 :group 'ibuffer)
273
274(defcustom ibuffer-marked-char ?>
275 "The character to display for marked buffers."
276 :type 'character
277 :group 'ibuffer)
278
279(defcustom ibuffer-deletion-char ?D
280 "The character to display for buffers marked for deletion."
281 :type 'character
282 :group 'ibuffer)
283
284(defcustom ibuffer-expert nil
285 "If non-nil, don't ask for confirmation of \"dangerous\" operations."
286 :type 'boolean
287 :group 'ibuffer)
288
289(defcustom ibuffer-view-ibuffer nil
290 "If non-nil, display the current Ibuffer buffer itself.
291Note that this has a drawback - the data about the current Ibuffer
292buffer will most likely be inaccurate. This includes modification
293state, size, etc."
294 :type 'boolean
295 :group 'ibuffer)
296
297(defcustom ibuffer-always-show-last-buffer nil
4e4a724c
JPW
298 "If non-nil, always display the previous buffer.
299This variable takes precedence over filtering, and even
25d2f683
CW
300`ibuffer-never-show-predicates'."
301 :type '(choice (const :tag "Always" :value t)
302 (const :tag "Never" :value nil)
303 (const :tag "Always except minibuffer" :value :nomini))
304 :group 'ibuffer)
305
0bdd7ae4
JPW
306(defcustom ibuffer-jump-offer-only-visible-buffers nil
307 "If non-nil, only offer buffers visible in the Ibuffer buffer
308in completion lists of the `ibuffer-jump-to-buffer' command."
309 :type 'boolean
310 :group 'ibuffer)
311
25d2f683 312(defcustom ibuffer-use-header-line (boundp 'header-line-format)
7ad5b902 313 "If non-nil, display a header line containing current filters."
25d2f683
CW
314 :type 'boolean
315 :group 'ibuffer)
316
317(defcustom ibuffer-default-directory nil
4e4a724c 318 "The default directory to use for a new Ibuffer buffer.
2e4fae7d 319If nil, inherit the directory of the buffer in which `ibuffer' was
25d2f683
CW
320called. Otherwise, this variable should be a string naming a
321directory, like `default-directory'."
322 :type '(choice (const :tag "Inherit" :value nil)
323 string)
324 :group 'ibuffer)
325
4e4a724c
JPW
326(defcustom ibuffer-help-buffer-modes
327 '(help-mode apropos-mode Info-mode Info-edit-mode)
60356fb5
CW
328 "List of \"Help\" major modes."
329 :type '(repeat function)
330 :group 'ibuffer)
331
9fe14abe 332(defcustom ibuffer-compressed-file-name-regexp
4c964351 333 "\\.\\(arj\\|bgz\\|bz2\\|gz\\|lzh\\|taz\\|tgz\\|xz\\|zip\\|z\\)$"
9fe14abe 334 "Regexp to match compressed file names."
4c964351 335 :version "24.1" ; added xz
9fe14abe 336 :type 'regexp
c7f5c0a8 337 :group 'ibuffer)
9fe14abe 338
cd6ef82d
GM
339(define-obsolete-variable-alias 'ibuffer-hooks 'ibuffer-hook "22.1")
340
e9e96ba0 341(defcustom ibuffer-hook nil
4e4a724c 342 "Hook run when `ibuffer' is called."
25d2f683
CW
343 :type 'hook
344 :group 'ibuffer)
cd6ef82d
GM
345
346(define-obsolete-variable-alias 'ibuffer-mode-hooks 'ibuffer-mode-hook "22.1")
25d2f683 347
e9e96ba0 348(defcustom ibuffer-mode-hook nil
4e4a724c 349 "Hook run upon entry into `ibuffer-mode'."
25d2f683
CW
350 :type 'hook
351 :group 'ibuffer)
352
4e4a724c
JPW
353(defcustom ibuffer-load-hook nil
354 "Hook run when Ibuffer is loaded."
355 :type 'hook
356 :group 'ibuffer)
357
f22f4808 358(defcustom ibuffer-marked-face 'warning
25d2f683
CW
359 "Face used for displaying marked buffers."
360 :type 'face
361 :group 'ibuffer)
362
f22f4808 363(defcustom ibuffer-deletion-face 'error
25d2f683
CW
364 "Face used for displaying buffers marked for deletion."
365 :type 'face
366 :group 'ibuffer)
367
368(defcustom ibuffer-title-face 'font-lock-type-face
369 "Face used for the title string."
370 :type 'face
371 :group 'ibuffer)
372
b5cd37ea
CW
373(defcustom ibuffer-filter-group-name-face 'bold
374 "Face used for displaying filtering group names."
375 :type 'face
376 :group 'ibuffer)
377
25d2f683
CW
378(defcustom ibuffer-directory-abbrev-alist nil
379 "An alist of file name abbreviations like `directory-abbrev-alist'."
380 :type '(repeat (cons :format "%v"
381 :value ("" . "")
382 (regexp :tag "From")
383 (regexp :tag "To")))
384 :group 'ibuffer)
385
b016851c
SM
386(defvar ibuffer-mode-groups-popup
387 (let ((groups-map (make-sparse-keymap "Filter Groups")))
388 ;; Filter groups
389
390 (define-key-after groups-map [filters-to-filter-group]
391 '(menu-item "Create filter group from current filters..."
392 ibuffer-filters-to-filter-group
393 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
394 (define-key-after groups-map [forward-filter-group]
395 '(menu-item "Move point to the next filter group"
396 ibuffer-forward-filter-group))
397 (define-key-after groups-map [backward-filter-group]
398 '(menu-item "Move point to the previous filter group"
399 ibuffer-backward-filter-group))
400 (define-key-after groups-map [jump-to-filter-group]
401 '(menu-item "Move point to a specific filter group..."
402 ibuffer-jump-to-filter-group))
403 (define-key-after groups-map [kill-filter-group]
404 '(menu-item "Kill filter group named..."
405 ibuffer-kill-filter-group
406 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
407 (define-key-after groups-map [yank-filter-group]
408 '(menu-item "Yank last killed filter group before..."
409 ibuffer-yank-filter-group
410 :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
411 (define-key-after groups-map [pop-filter-group]
412 '(menu-item "Remove top filter group"
413 ibuffer-pop-filter-group
414 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
415 (define-key-after groups-map [clear-filter-groups]
416 '(menu-item "Remove all filter groups"
417 ibuffer-clear-filter-groups
418 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
419 (define-key-after groups-map [pop-filter-group]
420 '(menu-item "Decompose filter group..."
421 ibuffer-pop-filter-group
422 :help "\"Unmake\" a filter group"
423 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
424 (define-key-after groups-map [save-filter-groups]
425 '(menu-item "Save current filter groups permanently..."
426 ibuffer-save-filter-groups
427 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)
c80e3b4a 428 :help "Use a mnemonic name to store current filter groups"))
b016851c
SM
429 (define-key-after groups-map [switch-to-saved-filter-groups]
430 '(menu-item "Restore permanently saved filters..."
431 ibuffer-switch-to-saved-filter-groups
432 :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)
433 :help "Replace current filters with a saved stack"))
434 (define-key-after groups-map [delete-saved-filter-groups]
435 '(menu-item "Delete permanently saved filter groups..."
436 ibuffer-delete-saved-filter-groups
437 :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)))
438 (define-key-after groups-map [set-filter-groups-by-mode]
439 '(menu-item "Set current filter groups to filter by mode"
440 ibuffer-set-filter-groups-by-mode))
441
442 groups-map))
4e4a724c 443
b016851c
SM
444(defvar ibuffer-mode-map
445 (let ((map (make-keymap)))
25d2f683
CW
446 (define-key map (kbd "0") 'digit-argument)
447 (define-key map (kbd "1") 'digit-argument)
448 (define-key map (kbd "2") 'digit-argument)
449 (define-key map (kbd "3") 'digit-argument)
450 (define-key map (kbd "4") 'digit-argument)
451 (define-key map (kbd "5") 'digit-argument)
452 (define-key map (kbd "6") 'digit-argument)
453 (define-key map (kbd "7") 'digit-argument)
454 (define-key map (kbd "8") 'digit-argument)
455 (define-key map (kbd "9") 'digit-argument)
456
457 (define-key map (kbd "m") 'ibuffer-mark-forward)
458 (define-key map (kbd "t") 'ibuffer-toggle-marks)
459 (define-key map (kbd "u") 'ibuffer-unmark-forward)
460 (define-key map (kbd "=") 'ibuffer-diff-with-file)
461 (define-key map (kbd "j") 'ibuffer-jump-to-buffer)
0bdd7ae4 462 (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
78176075
JL
463 (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch)
464 (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp)
25d2f683
CW
465 (define-key map (kbd "DEL") 'ibuffer-unmark-backward)
466 (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
467 (define-key map (kbd "* *") 'ibuffer-unmark-all)
468 (define-key map (kbd "* M") 'ibuffer-mark-by-mode)
469 (define-key map (kbd "* m") 'ibuffer-mark-modified-buffers)
470 (define-key map (kbd "* u") 'ibuffer-mark-unsaved-buffers)
471 (define-key map (kbd "* s") 'ibuffer-mark-special-buffers)
472 (define-key map (kbd "* r") 'ibuffer-mark-read-only-buffers)
473 (define-key map (kbd "* /") 'ibuffer-mark-dired-buffers)
474 (define-key map (kbd "* e") 'ibuffer-mark-dissociated-buffers)
475 (define-key map (kbd "* h") 'ibuffer-mark-help-buffers)
9fe14abe 476 (define-key map (kbd "* z") 'ibuffer-mark-compressed-file-buffers)
25d2f683 477 (define-key map (kbd ".") 'ibuffer-mark-old-buffers)
71296446 478
25d2f683
CW
479 (define-key map (kbd "d") 'ibuffer-mark-for-delete)
480 (define-key map (kbd "C-d") 'ibuffer-mark-for-delete-backwards)
481 (define-key map (kbd "k") 'ibuffer-mark-for-delete)
482 (define-key map (kbd "x") 'ibuffer-do-kill-on-deletion-marks)
71296446 483
25d2f683
CW
484 ;; immediate operations
485 (define-key map (kbd "n") 'ibuffer-forward-line)
486 (define-key map (kbd "SPC") 'forward-line)
487 (define-key map (kbd "p") 'ibuffer-backward-line)
488 (define-key map (kbd "M-}") 'ibuffer-forward-next-marked)
489 (define-key map (kbd "M-{") 'ibuffer-backwards-next-marked)
490 (define-key map (kbd "l") 'ibuffer-redisplay)
491 (define-key map (kbd "g") 'ibuffer-update)
492 (define-key map "`" 'ibuffer-switch-format)
493 (define-key map "-" 'ibuffer-add-to-tmp-hide)
494 (define-key map "+" 'ibuffer-add-to-tmp-show)
495 (define-key map "b" 'ibuffer-bury-buffer)
496 (define-key map (kbd ",") 'ibuffer-toggle-sorting-mode)
497 (define-key map (kbd "s i") 'ibuffer-invert-sorting)
498 (define-key map (kbd "s a") 'ibuffer-do-sort-by-alphabetic)
499 (define-key map (kbd "s v") 'ibuffer-do-sort-by-recency)
500 (define-key map (kbd "s s") 'ibuffer-do-sort-by-size)
d5794180 501 (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process)
25d2f683
CW
502 (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
503
d81bd059
SM
504 (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode)
505 (define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode)
25d2f683
CW
506 (define-key map (kbd "/ n") 'ibuffer-filter-by-name)
507 (define-key map (kbd "/ c") 'ibuffer-filter-by-content)
508 (define-key map (kbd "/ e") 'ibuffer-filter-by-predicate)
509 (define-key map (kbd "/ f") 'ibuffer-filter-by-filename)
510 (define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt)
511 (define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt)
512 (define-key map (kbd "/ r") 'ibuffer-switch-to-saved-filters)
513 (define-key map (kbd "/ a") 'ibuffer-add-saved-filters)
514 (define-key map (kbd "/ x") 'ibuffer-delete-saved-filters)
515 (define-key map (kbd "/ d") 'ibuffer-decompose-filter)
516 (define-key map (kbd "/ s") 'ibuffer-save-filters)
517 (define-key map (kbd "/ p") 'ibuffer-pop-filter)
518 (define-key map (kbd "/ !") 'ibuffer-negate-filter)
519 (define-key map (kbd "/ t") 'ibuffer-exchange-filters)
520 (define-key map (kbd "/ TAB") 'ibuffer-exchange-filters)
521 (define-key map (kbd "/ o") 'ibuffer-or-filter)
b5cd37ea
CW
522 (define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group)
523 (define-key map (kbd "/ P") 'ibuffer-pop-filter-group)
2bd26a6f 524 (define-key map (kbd "/ D") 'ibuffer-decompose-filter-group)
25d2f683 525 (define-key map (kbd "/ /") 'ibuffer-filter-disable)
b5cd37ea
CW
526
527 (define-key map (kbd "M-n") 'ibuffer-forward-filter-group)
77aec221 528 (define-key map "\t" 'ibuffer-forward-filter-group)
b5cd37ea 529 (define-key map (kbd "M-p") 'ibuffer-backward-filter-group)
77aec221 530 (define-key map [backtab] 'ibuffer-backward-filter-group)
b5cd37ea 531 (define-key map (kbd "M-j") 'ibuffer-jump-to-filter-group)
cba63a2d
CW
532 (define-key map (kbd "C-k") 'ibuffer-kill-line)
533 (define-key map (kbd "C-y") 'ibuffer-yank)
534 (define-key map (kbd "/ S") 'ibuffer-save-filter-groups)
535 (define-key map (kbd "/ R") 'ibuffer-switch-to-saved-filter-groups)
536 (define-key map (kbd "/ X") 'ibuffer-delete-saved-filter-groups)
537 (define-key map (kbd "/ \\") 'ibuffer-clear-filter-groups)
71296446 538
25d2f683
CW
539 (define-key map (kbd "q") 'ibuffer-quit)
540 (define-key map (kbd "h") 'describe-mode)
541 (define-key map (kbd "?") 'describe-mode)
542
543 (define-key map (kbd "% n") 'ibuffer-mark-by-name-regexp)
544 (define-key map (kbd "% m") 'ibuffer-mark-by-mode-regexp)
545 (define-key map (kbd "% f") 'ibuffer-mark-by-file-name-regexp)
71296446 546
25d2f683
CW
547 (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)
548
549 (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe)
550 (define-key map (kbd "!") 'ibuffer-do-shell-command-file)
551 (define-key map (kbd "~") 'ibuffer-do-toggle-modified)
552 ;; marked operations
553 (define-key map (kbd "A") 'ibuffer-do-view)
554 (define-key map (kbd "D") 'ibuffer-do-delete)
555 (define-key map (kbd "E") 'ibuffer-do-eval)
556 (define-key map (kbd "F") 'ibuffer-do-shell-command-file)
557 (define-key map (kbd "I") 'ibuffer-do-query-replace-regexp)
558 (define-key map (kbd "H") 'ibuffer-do-view-other-frame)
559 (define-key map (kbd "N") 'ibuffer-do-shell-command-pipe-replace)
560 (define-key map (kbd "M") 'ibuffer-do-toggle-modified)
561 (define-key map (kbd "O") 'ibuffer-do-occur)
562 (define-key map (kbd "P") 'ibuffer-do-print)
563 (define-key map (kbd "Q") 'ibuffer-do-query-replace)
564 (define-key map (kbd "R") 'ibuffer-do-rename-uniquely)
565 (define-key map (kbd "S") 'ibuffer-do-save)
566 (define-key map (kbd "T") 'ibuffer-do-toggle-read-only)
567 (define-key map (kbd "U") 'ibuffer-do-replace-regexp)
568 (define-key map (kbd "V") 'ibuffer-do-revert)
569 (define-key map (kbd "W") 'ibuffer-do-view-and-eval)
570 (define-key map (kbd "X") 'ibuffer-do-shell-command-pipe)
71296446 571
25d2f683
CW
572 (define-key map (kbd "k") 'ibuffer-do-kill-lines)
573 (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)
574
575 (define-key map (kbd "RET") 'ibuffer-visit-buffer)
576 (define-key map (kbd "e") 'ibuffer-visit-buffer)
577 (define-key map (kbd "f") 'ibuffer-visit-buffer)
578 (define-key map (kbd "C-x C-f") 'ibuffer-find-file)
579 (define-key map (kbd "o") 'ibuffer-visit-buffer-other-window)
580 (define-key map (kbd "C-o") 'ibuffer-visit-buffer-other-window-noselect)
581 (define-key map (kbd "M-o") 'ibuffer-visit-buffer-1-window)
582 (define-key map (kbd "v") 'ibuffer-do-view)
583 (define-key map (kbd "C-x v") 'ibuffer-do-view-horizontally)
584 (define-key map (kbd "C-c C-a") 'ibuffer-auto-mode)
585 (define-key map (kbd "C-x 4 RET") 'ibuffer-visit-buffer-other-window)
586 (define-key map (kbd "C-x 5 RET") 'ibuffer-visit-buffer-other-frame)
587
588 (define-key map [menu-bar view]
589 (cons "View" (make-sparse-keymap "View")))
590
591 (define-key-after map [menu-bar view visit-buffer]
592 '(menu-item "View this buffer" ibuffer-visit-buffer))
593 (define-key-after map [menu-bar view visit-buffer-other-window]
594 '(menu-item "View (other window)" ibuffer-visit-buffer-other-window))
595 (define-key-after map [menu-bar view visit-buffer-other-frame]
596 '(menu-item "View (other frame)" ibuffer-visit-buffer-other-frame))
597 (define-key-after map [menu-bar view ibuffer-update]
598 '(menu-item "Update" ibuffer-update
b016851c 599 :help "Regenerate the list of buffers"))
25d2f683
CW
600 (define-key-after map [menu-bar view switch-format]
601 '(menu-item "Switch display format" ibuffer-switch-format
b016851c 602 :help "Toggle between available values of `ibuffer-formats'"))
25d2f683
CW
603
604 (define-key-after map [menu-bar view dashes]
605 '("--"))
606
607 (define-key-after map [menu-bar view sort]
608 (cons "Sort" (make-sparse-keymap "Sort")))
609
610 (define-key-after map [menu-bar view sort do-sort-by-major-mode]
cba63a2d 611 '(menu-item "Sort by major mode" ibuffer-do-sort-by-major-mode))
25d2f683 612 (define-key-after map [menu-bar view sort do-sort-by-size]
cba63a2d 613 '(menu-item "Sort by buffer size" ibuffer-do-sort-by-size))
25d2f683
CW
614 (define-key-after map [menu-bar view sort do-sort-by-alphabetic]
615 '(menu-item "Sort lexicographically" ibuffer-do-sort-by-alphabetic
b016851c 616 :help "Sort by the alphabetic order of buffer name"))
25d2f683
CW
617 (define-key-after map [menu-bar view sort do-sort-by-recency]
618 '(menu-item "Sort by view time" ibuffer-do-sort-by-recency
b016851c 619 :help "Sort by the last time the buffer was displayed"))
4e4a724c
JPW
620 (define-key-after map [menu-bar view sort dashes]
621 '("--"))
25d2f683
CW
622 (define-key-after map [menu-bar view sort invert-sorting]
623 '(menu-item "Reverse sorting order" ibuffer-invert-sorting))
624 (define-key-after map [menu-bar view sort toggle-sorting-mode]
625 '(menu-item "Switch sorting mode" ibuffer-toggle-sorting-mode
b016851c 626 :help "Switch between the various sorting criteria"))
25d2f683
CW
627
628 (define-key-after map [menu-bar view filter]
629 (cons "Filter" (make-sparse-keymap "Filter")))
630
631 (define-key-after map [menu-bar view filter filter-disable]
05cc03af 632 '(menu-item "Disable all filtering" ibuffer-filter-disable
b016851c 633 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
25d2f683 634 (define-key-after map [menu-bar view filter filter-by-mode]
84acf328
GM
635 '(menu-item "Add filter by any major mode..." ibuffer-filter-by-mode))
636 (define-key-after map [menu-bar view filter filter-by-used-mode]
637 '(menu-item "Add filter by a major mode in use..."
b016851c 638 ibuffer-filter-by-used-mode))
a1d3e07e
GM
639 (define-key-after map [menu-bar view filter filter-by-derived-mode]
640 '(menu-item "Add filter by derived mode..."
641 ibuffer-filter-by-derived-mode))
25d2f683 642 (define-key-after map [menu-bar view filter filter-by-name]
cba63a2d 643 '(menu-item "Add filter by buffer name..." ibuffer-filter-by-name))
25d2f683 644 (define-key-after map [menu-bar view filter filter-by-filename]
cba63a2d 645 '(menu-item "Add filter by filename..." ibuffer-filter-by-filename))
25d2f683 646 (define-key-after map [menu-bar view filter filter-by-size-lt]
cba63a2d 647 '(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt))
25d2f683 648 (define-key-after map [menu-bar view filter filter-by-size-gt]
b016851c
SM
649 '(menu-item "Add filter by size greater than..."
650 ibuffer-filter-by-size-gt))
25d2f683 651 (define-key-after map [menu-bar view filter filter-by-content]
b016851c
SM
652 '(menu-item "Add filter by content (regexp)..."
653 ibuffer-filter-by-content))
25d2f683 654 (define-key-after map [menu-bar view filter filter-by-predicate]
b016851c
SM
655 '(menu-item "Add filter by Lisp predicate..."
656 ibuffer-filter-by-predicate))
25d2f683 657 (define-key-after map [menu-bar view filter pop-filter]
05cc03af 658 '(menu-item "Remove top filter" ibuffer-pop-filter
b016851c 659 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
25d2f683
CW
660 (define-key-after map [menu-bar view filter or-filter]
661 '(menu-item "OR top two filters" ibuffer-or-filter
b016851c
SM
662 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
663 (cdr ibuffer-filtering-qualifiers))
664 :help
665 "Create a new filter which is the logical OR of the top two filters"))
25d2f683 666 (define-key-after map [menu-bar view filter negate-filter]
05cc03af 667 '(menu-item "Negate top filter" ibuffer-negate-filter
b016851c 668 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
25d2f683
CW
669 (define-key-after map [menu-bar view filter decompose-filter]
670 '(menu-item "Decompose top filter" ibuffer-decompose-filter
b016851c
SM
671 :enable (and (featurep 'ibuf-ext)
672 (memq (car ibuffer-filtering-qualifiers) '(or saved not)))
673 :help "Break down a complex filter like OR or NOT"))
25d2f683 674 (define-key-after map [menu-bar view filter exchange-filters]
05cc03af 675 '(menu-item "Swap top two filters" ibuffer-exchange-filters
b016851c
SM
676 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
677 (cdr ibuffer-filtering-qualifiers))))
25d2f683
CW
678 (define-key-after map [menu-bar view filter save-filters]
679 '(menu-item "Save current filters permanently..." ibuffer-save-filters
b016851c 680 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
c80e3b4a 681 :help "Use a mnemonic name to store current filter stack"))
25d2f683 682 (define-key-after map [menu-bar view filter switch-to-saved-filters]
b016851c
SM
683 '(menu-item "Restore permanently saved filters..."
684 ibuffer-switch-to-saved-filters
685 :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)
686 :help "Replace current filters with a saved stack"))
25d2f683 687 (define-key-after map [menu-bar view filter add-saved-filters]
b016851c
SM
688 '(menu-item "Add to permanently saved filters..."
689 ibuffer-add-saved-filters
690 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
691 :help "Include already saved stack with current filters"))
25d2f683 692 (define-key-after map [menu-bar view filter delete-saved-filters]
cba63a2d 693 '(menu-item "Delete permanently saved filters..."
b016851c
SM
694 ibuffer-delete-saved-filters
695 :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)))
cba63a2d 696
b5e80d1a 697 (define-key-after map [menu-bar view filter-groups]
b016851c 698 (cons "Filter Groups" ibuffer-mode-groups-popup))
b5e80d1a 699
25d2f683
CW
700 (define-key-after map [menu-bar view dashes2]
701 '("--"))
702 (define-key-after map [menu-bar view diff-with-file]
703 '(menu-item "Diff with file" ibuffer-diff-with-file
b016851c 704 :help "View the differences between this buffer and its file"))
25d2f683
CW
705 (define-key-after map [menu-bar view auto-mode]
706 '(menu-item "Toggle Auto Mode" ibuffer-auto-mode
b016851c 707 :help "Attempt to automatically update the Ibuffer buffer"))
25d2f683 708 (define-key-after map [menu-bar view customize]
4e4a724c 709 '(menu-item "Customize Ibuffer" ibuffer-customize
b016851c 710 :help "Use Custom to customize Ibuffer"))
25d2f683
CW
711
712 (define-key-after map [menu-bar mark]
713 (cons "Mark" (make-sparse-keymap "Mark")))
714
715 (define-key-after map [menu-bar mark toggle-marks]
716 '(menu-item "Toggle marks" ibuffer-toggle-marks
b016851c 717 :help "Unmark marked buffers, and mark unmarked buffers"))
25d2f683
CW
718 (define-key-after map [menu-bar mark mark-forward]
719 '(menu-item "Mark" ibuffer-mark-forward
b016851c 720 :help "Mark the buffer at point"))
25d2f683
CW
721 (define-key-after map [menu-bar mark unmark-forward]
722 '(menu-item "Unmark" ibuffer-unmark-forward
b016851c 723 :help "Unmark the buffer at point"))
25d2f683
CW
724 (define-key-after map [menu-bar mark mark-by-mode]
725 '(menu-item "Mark by mode..." ibuffer-mark-by-mode
b016851c 726 :help "Mark all buffers in a particular major mode"))
25d2f683
CW
727 (define-key-after map [menu-bar mark mark-modified-buffers]
728 '(menu-item "Mark modified buffers" ibuffer-mark-modified-buffers
b016851c 729 :help "Mark all buffers which have been modified"))
25d2f683
CW
730 (define-key-after map [menu-bar mark mark-unsaved-buffers]
731 '(menu-item "Mark unsaved buffers" ibuffer-mark-unsaved-buffers
b016851c 732 :help "Mark all buffers which have a file and are modified"))
25d2f683
CW
733 (define-key-after map [menu-bar mark mark-read-only-buffers]
734 '(menu-item "Mark read-only buffers" ibuffer-mark-read-only-buffers
b016851c 735 :help "Mark all buffers which are read-only"))
25d2f683
CW
736 (define-key-after map [menu-bar mark mark-special-buffers]
737 '(menu-item "Mark special buffers" ibuffer-mark-special-buffers
b016851c 738 :help "Mark all buffers whose name begins with a *"))
25d2f683
CW
739 (define-key-after map [menu-bar mark mark-dired-buffers]
740 '(menu-item "Mark dired buffers" ibuffer-mark-dired-buffers
b016851c 741 :help "Mark buffers in dired-mode"))
25d2f683
CW
742 (define-key-after map [menu-bar mark mark-dissociated-buffers]
743 '(menu-item "Mark dissociated buffers" ibuffer-mark-dissociated-buffers
b016851c 744 :help "Mark buffers with a non-existent associated file"))
25d2f683
CW
745 (define-key-after map [menu-bar mark mark-help-buffers]
746 '(menu-item "Mark help buffers" ibuffer-mark-help-buffers
b016851c 747 :help "Mark buffers in help-mode"))
9fe14abe 748 (define-key-after map [menu-bar mark mark-compressed-file-buffers]
b016851c
SM
749 '(menu-item "Mark compressed file buffers"
750 ibuffer-mark-compressed-file-buffers
751 :help "Mark buffers which have a file that is compressed"))
25d2f683
CW
752 (define-key-after map [menu-bar mark mark-old-buffers]
753 '(menu-item "Mark old buffers" ibuffer-mark-old-buffers
b016851c 754 :help "Mark buffers which have not been viewed recently"))
25d2f683
CW
755 (define-key-after map [menu-bar mark unmark-all]
756 '(menu-item "Unmark All" ibuffer-unmark-all))
71296446 757
25d2f683
CW
758 (define-key-after map [menu-bar mark dashes]
759 '("--"))
71296446 760
25d2f683
CW
761 (define-key-after map [menu-bar mark mark-by-name-regexp]
762 '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
b016851c 763 :help "Mark buffers whose name matches a regexp"))
25d2f683
CW
764 (define-key-after map [menu-bar mark mark-by-mode-regexp]
765 '(menu-item "Mark by major mode (regexp)..." ibuffer-mark-by-mode-regexp
b016851c 766 :help "Mark buffers whose major mode name matches a regexp"))
25d2f683 767 (define-key-after map [menu-bar mark mark-by-file-name-regexp]
b016851c
SM
768 '(menu-item "Mark by file name (regexp)..."
769 ibuffer-mark-by-file-name-regexp
770 :help "Mark buffers whose file name matches a regexp"))
25d2f683 771
b016851c 772 map))
25d2f683 773
b016851c
SM
774(defvar ibuffer-mode-operate-map
775 (let ((operate-map (make-sparse-keymap "Operate")))
25d2f683
CW
776 (define-key-after operate-map [do-view]
777 '(menu-item "View" ibuffer-do-view))
778 (define-key-after operate-map [do-view-other-frame]
779 '(menu-item "View (separate frame)" ibuffer-do-view-other-frame))
780 (define-key-after operate-map [do-save]
781 '(menu-item "Save" ibuffer-do-save))
782 (define-key-after operate-map [do-replace-regexp]
783 '(menu-item "Replace (regexp)..." ibuffer-do-replace-regexp
b016851c 784 :help "Replace text inside marked buffers"))
25d2f683
CW
785 (define-key-after operate-map [do-query-replace]
786 '(menu-item "Query Replace..." ibuffer-do-query-replace
b016851c 787 :help "Replace text in marked buffers, asking each time"))
25d2f683
CW
788 (define-key-after operate-map [do-query-replace-regexp]
789 '(menu-item "Query Replace (regexp)..." ibuffer-do-query-replace-regexp
b016851c 790 :help "Replace text in marked buffers by regexp, asking each time"))
25d2f683
CW
791 (define-key-after operate-map [do-print]
792 '(menu-item "Print" ibuffer-do-print))
793 (define-key-after operate-map [do-toggle-modified]
794 '(menu-item "Toggle modification flag" ibuffer-do-toggle-modified))
795 (define-key-after operate-map [do-revert]
796 '(menu-item "Revert" ibuffer-do-revert
b016851c 797 :help "Revert marked buffers to their associated file"))
25d2f683
CW
798 (define-key-after operate-map [do-rename-uniquely]
799 '(menu-item "Rename Uniquely" ibuffer-do-rename-uniquely
b016851c 800 :help "Rename marked buffers to a new, unique name"))
25d2f683
CW
801 (define-key-after operate-map [do-delete]
802 '(menu-item "Kill" ibuffer-do-delete))
803 (define-key-after operate-map [do-occur]
804 '(menu-item "List lines matching..." ibuffer-do-occur
b016851c 805 :help "View all lines in marked buffers matching a regexp"))
25d2f683
CW
806 (define-key-after operate-map [do-shell-command-pipe]
807 '(menu-item "Pipe to shell command..." ibuffer-do-shell-command-pipe
b016851c 808 :help "For each marked buffer, send its contents to a shell command"))
25d2f683
CW
809 (define-key-after operate-map [do-shell-command-pipe-replace]
810 '(menu-item "Pipe to shell command (replace)..." ibuffer-do-shell-command-pipe-replace
b016851c 811 :help "For each marked buffer, replace its contents with output of shell command"))
25d2f683
CW
812 (define-key-after operate-map [do-shell-command-file]
813 '(menu-item "Shell command on buffer's file..." ibuffer-do-shell-command-file
b016851c 814 :help "For each marked buffer, run a shell command with its file as argument"))
25d2f683
CW
815 (define-key-after operate-map [do-eval]
816 '(menu-item "Eval..." ibuffer-do-eval
b016851c 817 :help "Evaluate a Lisp form in each marked buffer"))
25d2f683
CW
818 (define-key-after operate-map [do-view-and-eval]
819 '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
b016851c 820 :help "Evaluate a Lisp form in each marked buffer while viewing it"))
71296446 821
b016851c 822 operate-map))
2bd26a6f
CW
823
824(define-key ibuffer-mode-groups-popup [kill-filter-group]
4e4a724c
JPW
825 '(menu-item "Kill filter group"
826 ibuffer-kill-line
34a4faa0
JPW
827 :enable (and (featurep 'ibuf-ext)
828 ibuffer-filter-groups)))
545aad2f 829(define-key ibuffer-mode-groups-popup [yank-filter-group]
4e4a724c
JPW
830 '(menu-item "Yank last killed filter group"
831 ibuffer-yank
34a4faa0
JPW
832 :enable (and (featurep 'ibuf-ext)
833 ibuffer-filter-group-kill-ring)))
4e4a724c 834
acf88897 835(defvar ibuffer-name-map
25d2f683 836 (let ((map (make-sparse-keymap)))
25d2f683
CW
837 (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
838 (define-key map [(mouse-2)] 'ibuffer-mouse-visit-buffer)
839 (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
acf88897 840 map))
25d2f683 841
d5794180
DN
842(defvar ibuffer-filename/process-header-map
843 (let ((map (make-sparse-keymap)))
844 (define-key map [(mouse-1)] 'ibuffer-do-sort-by-filename/process)
845 map))
846
acf88897 847(defvar ibuffer-mode-name-map
25d2f683 848 (let ((map (make-sparse-keymap)))
25d2f683
CW
849 (define-key map [(mouse-2)] 'ibuffer-mouse-filter-by-mode)
850 (define-key map (kbd "RET") 'ibuffer-interactive-filter-by-mode)
acf88897 851 map))
25d2f683 852
f0b31589
DN
853(defvar ibuffer-name-header-map
854 (let ((map (make-sparse-keymap)))
855 (define-key map [(mouse-1)] 'ibuffer-do-sort-by-alphabetic)
856 map))
857
858(defvar ibuffer-size-header-map
859 (let ((map (make-sparse-keymap)))
860 (define-key map [(mouse-1)] 'ibuffer-do-sort-by-size)
861 map))
862
863(defvar ibuffer-mode-header-map
864 (let ((map (make-sparse-keymap)))
865 (define-key map [(mouse-1)] 'ibuffer-do-sort-by-major-mode)
866 map))
867
acf88897 868(defvar ibuffer-mode-filter-group-map
b5cd37ea 869 (let ((map (make-sparse-keymap)))
b5cd37ea
CW
870 (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
871 (define-key map [(mouse-2)] 'ibuffer-mouse-toggle-filter-group)
872 (define-key map (kbd "RET") 'ibuffer-toggle-filter-group)
b5e80d1a 873 (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
acf88897 874 map))
b5cd37ea 875
4ed1f829
JPW
876(defvar ibuffer-restore-window-config-on-quit nil
877 "If non-nil, restore previous window configuration upon exiting `ibuffer'.")
878
879(defvar ibuffer-prev-window-config nil
880 "Window configuration before starting Ibuffer.")
25d2f683
CW
881
882(defvar ibuffer-did-modification nil)
883
63f0a166
JB
884(defvar ibuffer-compiled-formats nil)
885(defvar ibuffer-cached-formats nil)
886(defvar ibuffer-cached-eliding-string nil)
887(defvar ibuffer-cached-elide-long-columns 0)
888
25d2f683
CW
889(defvar ibuffer-sorting-functions-alist nil
890 "An alist of functions which describe how to sort buffers.
891
892Note: You most likely do not want to modify this variable directly;
893use `define-ibuffer-sorter' instead.
894
895The alist elements are constructed like (NAME DESCRIPTION FUNCTION)
896Where NAME is a symbol describing the sorting method, DESCRIPTION is a
897short string which will be displayed in the minibuffer and menu, and
898FUNCTION is a function of two arguments, which will be the buffers to
899compare.")
900
901;;; Utility functions
902(defun ibuffer-columnize-and-insert-list (list &optional pad-width)
903 "Insert LIST into the current buffer in as many columns as possible.
904The maximum number of columns is determined by the current window
905width and the longest string in LIST."
906 (unless pad-width
907 (setq pad-width 3))
908 (let ((width (window-width))
909 (max (+ (apply #'max (mapcar #'length list))
910 pad-width)))
911 (let ((columns (/ width max)))
912 (when (zerop columns)
913 (setq columns 1))
914 (while list
915 (dotimes (i (1- columns))
916 (insert (concat (car list) (make-string (- max (length (car list)))
972b8f82 917 ?\s)))
25d2f683
CW
918 (setq list (cdr list)))
919 (when (not (null list))
920 (insert (pop list)))
921 (insert "\n")))))
922
25d2f683
CW
923(defsubst ibuffer-current-mark ()
924 (cadr (get-text-property (line-beginning-position)
925 'ibuffer-properties)))
926
927(defun ibuffer-mouse-toggle-mark (event)
928 "Toggle the marked status of the buffer chosen with the mouse."
929 (interactive "e")
930 (unwind-protect
b5cd37ea
CW
931 (let ((pt (save-excursion
932 (mouse-set-point event)
933 (point))))
934 (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
935 (ibuffer-toggle-marks it)
936 (goto-char pt)
937 (let ((mark (ibuffer-current-mark)))
938 (setq buffer-read-only nil)
939 (if (eq mark ibuffer-marked-char)
972b8f82 940 (ibuffer-set-mark ?\s)
b5cd37ea 941 (ibuffer-set-mark ibuffer-marked-char)))))
25d2f683
CW
942 (setq buffer-read-only t)))
943
944(defun ibuffer-find-file (file &optional wildcards)
945 "Like `find-file', but default to the directory of the buffer at point."
946 (interactive
947 (let ((default-directory (let ((buf (ibuffer-current-buffer)))
948 (if (buffer-live-p buf)
949 (with-current-buffer buf
950 default-directory)
951 default-directory))))
952 (list (read-file-name "Find file: " default-directory)
fe78af29
JPW
953 t)))
954 (find-file file wildcards))
25d2f683
CW
955
956(defun ibuffer-mouse-visit-buffer (event)
957 "Visit the buffer chosen with the mouse."
958 (interactive "e")
959 (switch-to-buffer
960 (save-excursion
961 (mouse-set-point event)
b5cd37ea 962 (ibuffer-current-buffer t))))
25d2f683
CW
963
964(defun ibuffer-mouse-popup-menu (event)
965 "Display a menu of operations."
966 (interactive "e")
a1793b2d
JPW
967 (let ((eventpt (posn-point (event-end event)))
968 (origpt (point)))
25d2f683 969 (unwind-protect
51922c04 970 (if (get-text-property eventpt 'ibuffer-filter-group-name)
a1793b2d
JPW
971 (progn
972 (goto-char eventpt)
973 (popup-menu ibuffer-mode-groups-popup))
51922c04 974 (let ((inhibit-read-only t))
b5e80d1a 975 (ibuffer-save-marks
4e4a724c
JPW
976 ;; hm. we could probably do this in a better fashion
977 (ibuffer-unmark-all ?\r)
978 (save-excursion
979 (goto-char eventpt)
980 (ibuffer-set-mark ibuffer-marked-char))
981 (save-excursion
982 (popup-menu ibuffer-mode-operate-map)))))
a1793b2d 983 (setq buffer-read-only t)
4ba16127 984 (if (= eventpt (point))
a1793b2d 985 (goto-char origpt)))))
51922c04 986
b5cd37ea
CW
987(defun ibuffer-skip-properties (props direction)
988 (while (and (not (eobp))
989 (let ((hit nil))
990 (dolist (prop props hit)
991 (when (get-text-property (point) prop)
992 (setq hit t)))))
993 (forward-line direction)
994 (beginning-of-line)))
25d2f683 995
4e4a724c
JPW
996(defun ibuffer-customize ()
997 "Begin customizing Ibuffer interactively."
998 (interactive)
999 (customize-group 'ibuffer))
1000
b5cd37ea 1001(defun ibuffer-backward-line (&optional arg skip-group-names)
25d2f683
CW
1002 "Move backwards ARG lines, wrapping around the list if necessary."
1003 (interactive "P")
34a4faa0 1004 (or arg (setq arg 1))
25d2f683
CW
1005 (beginning-of-line)
1006 (while (> arg 0)
1007 (forward-line -1)
0ce780e1
CW
1008 (when (and ibuffer-movement-cycle
1009 (or (get-text-property (point) 'ibuffer-title)
1010 (and skip-group-names
34a4faa0
JPW
1011 (get-text-property (point)
1012 'ibuffer-filter-group-name))))
25d2f683 1013 (goto-char (point-max))
60356fb5 1014 (beginning-of-line))
b5cd37ea
CW
1015 (ibuffer-skip-properties (append '(ibuffer-summary)
1016 (when skip-group-names
1017 '(ibuffer-filter-group-name)))
1018 -1)
60356fb5
CW
1019 ;; Handle the special case of no buffers.
1020 (when (get-text-property (point) 'ibuffer-title)
1021 (forward-line 1)
1022 (setq arg 1))
a464a6c7 1023 (cl-decf arg)))
25d2f683 1024
b5cd37ea 1025(defun ibuffer-forward-line (&optional arg skip-group-names)
25d2f683
CW
1026 "Move forward ARG lines, wrapping around the list if necessary."
1027 (interactive "P")
34a4faa0 1028 (or arg (setq arg 1))
25d2f683 1029 (beginning-of-line)
0ce780e1
CW
1030 (when (and ibuffer-movement-cycle
1031 (or (eobp)
1032 (get-text-property (point) 'ibuffer-summary)))
214b39be 1033 (goto-char (point-min)))
b5cd37ea
CW
1034 (when (or (get-text-property (point) 'ibuffer-title)
1035 (and skip-group-names
1036 (get-text-property (point) 'ibuffer-filter-group-name)))
1037 (when (> arg 0)
a464a6c7 1038 (cl-decf arg))
b5cd37ea
CW
1039 (ibuffer-skip-properties (append '(ibuffer-title)
1040 (when skip-group-names
1041 '(ibuffer-filter-group-name)))
1042 1))
25d2f683
CW
1043 (if (< arg 0)
1044 (ibuffer-backward-line (- arg))
60356fb5
CW
1045 (while (> arg 0)
1046 (forward-line 1)
0ce780e1
CW
1047 (when (and ibuffer-movement-cycle
1048 (or (eobp)
1049 (get-text-property (point) 'ibuffer-summary)))
60356fb5 1050 (goto-char (point-min)))
a464a6c7 1051 (cl-decf arg)
b5cd37ea
CW
1052 (ibuffer-skip-properties (append '(ibuffer-title)
1053 (when skip-group-names
1054 '(ibuffer-filter-group-name)))
1055 1))))
25d2f683 1056
d246cabf
CW
1057(defun ibuffer-visit-buffer (&optional single)
1058 "Visit the buffer on this line.
d246cabf
CW
1059If optional argument SINGLE is non-nil, then also ensure there is only
1060one window."
1061 (interactive "P")
b5cd37ea 1062 (let ((buf (ibuffer-current-buffer t)))
d246cabf
CW
1063 (switch-to-buffer buf)
1064 (when single
1065 (delete-other-windows))))
25d2f683
CW
1066
1067(defun ibuffer-visit-buffer-other-window (&optional noselect)
1068 "Visit the buffer on this line in another window."
1069 (interactive)
b5cd37ea 1070 (let ((buf (ibuffer-current-buffer t)))
25d2f683
CW
1071 (bury-buffer (current-buffer))
1072 (if noselect
1073 (let ((curwin (selected-window)))
1074 (pop-to-buffer buf)
1075 (select-window curwin))
1076 (switch-to-buffer-other-window buf))))
1077
1078(defun ibuffer-visit-buffer-other-window-noselect ()
1079 "Visit the buffer on this line in another window, but don't select it."
1080 (interactive)
1081 (ibuffer-visit-buffer-other-window t))
1082
1083(defun ibuffer-visit-buffer-other-frame ()
1084 "Visit the buffer on this line in another frame."
1085 (interactive)
b5cd37ea 1086 (let ((buf (ibuffer-current-buffer t)))
25d2f683
CW
1087 (bury-buffer (current-buffer))
1088 (switch-to-buffer-other-frame buf)))
1089
1090(defun ibuffer-visit-buffer-1-window ()
1091 "Visit the buffer on this line, and delete other windows."
1092 (interactive)
d246cabf 1093 (ibuffer-visit-buffer t))
25d2f683
CW
1094
1095(defun ibuffer-bury-buffer ()
1096 "Bury the buffer on this line."
1097 (interactive)
b5cd37ea 1098 (let ((buf (ibuffer-current-buffer t))
25d2f683 1099 (line (+ 1 (count-lines 1 (point)))))
25d2f683
CW
1100 (bury-buffer buf)
1101 (ibuffer-update nil t)
e6ce8c42
GM
1102 (goto-char (point-min))
1103 (forward-line (1- line))))
25d2f683
CW
1104
1105(defun ibuffer-visit-tags-table ()
1106 "Visit the tags table in the buffer on this line. See `visit-tags-table'."
1107 (interactive)
b5cd37ea 1108 (let ((file (buffer-file-name (ibuffer-current-buffer t))))
25d2f683
CW
1109 (if file
1110 (visit-tags-table file)
1111 (error "Specified buffer has no file"))))
1112
1113(defun ibuffer-do-view (&optional other-frame)
1114 "View marked buffers, or the buffer on the current line.
1115If optional argument OTHER-FRAME is non-nil, then display each
1116marked buffer in a new frame. Otherwise, display each buffer as
1117a new window in the current frame, splitting vertically."
1118 (interactive)
1119 (ibuffer-do-view-1 (if other-frame 'other-frame 'vertically)))
1120
1121(defun ibuffer-do-view-horizontally (&optional other-frame)
1122 "As `ibuffer-do-view', but split windows horizontally."
1123 (interactive)
1124 (ibuffer-do-view-1 (if other-frame 'other-frame 'horizontally)))
1125
1126(defun ibuffer-do-view-1 (type)
1127 (let ((marked-bufs (ibuffer-get-marked-buffers)))
1128 (when (null marked-bufs)
b5cd37ea 1129 (setq marked-bufs (list (ibuffer-current-buffer t))))
25d2f683
CW
1130 (unless (and (eq type 'other-frame)
1131 (not ibuffer-expert)
1132 (> (length marked-bufs) 3)
1133 (not (y-or-n-p (format "Really create a new frame for %s buffers? "
1134 (length marked-bufs)))))
4e4a724c 1135 (set-buffer-modified-p nil)
25d2f683
CW
1136 (delete-other-windows)
1137 (switch-to-buffer (pop marked-bufs))
1138 (let ((height (/ (1- (if (eq type 'horizontally) (frame-width)
4e4a724c 1139 (frame-height)))
25d2f683
CW
1140 (1+ (length marked-bufs)))))
1141 (mapcar (if (eq type 'other-frame)
06b60517
JB
1142 (lambda (buf)
1143 (let ((curframe (selected-frame)))
1144 (select-frame (make-frame))
1145 (switch-to-buffer buf)
1146 (select-frame curframe)))
1147 (lambda (buf)
1148 (split-window nil height (eq type 'horizontally))
1149 (other-window 1)
1150 (switch-to-buffer buf)))
25d2f683
CW
1151 marked-bufs)))))
1152
1153(defun ibuffer-do-view-other-frame ()
1154 "View each of the marked buffers in a separate frame."
1155 (interactive)
1156 (ibuffer-do-view t))
1157
1158(defsubst ibuffer-map-marked-lines (func)
1159 (prog1 (ibuffer-map-on-mark ibuffer-marked-char func)
1160 (ibuffer-redisplay t)))
1161
1162(defun ibuffer-shrink-to-fit (&optional owin)
54124194
MO
1163 ;; Make sure that redisplay is performed, otherwise there can be a
1164 ;; bad interaction with code in the window-scroll-functions hook
1165 (redisplay t)
25d2f683
CW
1166 (fit-window-to-buffer nil (when owin (/ (frame-height)
1167 (length (window-list (selected-frame)))))))
1168
1169(defun ibuffer-confirm-operation-on (operation names)
1170 "Display a buffer asking whether to perform OPERATION on NAMES."
1171 (or ibuffer-expert
1172 (if (= (length names) 1)
1173 (y-or-n-p (format "Really %s buffer %s? " operation (car names)))
1174 (let ((buf (get-buffer-create "*Ibuffer confirmation*")))
1175 (with-current-buffer buf
1176 (setq buffer-read-only nil)
1177 (erase-buffer)
1178 (ibuffer-columnize-and-insert-list names)
1179 (goto-char (point-min))
1180 (setq buffer-read-only t))
4e4a724c 1181 (let ((lastwin (car (last (window-list nil 'nomini)))))
25d2f683
CW
1182 ;; Now attempt to display the buffer...
1183 (save-window-excursion
1184 (select-window lastwin)
1185 ;; The window might be too small to split; in that case,
7ad5b902 1186 ;; try a few times to increase its size before giving up.
25d2f683
CW
1187 (let ((attempts 0)
1188 (trying t))
1189 (while trying
1190 (condition-case err
1191 (progn
1192 (split-window)
1193 (setq trying nil))
1194 (error
1195 ;; Handle a failure
a464a6c7 1196 (if (or (> (cl-incf attempts) 4)
25d2f683 1197 (and (stringp (cadr err))
71296446 1198 ;; This definitely falls in the
4e4a724c 1199 ;; ghetto hack category...
25d2f683 1200 (not (string-match "too small" (cadr err)))))
8131c345 1201 (signal (car err) (cdr err))
25d2f683 1202 (enlarge-window 3))))))
25d2f683
CW
1203 (select-window (next-window))
1204 (switch-to-buffer buf)
1205 (unwind-protect
1206 (progn
1207 (fit-window-to-buffer)
1208 (y-or-n-p (format "Really %s %d buffers? "
1209 operation (length names))))
1210 (kill-buffer buf))))))))
1211
1212(defsubst ibuffer-map-lines-nomodify (function)
1213 "As `ibuffer-map-lines', but don't set the modification flag."
1214 (ibuffer-map-lines function t))
1215
1216(defun ibuffer-buffer-names-with-mark (mark)
1217 (let ((ibuffer-buffer-names-with-mark-result nil))
1218 (ibuffer-map-lines-nomodify
06b60517
JB
1219 (lambda (buf mk)
1220 (when (char-equal mark mk)
1221 (push (buffer-name buf)
1222 ibuffer-buffer-names-with-mark-result))))
25d2f683
CW
1223 ibuffer-buffer-names-with-mark-result))
1224
1225(defsubst ibuffer-marked-buffer-names ()
1226 (ibuffer-buffer-names-with-mark ibuffer-marked-char))
1227
1228(defsubst ibuffer-deletion-marked-buffer-names ()
1229 (ibuffer-buffer-names-with-mark ibuffer-deletion-char))
1230
1231(defun ibuffer-count-marked-lines (&optional all)
1232 (if all
1233 (ibuffer-map-lines-nomodify
06b60517
JB
1234 (lambda (_buf mark)
1235 (not (char-equal mark ?\s))))
25d2f683 1236 (ibuffer-map-lines-nomodify
06b60517
JB
1237 (lambda (_buf mark)
1238 (char-equal mark ibuffer-marked-char)))))
25d2f683
CW
1239
1240(defsubst ibuffer-count-deletion-lines ()
1241 (ibuffer-map-lines-nomodify
06b60517
JB
1242 (lambda (_buf mark)
1243 (char-equal mark ibuffer-deletion-char))))
25d2f683
CW
1244
1245(defsubst ibuffer-map-deletion-lines (func)
1246 (ibuffer-map-on-mark ibuffer-deletion-char func))
1247
87a6a53a 1248(defsubst ibuffer-assert-ibuffer-mode ()
a464a6c7 1249 (cl-assert (derived-mode-p 'ibuffer-mode)))
87a6a53a 1250
92cb2eaf
JPW
1251(defun ibuffer-buffer-file-name ()
1252 (or buffer-file-name
1253 (let ((dirname (or (and (boundp 'dired-directory)
1254 (if (stringp dired-directory)
1255 dired-directory
1256 (car dired-directory)))
414408cd 1257 (bound-and-true-p list-buffers-directory))))
9d458edc 1258 (and dirname (expand-file-name dirname)))))
92cb2eaf 1259
fd225d80 1260(define-ibuffer-op ibuffer-do-save ()
25d2f683
CW
1261 "Save marked buffers as with `save-buffer'."
1262 (:complex t
1263 :opstring "saved"
1264 :modifier-p :maybe)
1265 (when (buffer-modified-p buf)
1266 (if (not (with-current-buffer buf
1267 buffer-file-name))
1268 ;; handle the case where we're prompted
1269 ;; for a file name
1270 (save-window-excursion
1271 (switch-to-buffer buf)
1272 (save-buffer))
1273 (with-current-buffer buf
1274 (save-buffer))))
1275 t)
1276
fd225d80 1277(define-ibuffer-op ibuffer-do-toggle-modified ()
25d2f683
CW
1278 "Toggle modification flag of marked buffers."
1279 (:opstring "(un)marked as modified"
1280 :modifier-p t)
1281 (set-buffer-modified-p (not (buffer-modified-p))))
1282
92be491c
RW
1283(define-ibuffer-op ibuffer-do-toggle-read-only (&optional arg)
1284 "Toggle read only status in marked buffers.
ba10c48c 1285With optional ARG, make read-only only if ARG is not negative."
25d2f683 1286 (:opstring "toggled read only status in"
92be491c 1287 :interactive "P"
25d2f683 1288 :modifier-p t)
9a930676 1289 (read-only-mode 'toggle))
25d2f683 1290
fd225d80 1291(define-ibuffer-op ibuffer-do-delete ()
25d2f683
CW
1292 "Kill marked buffers as with `kill-this-buffer'."
1293 (:opstring "killed"
1294 :active-opstring "kill"
1295 :dangerous t
1296 :complex t
1297 :modifier-p t)
1298 (if (kill-buffer buf)
1299 'kill
1300 nil))
1301
fd225d80 1302(define-ibuffer-op ibuffer-do-kill-on-deletion-marks ()
25d2f683
CW
1303 "Kill buffers marked for deletion as with `kill-this-buffer'."
1304 (:opstring "killed"
1305 :active-opstring "kill"
1306 :dangerous t
1307 :complex t
1308 :mark :deletion
1309 :modifier-p t)
1310 (if (kill-buffer buf)
1311 'kill
1312 nil))
1313
1314(defun ibuffer-unmark-all (mark)
1315 "Unmark all buffers with mark MARK."
1316 (interactive "cRemove marks (RET means all):")
1317 (if (= (ibuffer-count-marked-lines t) 0)
1318 (message "No buffers marked; use 'm' to mark a buffer")
1319 (cond
1320 ((char-equal mark ibuffer-marked-char)
1321 (ibuffer-map-marked-lines
06b60517
JB
1322 (lambda (_buf _mark)
1323 (ibuffer-set-mark-1 ?\s)
1324 t)))
25d2f683
CW
1325 ((char-equal mark ibuffer-deletion-char)
1326 (ibuffer-map-deletion-lines
06b60517
JB
1327 (lambda (_buf _mark)
1328 (ibuffer-set-mark-1 ?\s)
1329 t)))
25d2f683
CW
1330 (t
1331 (ibuffer-map-lines
06b60517
JB
1332 (lambda (_buf mark)
1333 (when (not (char-equal mark ?\s))
1334 (ibuffer-set-mark-1 ?\s))
1335 t)))))
25d2f683
CW
1336 (ibuffer-redisplay t))
1337
b5cd37ea 1338(defun ibuffer-toggle-marks (&optional group)
25d2f683
CW
1339 "Toggle which buffers are marked.
1340In other words, unmarked buffers become marked, and marked buffers
cba63a2d
CW
1341become unmarked.
1342If point is on a group name, then this function operates on that
1343group."
25d2f683 1344 (interactive)
cba63a2d
CW
1345 (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
1346 (setq group it))
25d2f683
CW
1347 (let ((count
1348 (ibuffer-map-lines
06b60517
JB
1349 (lambda (_buf mark)
1350 (cond ((eq mark ibuffer-marked-char)
1351 (ibuffer-set-mark-1 ?\s)
1352 nil)
1353 ((eq mark ?\s)
1354 (ibuffer-set-mark-1 ibuffer-marked-char)
1355 t)
1356 (t
1357 nil)))
b5cd37ea 1358 nil group)))
25d2f683
CW
1359 (message "%s buffers marked" count))
1360 (ibuffer-redisplay t))
1361
1362(defun ibuffer-mark-forward (arg)
cba63a2d
CW
1363 "Mark the buffer on this line, and move forward ARG lines.
1364If point is on a group name, this function operates on that group."
de959d4d
AP
1365 (interactive "p")
1366 (ibuffer-mark-interactive arg ibuffer-marked-char))
25d2f683
CW
1367
1368(defun ibuffer-unmark-forward (arg)
cba63a2d
CW
1369 "Unmark the buffer on this line, and move forward ARG lines.
1370If point is on a group name, this function operates on that group."
de959d4d
AP
1371 (interactive "p")
1372 (ibuffer-mark-interactive arg ?\s))
25d2f683
CW
1373
1374(defun ibuffer-unmark-backward (arg)
cba63a2d
CW
1375 "Unmark the buffer on this line, and move backward ARG lines.
1376If point is on a group name, this function operates on that group."
de959d4d
AP
1377 (interactive "p")
1378 (ibuffer-unmark-forward (- arg)))
25d2f683 1379
de959d4d 1380(defun ibuffer-mark-interactive (arg mark &optional movement)
87a6a53a 1381 (ibuffer-assert-ibuffer-mode)
34a4faa0 1382 (or arg (setq arg 1))
de959d4d
AP
1383 ;; deprecated movement argument
1384 (when (and movement (< movement 0))
1385 (setq arg (- arg)))
cba63a2d
CW
1386 (ibuffer-forward-line 0)
1387 (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
1388 (progn
1389 (require 'ibuf-ext)
1390 (ibuffer-mark-on-buffer #'identity mark it))
4e4a724c 1391 (ibuffer-forward-line 0 t)
cba63a2d
CW
1392 (let ((inhibit-read-only t))
1393 (while (> arg 0)
1394 (ibuffer-set-mark mark)
de959d4d
AP
1395 (ibuffer-forward-line 1 t)
1396 (setq arg (1- arg)))
1397 (while (< arg 0)
1398 (ibuffer-forward-line -1 t)
1399 (ibuffer-set-mark mark)
1400 (setq arg (1+ arg))))))
25d2f683
CW
1401
1402(defun ibuffer-set-mark (mark)
87a6a53a 1403 (ibuffer-assert-ibuffer-mode)
25d2f683
CW
1404 (let ((inhibit-read-only t))
1405 (ibuffer-set-mark-1 mark)
1406 (setq ibuffer-did-modification t)
559ac4c1
CW
1407 (ibuffer-redisplay-current)
1408 (beginning-of-line)))
25d2f683
CW
1409
1410(defun ibuffer-set-mark-1 (mark)
1411 (let ((beg (line-beginning-position))
1412 (end (line-end-position)))
1413 (put-text-property beg end 'ibuffer-properties
1414 (list (ibuffer-current-buffer)
1415 mark))))
1416
1417(defun ibuffer-mark-for-delete (arg)
cba63a2d
CW
1418 "Mark the buffers on ARG lines forward for deletion.
1419If point is on a group name, this function operates on that group."
25d2f683
CW
1420 (interactive "P")
1421 (ibuffer-mark-interactive arg ibuffer-deletion-char 1))
1422
1423(defun ibuffer-mark-for-delete-backwards (arg)
cba63a2d
CW
1424 "Mark the buffers on ARG lines backward for deletion.
1425If point is on a group name, this function operates on that group."
25d2f683
CW
1426 (interactive "P")
1427 (ibuffer-mark-interactive arg ibuffer-deletion-char -1))
1428
1429(defun ibuffer-current-buffer (&optional must-be-live)
1430 (let ((buf (car (get-text-property (line-beginning-position)
1431 'ibuffer-properties))))
b5cd37ea
CW
1432 (when must-be-live
1433 (if (bufferp buf)
1434 (unless (buffer-live-p buf)
1388485d 1435 (error "Buffer %s has been killed; %s" buf (substitute-command-keys "use `\\[ibuffer-update]' to update")))
b5cd37ea 1436 (error "No buffer on this line")))
25d2f683 1437 buf))
523304ed
CW
1438
1439(defun ibuffer-active-formats-name ()
1440 (if (boundp 'ibuffer-filter-format-alist)
1441 (let ((ret nil))
1442 (dolist (filter ibuffer-filtering-qualifiers ret)
1443 (let ((val (assq (car filter) ibuffer-filter-format-alist)))
1444 (when val
1445 (setq ret (car filter)))))
1446 (if ret
1447 ret
1448 :ibuffer-formats))
1449 :ibuffer-formats))
1450
1451(defun ibuffer-current-formats (uncompiledp)
1452 (let* ((name (ibuffer-active-formats-name)))
1453 (ibuffer-check-formats)
1454 (if (eq name :ibuffer-formats)
1455 (if uncompiledp
1456 ibuffer-formats
1457 ibuffer-compiled-formats)
1458 (cadr (assq name
1459 (if uncompiledp
1460 ibuffer-filter-format-alist
1461 ibuffer-compiled-filter-formats))))))
71296446 1462
523304ed 1463(defun ibuffer-current-format (&optional uncompiledp)
25d2f683
CW
1464 (or ibuffer-current-format
1465 (setq ibuffer-current-format 0))
4e4a724c 1466 (nth ibuffer-current-format (ibuffer-current-formats uncompiledp)))
25d2f683
CW
1467
1468(defun ibuffer-expand-format-entry (form)
1469 (if (or (consp form)
1470 (symbolp form))
4e4a724c
JPW
1471 (let ((sym (intern (concat "ibuffer-make-column-"
1472 (symbol-name (if (consp form)
1473 (car form)
1474 form))))))
1475 (unless (or (fboundp sym)
1476 (assq sym ibuffer-inline-columns))
1477 (error "Unknown column %s in ibuffer-formats" form))
1478 (let (min max align elide)
1479 (if (consp form)
1480 (setq min (or (nth 1 form) 0)
1481 max (or (nth 2 form) -1)
1482 align (or (nth 3 form) :left)
1483 elide (or (nth 4 form) nil))
1484 (setq min 0
1485 max -1
1486 align :left
1487 elide nil))
1488 (list sym min max align elide)))
25d2f683 1489 form))
71296446 1490
25d2f683 1491(defun ibuffer-compile-make-eliding-form (strvar elide from-end-p)
545aad2f 1492 (let ((ellipsis (propertize ibuffer-eliding-string 'font-lock-face 'bold)))
63f0a166 1493 (if (or elide (with-no-warnings ibuffer-elide-long-columns))
25d2f683
CW
1494 `(if (> strlen 5)
1495 ,(if from-end-p
1496 `(concat ,ellipsis
1497 (substring ,strvar
1498 (length ibuffer-eliding-string)))
1499 `(concat
1500 (substring ,strvar 0 (- strlen ,(length ellipsis)))
1501 ,ellipsis))
1502 ,strvar)
1503 strvar)))
1504
1505(defun ibuffer-compile-make-substring-form (strvar maxvar from-end-p)
1506 (if from-end-p
1507 `(substring str
1508 (- strlen ,maxvar))
1509 `(substring ,strvar 0 ,maxvar)))
1510
1511(defun ibuffer-compile-make-format-form (strvar widthform alignment)
972b8f82
JB
1512 (let* ((left `(make-string tmp2 ?\s))
1513 (right `(make-string (- tmp1 tmp2) ?\s)))
25d2f683
CW
1514 `(progn
1515 (setq tmp1 ,widthform
1516 tmp2 (/ tmp1 2))
a464a6c7 1517 ,(pcase alignment
25d2f683
CW
1518 (:right `(concat ,left ,right ,strvar))
1519 (:center `(concat ,left ,strvar ,right))
1520 (:left `(concat ,strvar ,left ,right))
a464a6c7 1521 (_ (error "Invalid alignment %s" alignment))))))
25d2f683
CW
1522
1523(defun ibuffer-compile-format (format)
1524 (let ((result nil)
cb059426
CW
1525 ;; We use these variables to keep track of which variables
1526 ;; inside the generated function we need to bind, since
1527 ;; binding variables in Emacs takes time.
1528 str-used tmp1-used tmp2-used global-strlen-used)
25d2f683
CW
1529 (dolist (form format)
1530 (push
cb059426
CW
1531 ;; Generate a form based on a particular format entry, like
1532 ;; " ", mark, or (mode 16 16 :right).
25d2f683 1533 (if (stringp form)
cb059426 1534 ;; It's a string; all we need to do is insert it.
25d2f683
CW
1535 `(insert ,form)
1536 (let* ((form (ibuffer-expand-format-entry form))
1537 (sym (nth 0 form))
1538 (min (nth 1 form))
1539 (max (nth 2 form))
1540 (align (nth 3 form))
1541 (elide (nth 4 form)))
a464a6c7 1542 (let* ((from-end-p (when (cl-minusp min)
25d2f683
CW
1543 (setq min (- min))
1544 t))
1545 (letbindings nil)
1546 (outforms nil)
1547 minform
1548 maxform
1549 min-used max-used strlen-used)
1550 (when (or (not (integerp min)) (>= min 0))
cb059426
CW
1551 ;; This is a complex case; they want it limited to a
1552 ;; minimum size.
25d2f683
CW
1553 (setq min-used t)
1554 (setq str-used t strlen-used t global-strlen-used t
1555 tmp1-used t tmp2-used t)
cb059426 1556 ;; Generate code to limit the string to a minimum size.
25d2f683
CW
1557 (setq minform `(progn
1558 (setq str
1559 ,(ibuffer-compile-make-format-form
1560 'str
1561 `(- ,(if (integerp min)
1562 min
1563 'min)
1564 strlen)
1565 align)))))
1566 (when (or (not (integerp max)) (> max 0))
1567 (setq str-used t max-used t)
cb059426 1568 ;; Generate code to limit the string to a maximum size.
25d2f683
CW
1569 (setq maxform `(progn
1570 (setq str
1571 ,(ibuffer-compile-make-substring-form
1572 'str
1573 (if (integerp max)
1574 max
1575 'max)
1576 from-end-p))
1577 (setq strlen (length str))
1578 (setq str
b016851c
SM
1579 ,(ibuffer-compile-make-eliding-form
1580 'str elide from-end-p)))))
cb059426
CW
1581 ;; Now, put these forms together with the rest of the code.
1582 (let ((callform
1583 ;; Is this an "inline" column? This means we have
1584 ;; to get the code from the
1585 ;; `ibuffer-inline-columns' alist and insert it
1586 ;; into our generated code. Otherwise, we just
1587 ;; generate a call to the column function.
1588 (ibuffer-aif (assq sym ibuffer-inline-columns)
4e4a724c
JPW
1589 (nth 1 it)
1590 `(,sym buffer mark)))
cb059426
CW
1591 ;; You're not expected to understand this. Hell, I
1592 ;; don't even understand it, and I wrote it five
1593 ;; minutes ago.
b016851c
SM
1594 (insertgenfn
1595 (ibuffer-aif (get sym 'ibuffer-column-summarizer)
1596 ;; I really, really wish Emacs Lisp had closures.
1597 (lambda (arg sym)
1598 `(insert
1599 (let ((ret ,arg))
1600 (put ',sym 'ibuffer-column-summary
1601 (cons ret (get ',sym
1602 'ibuffer-column-summary)))
1603 ret)))
1604 (lambda (arg sym)
1605 `(insert ,arg))))
25d2f683
CW
1606 (mincompform `(< strlen ,(if (integerp min)
1607 min
1608 'min)))
1609 (maxcompform `(> strlen ,(if (integerp max)
1610 max
1611 'max))))
4e4a724c
JPW
1612 (if (or min-used max-used)
1613 ;; The complex case, where we have to limit the
1614 ;; form to a maximum or minimum size.
1615 (progn
1616 (when (and min-used (not (integerp min)))
1617 (push `(min ,min) letbindings))
1618 (when (and max-used (not (integerp max)))
1619 (push `(max ,max) letbindings))
1620 (push
1621 (if (and min-used max-used)
1622 `(if ,mincompform
1623 ,minform
1624 (if ,maxcompform
1625 ,maxform))
1626 (if min-used
1627 `(when ,mincompform
1628 ,minform)
1629 `(when ,maxcompform
1630 ,maxform)))
1631 outforms)
1632 (push (append
1633 `(setq str ,callform)
1634 (when strlen-used
1635 `(strlen (length str))))
1636 outforms)
1637 (setq outforms
b016851c
SM
1638 (append outforms
1639 (list (funcall insertgenfn 'str sym)))))
4e4a724c
JPW
1640 ;; The simple case; just insert the string.
1641 (push (funcall insertgenfn callform sym) outforms))
1642 ;; Finally, return a `let' form which binds the
1643 ;; variables in `letbindings', and contains all the
1644 ;; code in `outforms'.
1645 `(let ,letbindings
1646 ,@outforms)))))
25d2f683
CW
1647 result))
1648 (setq result
cb059426 1649 ;; We don't want to unconditionally load the byte-compiler.
25d2f683
CW
1650 (funcall (if (or ibuffer-always-compile-formats
1651 (featurep 'bytecomp))
1652 #'byte-compile
1653 #'identity)
cb059426
CW
1654 ;; Here, we actually create a lambda form which
1655 ;; inserts all the generated forms for each entry
1656 ;; in the format string.
25d2f683 1657 (nconc (list 'lambda '(buffer mark))
d99b259b 1658 `((let ,(append (when str-used
25d2f683
CW
1659 '(str))
1660 (when global-strlen-used
1661 '(strlen))
1662 (when tmp1-used
1663 '(tmp1))
1664 (when tmp2-used
1665 '(tmp2)))
1666 ,@(nreverse result))))))))
1667
25d2f683
CW
1668(defun ibuffer-recompile-formats ()
1669 "Recompile `ibuffer-formats'."
1670 (interactive)
1671 (setq ibuffer-compiled-formats
4e4a724c 1672 (mapcar #'ibuffer-compile-format ibuffer-formats))
523304ed
CW
1673 (when (boundp 'ibuffer-filter-format-alist)
1674 (setq ibuffer-compiled-filter-formats
06b60517
JB
1675 (mapcar (lambda (entry)
1676 (cons (car entry)
1677 (mapcar (lambda (formats)
1678 (mapcar #'ibuffer-compile-format formats))
1679 (cdr entry))))
523304ed 1680 ibuffer-filter-format-alist))))
25d2f683 1681
cb059426
CW
1682(defun ibuffer-clear-summary-columns (format)
1683 (dolist (form format)
1684 (ibuffer-awhen (and (consp form)
1685 (get (car form) 'ibuffer-column-summarizer))
1686 (put (car form) 'ibuffer-column-summary nil))))
71296446 1687
25d2f683 1688(defun ibuffer-check-formats ()
523304ed
CW
1689 (when (null ibuffer-formats)
1690 (error "No formats!"))
b5cd37ea
CW
1691 (let ((ext-loaded (featurep 'ibuf-ext)))
1692 (when (or (null ibuffer-compiled-formats)
1693 (null ibuffer-cached-formats)
1694 (not (eq ibuffer-cached-formats ibuffer-formats))
1695 (null ibuffer-cached-eliding-string)
1696 (not (equal ibuffer-cached-eliding-string ibuffer-eliding-string))
1697 (eql 0 ibuffer-cached-elide-long-columns)
1698 (not (eql ibuffer-cached-elide-long-columns
63f0a166 1699 (with-no-warnings ibuffer-elide-long-columns)))
b5cd37ea
CW
1700 (and ext-loaded
1701 (not (eq ibuffer-cached-filter-formats
1702 ibuffer-filter-format-alist))
1703 (and ibuffer-filter-format-alist
1704 (null ibuffer-compiled-filter-formats))))
1705 (message "Formats have changed, recompiling...")
1706 (ibuffer-recompile-formats)
1707 (setq ibuffer-cached-formats ibuffer-formats
1708 ibuffer-cached-eliding-string ibuffer-eliding-string
63f0a166 1709 ibuffer-cached-elide-long-columns (with-no-warnings ibuffer-elide-long-columns))
b5cd37ea
CW
1710 (when ext-loaded
1711 (setq ibuffer-cached-filter-formats ibuffer-filter-format-alist))
1712 (message "Formats have changed, recompiling...done"))))
25d2f683
CW
1713
1714(defvar ibuffer-inline-columns nil)
1715
1716(define-ibuffer-column mark (:name " " :inline t)
1717 (string mark))
1718
1719(define-ibuffer-column read-only (:name "R" :inline t)
1720 (if buffer-read-only
34a4faa0 1721 (string ibuffer-read-only-char)
25d2f683
CW
1722 " "))
1723
1724(define-ibuffer-column modified (:name "M" :inline t)
1725 (if (buffer-modified-p)
1726 (string ibuffer-modified-char)
1727 " "))
1728
34a4faa0
JPW
1729(define-ibuffer-column name
1730 (:inline t
f0b31589 1731 :header-mouse-map ibuffer-name-header-map
34a4faa0
JPW
1732 :props
1733 ('mouse-face 'highlight 'keymap ibuffer-name-map
1734 'ibuffer-name-column t
1735 'help-echo '(if tooltip-mode
1736 "mouse-1: mark this buffer\nmouse-2: select this buffer\nmouse-3: operate on this buffer"
1737 "mouse-1: mark buffer mouse-2: select buffer mouse-3: operate"))
1738 :summarizer
1739 (lambda (strings)
1740 (let ((bufs (length strings)))
1741 (cond ((zerop bufs) "No buffers")
1742 ((= 1 bufs) "1 buffer")
1743 (t (format "%s buffers" bufs))))))
545aad2f 1744 (propertize (buffer-name) 'font-lock-face (ibuffer-buffer-name-face buffer mark)))
71296446 1745
34a4faa0
JPW
1746(define-ibuffer-column size
1747 (:inline t
f0b31589 1748 :header-mouse-map ibuffer-size-header-map
34a4faa0
JPW
1749 :summarizer
1750 (lambda (column-strings)
1751 (let ((total 0))
1752 (dolist (string column-strings)
1753 (setq total
1754 ;; like, ewww ...
7ad938e7 1755 (+ (float (string-to-number string))
34a4faa0
JPW
1756 total)))
1757 (format "%.0f" total))))
25d2f683
CW
1758 (format "%s" (buffer-size)))
1759
7ad938e7
JPW
1760(define-ibuffer-column mode
1761 (:inline t
f0b31589 1762 :header-mouse-map ibuffer-mode-header-map
7ad938e7
JPW
1763 :props
1764 ('mouse-face 'highlight
1765 'keymap ibuffer-mode-name-map
1766 'help-echo "mouse-2: filter by this mode"))
23eabff6 1767 (format-mode-line mode-name nil nil (current-buffer)))
25d2f683 1768
34a4faa0
JPW
1769(define-ibuffer-column process
1770 (:summarizer
1771 (lambda (strings)
1772 (let ((total (length (delete "" strings))))
1773 (cond ((zerop total) "No processes")
1774 ((= 1 total) "1 process")
1775 (t (format "%d processes" total))))))
96777edb
CW
1776 (ibuffer-aif (get-buffer-process buffer)
1777 (format "(%s %s)" it (process-status it))
34a4faa0
JPW
1778 ""))
1779
1780(define-ibuffer-column filename
1781 (:summarizer
1782 (lambda (strings)
1783 (let ((total (length (delete "" strings))))
1784 (cond ((zerop total) "No files")
1785 ((= 1 total) "1 file")
1786 (t (format "%d files" total))))))
25d2f683
CW
1787 (let ((directory-abbrev-alist ibuffer-directory-abbrev-alist))
1788 (abbreviate-file-name
9d458edc 1789 (or (ibuffer-buffer-file-name) ""))))
25d2f683 1790
34a4faa0
JPW
1791(define-ibuffer-column filename-and-process
1792 (:name "Filename/Process"
d5794180 1793 :header-mouse-map ibuffer-filename/process-header-map
34a4faa0
JPW
1794 :summarizer
1795 (lambda (strings)
1796 (setq strings (delete "" strings))
1797 (let ((procs 0)
1798 (files 0))
1799 (dolist (string strings)
1800 (if (string-match "\\(\?:\\`(\[\[:ascii:\]\]\+)\\)" string)
1801 (progn (setq procs (1+ procs))
1802 (if (< (match-end 0) (length string))
1803 (setq files (1+ files))))
1804 (setq files (1+ files))))
1805 (concat (cond ((zerop files) "No files")
1806 ((= 1 files) "1 file")
1807 (t (format "%d files" files)))
1808 ", "
1809 (cond ((zerop procs) "no processes")
1810 ((= 1 procs) "1 process")
1811 (t (format "%d processes" procs)))))))
fd225d80 1812 (let ((proc (get-buffer-process buffer))
63e0bf5e 1813 (filename (ibuffer-make-column-filename buffer mark)))
fd225d80 1814 (if proc
34a4faa0 1815 (concat (propertize (format "(%s %s)" proc (process-status proc))
545aad2f 1816 'font-lock-face 'italic)
34a4faa0
JPW
1817 (if (> (length filename) 0)
1818 (format " %s" filename)
1819 ""))
fd225d80
CW
1820 filename)))
1821
25d2f683 1822(defun ibuffer-format-column (str width alignment)
972b8f82
JB
1823 (let ((left (make-string (/ width 2) ?\s))
1824 (right (make-string (- width (/ width 2)) ?\s)))
a464a6c7 1825 (pcase alignment
25d2f683
CW
1826 (:right (concat left right str))
1827 (:center (concat left str right))
a464a6c7 1828 (_ (concat str left right)))))
25d2f683 1829
545aad2f 1830(defun ibuffer-buffer-name-face (buf mark)
fd225d80 1831 (cond ((char-equal mark ibuffer-marked-char)
545aad2f 1832 ibuffer-marked-face)
fd225d80 1833 ((char-equal mark ibuffer-deletion-char)
545aad2f 1834 ibuffer-deletion-face)
fd225d80
CW
1835 (t
1836 (let ((level -1)
fd225d80
CW
1837 result)
1838 (dolist (e ibuffer-fontification-alist result)
1839 (when (and (> (car e) level)
1840 (with-current-buffer buf
545aad2f 1841 (eval (nth 1 e))))
fd225d80 1842 (setq level (car e)
545aad2f 1843 result (nth 2 e))))))))
25d2f683
CW
1844
1845(defun ibuffer-insert-buffer-line (buffer mark format)
1846 "Insert a line describing BUFFER and MARK using FORMAT."
87a6a53a 1847 (ibuffer-assert-ibuffer-mode)
25d2f683 1848 (let ((beg (point)))
25d2f683 1849 (funcall format buffer mark)
cb059426
CW
1850 (put-text-property beg (point) 'ibuffer-properties (list buffer mark)))
1851 (insert "\n"))
25d2f683 1852
cb059426 1853;; This function knows a bit too much of the internals. It would be
b5cd37ea 1854;; nice if it was all abstracted away.
25d2f683 1855(defun ibuffer-redisplay-current ()
87a6a53a 1856 (ibuffer-assert-ibuffer-mode)
25d2f683
CW
1857 (when (eobp)
1858 (forward-line -1))
1859 (beginning-of-line)
cb059426
CW
1860 (let ((curformat (mapcar #'ibuffer-expand-format-entry
1861 (ibuffer-current-format t))))
1862 (ibuffer-clear-summary-columns curformat)
1863 (let ((buf (ibuffer-current-buffer)))
1864 (when buf
1865 (let ((mark (ibuffer-current-mark)))
ed233dd8
CW
1866 (save-excursion
1867 (delete-region (point) (1+ (line-end-position)))
1868 (ibuffer-insert-buffer-line
1869 buf mark
1870 (ibuffer-current-format)))
cb059426
CW
1871 (when ibuffer-shrink-to-minimum-size
1872 (ibuffer-shrink-to-fit)))))))
71296446 1873
25d2f683
CW
1874(defun ibuffer-map-on-mark (mark func)
1875 (ibuffer-map-lines
06b60517
JB
1876 (lambda (buf mk)
1877 (if (char-equal mark mk)
1878 (funcall func buf mark)
1879 nil))))
25d2f683 1880
b5cd37ea
CW
1881(defun ibuffer-map-lines (function &optional nomodify group)
1882 "Call FUNCTION for each buffer.
4837b516 1883Set the ibuffer modification flag unless NOMODIFY is non-nil.
25d2f683 1884
b5cd37ea
CW
1885If optional argument GROUP is non-nil, then only call FUNCTION on
1886buffers in filtering group GROUP.
1887
4e4a724c
JPW
1888FUNCTION is called with two arguments:
1889the buffer object itself and the current mark symbol."
87a6a53a 1890 (ibuffer-assert-ibuffer-mode)
b5cd37ea
CW
1891 (ibuffer-forward-line 0)
1892 (let* ((orig-target-line (1+ (count-lines (save-excursion
1893 (goto-char (point-min))
1894 (ibuffer-forward-line 0)
1895 (point))
1896 (point))))
1897 (target-line-offset orig-target-line)
1898 (ibuffer-map-lines-total 0)
1899 (ibuffer-map-lines-count 0))
25d2f683 1900 (unwind-protect
57c9cc3e
CW
1901 (progn
1902 (setq buffer-read-only nil)
1903 (goto-char (point-min))
4e4a724c 1904 (ibuffer-forward-line 0 t)
57c9cc3e 1905 (while (and (not (eobp))
b5cd37ea
CW
1906 (not (get-text-property (point) 'ibuffer-summary))
1907 (progn
1908 (ibuffer-forward-line 0 t)
1909 (and (not (eobp))
1910 (not (get-text-property (point) 'ibuffer-summary)))))
57c9cc3e
CW
1911 (let ((result
1912 (if (buffer-live-p (ibuffer-current-buffer))
b5cd37ea
CW
1913 (when (or (null group)
1914 (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group)
1915 (equal group it)))
1916 (save-excursion
1917 (funcall function
1918 (ibuffer-current-buffer)
1919 (ibuffer-current-mark))))
57c9cc3e
CW
1920 ;; Kill the line if the buffer is dead
1921 'kill)))
1922 ;; A given mapping function should return:
1923 ;; `nil' if it chose not to affect the buffer
1924 ;; `kill' means the remove line from the buffer list
1925 ;; `t' otherwise
a464a6c7 1926 (cl-incf ibuffer-map-lines-total)
57c9cc3e
CW
1927 (cond ((null result)
1928 (forward-line 1))
1929 ((eq result 'kill)
1930 (delete-region (line-beginning-position)
1931 (1+ (line-end-position)))
a464a6c7 1932 (cl-incf ibuffer-map-lines-count)
57c9cc3e 1933 (when (< ibuffer-map-lines-total
4e4a724c 1934 orig-target-line)
a464a6c7 1935 (cl-decf target-line-offset)))
57c9cc3e 1936 (t
a464a6c7 1937 (cl-incf ibuffer-map-lines-count)
57c9cc3e
CW
1938 (forward-line 1)))))
1939 ibuffer-map-lines-count)
25d2f683
CW
1940 (progn
1941 (setq buffer-read-only t)
1942 (unless nomodify
1943 (set-buffer-modified-p nil))
57c9cc3e
CW
1944 (goto-char (point-min))
1945 (ibuffer-forward-line 0)
b5cd37ea 1946 (ibuffer-forward-line (1- target-line-offset))))))
25d2f683
CW
1947
1948(defun ibuffer-get-marked-buffers ()
1949 "Return a list of buffer objects currently marked."
1950 (delq nil
06b60517
JB
1951 (mapcar (lambda (e)
1952 (when (eq (cdr e) ibuffer-marked-char)
1953 (car e)))
25d2f683
CW
1954 (ibuffer-current-state-list))))
1955
d246cabf
CW
1956(defun ibuffer-current-state-list (&optional pos)
1957 "Return a list like (BUF . MARK) of all buffers in an ibuffer.
1958If POS is non-nil, return a list like (BUF MARK POINT), where POINT is
1959the value of point at the beginning of the line for that buffer."
25d2f683
CW
1960 (let ((ibuffer-current-state-list-tmp '()))
1961 ;; ah, if only we had closures. I bet this will mysteriously
1962 ;; break later. Don't blame me.
d246cabf
CW
1963 (if pos
1964 (ibuffer-map-lines-nomodify
06b60517 1965 (lambda (buf mark)
d246cabf 1966 (when (buffer-live-p buf)
06b60517
JB
1967 (push (list buf mark (point)) ibuffer-current-state-list-tmp))))
1968 (ibuffer-map-lines-nomodify
1969 (lambda (buf mark)
1970 (when (buffer-live-p buf)
1971 (push (cons buf mark) ibuffer-current-state-list-tmp)))))
25d2f683
CW
1972 (nreverse ibuffer-current-state-list-tmp)))
1973
851476d4 1974(defun ibuffer-current-buffers-with-marks (curbufs)
25d2f683
CW
1975 "Return a list like (BUF . MARK) of all open buffers."
1976 (let ((bufs (ibuffer-current-state-list)))
06b60517
JB
1977 (mapcar (lambda (buf) (let ((e (assq buf bufs)))
1978 (if e
1979 e
1980 (cons buf ?\s))))
851476d4 1981 curbufs)))
25d2f683
CW
1982
1983(defun ibuffer-buf-matches-predicates (buf predicates)
1984 (let ((hit nil)
1985 (name (buffer-name buf)))
1986 (dolist (pred predicates)
1987 (when (if (stringp pred)
1988 (string-match pred name)
1989 (funcall pred buf))
1990 (setq hit t)))
1991 hit))
71296446 1992
25d2f683
CW
1993(defun ibuffer-filter-buffers (ibuffer-buf last bmarklist all)
1994 (let ((ext-loaded (featurep 'ibuf-ext)))
1995 (delq nil
b5cd37ea
CW
1996 (mapcar
1997 ;; element should be like (BUFFER . MARK)
06b60517
JB
1998 (lambda (e)
1999 (let* ((buf (car e)))
2000 (when
2001 ;; This takes precedence over anything else
2002 (or (and ibuffer-always-show-last-buffer
2003 (eq last buf))
2004 (funcall (if ext-loaded
2005 #'ibuffer-ext-visible-p
2006 #'ibuffer-visible-p)
2007 buf all ibuffer-buf))
2008 e)))
b5cd37ea 2009 bmarklist))))
25d2f683
CW
2010
2011(defun ibuffer-visible-p (buf all &optional ibuffer-buf)
2012 (and (or all
2013 (not
2014 (ibuffer-buf-matches-predicates buf ibuffer-maybe-show-predicates)))
2015 (or ibuffer-view-ibuffer
4e4a724c 2016 (and ibuffer-buf
25d2f683
CW
2017 (not (eq ibuffer-buf buf))))))
2018
2019;; This function is a special case; it's not defined by
6081889e 2020;; `define-ibuffer-sorter'.
25d2f683
CW
2021(defun ibuffer-do-sort-by-recency ()
2022 "Sort the buffers by last view time."
2023 (interactive)
2024 (setq ibuffer-sorting-mode 'recency)
e7820654
JPW
2025 (when (eq ibuffer-last-sorting-mode 'recency)
2026 (setq ibuffer-sorting-reversep (not ibuffer-sorting-reversep)))
2027 (ibuffer-update nil t)
2028 (setq ibuffer-last-sorting-mode 'recency))
25d2f683
CW
2029
2030(defun ibuffer-update-format ()
2031 (when (null ibuffer-current-format)
2032 (setq ibuffer-current-format 0))
2033 (when (null ibuffer-formats)
2034 (error "Ibuffer error: no formats!")))
2035
2036(defun ibuffer-switch-format ()
2037 "Switch the current display format."
2038 (interactive)
87a6a53a 2039 (ibuffer-assert-ibuffer-mode)
25d2f683
CW
2040 (unless (consp ibuffer-formats)
2041 (error "Ibuffer error: No formats!"))
2042 (setq ibuffer-current-format
80a06d64 2043 (if (>= ibuffer-current-format (1- (length (ibuffer-current-formats nil))))
25d2f683
CW
2044 0
2045 (1+ ibuffer-current-format)))
2046 (ibuffer-update-format)
2047 (ibuffer-redisplay t))
2048
cb059426 2049(defun ibuffer-update-title-and-summary (format)
87a6a53a 2050 (ibuffer-assert-ibuffer-mode)
25d2f683
CW
2051 ;; Don't do funky font-lock stuff here
2052 (let ((after-change-functions nil))
2053 (if (get-text-property (point-min) 'ibuffer-title)
2054 (delete-region (point-min)
2055 (next-single-property-change
2056 (point-min) 'ibuffer-title)))
2057 (goto-char (point-min))
fd225d80 2058 (add-text-properties
25d2f683
CW
2059 (point)
2060 (progn
2061 (let ((opos (point)))
2062 ;; Insert the title names.
cb059426 2063 (dolist (element format)
25d2f683
CW
2064 (insert
2065 (if (stringp element)
2066 element
a464a6c7 2067 (pcase-let ((`(,sym ,min ,_max ,align) element))
4e4a724c 2068 ;; Ignore a negative min when we're inserting the title
a464a6c7 2069 (when (cl-minusp min)
25d2f683
CW
2070 (setq min (- min)))
2071 (let* ((name (or (get sym 'ibuffer-column-name)
2072 (error "Unknown column %s in ibuffer-formats" sym)))
f0b31589
DN
2073 (len (length name))
2074 (hmap (get sym 'header-mouse-map))
2075 (strname (if (< len min)
2076 (ibuffer-format-column name
2077 (- min len)
2078 align)
2079 name)))
2080 (when hmap
2081 (setq
2ead9289 2082 strname
f0b31589
DN
2083 (propertize strname 'mouse-face 'highlight 'keymap hmap)))
2084 strname)))))
fd225d80 2085 (add-text-properties opos (point) `(ibuffer-title-header t))
25d2f683
CW
2086 (insert "\n")
2087 ;; Add the underlines
2088 (let ((str (save-excursion
2089 (forward-line -1)
2090 (beginning-of-line)
2091 (buffer-substring (point) (line-end-position)))))
2092 (apply #'insert (mapcar
06b60517
JB
2093 (lambda (c)
2094 (if (not (or (char-equal c ?\s)
2095 (char-equal c ?\n)))
2096 ?-
2097 ?\s))
25d2f683
CW
2098 str)))
2099 (insert "\n"))
2100 (point))
545aad2f 2101 `(ibuffer-title t font-lock-face ,ibuffer-title-face))
cb059426
CW
2102 ;; Now, insert the summary columns.
2103 (goto-char (point-max))
2104 (if (get-text-property (1- (point-max)) 'ibuffer-summary)
2105 (delete-region (previous-single-property-change
2106 (point-max) 'ibuffer-summary)
2107 (point-max)))
0740098c
JPW
2108 (if ibuffer-display-summary
2109 (add-text-properties
2110 (point)
2111 (progn
2112 (insert "\n")
2113 (dolist (element format)
2114 (insert
2115 (if (stringp element)
972b8f82 2116 (make-string (length element) ?\s)
a464a6c7
SM
2117 (pcase-let ((`(,sym ,min ,_max ,align) element))
2118 ;; Ignore a negative min when we're inserting the title.
2119 (when (cl-minusp min)
2120 (setq min (- min)))
2121 (let* ((summary
2122 (if (get sym 'ibuffer-column-summarizer)
2123 (funcall (get sym 'ibuffer-column-summarizer)
2124 (get sym 'ibuffer-column-summary))
2125 (make-string
2126 (length (get sym 'ibuffer-column-name))
2127 ?\s)))
2128 (len (length summary)))
2129 (if (< len min)
2130 (ibuffer-format-column summary
2131 (- min len)
2132 align)
2133 summary))))))
0740098c
JPW
2134 (point))
2135 `(ibuffer-summary t)))))
25d2f683 2136
25d2f683
CW
2137
2138(defun ibuffer-redisplay (&optional silent)
2139 "Redisplay the current list of buffers.
25d2f683
CW
2140This does not show new buffers; use `ibuffer-update' for that.
2141
7ad5b902 2142If optional arg SILENT is non-nil, do not display progress messages."
25d2f683 2143 (interactive)
57c9cc3e 2144 (ibuffer-forward-line 0)
25d2f683
CW
2145 (unless silent
2146 (message "Redisplaying current buffer list..."))
2147 (let ((blist (ibuffer-current-state-list)))
de5939ba
CS
2148 (when (and (null blist)
2149 (featurep 'ibuf-ext)
cba63a2d 2150 (or ibuffer-filtering-qualifiers ibuffer-hidden-filter-groups))
de5939ba 2151 (message "No buffers! (note: filtering in effect)"))
b5cd37ea 2152 (ibuffer-redisplay-engine blist t)
25d2f683 2153 (unless silent
57c9cc3e
CW
2154 (message "Redisplaying current buffer list...done"))
2155 (ibuffer-forward-line 0)))
25d2f683
CW
2156
2157(defun ibuffer-update (arg &optional silent)
2158 "Regenerate the list of all buffers.
957237cb
JPW
2159
2160Prefix arg non-nil means to toggle whether buffers that match
2161`ibuffer-maybe-show-predicates' should be displayed.
25d2f683 2162
7ad5b902 2163If optional arg SILENT is non-nil, do not display progress messages."
25d2f683 2164 (interactive "P")
957237cb
JPW
2165 (if arg
2166 (setq ibuffer-display-maybe-show-predicates
2167 (not ibuffer-display-maybe-show-predicates)))
57c9cc3e 2168 (ibuffer-forward-line 0)
25d2f683
CW
2169 (let* ((bufs (buffer-list))
2170 (blist (ibuffer-filter-buffers
94394914
JPW
2171 (current-buffer)
2172 (if (and
2173 (cadr bufs)
2174 (eq ibuffer-always-show-last-buffer
2175 :nomini)
8e7dbfdb 2176 (minibufferp (cadr bufs)))
a464a6c7 2177 (cl-caddr bufs)
94394914
JPW
2178 (cadr bufs))
2179 (ibuffer-current-buffers-with-marks bufs)
957237cb 2180 ibuffer-display-maybe-show-predicates)))
4098f8f7
CS
2181 (and (null blist)
2182 (featurep 'ibuf-ext)
2183 ibuffer-filtering-qualifiers
2184 (message "No buffers! (note: filtering in effect)"))
25d2f683
CW
2185 (unless silent
2186 (message "Updating buffer list..."))
b5cd37ea 2187 (ibuffer-redisplay-engine blist arg)
25d2f683
CW
2188 (unless silent
2189 (message "Updating buffer list...done")))
2190 (if (eq ibuffer-shrink-to-minimum-size 'onewindow)
2191 (ibuffer-shrink-to-fit t)
2192 (when ibuffer-shrink-to-minimum-size
2193 (ibuffer-shrink-to-fit)))
6d11a78b
SM
2194 (ibuffer-forward-line 0)
2195 ;; I tried to update this automatically from the mode-line-process format,
2196 ;; but changing nil-ness of header-line-format while computing
2197 ;; mode-line-format is asking a bit too much it seems. --Stef
2198 (setq header-line-format
2199 (and ibuffer-use-header-line
2200 ibuffer-filtering-qualifiers
2201 ibuffer-header-line-format)))
25d2f683 2202
b5cd37ea 2203(defun ibuffer-sort-bufferlist (bmarklist)
e19fff38
JB
2204 (unless ibuffer-sorting-functions-alist
2205 ;; make sure the sorting functions are loaded
2206 (require 'ibuf-ext))
b5cd37ea
CW
2207 (let* ((sortdat (assq ibuffer-sorting-mode
2208 ibuffer-sorting-functions-alist))
a464a6c7 2209 (func (cl-caddr sortdat)))
b5cd37ea
CW
2210 (let ((result
2211 ;; actually sort the buffers
2212 (if (and sortdat func)
2213 (sort bmarklist func)
2214 bmarklist)))
2215 ;; perhaps reverse the sorted buffer list
2216 (if ibuffer-sorting-reversep
2217 (nreverse result)
2218 result))))
2219
7fbac645 2220(defun ibuffer-insert-filter-group (name display-name filter-string format bmarklist)
b5cd37ea
CW
2221 (add-text-properties
2222 (point)
2223 (progn
2224 (insert "[ " display-name " ]")
2225 (point))
fd225d80
CW
2226 `(ibuffer-filter-group-name
2227 ,name
545aad2f 2228 font-lock-face ,ibuffer-filter-group-name-face
fd225d80
CW
2229 keymap ,ibuffer-mode-filter-group-map
2230 mouse-face highlight
1cd7affa
JPW
2231 help-echo ,(let ((echo '(if tooltip-mode
2232 "mouse-1: toggle marks in this group\nmouse-2: hide/show this filtering group"
ce3a4c83 2233 "mouse-1: toggle marks mouse-2: hide/show")))
1cd7affa 2234 (if (> (length filter-string) 0)
ce3a4c83
JPW
2235 `(concat ,filter-string
2236 (if tooltip-mode "\n" " ")
2237 ,echo)
1cd7affa 2238 echo))))
b5cd37ea
CW
2239 (insert "\n")
2240 (when bmarklist
2241 (put-text-property
2242 (point)
2243 (progn
2244 (dolist (entry bmarklist)
2245 (ibuffer-insert-buffer-line (car entry) (cdr entry) format))
2246 (point))
2247 'ibuffer-filter-group
2248 name)))
2249
06b60517 2250(defun ibuffer-redisplay-engine (bmarklist &optional _ignore)
87a6a53a 2251 (ibuffer-assert-ibuffer-mode)
b5cd37ea
CW
2252 (let* ((--ibuffer-insert-buffers-and-marks-format
2253 (ibuffer-current-format))
2254 (--ibuffer-expanded-format (mapcar #'ibuffer-expand-format-entry
2255 (ibuffer-current-format t)))
2256 (orig (count-lines (point-min) (point)))
2257 ;; Inhibit font-lock caching tricks, since we're modifying the
2258 ;; entire buffer at once
2259 (after-change-functions nil)
2260 (ext-loaded (featurep 'ibuf-ext))
2261 (bgroups (if ext-loaded
2262 (ibuffer-generate-filter-groups bmarklist)
2263 (list (cons "Default" bmarklist)))))
cb059426 2264 (ibuffer-clear-summary-columns --ibuffer-expanded-format)
25d2f683
CW
2265 (unwind-protect
2266 (progn
2267 (setq buffer-read-only nil)
2268 (erase-buffer)
2269 (ibuffer-update-format)
b5cd37ea
CW
2270 (dolist (group (nreverse bgroups))
2271 (let* ((name (car group))
2272 (disabled (and ext-loaded
cba63a2d 2273 (member name ibuffer-hidden-filter-groups)))
b5cd37ea 2274 (bmarklist (cdr group)))
cba63a2d 2275 (unless (and (null bmarklist)
b90a6a12 2276 (not disabled)
cba63a2d
CW
2277 ext-loaded
2278 (null ibuffer-show-empty-filter-groups))
2279 (ibuffer-insert-filter-group
2280 name
2281 (if disabled (concat name " ...") name)
7fbac645
CW
2282 (if ext-loaded
2283 (ibuffer-format-filter-group-data name)
2284 "")
cba63a2d
CW
2285 --ibuffer-insert-buffers-and-marks-format
2286 (if disabled
2287 nil
2288 (ibuffer-sort-bufferlist bmarklist))))))
cb059426 2289 (ibuffer-update-title-and-summary --ibuffer-expanded-format))
25d2f683
CW
2290 (setq buffer-read-only t)
2291 (set-buffer-modified-p ibuffer-did-modification)
2292 (setq ibuffer-did-modification nil)
e600eb79 2293 (goto-char (point-min))
2ead9289 2294 (forward-line orig))))
25d2f683
CW
2295
2296(defun ibuffer-quit ()
2297 "Quit this `ibuffer' session.
4837b516 2298Try to restore the previous window configuration if
4ed1f829 2299`ibuffer-restore-window-config-on-quit' is non-nil."
25d2f683 2300 (interactive)
4ed1f829 2301 (if ibuffer-restore-window-config-on-quit
7ad938e7 2302 (progn
25d2f683
CW
2303 (bury-buffer)
2304 (unless (= (count-windows) 1)
4ed1f829 2305 (set-window-configuration ibuffer-prev-window-config)))
25d2f683
CW
2306 (bury-buffer)))
2307
2308;;;###autoload
2309(defun ibuffer-list-buffers (&optional files-only)
2310 "Display a list of buffers, in another window.
2311If optional argument FILES-ONLY is non-nil, then add a filter for
2312buffers which are visiting a file."
2313 (interactive "P")
2314 (ibuffer t nil (when files-only
2315 '((filename . ".*"))) t))
2316
2317;;;###autoload
2318(defun ibuffer-other-window (&optional files-only)
2319 "Like `ibuffer', but displayed in another window by default.
2320If optional argument FILES-ONLY is non-nil, then add a filter for
2321buffers which are visiting a file."
2322 (interactive "P")
2323 (ibuffer t nil (when files-only
2324 '((filename . ".*")))))
2325
2326;;;###autoload
b5cd37ea 2327(defun ibuffer (&optional other-window-p name qualifiers noselect
fd225d80 2328 shrink filter-groups formats)
972b8f82 2329 "Begin using Ibuffer to edit a list of buffers.
25d2f683
CW
2330Type 'h' after entering ibuffer for more information.
2331
972b8f82
JB
2332All arguments are optional.
2333OTHER-WINDOW-P says to use another window.
2334NAME specifies the name of the buffer (defaults to \"*Ibuffer*\").
2335QUALIFIERS is an initial set of filtering qualifiers to use;
2336 see `ibuffer-filtering-qualifiers'.
2337NOSELECT means don't select the Ibuffer buffer.
2338SHRINK means shrink the buffer to minimal size. The special
2339 value `onewindow' means always use another window.
2340FILTER-GROUPS is an initial set of filtering groups to use;
2341 see `ibuffer-filter-groups'.
2342FORMATS is the value to use for `ibuffer-formats'.
2343 If specified, then the variable `ibuffer-formats' will have
2344 that value locally in this buffer."
25d2f683
CW
2345 (interactive "P")
2346 (when ibuffer-use-other-window
34b8f593 2347 (setq other-window-p t))
4ed1f829 2348 (setq ibuffer-prev-window-config (current-window-configuration))
34a4faa0 2349 (let ((buf (get-buffer-create (or name "*Ibuffer*"))))
25d2f683 2350 (if other-window-p
06b60517 2351 (funcall (if noselect (lambda (buf) (display-buffer buf t)) #'pop-to-buffer) buf)
25d2f683
CW
2352 (funcall (if noselect #'display-buffer #'switch-to-buffer) buf))
2353 (with-current-buffer buf
b5cd37ea
CW
2354 (save-selected-window
2355 ;; We switch to the buffer's window in order to be able
2356 ;; to modify the value of point
fab0d308 2357 (select-window (get-buffer-window buf 0))
34a4faa0
JPW
2358 (or (eq major-mode 'ibuffer-mode)
2359 (ibuffer-mode))
4ed1f829 2360 (setq ibuffer-restore-window-config-on-quit other-window-p)
b5cd37ea
CW
2361 (when shrink
2362 (setq ibuffer-shrink-to-minimum-size shrink))
2363 (when qualifiers
2364 (require 'ibuf-ext)
2365 (setq ibuffer-filtering-qualifiers qualifiers))
2366 (when filter-groups
2367 (require 'ibuf-ext)
cba63a2d 2368 (setq ibuffer-filter-groups filter-groups))
fd225d80
CW
2369 (when formats
2370 (set (make-local-variable 'ibuffer-formats) formats))
b5cd37ea
CW
2371 (ibuffer-update nil)
2372 ;; Skip the group name by default.
2373 (ibuffer-forward-line 0 t)
25d2f683
CW
2374 (unwind-protect
2375 (progn
b5cd37ea 2376 (setq buffer-read-only nil)
7ad5b902 2377 (run-hooks 'ibuffer-hook))
b5cd37ea
CW
2378 (setq buffer-read-only t))
2379 (unless ibuffer-expert
2380 (message "Commands: m, u, t, RET, g, k, S, D, Q; q to quit; h for help"))))))
25d2f683 2381
b23af469 2382(put 'ibuffer-mode 'mode-class 'special)
25d2f683
CW
2383(defun ibuffer-mode ()
2384 "A major mode for viewing a list of buffers.
972b8f82 2385In Ibuffer, you can conveniently perform many operations on the
25d2f683
CW
2386currently open buffers, in addition to filtering your view to a
2387particular subset of them, and sorting by various criteria.
2388
2389Operations on marked buffers:
8e66aebe 2390\\<ibuffer-mode-map>
25d2f683
CW
2391 '\\[ibuffer-do-save]' - Save the marked buffers
2392 '\\[ibuffer-do-view]' - View the marked buffers in this frame.
2393 '\\[ibuffer-do-view-other-frame]' - View the marked buffers in another frame.
2394 '\\[ibuffer-do-revert]' - Revert the marked buffers.
2395 '\\[ibuffer-do-toggle-read-only]' - Toggle read-only state of marked buffers.
2396 '\\[ibuffer-do-delete]' - Kill the marked buffers.
78176075
JL
2397 '\\[ibuffer-do-isearch]' - Do incremental search in the marked buffers.
2398 '\\[ibuffer-do-isearch-regexp]' - Isearch for regexp in the marked buffers.
25d2f683
CW
2399 '\\[ibuffer-do-replace-regexp]' - Replace by regexp in each of the marked
2400 buffers.
2401 '\\[ibuffer-do-query-replace]' - Query replace in each of the marked buffers.
2402 '\\[ibuffer-do-query-replace-regexp]' - As above, with a regular expression.
2403 '\\[ibuffer-do-print]' - Print the marked buffers.
2404 '\\[ibuffer-do-occur]' - List lines in all marked buffers which match
2405 a given regexp (like the function `occur').
2406 '\\[ibuffer-do-shell-command-pipe]' - Pipe the contents of the marked
2407 buffers to a shell command.
2408 '\\[ibuffer-do-shell-command-pipe-replace]' - Replace the contents of the marked
2409 buffers with the output of a shell command.
2410 '\\[ibuffer-do-shell-command-file]' - Run a shell command with the
2411 buffer's file as an argument.
2412 '\\[ibuffer-do-eval]' - Evaluate a form in each of the marked buffers. This
2413 is a very flexible command. For example, if you want to make all
35e62fc9 2414 of the marked buffers read only, try using (read-only-mode 1) as
25d2f683
CW
2415 the input form.
2416 '\\[ibuffer-do-view-and-eval]' - As above, but view each buffer while the form
2417 is evaluated.
2418 '\\[ibuffer-do-kill-lines]' - Remove the marked lines from the *Ibuffer* buffer,
2419 but don't kill the associated buffer.
2420 '\\[ibuffer-do-kill-on-deletion-marks]' - Kill all buffers marked for deletion.
2421
2422Marking commands:
2423
2424 '\\[ibuffer-mark-forward]' - Mark the buffer at point.
2425 '\\[ibuffer-toggle-marks]' - Unmark all currently marked buffers, and mark
2426 all unmarked buffers.
2427 '\\[ibuffer-unmark-forward]' - Unmark the buffer at point.
2428 '\\[ibuffer-unmark-backward]' - Unmark the buffer at point, and move to the
2429 previous line.
2430 '\\[ibuffer-unmark-all]' - Unmark all marked buffers.
2431 '\\[ibuffer-mark-by-mode]' - Mark buffers by major mode.
2432 '\\[ibuffer-mark-unsaved-buffers]' - Mark all \"unsaved\" buffers.
2433 This means that the buffer is modified, and has an associated file.
2434 '\\[ibuffer-mark-modified-buffers]' - Mark all modified buffers,
2435 regardless of whether or not they have an associated file.
2436 '\\[ibuffer-mark-special-buffers]' - Mark all buffers whose name begins and
2437 ends with '*'.
2438 '\\[ibuffer-mark-dissociated-buffers]' - Mark all buffers which have
2439 an associated file, but that file doesn't currently exist.
2440 '\\[ibuffer-mark-read-only-buffers]' - Mark all read-only buffers.
2441 '\\[ibuffer-mark-dired-buffers]' - Mark buffers in `dired' mode.
2442 '\\[ibuffer-mark-help-buffers]' - Mark buffers in `help-mode', `apropos-mode', etc.
2443 '\\[ibuffer-mark-old-buffers]' - Mark buffers older than `ibuffer-old-time'.
2444 '\\[ibuffer-mark-for-delete]' - Mark the buffer at point for deletion.
2445 '\\[ibuffer-mark-by-name-regexp]' - Mark buffers by their name, using a regexp.
2446 '\\[ibuffer-mark-by-mode-regexp]' - Mark buffers by their major mode, using a regexp.
2447 '\\[ibuffer-mark-by-file-name-regexp]' - Mark buffers by their filename, using a regexp.
2448
2449Filtering commands:
2450
a1d3e07e
GM
2451 '\\[ibuffer-filter-by-mode]' - Add a filter by any major mode.
2452 '\\[ibuffer-filter-by-used-mode]' - Add a filter by a major mode now in use.
2453 '\\[ibuffer-filter-by-derived-mode]' - Add a filter by derived mode.
25d2f683
CW
2454 '\\[ibuffer-filter-by-name]' - Add a filter by buffer name.
2455 '\\[ibuffer-filter-by-content]' - Add a filter by buffer content.
2456 '\\[ibuffer-filter-by-filename]' - Add a filter by filename.
2457 '\\[ibuffer-filter-by-size-gt]' - Add a filter by buffer size.
2458 '\\[ibuffer-filter-by-size-lt]' - Add a filter by buffer size.
2459 '\\[ibuffer-filter-by-predicate]' - Add a filter by an arbitrary Lisp predicate.
2460 '\\[ibuffer-save-filters]' - Save the current filters with a name.
2461 '\\[ibuffer-switch-to-saved-filters]' - Switch to previously saved filters.
2462 '\\[ibuffer-add-saved-filters]' - Add saved filters to current filters.
2463 '\\[ibuffer-or-filter]' - Replace the top two filters with their logical OR.
2464 '\\[ibuffer-pop-filter]' - Remove the top filter.
2465 '\\[ibuffer-negate-filter]' - Invert the logical sense of the top filter.
2466 '\\[ibuffer-decompose-filter]' - Break down the topmost filter.
2467 '\\[ibuffer-filter-disable]' - Remove all filtering currently in effect.
cba63a2d
CW
2468
2469Filter group commands:
2470
2471 '\\[ibuffer-filters-to-filter-group]' - Create filter group from filters.
2472 '\\[ibuffer-pop-filter-group]' - Remove top filter group.
b098e753
CW
2473 '\\[ibuffer-forward-filter-group]' - Move to the next filter group.
2474 '\\[ibuffer-backward-filter-group]' - Move to the previous filter group.
2475 '\\[ibuffer-clear-filter-groups]' - Remove all active filter groups.
2476 '\\[ibuffer-save-filter-groups]' - Save the current groups with a name.
2477 '\\[ibuffer-switch-to-saved-filter-groups]' - Restore previously saved groups.
2478 '\\[ibuffer-delete-saved-filter-groups]' - Delete previously saved groups.
71296446 2479
25d2f683
CW
2480Sorting commands:
2481
2482 '\\[ibuffer-toggle-sorting-mode]' - Rotate between the various sorting modes.
2483 '\\[ibuffer-invert-sorting]' - Reverse the current sorting order.
2484 '\\[ibuffer-do-sort-by-alphabetic]' - Sort the buffers lexicographically.
d5794180 2485 '\\[ibuffer-do-sort-by-filename/process]' - Sort the buffers by the file name.
25d2f683
CW
2486 '\\[ibuffer-do-sort-by-recency]' - Sort the buffers by last viewing time.
2487 '\\[ibuffer-do-sort-by-size]' - Sort the buffers by size.
2488 '\\[ibuffer-do-sort-by-major-mode]' - Sort the buffers by major mode.
2489
2490Other commands:
2491
4c38df30
JPW
2492 '\\[ibuffer-update]' - Regenerate the list of all buffers.
2493 Prefix arg means to toggle whether buffers that match
2494 `ibuffer-maybe-show-predicates' should be displayed.
2495
25d2f683
CW
2496 '\\[ibuffer-switch-format]' - Change the current display format.
2497 '\\[forward-line]' - Move point to the next line.
2498 '\\[previous-line]' - Move point to the previous line.
25d2f683
CW
2499 '\\[ibuffer-quit]' - Bury the Ibuffer buffer.
2500 '\\[describe-mode]' - This help.
2501 '\\[ibuffer-diff-with-file]' - View the differences between this buffer
2502 and its associated file.
2503 '\\[ibuffer-visit-buffer]' - View the buffer on this line.
2504 '\\[ibuffer-visit-buffer-other-window]' - As above, but in another window.
2505 '\\[ibuffer-visit-buffer-other-window-noselect]' - As both above, but don't select
2506 the new window.
2507 '\\[ibuffer-bury-buffer]' - Bury (not kill!) the buffer on this line.
2508
cba63a2d 2509** Information on Filtering:
25d2f683 2510
da6062e6 2511 You can filter your ibuffer view via different criteria. Each Ibuffer
25d2f683
CW
2512buffer has its own stack of active filters. For example, suppose you
2513are working on an Emacs Lisp project. You can create an Ibuffer
2514buffer displays buffers in just `emacs-lisp' modes via
2515'\\[ibuffer-filter-by-mode] emacs-lisp-mode RET'. In this case, there
2516is just one entry on the filtering stack.
2517
2518You can also combine filters. The various filtering commands push a
2519new filter onto the stack, and the filters combine to show just
2520buffers which satisfy ALL criteria on the stack. For example, suppose
2521you only want to see buffers in `emacs-lisp' mode, whose names begin
2522with \"gnus\". You can accomplish this via:
2523'\\[ibuffer-filter-by-mode] emacs-lisp-mode RET
2524\\[ibuffer-filter-by-name] ^gnus RET'.
2525
2526Additionally, you can OR the top two filters together with
2527'\\[ibuffer-or-filters]'. To see all buffers in either
2528`emacs-lisp-mode' or `lisp-interaction-mode', type:
2529
2530'\\[ibuffer-filter-by-mode] emacs-lisp-mode RET \\[ibuffer-filter-by-mode] lisp-interaction-mode RET \\[ibuffer-or-filters]'.
2531
2532Filters can also be saved and restored using mnemonic names: see the
2533functions `ibuffer-save-filters' and `ibuffer-switch-to-saved-filters'.
2534
2535To remove the top filter on the stack, use '\\[ibuffer-pop-filter]', and
2536to disable all filtering currently in effect, use
cba63a2d
CW
2537'\\[ibuffer-filter-disable]'.
2538
2539** Filter Groups:
2540
2541Once one has mastered filters, the next logical step up is \"filter
2542groups\". A filter group is basically a named group of buffers which
2543match a filter, which are displayed together in an Ibuffer buffer. To
2544create a filter group, simply use the regular functions to create a
2545filter, and then type '\\[ibuffer-filters-to-filter-group]'.
2546
2547A quick example will make things clearer. Suppose that one wants to
2548group all of one's Emacs Lisp buffers together. To do this, type
2549
2550'\\[ibuffer-filter-by-mode] emacs-lisp-mode RET \\[ibuffer-filters-to-filter-group] RET emacs lisp buffers RET'
2551
2552You may, of course, name the group whatever you want; it doesn't have
2553to be \"emacs lisp buffers\". Filter groups may be composed of any
2554arbitrary combination of filters.
2555
2556Just like filters themselves, filter groups act as a stack. Buffers
2557will not be displayed multiple times if they would be included in
2558multiple filter groups; instead, the first filter group is used. The
2559filter groups are displayed in this order of precedence.
2560
2561You may rearrange filter groups by using the regular
2562'\\[ibuffer-kill-line]' and '\\[ibuffer-yank]' pair. Yanked groups
2563will be inserted before the group at point."
25d2f683
CW
2564 (kill-all-local-variables)
2565 (use-local-map ibuffer-mode-map)
2566 (setq major-mode 'ibuffer-mode)
2567 (setq mode-name "Ibuffer")
23eabff6 2568 ;; Include state info next to the mode name.
e47b4224 2569 (set (make-local-variable 'mode-line-process)
56618a0a
SM
2570 '(" by "
2571 (ibuffer-sorting-mode (:eval (symbol-name ibuffer-sorting-mode))
23eabff6
SM
2572 "view time")
2573 (ibuffer-sorting-reversep " [rev]")
2574 (ibuffer-auto-mode " (Auto)")
2575 ;; Only list the filters if they're not already in the header-line.
2576 (header-line-format
2577 ""
2578 (:eval (if (functionp 'ibuffer-format-qualifier)
2579 (mapconcat 'ibuffer-format-qualifier
2580 ibuffer-filtering-qualifiers ""))))))
6d11a78b
SM
2581 ;; `ibuffer-update' puts this on header-line-format when needed.
2582 (setq ibuffer-header-line-format
2583 ;; Display the part that won't be in the mode-line.
a464a6c7
SM
2584 `("" ,mode-name
2585 ,@(mapcar (lambda (elem)
2586 (if (eq (car-safe elem) 'header-line-format)
2587 (nth 2 elem) elem))
2588 mode-line-process)))
23eabff6 2589
25d2f683
CW
2590 (setq buffer-read-only t)
2591 (buffer-disable-undo)
3eda3649 2592 (setq truncate-lines ibuffer-truncate-lines)
25d2f683
CW
2593 ;; This makes things less ugly for Emacs 21 users with a non-nil
2594 ;; `show-trailing-whitespace'.
2595 (setq show-trailing-whitespace nil)
4ba16127
JPW
2596 ;; disable `show-paren-mode' buffer-locally
2597 (if (bound-and-true-p show-paren-mode)
2598 (set (make-local-variable 'show-paren-mode) nil))
25d2f683
CW
2599 (set (make-local-variable 'revert-buffer-function)
2600 #'ibuffer-update)
2601 (set (make-local-variable 'ibuffer-sorting-mode)
2602 ibuffer-default-sorting-mode)
2603 (set (make-local-variable 'ibuffer-sorting-reversep)
2604 ibuffer-default-sorting-reversep)
2605 (set (make-local-variable 'ibuffer-shrink-to-minimum-size)
2606 ibuffer-default-shrink-to-minimum-size)
957237cb
JPW
2607 (set (make-local-variable 'ibuffer-display-maybe-show-predicates)
2608 ibuffer-default-display-maybe-show-predicates)
25d2f683 2609 (set (make-local-variable 'ibuffer-filtering-qualifiers) nil)
cba63a2d
CW
2610 (set (make-local-variable 'ibuffer-filter-groups) nil)
2611 (set (make-local-variable 'ibuffer-filter-group-kill-ring) nil)
2612 (set (make-local-variable 'ibuffer-hidden-filter-groups) nil)
25d2f683
CW
2613 (set (make-local-variable 'ibuffer-compiled-formats) nil)
2614 (set (make-local-variable 'ibuffer-cached-formats) nil)
2615 (set (make-local-variable 'ibuffer-cached-eliding-string) nil)
2616 (set (make-local-variable 'ibuffer-cached-elide-long-columns) nil)
2617 (set (make-local-variable 'ibuffer-current-format) nil)
4ed1f829 2618 (set (make-local-variable 'ibuffer-restore-window-config-on-quit) nil)
25d2f683 2619 (set (make-local-variable 'ibuffer-did-modification) nil)
b5cd37ea
CW
2620 (set (make-local-variable 'ibuffer-tmp-hide-regexps) nil)
2621 (set (make-local-variable 'ibuffer-tmp-show-regexps) nil)
25d2f683
CW
2622 (define-key ibuffer-mode-map [menu-bar edit] 'undefined)
2623 (define-key ibuffer-mode-map [menu-bar operate] (cons "Operate" ibuffer-mode-operate-map))
2624 (ibuffer-update-format)
2625 (when ibuffer-default-directory
2626 (setq default-directory ibuffer-default-directory))
214fee7a 2627 (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
23eabff6 2628 (run-mode-hooks 'ibuffer-mode-hook))
25d2f683 2629
45a68029
GM
2630\f
2631;;; Start of automatically extracted autoloads.
2632\f
2633;;;### (autoloads (ibuffer-do-occur ibuffer-mark-dired-buffers ibuffer-mark-read-only-buffers
2634;;;;;; ibuffer-mark-special-buffers ibuffer-mark-old-buffers ibuffer-mark-compressed-file-buffers
2635;;;;;; ibuffer-mark-help-buffers ibuffer-mark-dissociated-buffers
2636;;;;;; ibuffer-mark-unsaved-buffers ibuffer-mark-modified-buffers
2637;;;;;; ibuffer-mark-by-mode ibuffer-mark-by-file-name-regexp ibuffer-mark-by-mode-regexp
2638;;;;;; ibuffer-mark-by-name-regexp ibuffer-copy-filename-as-kill
2639;;;;;; ibuffer-diff-with-file ibuffer-jump-to-buffer ibuffer-do-kill-lines
2640;;;;;; ibuffer-backwards-next-marked ibuffer-forward-next-marked
2641;;;;;; ibuffer-add-to-tmp-show ibuffer-add-to-tmp-hide ibuffer-bs-show
2642;;;;;; ibuffer-invert-sorting ibuffer-toggle-sorting-mode ibuffer-switch-to-saved-filters
2643;;;;;; ibuffer-add-saved-filters ibuffer-delete-saved-filters ibuffer-save-filters
2644;;;;;; ibuffer-or-filter ibuffer-negate-filter ibuffer-exchange-filters
2645;;;;;; ibuffer-decompose-filter ibuffer-pop-filter ibuffer-filter-disable
2646;;;;;; ibuffer-switch-to-saved-filter-groups ibuffer-delete-saved-filter-groups
2647;;;;;; ibuffer-save-filter-groups ibuffer-yank-filter-group ibuffer-yank
2648;;;;;; ibuffer-kill-line ibuffer-kill-filter-group ibuffer-jump-to-filter-group
2649;;;;;; ibuffer-clear-filter-groups ibuffer-decompose-filter-group
2650;;;;;; ibuffer-pop-filter-group ibuffer-set-filter-groups-by-mode
2651;;;;;; ibuffer-filters-to-filter-group ibuffer-included-in-filters-p
2652;;;;;; ibuffer-backward-filter-group ibuffer-forward-filter-group
2653;;;;;; ibuffer-toggle-filter-group ibuffer-mouse-toggle-filter-group
2654;;;;;; ibuffer-interactive-filter-by-mode ibuffer-mouse-filter-by-mode
d8fb8cce 2655;;;;;; ibuffer-auto-mode) "ibuf-ext" "ibuf-ext.el" "9950bdf995e4b5e962a17d754a35f2c6")
45a68029
GM
2656;;; Generated autoloads from ibuf-ext.el
2657
2658(autoload 'ibuffer-auto-mode "ibuf-ext" "\
06e21633
CY
2659Toggle use of Ibuffer's auto-update facility (Ibuffer Auto mode).
2660With a prefix argument ARG, enable Ibuffer Auto mode if ARG is
2661positive, and disable it otherwise. If called from Lisp, enable
2662the mode if ARG is omitted or nil.
45a68029
GM
2663
2664\(fn &optional ARG)" t nil)
2665
2666(autoload 'ibuffer-mouse-filter-by-mode "ibuf-ext" "\
2667Enable or disable filtering by the major mode chosen via mouse.
2668
2669\(fn EVENT)" t nil)
2670
2671(autoload 'ibuffer-interactive-filter-by-mode "ibuf-ext" "\
2672Enable or disable filtering by the major mode at point.
2673
2674\(fn EVENT-OR-POINT)" t nil)
2675
2676(autoload 'ibuffer-mouse-toggle-filter-group "ibuf-ext" "\
2677Toggle the display status of the filter group chosen with the mouse.
2678
2679\(fn EVENT)" t nil)
2680
2681(autoload 'ibuffer-toggle-filter-group "ibuf-ext" "\
2682Toggle the display status of the filter group on this line.
2683
2684\(fn)" t nil)
2685
2686(autoload 'ibuffer-forward-filter-group "ibuf-ext" "\
2687Move point forwards by COUNT filtering groups.
2688
2689\(fn &optional COUNT)" t nil)
2690
2691(autoload 'ibuffer-backward-filter-group "ibuf-ext" "\
2692Move point backwards by COUNT filtering groups.
2693
2694\(fn &optional COUNT)" t nil)
2695 (autoload 'ibuffer-do-shell-command-pipe "ibuf-ext")
2696 (autoload 'ibuffer-do-shell-command-pipe-replace "ibuf-ext")
2697 (autoload 'ibuffer-do-shell-command-file "ibuf-ext")
2698 (autoload 'ibuffer-do-eval "ibuf-ext")
2699 (autoload 'ibuffer-do-view-and-eval "ibuf-ext")
2700 (autoload 'ibuffer-do-rename-uniquely "ibuf-ext")
2701 (autoload 'ibuffer-do-revert "ibuf-ext")
2702 (autoload 'ibuffer-do-isearch "ibuf-ext")
2703 (autoload 'ibuffer-do-isearch-regexp "ibuf-ext")
2704 (autoload 'ibuffer-do-replace-regexp "ibuf-ext")
2705 (autoload 'ibuffer-do-query-replace "ibuf-ext")
2706 (autoload 'ibuffer-do-query-replace-regexp "ibuf-ext")
2707 (autoload 'ibuffer-do-print "ibuf-ext")
2708
2709(autoload 'ibuffer-included-in-filters-p "ibuf-ext" "\
06b60517 2710
45a68029
GM
2711
2712\(fn BUF FILTERS)" nil nil)
2713
2714(autoload 'ibuffer-filters-to-filter-group "ibuf-ext" "\
2715Make the current filters into a filtering group.
2716
2717\(fn NAME)" t nil)
2718
2719(autoload 'ibuffer-set-filter-groups-by-mode "ibuf-ext" "\
2720Set the current filter groups to filter by mode.
2721
2722\(fn)" t nil)
2723
2724(autoload 'ibuffer-pop-filter-group "ibuf-ext" "\
2725Remove the first filter group.
2726
2727\(fn)" t nil)
2728
2729(autoload 'ibuffer-decompose-filter-group "ibuf-ext" "\
2730Decompose the filter group GROUP into active filters.
2731
2732\(fn GROUP)" t nil)
2733
2734(autoload 'ibuffer-clear-filter-groups "ibuf-ext" "\
2735Remove all filter groups.
2736
2737\(fn)" t nil)
2738
2739(autoload 'ibuffer-jump-to-filter-group "ibuf-ext" "\
2740Move point to the filter group whose name is NAME.
2741
2742\(fn NAME)" t nil)
2743
2744(autoload 'ibuffer-kill-filter-group "ibuf-ext" "\
2745Kill the filter group named NAME.
2746The group will be added to `ibuffer-filter-group-kill-ring'.
2747
2748\(fn NAME)" t nil)
2749
2750(autoload 'ibuffer-kill-line "ibuf-ext" "\
2751Kill the filter group at point.
2752See also `ibuffer-kill-filter-group'.
2753
2754\(fn &optional ARG INTERACTIVE-P)" t nil)
2755
2756(autoload 'ibuffer-yank "ibuf-ext" "\
2757Yank the last killed filter group before group at point.
2758
2759\(fn)" t nil)
2760
2761(autoload 'ibuffer-yank-filter-group "ibuf-ext" "\
2762Yank the last killed filter group before group named NAME.
2763
2764\(fn NAME)" t nil)
2765
2766(autoload 'ibuffer-save-filter-groups "ibuf-ext" "\
2767Save all active filter groups GROUPS as NAME.
2768They are added to `ibuffer-saved-filter-groups'. Interactively,
2769prompt for NAME, and use the current filters.
2770
2771\(fn NAME GROUPS)" t nil)
2772
2773(autoload 'ibuffer-delete-saved-filter-groups "ibuf-ext" "\
2774Delete saved filter groups with NAME.
2775They are removed from `ibuffer-saved-filter-groups'.
2776
2777\(fn NAME)" t nil)
2778
2779(autoload 'ibuffer-switch-to-saved-filter-groups "ibuf-ext" "\
2780Set this buffer's filter groups to saved version with NAME.
2781The value from `ibuffer-saved-filter-groups' is used.
2782
2783\(fn NAME)" t nil)
2784
2785(autoload 'ibuffer-filter-disable "ibuf-ext" "\
2786Disable all filters currently in effect in this buffer.
85949b6c
GM
2787With optional arg DELETE-FILTER-GROUPS non-nil, delete all filter
2788group definitions by setting `ibuffer-filter-groups' to nil.
45a68029 2789
85949b6c 2790\(fn &optional DELETE-FILTER-GROUPS)" t nil)
45a68029
GM
2791
2792(autoload 'ibuffer-pop-filter "ibuf-ext" "\
2793Remove the top filter in this buffer.
2794
2795\(fn)" t nil)
2796
2797(autoload 'ibuffer-decompose-filter "ibuf-ext" "\
2798Separate the top compound filter (OR, NOT, or SAVED) in this buffer.
2799
2800This means that the topmost filter on the filtering stack, which must
2801be a complex filter like (OR [name: foo] [mode: bar-mode]), will be
2802turned into two separate filters [name: foo] and [mode: bar-mode].
2803
2804\(fn)" t nil)
2805
2806(autoload 'ibuffer-exchange-filters "ibuf-ext" "\
2807Exchange the top two filters on the stack in this buffer.
2808
2809\(fn)" t nil)
2810
2811(autoload 'ibuffer-negate-filter "ibuf-ext" "\
2812Negate the sense of the top filter in the current buffer.
2813
2814\(fn)" t nil)
2815
2816(autoload 'ibuffer-or-filter "ibuf-ext" "\
2817Replace the top two filters in this buffer with their logical OR.
2818If optional argument REVERSE is non-nil, instead break the top OR
2819filter into parts.
2820
2821\(fn &optional REVERSE)" t nil)
2822
2823(autoload 'ibuffer-save-filters "ibuf-ext" "\
2824Save FILTERS in this buffer with name NAME in `ibuffer-saved-filters'.
2825Interactively, prompt for NAME, and use the current filters.
2826
2827\(fn NAME FILTERS)" t nil)
2828
2829(autoload 'ibuffer-delete-saved-filters "ibuf-ext" "\
2830Delete saved filters with NAME from `ibuffer-saved-filters'.
2831
2832\(fn NAME)" t nil)
2833
2834(autoload 'ibuffer-add-saved-filters "ibuf-ext" "\
2835Add saved filters from `ibuffer-saved-filters' to this buffer's filters.
2836
2837\(fn NAME)" t nil)
2838
2839(autoload 'ibuffer-switch-to-saved-filters "ibuf-ext" "\
2840Set this buffer's filters to filters with NAME from `ibuffer-saved-filters'.
2841
2842\(fn NAME)" t nil)
2843 (autoload 'ibuffer-filter-by-mode "ibuf-ext")
2844 (autoload 'ibuffer-filter-by-used-mode "ibuf-ext")
d81bd059 2845 (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
45a68029
GM
2846 (autoload 'ibuffer-filter-by-name "ibuf-ext")
2847 (autoload 'ibuffer-filter-by-filename "ibuf-ext")
2848 (autoload 'ibuffer-filter-by-size-gt "ibuf-ext")
2849 (autoload 'ibuffer-filter-by-size-lt "ibuf-ext")
2850 (autoload 'ibuffer-filter-by-content "ibuf-ext")
2851 (autoload 'ibuffer-filter-by-predicate "ibuf-ext")
2852
2853(autoload 'ibuffer-toggle-sorting-mode "ibuf-ext" "\
2854Toggle the current sorting mode.
2855Default sorting modes are:
2856 Recency - the last time the buffer was viewed
2857 Name - the name of the buffer
2858 Major Mode - the name of the major mode of the buffer
2859 Size - the size of the buffer
2860
2861\(fn)" t nil)
2862
2863(autoload 'ibuffer-invert-sorting "ibuf-ext" "\
2864Toggle whether or not sorting is in reverse order.
2865
2866\(fn)" t nil)
2867 (autoload 'ibuffer-do-sort-by-major-mode "ibuf-ext")
2868 (autoload 'ibuffer-do-sort-by-mode-name "ibuf-ext")
2869 (autoload 'ibuffer-do-sort-by-alphabetic "ibuf-ext")
2870 (autoload 'ibuffer-do-sort-by-size "ibuf-ext")
2871 (autoload 'ibuffer-do-sort-by-filename/process "ibuf-ext")
2872
2873(autoload 'ibuffer-bs-show "ibuf-ext" "\
2874Emulate `bs-show' from the bs.el package.
2875
2876\(fn)" t nil)
2877
2878(autoload 'ibuffer-add-to-tmp-hide "ibuf-ext" "\
2879Add REGEXP to `ibuffer-tmp-hide-regexps'.
2880This means that buffers whose name matches REGEXP will not be shown
2881for this Ibuffer session.
2882
2883\(fn REGEXP)" t nil)
2884
2885(autoload 'ibuffer-add-to-tmp-show "ibuf-ext" "\
2886Add REGEXP to `ibuffer-tmp-show-regexps'.
2887This means that buffers whose name matches REGEXP will always be shown
2888for this Ibuffer session.
2889
2890\(fn REGEXP)" t nil)
2891
2892(autoload 'ibuffer-forward-next-marked "ibuf-ext" "\
2893Move forward by COUNT marked buffers (default 1).
2894
2895If MARK is non-nil, it should be a character denoting the type of mark
2896to move by. The default is `ibuffer-marked-char'.
2897
2898If DIRECTION is non-nil, it should be an integer; negative integers
2899mean move backwards, non-negative integers mean move forwards.
2900
2901\(fn &optional COUNT MARK DIRECTION)" t nil)
2902
2903(autoload 'ibuffer-backwards-next-marked "ibuf-ext" "\
2904Move backwards by COUNT marked buffers (default 1).
2905
2906If MARK is non-nil, it should be a character denoting the type of mark
2907to move by. The default is `ibuffer-marked-char'.
2908
2909\(fn &optional COUNT MARK)" t nil)
2910
2911(autoload 'ibuffer-do-kill-lines "ibuf-ext" "\
2912Hide all of the currently marked lines.
2913
2914\(fn)" t nil)
2915
2916(autoload 'ibuffer-jump-to-buffer "ibuf-ext" "\
2917Move point to the buffer whose name is NAME.
2918
2919If called interactively, prompt for a buffer name and go to the
2920corresponding line in the Ibuffer buffer. If said buffer is in a
2921hidden group filter, open it.
2922
2923If `ibuffer-jump-offer-only-visible-buffers' is non-nil, only offer
2924visible buffers in the completion list. Calling the command with
2925a prefix argument reverses the meaning of that variable.
2926
2927\(fn NAME)" t nil)
2928
2929(autoload 'ibuffer-diff-with-file "ibuf-ext" "\
2930View the differences between marked buffers and their associated files.
2931If no buffers are marked, use buffer at point.
2932This requires the external program \"diff\" to be in your `exec-path'.
2933
2934\(fn)" t nil)
2935
2936(autoload 'ibuffer-copy-filename-as-kill "ibuf-ext" "\
2937Copy filenames of marked buffers into the kill ring.
2938
2939The names are separated by a space.
2940If a buffer has no filename, it is ignored.
2941
2942With no prefix arg, use the filename sans its directory of each marked file.
2943With a zero prefix arg, use the complete filename of each marked file.
2944With \\[universal-argument], use the filename of each marked file relative
2945to `ibuffer-default-directory' if non-nil, otherwise `default-directory'.
2946
2947You can then feed the file name(s) to other commands with \\[yank].
2948
2949\(fn &optional ARG)" t nil)
2950
2951(autoload 'ibuffer-mark-by-name-regexp "ibuf-ext" "\
2952Mark all buffers whose name matches REGEXP.
2953
2954\(fn REGEXP)" t nil)
2955
2956(autoload 'ibuffer-mark-by-mode-regexp "ibuf-ext" "\
2957Mark all buffers whose major mode matches REGEXP.
2958
2959\(fn REGEXP)" t nil)
2960
2961(autoload 'ibuffer-mark-by-file-name-regexp "ibuf-ext" "\
2962Mark all buffers whose file name matches REGEXP.
2963
2964\(fn REGEXP)" t nil)
2965
2966(autoload 'ibuffer-mark-by-mode "ibuf-ext" "\
2967Mark all buffers whose major mode equals MODE.
2968
2969\(fn MODE)" t nil)
2970
2971(autoload 'ibuffer-mark-modified-buffers "ibuf-ext" "\
2972Mark all modified buffers.
2973
2974\(fn)" t nil)
2975
2976(autoload 'ibuffer-mark-unsaved-buffers "ibuf-ext" "\
2977Mark all modified buffers that have an associated file.
2978
2979\(fn)" t nil)
2980
2981(autoload 'ibuffer-mark-dissociated-buffers "ibuf-ext" "\
2982Mark all buffers whose associated file does not exist.
2983
2984\(fn)" t nil)
2985
2986(autoload 'ibuffer-mark-help-buffers "ibuf-ext" "\
2987Mark buffers like *Help*, *Apropos*, *Info*.
2988
2989\(fn)" t nil)
2990
2991(autoload 'ibuffer-mark-compressed-file-buffers "ibuf-ext" "\
2992Mark buffers whose associated file is compressed.
2993
2994\(fn)" t nil)
2995
2996(autoload 'ibuffer-mark-old-buffers "ibuf-ext" "\
2997Mark buffers which have not been viewed in `ibuffer-old-time' hours.
2998
2999\(fn)" t nil)
3000
3001(autoload 'ibuffer-mark-special-buffers "ibuf-ext" "\
3002Mark all buffers whose name begins and ends with '*'.
3003
3004\(fn)" t nil)
3005
3006(autoload 'ibuffer-mark-read-only-buffers "ibuf-ext" "\
3007Mark all read-only buffers.
3008
3009\(fn)" t nil)
3010
3011(autoload 'ibuffer-mark-dired-buffers "ibuf-ext" "\
3012Mark all `dired' buffers.
3013
3014\(fn)" t nil)
3015
3016(autoload 'ibuffer-do-occur "ibuf-ext" "\
3017View lines which match REGEXP in all marked buffers.
3018Optional argument NLINES says how many lines of context to display: it
3019defaults to one.
3020
3021\(fn REGEXP &optional NLINES)" t nil)
3022
3023;;;***
3024\f
3025;;; End of automatically extracted autoloads.
3026
3027
25d2f683
CW
3028(provide 'ibuffer)
3029
4e4a724c
JPW
3030(run-hooks 'ibuffer-load-hook)
3031
25d2f683
CW
3032;; Local Variables:
3033;; coding: iso-8859-1
3034;; End:
3035
3036;;; ibuffer.el ends here