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