ibuffer.el 111 KB
Newer Older
Colin Walters's avatar
Colin Walters committed
1 2
;;; ibuffer.el --- operate on buffers like dired

3
;; Copyright (C) 2000-2012  Free Software Foundation, Inc.
Colin Walters's avatar
Colin Walters committed
4 5

;; Author: Colin Walters <walters@verbum.org>
6
;; Maintainer: John Paul Wallington <jpw@gnu.org>
Colin Walters's avatar
Colin Walters committed
7 8 9
;; Created: 8 Sep 2000
;; Keywords: buffer, convenience

10
;; This file is part of GNU Emacs.
Colin Walters's avatar
Colin Walters committed
11

12 13 14 15
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Colin Walters's avatar
Colin Walters committed
16

17 18 19 20
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
Colin Walters's avatar
Colin Walters committed
21 22

;; You should have received a copy of the GNU General Public License
23
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Colin Walters's avatar
Colin Walters committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37

;;; Commentary:

;; ibuffer.el is an advanced replacement for the `buffer-menu' which
;; is normally distributed with Emacs.  Its interface is intended to
;; be analogous to that of Dired.

;;; Code:

(eval-when-compile
  (require 'cl)
  (require 'ibuf-macs)
  (require 'dired))

38
(require 'font-core)
39

40 41 42 43 44 45 46 47 48
;; These come from ibuf-ext.el, which can not be require'd at compile time
;; because it has a recursive dependency on ibuffer.el
(defvar ibuffer-auto-mode)
(defvar ibuffer-cached-filter-formats)
(defvar ibuffer-compiled-filter-formats)
(defvar ibuffer-filter-format-alist)
(defvar ibuffer-filter-group-kill-ring)
(defvar ibuffer-filter-groups)
(defvar ibuffer-filtering-qualifiers)
49
(defvar ibuffer-header-line-format)
50 51 52 53 54
(defvar ibuffer-hidden-filter-groups)
(defvar ibuffer-inline-columns)
(defvar ibuffer-show-empty-filter-groups)
(defvar ibuffer-tmp-hide-regexps)
(defvar ibuffer-tmp-show-regexps)
55

56
(declare-function ibuffer-mark-on-buffer "ibuf-ext"
57
		  (func &optional ibuffer-mark-on-buffer-mark group))
58
(declare-function ibuffer-generate-filter-groups "ibuf-ext"
59 60 61
		  (bmarklist &optional noempty nodefault))
(declare-function ibuffer-format-filter-group-data "ibuf-ext" (filter))

Colin Walters's avatar
Colin Walters committed
62
(defgroup ibuffer nil
63 64 65 66
  "Advanced replacement for `buffer-menu'.
Ibuffer lets you operate on buffers in a Dired-like way,
with the ability to sort, mark by regular expression,
and filter displayed buffers by various criteria."
67
  :version "22.1"
Colin Walters's avatar
Colin Walters committed
68 69
  :group 'convenience)

70 71
(defcustom ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide)
				   " " (size 9 -1 :right)
72
				   " " (mode 16 16 :left :elide) " " filename-and-process)
Colin Walters's avatar
Colin Walters committed
73 74 75 76 77
			     (mark " " (name 16 -1) " " filename))
  "A list of ways to display buffer lines.

With Ibuffer, you are not limited to displaying just certain
attributes of a buffer such as size, name, and mode in a particular
Colin Walters's avatar
Colin Walters committed
78
order.  Through this variable, you can completely customize and
Colin Walters's avatar
Colin Walters committed
79 80 81 82 83
control the appearance of an Ibuffer buffer.  See also
`define-ibuffer-column', which allows you to define your own columns
for display.

This variable has the form
84
 ((COLUMN COLUMN ...) (COLUMN COLUMN ...) ...)
Colin Walters's avatar
Colin Walters committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
Each element in `ibuffer-formats' should be a list containing COLUMN
specifiers.  A COLUMN can be any of the following:

  SYMBOL - A symbol naming the column.  Predefined columns are:
       mark modified read-only name size mode process filename
   When you define your own columns using `define-ibuffer-column', just
   use their name like the predefined columns here.  This entry can
   also be a function of two arguments, which should return a string.
   The first argument is the buffer object, and the second is the mark
   on that buffer.
 or
  \"STRING\" - A literal string to display.
 or
  (SYMBOL MIN-SIZE MAX-SIZE &optional ALIGN ELIDE) - SYMBOL is a
   symbol naming the column, and MIN-SIZE and MAX-SIZE are integers (or
   functions of no arguments returning an integer) which constrict the
   size of a column.  If MAX-SIZE is -1, there is no upper bound.  The
   default values are 0 and -1, respectively.  If MIN-SIZE is negative,
   use the end of the string.  The optional element ALIGN describes the
   alignment of the column; it can be :left, :center or :right.  The
   optional element ELIDE describes whether or not to elide the column
   if it is too long; valid values are :elide and nil.  The default is
   nil (don't elide).

Some example of valid entries in `ibuffer-formats', with
description (also, feel free to try them out, and experiment with your
own!):

 (mark \" \" name)
  This format just displays the current mark (if any) and the name of
  the buffer, separated by a space.
 (mark modified read-only \" \" (name 16 16 :left) \" \" (size 6 -1 :right))
  This format displays the current mark (if any), its modification and
  read-only status, as well as the name of the buffer and its size.  In
  this format, the name is restricted to 16 characters (longer names
120
  will be truncated, and shorter names will be padded with spaces), and
Colin Walters's avatar
Colin Walters committed
121
  the name is also aligned to the left.  The size of the buffer will
Colin Walters's avatar
Colin Walters committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
  be padded with spaces up to a minimum of six characters, but there is
  no upper limit on its size.  The size will also be aligned to the
  right.

Thus, if you wanted to use these two formats, add

 (setq ibuffer-formats '((mark \" \" name)
		         (mark modified read-only
			  (name 16 16 :left) (size 6 -1 :right))))

to your ~/.emacs file.

Using \\[ibuffer-switch-format], you can rotate the display between
the specified formats in the list."
  :type '(repeat sexp)
  :group 'ibuffer)

(defcustom ibuffer-always-compile-formats (featurep 'bytecomp)
  "If non-nil, then use the byte-compiler to optimize `ibuffer-formats'.
This will increase the redisplay speed, at the cost of loading the
elisp byte-compiler."
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-fontification-alist
147
  `((10 buffer-read-only font-lock-constant-face)
148 149 150 151 152 153
    (15 (and buffer-file-name
	     (string-match ibuffer-compressed-file-name-regexp
			   buffer-file-name))
	font-lock-doc-face)
    (20 (string-match "^*" (buffer-name)) font-lock-keyword-face)
    (25 (and (string-match "^ " (buffer-name))
154 155
	     (null buffer-file-name))
	italic)
156 157
    (30 (memq major-mode ibuffer-help-buffer-modes) font-lock-comment-face)
    (35 (eq major-mode 'dired-mode) font-lock-function-name-face))
Colin Walters's avatar
Colin Walters committed
158 159 160 161 162
  "An alist describing how to fontify buffers.
Each element should be of the form (PRIORITY FORM FACE), where
PRIORITY is an integer, FORM is an arbitrary form to evaluate in the
buffer, and FACE is the face to use for fontification.  If the FORM
evaluates to non-nil, then FACE will be put on the buffer name.  The
163 164
element with the highest PRIORITY takes precedence.

165
If you change this variable, you must kill the Ibuffer buffer and
166
recreate it for the change to take effect."
Colin Walters's avatar
Colin Walters committed
167 168 169 170 171 172 173
  :type '(repeat
	  (list (integer :tag "Priority")
		(sexp :tag "Test Form")
		face))
  :group 'ibuffer)

(defcustom ibuffer-use-other-window nil
174
  "If non-nil, display Ibuffer in another window by default."
Colin Walters's avatar
Colin Walters committed
175 176 177 178 179 180 181 182 183
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-default-shrink-to-minimum-size nil
  "If non-nil, minimize the size of the Ibuffer window by default."
  :type 'boolean
  :group 'ibuffer)
(defvar ibuffer-shrink-to-minimum-size nil)

184 185 186 187 188
(defcustom ibuffer-display-summary t
  "If non-nil, summarize Ibuffer columns."
  :type 'boolean
  :group 'ibuffer)

189 190 191 192 193
(defcustom ibuffer-truncate-lines t
  "If non-nil, do not display continuation lines."
  :type 'boolean
  :group 'ibuffer)

Colin Walters's avatar
Colin Walters committed
194 195 196 197 198 199 200 201
(defcustom ibuffer-case-fold-search case-fold-search
  "If non-nil, ignore case when searching."
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-default-sorting-mode 'recency
  "The criteria by which to sort the buffers.

202 203
Note that this variable is local to each Ibuffer buffer.  Thus, you
can have multiple Ibuffer buffers open, each with a different sorted
Colin Walters's avatar
Colin Walters committed
204 205 206 207
view of the buffers."
  :type '(choice (const :tag "Last view time" :value recency)
		 (const :tag "Lexicographic" :value alphabetic)
		 (const :tag "Buffer size" :value size)
208
		 (const :tag "File name" :value filename/process)
Colin Walters's avatar
Colin Walters committed
209 210 211
		 (const :tag "Major mode" :value major-mode))
  :group 'ibuffer)
(defvar ibuffer-sorting-mode nil)
212
(defvar ibuffer-last-sorting-mode nil)
Colin Walters's avatar
Colin Walters committed
213 214 215 216 217 218 219 220

(defcustom ibuffer-default-sorting-reversep nil
  "If non-nil, reverse the default sorting order."
  :type 'boolean
  :group 'ibuffer)
(defvar ibuffer-sorting-reversep nil)

(defcustom ibuffer-elide-long-columns nil
221
  "If non-nil, then elide column entries which exceed their max length."
Colin Walters's avatar
Colin Walters committed
222 223
  :type 'boolean
  :group 'ibuffer)
224 225 226
(make-obsolete-variable 'ibuffer-elide-long-columns
                        "use the :elide argument of `ibuffer-formats'."
                        "22.1")
Colin Walters's avatar
Colin Walters committed
227 228 229 230 231 232 233 234 235

(defcustom ibuffer-eliding-string "..."
  "The string to use for eliding long columns."
  :type 'string
  :group 'ibuffer)

(defcustom ibuffer-maybe-show-predicates `(,(lambda (buf)
					      (and (string-match "^ " (buffer-name buf))
						   (null buffer-file-name))))
236 237 238
  "A list of predicates for buffers to display conditionally.

A predicate can be a regexp or a function.
Colin Walters's avatar
Colin Walters committed
239 240 241 242
If a regexp, then it will be matched against the buffer's name.
If a function, it will be called with the buffer as an argument, and
should return non-nil if this buffer should be shown.

243
Viewing of buffers hidden because of these predicates may be customized
244
via `ibuffer-default-display-maybe-show-predicates' and is toggled by
245 246
giving a non-nil prefix argument to `ibuffer-update'.
Note that this specialized filtering occurs before real filtering."
Colin Walters's avatar
Colin Walters committed
247 248 249
  :type '(repeat (choice regexp function))
  :group 'ibuffer)

250 251 252 253 254 255 256
(defcustom ibuffer-default-display-maybe-show-predicates nil
  "Non-nil means show buffers that match `ibuffer-maybe-show-predicates'."
  :type 'boolean
  :group 'ibuffer)

(defvar ibuffer-display-maybe-show-predicates nil)

Colin Walters's avatar
Colin Walters committed
257 258
(defvar ibuffer-current-format nil)

259 260 261 262 263
(defcustom ibuffer-movement-cycle t
  "If non-nil, then forward and backwards movement commands cycle."
  :type 'boolean
  :group 'ibuffer)

Colin Walters's avatar
Colin Walters committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
(defcustom ibuffer-modified-char ?*
  "The character to display for modified buffers."
  :type 'character
  :group 'ibuffer)

(defcustom ibuffer-read-only-char ?%
  "The character to display for read-only buffers."
  :type 'character
  :group 'ibuffer)

(defcustom ibuffer-marked-char ?>
  "The character to display for marked buffers."
  :type 'character
  :group 'ibuffer)

(defcustom ibuffer-deletion-char ?D
  "The character to display for buffers marked for deletion."
  :type 'character
  :group 'ibuffer)

(defcustom ibuffer-expert nil
  "If non-nil, don't ask for confirmation of \"dangerous\" operations."
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-view-ibuffer nil
  "If non-nil, display the current Ibuffer buffer itself.
Note that this has a drawback - the data about the current Ibuffer
buffer will most likely be inaccurate.  This includes modification
state, size, etc."
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-always-show-last-buffer nil
298 299
  "If non-nil, always display the previous buffer.
This variable takes precedence over filtering, and even
Colin Walters's avatar
Colin Walters committed
300 301 302 303 304 305
`ibuffer-never-show-predicates'."
  :type '(choice (const :tag "Always" :value t)
		 (const :tag "Never" :value nil)
		 (const :tag "Always except minibuffer" :value :nomini))
  :group 'ibuffer)

306 307 308 309 310 311
(defcustom ibuffer-jump-offer-only-visible-buffers nil
  "If non-nil, only offer buffers visible in the Ibuffer buffer
in completion lists of the `ibuffer-jump-to-buffer' command."
  :type 'boolean
  :group 'ibuffer)

Colin Walters's avatar
Colin Walters committed
312
(defcustom ibuffer-use-header-line (boundp 'header-line-format)
313
  "If non-nil, display a header line containing current filters."
Colin Walters's avatar
Colin Walters committed
314 315 316 317
  :type 'boolean
  :group 'ibuffer)

(defcustom ibuffer-default-directory nil
318
  "The default directory to use for a new Ibuffer buffer.
319
If nil, inherit the directory of the buffer in which `ibuffer' was
Colin Walters's avatar
Colin Walters committed
320 321 322 323 324 325
called.  Otherwise, this variable should be a string naming a
directory, like `default-directory'."
  :type '(choice (const :tag "Inherit" :value nil)
		 string)
  :group 'ibuffer)

326 327
(defcustom ibuffer-help-buffer-modes
  '(help-mode apropos-mode Info-mode Info-edit-mode)
328 329 330 331
  "List of \"Help\" major modes."
  :type '(repeat function)
  :group 'ibuffer)

332
(defcustom ibuffer-compressed-file-name-regexp
333
  "\\.\\(arj\\|bgz\\|bz2\\|gz\\|lzh\\|taz\\|tgz\\|xz\\|zip\\|z\\)$"
334
  "Regexp to match compressed file names."
335
  :version "24.1"                       ; added xz
336
  :type 'regexp
337
  :group 'ibuffer)
338

339 340
(define-obsolete-variable-alias 'ibuffer-hooks 'ibuffer-hook "22.1")

341
(defcustom ibuffer-hook nil
342
  "Hook run when `ibuffer' is called."
Colin Walters's avatar
Colin Walters committed
343 344
  :type 'hook
  :group 'ibuffer)
345 346

(define-obsolete-variable-alias 'ibuffer-mode-hooks 'ibuffer-mode-hook "22.1")
Colin Walters's avatar
Colin Walters committed
347

348
(defcustom ibuffer-mode-hook nil
349
  "Hook run upon entry into `ibuffer-mode'."
Colin Walters's avatar
Colin Walters committed
350 351 352
  :type 'hook
  :group 'ibuffer)

353 354 355 356 357
(defcustom ibuffer-load-hook nil
  "Hook run when Ibuffer is loaded."
  :type 'hook
  :group 'ibuffer)

358
(defcustom ibuffer-marked-face 'warning
Colin Walters's avatar
Colin Walters committed
359 360 361 362
  "Face used for displaying marked buffers."
  :type 'face
  :group 'ibuffer)

363
(defcustom ibuffer-deletion-face 'error
Colin Walters's avatar
Colin Walters committed
364 365 366 367 368 369 370 371 372
  "Face used for displaying buffers marked for deletion."
  :type 'face
  :group 'ibuffer)

(defcustom ibuffer-title-face 'font-lock-type-face
  "Face used for the title string."
  :type 'face
  :group 'ibuffer)

373 374 375 376 377
(defcustom ibuffer-filter-group-name-face 'bold
  "Face used for displaying filtering group names."
  :type 'face
  :group 'ibuffer)

Colin Walters's avatar
Colin Walters committed
378 379 380 381 382 383 384 385
(defcustom ibuffer-directory-abbrev-alist nil
  "An alist of file name abbreviations like `directory-abbrev-alist'."
  :type '(repeat (cons :format "%v"
		       :value ("" . "")
		       (regexp :tag "From")
		       (regexp :tag "To")))
  :group 'ibuffer)

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
(defvar ibuffer-mode-groups-popup
  (let ((groups-map (make-sparse-keymap "Filter Groups")))
    ;; Filter groups

    (define-key-after groups-map [filters-to-filter-group]
      '(menu-item "Create filter group from current filters..."
        ibuffer-filters-to-filter-group
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
    (define-key-after groups-map [forward-filter-group]
      '(menu-item "Move point to the next filter group"
        ibuffer-forward-filter-group))
    (define-key-after groups-map [backward-filter-group]
      '(menu-item "Move point to the previous filter group"
        ibuffer-backward-filter-group))
    (define-key-after groups-map [jump-to-filter-group]
      '(menu-item "Move point to a specific filter group..."
        ibuffer-jump-to-filter-group))
    (define-key-after groups-map [kill-filter-group]
      '(menu-item "Kill filter group named..."
        ibuffer-kill-filter-group
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
    (define-key-after groups-map [yank-filter-group]
      '(menu-item "Yank last killed filter group before..."
        ibuffer-yank-filter-group
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
    (define-key-after groups-map [pop-filter-group]
      '(menu-item "Remove top filter group"
        ibuffer-pop-filter-group
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
    (define-key-after groups-map [clear-filter-groups]
      '(menu-item "Remove all filter groups"
        ibuffer-clear-filter-groups
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
    (define-key-after groups-map [pop-filter-group]
      '(menu-item "Decompose filter group..."
        ibuffer-pop-filter-group
        :help "\"Unmake\" a filter group"
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
    (define-key-after groups-map [save-filter-groups]
      '(menu-item "Save current filter groups permanently..."
        ibuffer-save-filter-groups
        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)
Paul Eggert's avatar
Paul Eggert committed
428
        :help "Use a mnemonic name to store current filter groups"))
429 430 431 432 433 434 435 436 437 438 439 440 441 442
    (define-key-after groups-map [switch-to-saved-filter-groups]
      '(menu-item "Restore permanently saved filters..."
        ibuffer-switch-to-saved-filter-groups
        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)
        :help "Replace current filters with a saved stack"))
    (define-key-after groups-map [delete-saved-filter-groups]
      '(menu-item "Delete permanently saved filter groups..."
        ibuffer-delete-saved-filter-groups
        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)))
    (define-key-after groups-map [set-filter-groups-by-mode]
      '(menu-item "Set current filter groups to filter by mode"
        ibuffer-set-filter-groups-by-mode))

    groups-map))
443

444 445
(defvar ibuffer-mode-map
  (let ((map (make-keymap)))
Colin Walters's avatar
Colin Walters committed
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
    (define-key map (kbd "0") 'digit-argument)
    (define-key map (kbd "1") 'digit-argument)
    (define-key map (kbd "2") 'digit-argument)
    (define-key map (kbd "3") 'digit-argument)
    (define-key map (kbd "4") 'digit-argument)
    (define-key map (kbd "5") 'digit-argument)
    (define-key map (kbd "6") 'digit-argument)
    (define-key map (kbd "7") 'digit-argument)
    (define-key map (kbd "8") 'digit-argument)
    (define-key map (kbd "9") 'digit-argument)

    (define-key map (kbd "m") 'ibuffer-mark-forward)
    (define-key map (kbd "t") 'ibuffer-toggle-marks)
    (define-key map (kbd "u") 'ibuffer-unmark-forward)
    (define-key map (kbd "=") 'ibuffer-diff-with-file)
    (define-key map (kbd "j") 'ibuffer-jump-to-buffer)
462
    (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
463 464
    (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch)
    (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp)
Colin Walters's avatar
Colin Walters committed
465 466 467 468 469 470 471 472 473 474 475
    (define-key map (kbd "DEL") 'ibuffer-unmark-backward)
    (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
    (define-key map (kbd "* *") 'ibuffer-unmark-all)
    (define-key map (kbd "* M") 'ibuffer-mark-by-mode)
    (define-key map (kbd "* m") 'ibuffer-mark-modified-buffers)
    (define-key map (kbd "* u") 'ibuffer-mark-unsaved-buffers)
    (define-key map (kbd "* s") 'ibuffer-mark-special-buffers)
    (define-key map (kbd "* r") 'ibuffer-mark-read-only-buffers)
    (define-key map (kbd "* /") 'ibuffer-mark-dired-buffers)
    (define-key map (kbd "* e") 'ibuffer-mark-dissociated-buffers)
    (define-key map (kbd "* h") 'ibuffer-mark-help-buffers)
476
    (define-key map (kbd "* z") 'ibuffer-mark-compressed-file-buffers)
Colin Walters's avatar
Colin Walters committed
477
    (define-key map (kbd ".") 'ibuffer-mark-old-buffers)
478

Colin Walters's avatar
Colin Walters committed
479 480 481 482
    (define-key map (kbd "d") 'ibuffer-mark-for-delete)
    (define-key map (kbd "C-d") 'ibuffer-mark-for-delete-backwards)
    (define-key map (kbd "k") 'ibuffer-mark-for-delete)
    (define-key map (kbd "x") 'ibuffer-do-kill-on-deletion-marks)
483

Colin Walters's avatar
Colin Walters committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
    ;; immediate operations
    (define-key map (kbd "n") 'ibuffer-forward-line)
    (define-key map (kbd "SPC") 'forward-line)
    (define-key map (kbd "p") 'ibuffer-backward-line)
    (define-key map (kbd "M-}") 'ibuffer-forward-next-marked)
    (define-key map (kbd "M-{") 'ibuffer-backwards-next-marked)
    (define-key map (kbd "l") 'ibuffer-redisplay)
    (define-key map (kbd "g") 'ibuffer-update)
    (define-key map "`" 'ibuffer-switch-format)
    (define-key map "-" 'ibuffer-add-to-tmp-hide)
    (define-key map "+" 'ibuffer-add-to-tmp-show)
    (define-key map "b" 'ibuffer-bury-buffer)
    (define-key map (kbd ",") 'ibuffer-toggle-sorting-mode)
    (define-key map (kbd "s i") 'ibuffer-invert-sorting)
    (define-key map (kbd "s a") 'ibuffer-do-sort-by-alphabetic)
    (define-key map (kbd "s v") 'ibuffer-do-sort-by-recency)
    (define-key map (kbd "s s") 'ibuffer-do-sort-by-size)
501
    (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process)
Colin Walters's avatar
Colin Walters committed
502 503 504
    (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)

    (define-key map (kbd "/ m") 'ibuffer-filter-by-mode)
505
    (define-key map (kbd "/ M") 'ibuffer-filter-by-used-mode)
Colin Walters's avatar
Colin Walters committed
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
    (define-key map (kbd "/ n") 'ibuffer-filter-by-name)
    (define-key map (kbd "/ c") 'ibuffer-filter-by-content)
    (define-key map (kbd "/ e") 'ibuffer-filter-by-predicate)
    (define-key map (kbd "/ f") 'ibuffer-filter-by-filename)
    (define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt)
    (define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt)
    (define-key map (kbd "/ r") 'ibuffer-switch-to-saved-filters)
    (define-key map (kbd "/ a") 'ibuffer-add-saved-filters)
    (define-key map (kbd "/ x") 'ibuffer-delete-saved-filters)
    (define-key map (kbd "/ d") 'ibuffer-decompose-filter)
    (define-key map (kbd "/ s") 'ibuffer-save-filters)
    (define-key map (kbd "/ p") 'ibuffer-pop-filter)
    (define-key map (kbd "/ !") 'ibuffer-negate-filter)
    (define-key map (kbd "/ t") 'ibuffer-exchange-filters)
    (define-key map (kbd "/ TAB") 'ibuffer-exchange-filters)
    (define-key map (kbd "/ o") 'ibuffer-or-filter)
522 523
    (define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group)
    (define-key map (kbd "/ P") 'ibuffer-pop-filter-group)
524
    (define-key map (kbd "/ D") 'ibuffer-decompose-filter-group)
Colin Walters's avatar
Colin Walters committed
525
    (define-key map (kbd "/ /") 'ibuffer-filter-disable)
526 527

    (define-key map (kbd "M-n") 'ibuffer-forward-filter-group)
528
    (define-key map "\t" 'ibuffer-forward-filter-group)
529
    (define-key map (kbd "M-p") 'ibuffer-backward-filter-group)
530
    (define-key map [backtab] 'ibuffer-backward-filter-group)
531
    (define-key map (kbd "M-j") 'ibuffer-jump-to-filter-group)
Colin Walters's avatar
Colin Walters committed
532 533 534 535 536 537
    (define-key map (kbd "C-k") 'ibuffer-kill-line)
    (define-key map (kbd "C-y") 'ibuffer-yank)
    (define-key map (kbd "/ S") 'ibuffer-save-filter-groups)
    (define-key map (kbd "/ R") 'ibuffer-switch-to-saved-filter-groups)
    (define-key map (kbd "/ X") 'ibuffer-delete-saved-filter-groups)
    (define-key map (kbd "/ \\") 'ibuffer-clear-filter-groups)
538

Colin Walters's avatar
Colin Walters committed
539 540 541 542 543 544 545
    (define-key map (kbd "q") 'ibuffer-quit)
    (define-key map (kbd "h") 'describe-mode)
    (define-key map (kbd "?") 'describe-mode)

    (define-key map (kbd "% n") 'ibuffer-mark-by-name-regexp)
    (define-key map (kbd "% m") 'ibuffer-mark-by-mode-regexp)
    (define-key map (kbd "% f") 'ibuffer-mark-by-file-name-regexp)
546

Colin Walters's avatar
Colin Walters committed
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
    (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)

    (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe)
    (define-key map (kbd "!") 'ibuffer-do-shell-command-file)
    (define-key map (kbd "~") 'ibuffer-do-toggle-modified)
    ;; marked operations
    (define-key map (kbd "A") 'ibuffer-do-view)
    (define-key map (kbd "D") 'ibuffer-do-delete)
    (define-key map (kbd "E") 'ibuffer-do-eval)
    (define-key map (kbd "F") 'ibuffer-do-shell-command-file)
    (define-key map (kbd "I") 'ibuffer-do-query-replace-regexp)
    (define-key map (kbd "H") 'ibuffer-do-view-other-frame)
    (define-key map (kbd "N") 'ibuffer-do-shell-command-pipe-replace)
    (define-key map (kbd "M") 'ibuffer-do-toggle-modified)
    (define-key map (kbd "O") 'ibuffer-do-occur)
    (define-key map (kbd "P") 'ibuffer-do-print)
    (define-key map (kbd "Q") 'ibuffer-do-query-replace)
    (define-key map (kbd "R") 'ibuffer-do-rename-uniquely)
    (define-key map (kbd "S") 'ibuffer-do-save)
    (define-key map (kbd "T") 'ibuffer-do-toggle-read-only)
    (define-key map (kbd "U") 'ibuffer-do-replace-regexp)
    (define-key map (kbd "V") 'ibuffer-do-revert)
    (define-key map (kbd "W") 'ibuffer-do-view-and-eval)
    (define-key map (kbd "X") 'ibuffer-do-shell-command-pipe)
571

Colin Walters's avatar
Colin Walters committed
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
    (define-key map (kbd "k") 'ibuffer-do-kill-lines)
    (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)

    (define-key map (kbd "RET") 'ibuffer-visit-buffer)
    (define-key map (kbd "e") 'ibuffer-visit-buffer)
    (define-key map (kbd "f") 'ibuffer-visit-buffer)
    (define-key map (kbd "C-x C-f") 'ibuffer-find-file)
    (define-key map (kbd "o") 'ibuffer-visit-buffer-other-window)
    (define-key map (kbd "C-o") 'ibuffer-visit-buffer-other-window-noselect)
    (define-key map (kbd "M-o") 'ibuffer-visit-buffer-1-window)
    (define-key map (kbd "v") 'ibuffer-do-view)
    (define-key map (kbd "C-x v") 'ibuffer-do-view-horizontally)
    (define-key map (kbd "C-c C-a") 'ibuffer-auto-mode)
    (define-key map (kbd "C-x 4 RET") 'ibuffer-visit-buffer-other-window)
    (define-key map (kbd "C-x 5 RET") 'ibuffer-visit-buffer-other-frame)

    (define-key map [menu-bar view]
      (cons "View" (make-sparse-keymap "View")))

    (define-key-after map [menu-bar view visit-buffer]
      '(menu-item "View this buffer" ibuffer-visit-buffer))
    (define-key-after map [menu-bar view visit-buffer-other-window]
      '(menu-item "View (other window)" ibuffer-visit-buffer-other-window))
    (define-key-after map [menu-bar view visit-buffer-other-frame]
      '(menu-item "View (other frame)" ibuffer-visit-buffer-other-frame))
    (define-key-after map [menu-bar view ibuffer-update]
      '(menu-item "Update" ibuffer-update
599
        :help "Regenerate the list of buffers"))
Colin Walters's avatar
Colin Walters committed
600 601
    (define-key-after map [menu-bar view switch-format]
      '(menu-item "Switch display format" ibuffer-switch-format
602
        :help "Toggle between available values of `ibuffer-formats'"))
Colin Walters's avatar
Colin Walters committed
603 604 605 606 607 608 609 610

    (define-key-after map [menu-bar view dashes]
      '("--"))

    (define-key-after map [menu-bar view sort]
      (cons "Sort" (make-sparse-keymap "Sort")))

    (define-key-after map [menu-bar view sort do-sort-by-major-mode]
Colin Walters's avatar
Colin Walters committed
611
      '(menu-item "Sort by major mode" ibuffer-do-sort-by-major-mode))
Colin Walters's avatar
Colin Walters committed
612
    (define-key-after map [menu-bar view sort do-sort-by-size]
Colin Walters's avatar
Colin Walters committed
613
      '(menu-item "Sort by buffer size" ibuffer-do-sort-by-size))
Colin Walters's avatar
Colin Walters committed
614 615
    (define-key-after map [menu-bar view sort do-sort-by-alphabetic]
      '(menu-item "Sort lexicographically" ibuffer-do-sort-by-alphabetic
616
        :help "Sort by the alphabetic order of buffer name"))
Colin Walters's avatar
Colin Walters committed
617 618
    (define-key-after map [menu-bar view sort do-sort-by-recency]
      '(menu-item "Sort by view time" ibuffer-do-sort-by-recency
619
        :help "Sort by the last time the buffer was displayed"))
620 621
    (define-key-after map [menu-bar view sort dashes]
      '("--"))
Colin Walters's avatar
Colin Walters committed
622 623 624 625
    (define-key-after map [menu-bar view sort invert-sorting]
      '(menu-item "Reverse sorting order" ibuffer-invert-sorting))
    (define-key-after map [menu-bar view sort toggle-sorting-mode]
      '(menu-item "Switch sorting mode" ibuffer-toggle-sorting-mode
626
        :help "Switch between the various sorting criteria"))
Colin Walters's avatar
Colin Walters committed
627 628 629 630 631

    (define-key-after map [menu-bar view filter]
      (cons "Filter" (make-sparse-keymap "Filter")))

    (define-key-after map [menu-bar view filter filter-disable]
632
      '(menu-item "Disable all filtering" ibuffer-filter-disable
633
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
Colin Walters's avatar
Colin Walters committed
634
    (define-key-after map [menu-bar view filter filter-by-mode]
Colin Walters's avatar
Colin Walters committed
635
      '(menu-item "Add filter by major mode..." ibuffer-filter-by-mode))
636
    (define-key-after map [menu-bar view filter filter-by-mode]
637 638
      '(menu-item "Add filter by major mode in use..."
        ibuffer-filter-by-used-mode))
Colin Walters's avatar
Colin Walters committed
639
    (define-key-after map [menu-bar view filter filter-by-name]
Colin Walters's avatar
Colin Walters committed
640
      '(menu-item "Add filter by buffer name..." ibuffer-filter-by-name))
Colin Walters's avatar
Colin Walters committed
641
    (define-key-after map [menu-bar view filter filter-by-filename]
Colin Walters's avatar
Colin Walters committed
642
      '(menu-item "Add filter by filename..." ibuffer-filter-by-filename))
Colin Walters's avatar
Colin Walters committed
643
    (define-key-after map [menu-bar view filter filter-by-size-lt]
Colin Walters's avatar
Colin Walters committed
644
      '(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt))
Colin Walters's avatar
Colin Walters committed
645
    (define-key-after map [menu-bar view filter filter-by-size-gt]
646 647
      '(menu-item "Add filter by size greater than..."
        ibuffer-filter-by-size-gt))
Colin Walters's avatar
Colin Walters committed
648
    (define-key-after map [menu-bar view filter filter-by-content]
649 650
      '(menu-item "Add filter by content (regexp)..."
        ibuffer-filter-by-content))
Colin Walters's avatar
Colin Walters committed
651
    (define-key-after map [menu-bar view filter filter-by-predicate]
652 653
      '(menu-item "Add filter by Lisp predicate..."
        ibuffer-filter-by-predicate))
Colin Walters's avatar
Colin Walters committed
654
    (define-key-after map [menu-bar view filter pop-filter]
655
      '(menu-item "Remove top filter" ibuffer-pop-filter
656
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
Colin Walters's avatar
Colin Walters committed
657 658
    (define-key-after map [menu-bar view filter or-filter]
      '(menu-item "OR top two filters" ibuffer-or-filter
659 660 661 662
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
                     (cdr ibuffer-filtering-qualifiers))
        :help
        "Create a new filter which is the logical OR of the top two filters"))
Colin Walters's avatar
Colin Walters committed
663
    (define-key-after map [menu-bar view filter negate-filter]
664
      '(menu-item "Negate top filter" ibuffer-negate-filter
665
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
Colin Walters's avatar
Colin Walters committed
666 667
    (define-key-after map [menu-bar view filter decompose-filter]
      '(menu-item "Decompose top filter" ibuffer-decompose-filter
668 669 670
        :enable (and (featurep 'ibuf-ext)
                     (memq (car ibuffer-filtering-qualifiers) '(or saved not)))
        :help "Break down a complex filter like OR or NOT"))
Colin Walters's avatar
Colin Walters committed
671
    (define-key-after map [menu-bar view filter exchange-filters]
672
      '(menu-item "Swap top two filters" ibuffer-exchange-filters
673 674
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
                     (cdr ibuffer-filtering-qualifiers))))
Colin Walters's avatar
Colin Walters committed
675 676
    (define-key-after map [menu-bar view filter save-filters]
      '(menu-item "Save current filters permanently..." ibuffer-save-filters
677
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
Paul Eggert's avatar
Paul Eggert committed
678
        :help "Use a mnemonic name to store current filter stack"))
Colin Walters's avatar
Colin Walters committed
679
    (define-key-after map [menu-bar view filter switch-to-saved-filters]
680 681 682 683
      '(menu-item "Restore permanently saved filters..."
        ibuffer-switch-to-saved-filters
        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)
        :help "Replace current filters with a saved stack"))
Colin Walters's avatar
Colin Walters committed
684
    (define-key-after map [menu-bar view filter add-saved-filters]
685 686 687 688
      '(menu-item "Add to permanently saved filters..."
        ibuffer-add-saved-filters
        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
        :help "Include already saved stack with current filters"))
Colin Walters's avatar
Colin Walters committed
689
    (define-key-after map [menu-bar view filter delete-saved-filters]
Colin Walters's avatar
Colin Walters committed
690
      '(menu-item "Delete permanently saved filters..."
691 692
        ibuffer-delete-saved-filters
        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)))
Colin Walters's avatar
Colin Walters committed
693

694
    (define-key-after map [menu-bar view filter-groups]
695
      (cons "Filter Groups" ibuffer-mode-groups-popup))
696

Colin Walters's avatar
Colin Walters committed
697 698 699 700
    (define-key-after map [menu-bar view dashes2]
      '("--"))
    (define-key-after map [menu-bar view diff-with-file]
      '(menu-item "Diff with file" ibuffer-diff-with-file
701
        :help "View the differences between this buffer and its file"))
Colin Walters's avatar
Colin Walters committed
702 703
    (define-key-after map [menu-bar view auto-mode]
      '(menu-item "Toggle Auto Mode" ibuffer-auto-mode
704
        :help "Attempt to automatically update the Ibuffer buffer"))
Colin Walters's avatar
Colin Walters committed
705
    (define-key-after map [menu-bar view customize]
706
      '(menu-item "Customize Ibuffer" ibuffer-customize
707
        :help "Use Custom to customize Ibuffer"))
Colin Walters's avatar
Colin Walters committed
708 709 710 711 712 713

    (define-key-after map [menu-bar mark]
      (cons "Mark" (make-sparse-keymap "Mark")))

    (define-key-after map [menu-bar mark toggle-marks]
      '(menu-item "Toggle marks" ibuffer-toggle-marks
714
        :help "Unmark marked buffers, and mark unmarked buffers"))
Colin Walters's avatar
Colin Walters committed
715 716
    (define-key-after map [menu-bar mark mark-forward]
      '(menu-item "Mark" ibuffer-mark-forward
717
        :help "Mark the buffer at point"))
Colin Walters's avatar
Colin Walters committed
718 719
    (define-key-after map [menu-bar mark unmark-forward]
      '(menu-item "Unmark" ibuffer-unmark-forward
720
        :help "Unmark the buffer at point"))
Colin Walters's avatar
Colin Walters committed
721 722
    (define-key-after map [menu-bar mark mark-by-mode]
      '(menu-item "Mark by mode..." ibuffer-mark-by-mode
723
        :help "Mark all buffers in a particular major mode"))
Colin Walters's avatar
Colin Walters committed
724 725
    (define-key-after map [menu-bar mark mark-modified-buffers]
      '(menu-item "Mark modified buffers" ibuffer-mark-modified-buffers
726
        :help "Mark all buffers which have been modified"))
Colin Walters's avatar
Colin Walters committed
727 728
    (define-key-after map [menu-bar mark mark-unsaved-buffers]
      '(menu-item "Mark unsaved buffers" ibuffer-mark-unsaved-buffers
729
        :help "Mark all buffers which have a file and are modified"))
Colin Walters's avatar
Colin Walters committed
730 731
    (define-key-after map [menu-bar mark mark-read-only-buffers]
      '(menu-item "Mark read-only buffers" ibuffer-mark-read-only-buffers
732
        :help "Mark all buffers which are read-only"))
Colin Walters's avatar
Colin Walters committed
733 734
    (define-key-after map [menu-bar mark mark-special-buffers]
      '(menu-item "Mark special buffers" ibuffer-mark-special-buffers
735
        :help "Mark all buffers whose name begins with a *"))
Colin Walters's avatar
Colin Walters committed
736 737
    (define-key-after map [menu-bar mark mark-dired-buffers]
      '(menu-item "Mark dired buffers" ibuffer-mark-dired-buffers
738
        :help "Mark buffers in dired-mode"))
Colin Walters's avatar
Colin Walters committed
739 740
    (define-key-after map [menu-bar mark mark-dissociated-buffers]
      '(menu-item "Mark dissociated buffers" ibuffer-mark-dissociated-buffers
741
        :help "Mark buffers with a non-existent associated file"))
Colin Walters's avatar
Colin Walters committed
742 743
    (define-key-after map [menu-bar mark mark-help-buffers]
      '(menu-item "Mark help buffers" ibuffer-mark-help-buffers
744
        :help "Mark buffers in help-mode"))
745
    (define-key-after map [menu-bar mark mark-compressed-file-buffers]
746 747 748
      '(menu-item "Mark compressed file buffers"
        ibuffer-mark-compressed-file-buffers
        :help "Mark buffers which have a file that is compressed"))
Colin Walters's avatar
Colin Walters committed
749 750
    (define-key-after map [menu-bar mark mark-old-buffers]
      '(menu-item "Mark old buffers" ibuffer-mark-old-buffers
751
        :help "Mark buffers which have not been viewed recently"))
Colin Walters's avatar
Colin Walters committed
752 753
    (define-key-after map [menu-bar mark unmark-all]
      '(menu-item "Unmark All" ibuffer-unmark-all))
754

Colin Walters's avatar
Colin Walters committed
755 756
    (define-key-after map [menu-bar mark dashes]
      '("--"))
757

Colin Walters's avatar
Colin Walters committed
758 759
    (define-key-after map [menu-bar mark mark-by-name-regexp]
      '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
760
        :help "Mark buffers whose name matches a regexp"))
Colin Walters's avatar
Colin Walters committed
761 762
    (define-key-after map [menu-bar mark mark-by-mode-regexp]
      '(menu-item "Mark by major mode (regexp)..." ibuffer-mark-by-mode-regexp
763
        :help "Mark buffers whose major mode name matches a regexp"))
Colin Walters's avatar
Colin Walters committed
764
    (define-key-after map [menu-bar mark mark-by-file-name-regexp]
765 766 767
      '(menu-item "Mark by file name (regexp)..."
        ibuffer-mark-by-file-name-regexp
        :help "Mark buffers whose file name matches a regexp"))
Colin Walters's avatar
Colin Walters committed
768

769
    map))
Colin Walters's avatar
Colin Walters committed
770

771 772
(defvar ibuffer-mode-operate-map
  (let ((operate-map (make-sparse-keymap "Operate")))
Colin Walters's avatar
Colin Walters committed
773 774 775 776 777 778 779 780
    (define-key-after operate-map [do-view]
      '(menu-item "View" ibuffer-do-view))
    (define-key-after operate-map [do-view-other-frame]
      '(menu-item "View (separate frame)" ibuffer-do-view-other-frame))
    (define-key-after operate-map [do-save]
      '(menu-item "Save" ibuffer-do-save))
    (define-key-after operate-map [do-replace-regexp]
      '(menu-item "Replace (regexp)..." ibuffer-do-replace-regexp
781
        :help "Replace text inside marked buffers"))
Colin Walters's avatar
Colin Walters committed
782 783
    (define-key-after operate-map [do-query-replace]
      '(menu-item "Query Replace..." ibuffer-do-query-replace
784
        :help "Replace text in marked buffers, asking each time"))
Colin Walters's avatar
Colin Walters committed
785 786
    (define-key-after operate-map [do-query-replace-regexp]
      '(menu-item "Query Replace (regexp)..." ibuffer-do-query-replace-regexp
787
        :help "Replace text in marked buffers by regexp, asking each time"))
Colin Walters's avatar
Colin Walters committed
788 789 790 791 792 793
    (define-key-after operate-map [do-print]
      '(menu-item "Print" ibuffer-do-print))
    (define-key-after operate-map [do-toggle-modified]
      '(menu-item "Toggle modification flag" ibuffer-do-toggle-modified))
    (define-key-after operate-map [do-revert]
      '(menu-item "Revert" ibuffer-do-revert
794
        :help "Revert marked buffers to their associated file"))
Colin Walters's avatar
Colin Walters committed
795 796
    (define-key-after operate-map [do-rename-uniquely]
      '(menu-item "Rename Uniquely" ibuffer-do-rename-uniquely
797
        :help "Rename marked buffers to a new, unique name"))
Colin Walters's avatar
Colin Walters committed
798 799 800 801
    (define-key-after operate-map [do-delete]
      '(menu-item "Kill" ibuffer-do-delete))
    (define-key-after operate-map [do-occur]
      '(menu-item "List lines matching..." ibuffer-do-occur
802
        :help "View all lines in marked buffers matching a regexp"))
Colin Walters's avatar
Colin Walters committed
803 804
    (define-key-after operate-map [do-shell-command-pipe]
      '(menu-item "Pipe to shell command..." ibuffer-do-shell-command-pipe
805
        :help "For each marked buffer, send its contents to a shell command"))
Colin Walters's avatar
Colin Walters committed
806 807
    (define-key-after operate-map [do-shell-command-pipe-replace]
      '(menu-item "Pipe to shell command (replace)..." ibuffer-do-shell-command-pipe-replace
808
        :help "For each marked buffer, replace its contents with output of shell command"))
Colin Walters's avatar
Colin Walters committed
809 810
    (define-key-after operate-map [do-shell-command-file]
      '(menu-item "Shell command on buffer's file..." ibuffer-do-shell-command-file
811
        :help "For each marked buffer, run a shell command with its file as argument"))
Colin Walters's avatar
Colin Walters committed
812 813
    (define-key-after operate-map [do-eval]
      '(menu-item "Eval..." ibuffer-do-eval
814
        :help "Evaluate a Lisp form in each marked buffer"))
Colin Walters's avatar
Colin Walters committed
815 816
    (define-key-after operate-map [do-view-and-eval]
      '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
817
        :help "Evaluate a Lisp form in each marked buffer while viewing it"))
818

819
    operate-map))
820 821

(define-key ibuffer-mode-groups-popup [kill-filter-group]
822 823
  '(menu-item "Kill filter group"
	      ibuffer-kill-line
824 825
	      :enable (and (featurep 'ibuf-ext)
			   ibuffer-filter-groups)))
826
(define-key ibuffer-mode-groups-popup [yank-filter-group]
827 828
  '(menu-item "Yank last killed filter group"
	      ibuffer-yank
829 830
	      :enable (and (featurep 'ibuf-ext)
			   ibuffer-filter-group-kill-ring)))
831

832
(defvar ibuffer-name-map
Colin Walters's avatar
Colin Walters committed
833 834 835 836
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
    (define-key map [(mouse-2)] 'ibuffer-mouse-visit-buffer)
    (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
837
    map))
Colin Walters's avatar
Colin Walters committed
838

839 840 841 842 843
(defvar ibuffer-filename/process-header-map
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-do-sort-by-filename/process)
    map))

844
(defvar ibuffer-mode-name-map
Colin Walters's avatar
Colin Walters committed
845 846 847
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-2)] 'ibuffer-mouse-filter-by-mode)
    (define-key map (kbd "RET") 'ibuffer-interactive-filter-by-mode)
848
    map))
Colin Walters's avatar
Colin Walters committed
849

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
(defvar ibuffer-name-header-map
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-do-sort-by-alphabetic)
    map))

(defvar ibuffer-size-header-map
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-do-sort-by-size)
    map))

(defvar ibuffer-mode-header-map
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-do-sort-by-major-mode)
    map))

865
(defvar ibuffer-mode-filter-group-map
866 867 868 869
  (let ((map (make-sparse-keymap)))
    (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
    (define-key map [(mouse-2)] 'ibuffer-mouse-toggle-filter-group)
    (define-key map (kbd "RET") 'ibuffer-toggle-filter-group)
870
    (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
871
    map))
872

873 874 875 876 877
(defvar ibuffer-restore-window-config-on-quit nil
  "If non-nil, restore previous window configuration upon exiting `ibuffer'.")

(defvar ibuffer-prev-window-config nil
  "Window configuration before starting Ibuffer.")
Colin Walters's avatar
Colin Walters committed
878 879 880

(defvar ibuffer-did-modification nil)

881 882 883 884 885
(defvar ibuffer-compiled-formats nil)
(defvar ibuffer-cached-formats nil)
(defvar ibuffer-cached-eliding-string nil)
(defvar ibuffer-cached-elide-long-columns 0)

Colin Walters's avatar
Colin Walters committed
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
(defvar ibuffer-sorting-functions-alist nil
  "An alist of functions which describe how to sort buffers.

Note: You most likely do not want to modify this variable directly;
use `define-ibuffer-sorter' instead.

The alist elements are constructed like (NAME DESCRIPTION FUNCTION)
Where NAME is a symbol describing the sorting method, DESCRIPTION is a
short string which will be displayed in the minibuffer and menu, and
FUNCTION is a function of two arguments, which will be the buffers to
compare.")

;;; Utility functions
(defun ibuffer-columnize-and-insert-list (list &optional pad-width)
  "Insert LIST into the current buffer in as many columns as possible.
The maximum number of columns is determined by the current window
width and the longest string in LIST."
  (unless pad-width
    (setq pad-width 3))
  (let ((width (window-width))
	(max (+ (apply #'max (mapcar #'length list))
		pad-width)))
    (let ((columns (/ width max)))
      (when (zerop columns)
	(setq columns 1))
      (while list
	(dotimes (i (1- columns))
	  (insert (concat (car list) (make-string (- max (length (car list)))
914
						  ?\s)))
Colin Walters's avatar
Colin Walters committed
915 916 917 918 919 920 921 922 923 924 925 926 927
	  (setq list (cdr list)))
	(when (not (null list))
	  (insert (pop list)))
	(insert "\n")))))

(defsubst ibuffer-current-mark ()
  (cadr (get-text-property (line-beginning-position)
			   'ibuffer-properties)))

(defun ibuffer-mouse-toggle-mark (event)
  "Toggle the marked status of the buffer chosen with the mouse."
  (interactive "e")
  (unwind-protect
928 929 930 931 932 933 934 935 936
      (let ((pt (save-excursion
		  (mouse-set-point event)
		  (point))))
	(ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
	    (ibuffer-toggle-marks it)
	  (goto-char pt)
	  (let ((mark (ibuffer-current-mark)))
	    (setq buffer-read-only nil)
	    (if (eq mark ibuffer-marked-char)
937
		(ibuffer-set-mark ?\s)
938
	      (ibuffer-set-mark ibuffer-marked-char)))))
Colin Walters's avatar
Colin Walters committed
939 940 941 942 943 944 945 946 947 948 949
    (setq buffer-read-only t)))

(defun ibuffer-find-file (file &optional wildcards)
  "Like `find-file', but default to the directory of the buffer at point."
  (interactive
   (let ((default-directory (let ((buf (ibuffer-current-buffer)))
			      (if (buffer-live-p buf)
				  (with-current-buffer buf
				    default-directory)
				default-directory))))
     (list (read-file-name "Find file: " default-directory)
950 951
	   t)))
  (find-file file wildcards))
Colin Walters's avatar
Colin Walters committed
952 953 954 955 956 957 958

(defun ibuffer-mouse-visit-buffer (event)
  "Visit the buffer chosen with the mouse."
  (interactive "e")
  (switch-to-buffer
   (save-excursion
     (mouse-set-point event)
959
     (ibuffer-current-buffer t))))
Colin Walters's avatar
Colin Walters committed
960 961 962 963

(defun ibuffer-mouse-popup-menu (event)
  "Display a menu of operations."
  (interactive "e")
964 965
  (let ((eventpt (posn-point (event-end event)))
	(origpt (point)))
Colin Walters's avatar
Colin Walters committed
966
    (unwind-protect
967
	(if (get-text-property eventpt 'ibuffer-filter-group-name)
968 969 970
	    (progn
	      (goto-char eventpt)
	      (popup-menu ibuffer-mode-groups-popup))
971
	  (let ((inhibit-read-only t))
972
	    (ibuffer-save-marks
973 974 975 976 977 978 979
	      ;; hm.  we could probably do this in a better fashion
	      (ibuffer-unmark-all ?\r)
	      (save-excursion
		(goto-char eventpt)
		(ibuffer-set-mark ibuffer-marked-char))
	      (save-excursion
		(popup-menu ibuffer-mode-operate-map)))))
980
      (setq buffer-read-only t)
981
      (if (= eventpt (point))
982
	  (goto-char origpt)))))
983

984 985 986 987 988 989 990 991
(defun ibuffer-skip-properties (props direction)
  (while (and (not (eobp))
	      (let ((hit nil))
		(dolist (prop props hit)
		  (when (get-text-property (point) prop)
		    (setq hit t)))))
    (forward-line direction)
    (beginning-of-line)))
Colin Walters's avatar
Colin Walters committed
992

993 994 995 996 997
(defun ibuffer-customize ()
  "Begin customizing Ibuffer interactively."
  (interactive)
  (customize-group 'ibuffer))

998
(defun ibuffer-backward-line (&optional arg skip-group-names)
Colin Walters's avatar
Colin Walters committed
999 1000
  "Move backwards ARG lines, wrapping around the list if necessary."
  (interactive "P")
1001
  (or arg (setq arg 1))
Colin Walters's avatar
Colin Walters committed
1002 1003 1004
  (beginning-of-line)
  (while (> arg 0)
    (forward-line -1)
1005 1006 1007
    (when (and ibuffer-movement-cycle
	       (or (get-text-property (point) 'ibuffer-title)
		   (and skip-group-names
1008 1009
			(get-text-property (point)
					   'ibuffer-filter-group-name))))
Colin Walters's avatar
Colin Walters committed
1010
      (goto-char (point-max))
1011
      (beginning-of-line))
1012 1013 1014 1015
    (ibuffer-skip-properties (append '(ibuffer-summary)
				     (when skip-group-names
				       '(ibuffer-filter-group-name)))
			     -1)
1016 1017 1018 1019 1020
    ;; Handle the special case of no buffers.
    (when (get-text-property (point) 'ibuffer-title)
      (forward-line 1)
      (setq arg 1))
    (decf arg)))
Colin Walters's avatar
Colin Walters committed
1021

1022
(defun ibuffer-forward-line (&optional arg skip-group-names)
Colin Walters's avatar
Colin Walters committed
1023 1024
  "Move forward ARG lines, wrapping around the list if necessary."
  (interactive "P")
1025
  (or arg (setq arg 1))
Colin Walters's avatar
Colin Walters committed