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