(follow-mode): Don't run hooks twice. Use `when'.
[bpt/emacs.git] / lisp / ibuffer.el
index 03722a8..80133d2 100644 (file)
@@ -1,9 +1,10 @@
 ;;; ibuffer.el --- operate on buffers like dired
 
 ;;; ibuffer.el --- operate on buffers like dired
 
-;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Colin Walters <walters@verbum.org>
 
 ;; Author: Colin Walters <walters@verbum.org>
-;; Maintainer: John Paul Wallington <jpw@shootybangbang.com>
+;; Maintainer: John Paul Wallington <jpw@gnu.org>
 ;; Created: 8 Sep 2000
 ;; Keywords: buffer, convenience
 
 ;; Created: 8 Sep 2000
 ;; Keywords: buffer, convenience
 
@@ -11,7 +12,7 @@
 
 ;; This program is free software; you can redistribute it and/or
 ;; modify it under the terms of the GNU General Public License as
 
 ;; This program 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 2, or (at
+;; published by the Free Software Foundation; either version 3, or (at
 ;; your option) any later version.
 
 ;; This program is distributed in the hope that it will be useful, but
 ;; your option) any later version.
 
 ;; This program is distributed in the hope that it will be useful, but
@@ -21,8 +22,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program ; see the file COPYING.  If not, write to
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
   (require 'ibuf-macs)
   (require 'dired))
 
   (require 'ibuf-macs)
   (require 'dired))
 
-(require 'font-lock)
-
-;;; Compatibility
-(eval-and-compile
-  (if (fboundp 'window-list)
-      (defun ibuffer-window-list ()
-       (window-list nil 'nomini))
-    (defun ibuffer-window-list ()
-      (let ((ibuffer-window-list-result nil))
-       (walk-windows #'(lambda (win) (push win ibuffer-window-list-result)) 'nomini)
-       (nreverse ibuffer-window-list-result)))))
+(require 'font-core)
+
+;; 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)
+(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)
 
 (defgroup ibuffer nil
   "An advanced replacement for `buffer-menu'.
 
 (defgroup ibuffer nil
   "An advanced replacement for `buffer-menu'.
 Ibuffer allows you to operate on buffers in a manner much like Dired.
 Operations include sorting, marking by regular expression, and
 the ability to filter the displayed buffers by various criteria."
 Ibuffer allows you to operate on buffers in a manner much like Dired.
 Operations include sorting, marking by regular expression, and
 the ability to filter the displayed buffers by various criteria."
+  :version "22.1"
   :group 'convenience)
 
   :group 'convenience)
 
-(defcustom ibuffer-formats '((mark modified read-only " " (name 16 16 :left :elide)
-                                  " " (size 6 -1 :right)
-                                  " " (mode 16 16 :right :elide) " " filename-and-process)
+(defcustom ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide)
+                                  " " (size 9 -1 :right)
+                                  " " (mode 16 16 :left :elide) " " filename-and-process)
                             (mark " " (name 16 -1) " " filename))
   "A list of ways to display buffer lines.
 
                             (mark " " (name 16 -1) " " filename))
   "A list of ways to display buffer lines.
 
@@ -135,12 +142,16 @@ elisp byte-compiler."
 
 (defcustom ibuffer-fontification-alist
   `((10 buffer-read-only font-lock-constant-face)
 
 (defcustom ibuffer-fontification-alist
   `((10 buffer-read-only font-lock-constant-face)
-    (15 (string-match "^*" (buffer-name)) font-lock-keyword-face)
-    (20 (and (string-match "^ " (buffer-name))
+    (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))
             (null buffer-file-name))
        italic)
             (null buffer-file-name))
        italic)
-    (25 (memq major-mode ibuffer-help-buffer-modes) font-lock-comment-face)
-    (30 (eq major-mode 'dired-mode) font-lock-function-name-face))
+    (30 (memq major-mode ibuffer-help-buffer-modes) font-lock-comment-face)
+    (35 (eq major-mode 'dired-mode) font-lock-function-name-face))
   "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
   "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
@@ -148,7 +159,7 @@ 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
 element with the highest PRIORITY takes precedence.
 
 evaluates to non-nil, then FACE will be put on the buffer name.  The
 element with the highest PRIORITY takes precedence.
 
-If you change this variable, you must kill the ibuffer buffer and
+If you change this variable, you must kill the Ibuffer buffer and
 recreate it for the change to take effect."
   :type '(repeat
          (list (integer :tag "Priority")
 recreate it for the change to take effect."
   :type '(repeat
          (list (integer :tag "Priority")
@@ -167,6 +178,11 @@ recreate it for the change to take effect."
   :group 'ibuffer)
 (defvar ibuffer-shrink-to-minimum-size nil)
 
   :group 'ibuffer)
 (defvar ibuffer-shrink-to-minimum-size nil)
 
+(defcustom ibuffer-display-summary t
+  "If non-nil, summarize Ibuffer columns."
+  :type 'boolean
+  :group 'ibuffer)
+
 (defcustom ibuffer-truncate-lines t
   "If non-nil, do not display continuation lines."
   :type 'boolean
 (defcustom ibuffer-truncate-lines t
   "If non-nil, do not display continuation lines."
   :type 'boolean
@@ -180,8 +196,8 @@ recreate it for the change to take effect."
 (defcustom ibuffer-default-sorting-mode 'recency
   "The criteria by which to sort the buffers.
 
 (defcustom ibuffer-default-sorting-mode 'recency
   "The criteria by which to sort the buffers.
 
-Note that this variable is local to each ibuffer buffer.  Thus, you
-can have multiple ibuffer buffers open, each with a different sorted
+Note that this variable is local to each Ibuffer buffer.  Thus, you
+can have multiple Ibuffer buffers open, each with a different sorted
 view of the buffers."
   :type '(choice (const :tag "Last view time" :value recency)
                 (const :tag "Lexicographic" :value alphabetic)
 view of the buffers."
   :type '(choice (const :tag "Last view time" :value recency)
                 (const :tag "Lexicographic" :value alphabetic)
@@ -197,11 +213,12 @@ view of the buffers."
 (defvar ibuffer-sorting-reversep nil)
 
 (defcustom ibuffer-elide-long-columns nil
 (defvar ibuffer-sorting-reversep nil)
 
 (defcustom ibuffer-elide-long-columns nil
-  "If non-nil, then elide column entries which exceed their max length.
-This variable is deprecated; use the :elide argument of
-`ibuffer-formats' to elide just certain columns."
+  "If non-nil, then elide column entries which exceed their max length."
   :type 'boolean
   :group 'ibuffer)
   :type 'boolean
   :group 'ibuffer)
+(make-obsolete-variable 'ibuffer-elide-long-columns
+                        "use the :elide argument of `ibuffer-formats'."
+                        "22.1")
 
 (defcustom ibuffer-eliding-string "..."
   "The string to use for eliding long columns."
 
 (defcustom ibuffer-eliding-string "..."
   "The string to use for eliding long columns."
@@ -211,17 +228,27 @@ This variable is deprecated; use the :elide argument of
 (defcustom ibuffer-maybe-show-predicates `(,(lambda (buf)
                                              (and (string-match "^ " (buffer-name buf))
                                                   (null buffer-file-name))))
 (defcustom ibuffer-maybe-show-predicates `(,(lambda (buf)
                                              (and (string-match "^ " (buffer-name buf))
                                                   (null buffer-file-name))))
-  "A list of predicates (a regexp or function) for buffers to display conditionally.
+  "A list of predicates for buffers to display conditionally.
+
+A predicate can be a regexp or a function.
 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.
 
 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.
 
-Viewing of buffers hidden because of these predicates is enabled by
-giving a non-nil prefix argument to `ibuffer-update'.  Note that this
-specialized filtering occurs before real filtering."
+Viewing of buffers hidden because of these predicates may be customized
+via `ibuffer-default-display-maybe-show-predicates' and is toggled by
+giving a non-nil prefix argument to `ibuffer-update'.
+Note that this specialized filtering occurs before real filtering."
   :type '(repeat (choice regexp function))
   :group 'ibuffer)
 
   :type '(repeat (choice regexp function))
   :group 'ibuffer)
 
+(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)
+
 (defvar ibuffer-current-format nil)
 
 (defcustom ibuffer-movement-cycle t
 (defvar ibuffer-current-format nil)
 
 (defcustom ibuffer-movement-cycle t
@@ -263,21 +290,27 @@ state, size, etc."
   :group 'ibuffer)
 
 (defcustom ibuffer-always-show-last-buffer nil
   :group 'ibuffer)
 
 (defcustom ibuffer-always-show-last-buffer nil
-  "If non-nil, always display the previous buffer.  This variable
-takes precedence over filtering, and even
+  "If non-nil, always display the previous buffer.
+This variable takes precedence over filtering, and even
 `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)
 
 `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)
 
+(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)
+
 (defcustom ibuffer-use-header-line (boundp 'header-line-format)
   "If non-nil, display a header line containing current filters."
   :type 'boolean
   :group 'ibuffer)
 
 (defcustom ibuffer-default-directory nil
 (defcustom ibuffer-use-header-line (boundp 'header-line-format)
   "If non-nil, display a header line containing current filters."
   :type 'boolean
   :group 'ibuffer)
 
 (defcustom ibuffer-default-directory nil
-  "The default directory to use for a new ibuffer buffer.
+  "The default directory to use for a new Ibuffer buffer.
 If nil, inherit the directory of the buffer in which `ibuffer' was
 called.  Otherwise, this variable should be a string naming a
 directory, like `default-directory'."
 If nil, inherit the directory of the buffer in which `ibuffer' was
 called.  Otherwise, this variable should be a string naming a
 directory, like `default-directory'."
@@ -285,23 +318,36 @@ directory, like `default-directory'."
                 string)
   :group 'ibuffer)
 
                 string)
   :group 'ibuffer)
 
-(defcustom ibuffer-help-buffer-modes '(help-mode apropos-mode
-                                      Info-mode Info-edit-mode)
+(defcustom ibuffer-help-buffer-modes
+  '(help-mode apropos-mode Info-mode Info-edit-mode)
   "List of \"Help\" major modes."
   :type '(repeat function)
   :group 'ibuffer)
 
   "List of \"Help\" major modes."
   :type '(repeat function)
   :group 'ibuffer)
 
+(defcustom ibuffer-compressed-file-name-regexp
+  "\\.\\(arj\\|bgz\\|bz2\\|gz\\|lzh\\|taz\\|tgz\\|zip\\|z\\)$"
+  "Regexp to match compressed file names."
+  :type 'regexp
+  :group 'ibuffer)
+
 (defcustom ibuffer-hook nil
 (defcustom ibuffer-hook nil
-  "Hooks run when `ibuffer' is called."
+  "Hook run when `ibuffer' is called."
   :type 'hook
   :group 'ibuffer)
   :type 'hook
   :group 'ibuffer)
-(defvaralias 'ibuffer-hooks 'ibuffer-hook)
+(define-obsolete-variable-alias 'ibuffer-hooks
+                                'ibuffer-hook "22.1")
 
 (defcustom ibuffer-mode-hook nil
 
 (defcustom ibuffer-mode-hook nil
-  "Hooks run upon entry into `ibuffer-mode'."
+  "Hook run upon entry into `ibuffer-mode'."
+  :type 'hook
+  :group 'ibuffer)
+(define-obsolete-variable-alias 'ibuffer-mode-hooks
+                                'ibuffer-mode-hook "22.1")
+
+(defcustom ibuffer-load-hook nil
+  "Hook run when Ibuffer is loaded."
   :type 'hook
   :group 'ibuffer)
   :type 'hook
   :group 'ibuffer)
-(defvaralias 'ibuffer-mode-hooks 'ibuffer-mode-hook)
 
 (defcustom ibuffer-marked-face 'font-lock-warning-face
   "Face used for displaying marked buffers."
 
 (defcustom ibuffer-marked-face 'font-lock-warning-face
   "Face used for displaying marked buffers."
@@ -331,6 +377,7 @@ directory, like `default-directory'."
                       (regexp :tag "To")))
   :group 'ibuffer)
 
                       (regexp :tag "To")))
   :group 'ibuffer)
 
+
 (defvar ibuffer-mode-map nil)
 (defvar ibuffer-mode-operate-map nil)
 (defvar ibuffer-mode-groups-popup nil)
 (defvar ibuffer-mode-map nil)
 (defvar ibuffer-mode-operate-map nil)
 (defvar ibuffer-mode-groups-popup nil)
@@ -354,6 +401,7 @@ directory, like `default-directory'."
     (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)
     (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)
+    (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
     (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 "DEL") 'ibuffer-unmark-backward)
     (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
     (define-key map (kbd "* *") 'ibuffer-unmark-all)
@@ -365,13 +413,14 @@ directory, like `default-directory'."
     (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)
     (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)
+    (define-key map (kbd "* z") 'ibuffer-mark-compressed-file-buffers)
     (define-key map (kbd ".") 'ibuffer-mark-old-buffers)
     (define-key map (kbd ".") 'ibuffer-mark-old-buffers)
-    
+
     (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)
     (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)
-  
+
     ;; immediate operations
     (define-key map (kbd "n") 'ibuffer-forward-line)
     (define-key map (kbd "<down>") 'ibuffer-forward-line)
     ;; immediate operations
     (define-key map (kbd "n") 'ibuffer-forward-line)
     (define-key map (kbd "<down>") 'ibuffer-forward-line)
@@ -427,7 +476,7 @@ directory, like `default-directory'."
     (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)
     (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)
-  
+
     (define-key map (kbd "q") 'ibuffer-quit)
     (define-key map (kbd "h") 'describe-mode)
     (define-key map (kbd "?") 'describe-mode)
     (define-key map (kbd "q") 'ibuffer-quit)
     (define-key map (kbd "h") 'describe-mode)
     (define-key map (kbd "?") 'describe-mode)
@@ -435,7 +484,7 @@ directory, like `default-directory'."
     (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)
     (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)
-  
+
     (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)
 
     (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe)
     (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)
 
     (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe)
@@ -460,7 +509,7 @@ directory, like `default-directory'."
     (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)
     (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)
-  
+
     (define-key map (kbd "k") 'ibuffer-do-kill-lines)
     (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)
 
     (define-key map (kbd "k") 'ibuffer-do-kill-lines)
     (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)
 
@@ -509,6 +558,8 @@ directory, like `default-directory'."
     (define-key-after map [menu-bar view sort do-sort-by-recency]
       '(menu-item "Sort by view time" ibuffer-do-sort-by-recency
                  :help "Sort by the last time the buffer was displayed"))
     (define-key-after map [menu-bar view sort do-sort-by-recency]
       '(menu-item "Sort by view time" ibuffer-do-sort-by-recency
                  :help "Sort by the last time the buffer was displayed"))
+    (define-key-after map [menu-bar view sort dashes]
+      '("--"))
     (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]
     (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]
@@ -558,7 +609,7 @@ directory, like `default-directory'."
                               (cdr ibuffer-filtering-qualifiers))))
     (define-key-after map [menu-bar view filter save-filters]
       '(menu-item "Save current filters permanently..." ibuffer-save-filters
                               (cdr ibuffer-filtering-qualifiers))))
     (define-key-after map [menu-bar view filter save-filters]
       '(menu-item "Save current filters permanently..." ibuffer-save-filters
-                 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)                 
+                 :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
                  :help "Use a mnemnonic name to store current filter stack"))
     (define-key-after map [menu-bar view filter switch-to-saved-filters]
       '(menu-item "Restore permanently saved filters..." ibuffer-switch-to-saved-filters
                  :help "Use a mnemnonic name to store current filter stack"))
     (define-key-after map [menu-bar view filter switch-to-saved-filters]
       '(menu-item "Restore permanently saved filters..." ibuffer-switch-to-saved-filters
@@ -581,7 +632,7 @@ directory, like `default-directory'."
                  :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"
                  :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))    
+                 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 [backward-filter-group]
       '(menu-item "Move point to the previous filter group"
                  ibuffer-backward-filter-group))
@@ -618,7 +669,7 @@ directory, like `default-directory'."
       '(menu-item "Restore permanently saved filters..."
                  ibuffer-switch-to-saved-filter-groups
                  :enable (and (featurep 'ibuf-ext) ibuffer-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"))    
+                 :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
     (define-key-after groups-map [delete-saved-filter-groups]
       '(menu-item "Delete permanently saved filter groups..."
                  ibuffer-delete-saved-filter-groups
@@ -639,8 +690,7 @@ directory, like `default-directory'."
       '(menu-item "Toggle Auto Mode" ibuffer-auto-mode
                  :help "Attempt to automatically update the Ibuffer buffer"))
     (define-key-after map [menu-bar view customize]
       '(menu-item "Toggle Auto Mode" ibuffer-auto-mode
                  :help "Attempt to automatically update the Ibuffer buffer"))
     (define-key-after map [menu-bar view customize]
-      '(menu-item "Customize Ibuffer" (lambda () (interactive)
-                                       (customize-group 'ibuffer))
+      '(menu-item "Customize Ibuffer" ibuffer-customize
                  :help "Use Custom to customize Ibuffer"))
 
     (define-key-after map [menu-bar mark]
                  :help "Use Custom to customize Ibuffer"))
 
     (define-key-after map [menu-bar mark]
@@ -679,15 +729,18 @@ directory, like `default-directory'."
     (define-key-after map [menu-bar mark mark-help-buffers]
       '(menu-item "Mark help buffers" ibuffer-mark-help-buffers
                  :help "Mark buffers in help-mode"))
     (define-key-after map [menu-bar mark mark-help-buffers]
       '(menu-item "Mark help buffers" ibuffer-mark-help-buffers
                  :help "Mark buffers in help-mode"))
+    (define-key-after map [menu-bar mark mark-compressed-file-buffers]
+      '(menu-item "Mark compressed file buffers" ibuffer-mark-compressed-file-buffers
+                 :help "Mark buffers which have a file that is compressed"))
     (define-key-after map [menu-bar mark mark-old-buffers]
       '(menu-item "Mark old buffers" ibuffer-mark-old-buffers
                  :help "Mark buffers which have not been viewed recently"))
     (define-key-after map [menu-bar mark unmark-all]
       '(menu-item "Unmark All" ibuffer-unmark-all))
     (define-key-after map [menu-bar mark mark-old-buffers]
       '(menu-item "Mark old buffers" ibuffer-mark-old-buffers
                  :help "Mark buffers which have not been viewed recently"))
     (define-key-after map [menu-bar mark unmark-all]
       '(menu-item "Unmark All" ibuffer-unmark-all))
-    
+
     (define-key-after map [menu-bar mark dashes]
       '("--"))
     (define-key-after map [menu-bar mark dashes]
       '("--"))
-      
+
     (define-key-after map [menu-bar mark mark-by-name-regexp]
       '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
                  :help "Mark buffers whose name matches a regexp"))
     (define-key-after map [menu-bar mark mark-by-name-regexp]
       '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
                  :help "Mark buffers whose name matches a regexp"))
@@ -745,49 +798,71 @@ directory, like `default-directory'."
     (define-key-after operate-map [do-view-and-eval]
       '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
                  :help "Evaluate a Lisp form in each marked buffer while viewing it"))
     (define-key-after operate-map [do-view-and-eval]
       '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
                  :help "Evaluate a Lisp form in each marked buffer while viewing it"))
-    
+
     (setq ibuffer-mode-map map
          ibuffer-mode-operate-map operate-map
          ibuffer-mode-groups-popup (copy-keymap groups-map))))
 
 (define-key ibuffer-mode-groups-popup [kill-filter-group]
     (setq ibuffer-mode-map map
          ibuffer-mode-operate-map operate-map
          ibuffer-mode-groups-popup (copy-keymap groups-map))))
 
 (define-key ibuffer-mode-groups-popup [kill-filter-group]
-      '(menu-item "Kill filter group"
-                 ibuffer-kill-line
-                 :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
+  '(menu-item "Kill filter group"
+             ibuffer-kill-line
+             :enable (and (featurep 'ibuf-ext)
+                          ibuffer-filter-groups)))
 (define-key ibuffer-mode-groups-popup [yank-filter-group]
 (define-key ibuffer-mode-groups-popup [yank-filter-group]
-      '(menu-item "Yank last killed filter group"
-                 ibuffer-yank
-                 :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
-(defvar ibuffer-name-map nil)
-(unless ibuffer-name-map
+  '(menu-item "Yank last killed filter group"
+             ibuffer-yank
+             :enable (and (featurep 'ibuf-ext)
+                          ibuffer-filter-group-kill-ring)))
+
+(defvar ibuffer-name-map
   (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)
   (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)
-    (setq ibuffer-name-map map)))
+    map))
 
 
-(defvar ibuffer-mode-name-map nil)
-(unless ibuffer-mode-name-map
+(defvar ibuffer-mode-name-map
   (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)
   (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)
-    (setq ibuffer-mode-name-map map)))
+    map))
+
+(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))
 
 
-(defvar ibuffer-mode-filter-group-map nil)
-(unless ibuffer-mode-filter-group-map
+(defvar ibuffer-mode-filter-group-map
   (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)
     (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
   (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)
     (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
-    (setq ibuffer-mode-filter-group-map map)))
+    map))
 
 
-(defvar ibuffer-delete-window-on-quit nil
-  "Whether or not to delete the window upon exiting `ibuffer'.")
+(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.")
 
 (defvar ibuffer-did-modification nil)
 
 
 (defvar ibuffer-did-modification nil)
 
+(defvar ibuffer-compiled-formats nil)
+(defvar ibuffer-cached-formats nil)
+(defvar ibuffer-cached-eliding-string nil)
+(defvar ibuffer-cached-elide-long-columns 0)
+
 (defvar ibuffer-sorting-functions-alist nil
   "An alist of functions which describe how to sort buffers.
 
 (defvar ibuffer-sorting-functions-alist nil
   "An alist of functions which describe how to sort buffers.
 
@@ -816,7 +891,7 @@ width and the longest string in LIST."
       (while list
        (dotimes (i (1- columns))
          (insert (concat (car list) (make-string (- max (length (car list)))
       (while list
        (dotimes (i (1- columns))
          (insert (concat (car list) (make-string (- max (length (car list)))
-                                                 ? )))
+                                                 ?\s)))
          (setq list (cdr list)))
        (when (not (null list))
          (insert (pop list)))
          (setq list (cdr list)))
        (when (not (null list))
          (insert (pop list)))
@@ -839,7 +914,7 @@ width and the longest string in LIST."
          (let ((mark (ibuffer-current-mark)))
            (setq buffer-read-only nil)
            (if (eq mark ibuffer-marked-char)
          (let ((mark (ibuffer-current-mark)))
            (setq buffer-read-only nil)
            (if (eq mark ibuffer-marked-char)
-               (ibuffer-set-mark ? )
+               (ibuffer-set-mark ?\s)
              (ibuffer-set-mark ibuffer-marked-char)))))
     (setq buffer-read-only t)))
 
              (ibuffer-set-mark ibuffer-marked-char)))))
     (setq buffer-read-only t)))
 
@@ -852,8 +927,8 @@ width and the longest string in LIST."
                                    default-directory)
                                default-directory))))
      (list (read-file-name "Find file: " default-directory)
                                    default-directory)
                                default-directory))))
      (list (read-file-name "Find file: " default-directory)
-          current-prefix-arg)))
-  (find-file file (or wildcards (interactive-p))))
+          t)))
+  (find-file file wildcards))
 
 (defun ibuffer-mouse-visit-buffer (event)
   "Visit the buffer chosen with the mouse."
 
 (defun ibuffer-mouse-visit-buffer (event)
   "Visit the buffer chosen with the mouse."
@@ -875,15 +950,15 @@ width and the longest string in LIST."
              (popup-menu ibuffer-mode-groups-popup))
          (let ((inhibit-read-only t))
            (ibuffer-save-marks
              (popup-menu ibuffer-mode-groups-popup))
          (let ((inhibit-read-only t))
            (ibuffer-save-marks
-            ;; 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)))))
+             ;; 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)))))
       (setq buffer-read-only t)
       (setq buffer-read-only t)
-      (if (eq eventpt (point))
+      (if (= eventpt (point))
          (goto-char origpt)))))
 
 (defun ibuffer-skip-properties (props direction)
          (goto-char origpt)))))
 
 (defun ibuffer-skip-properties (props direction)
@@ -895,18 +970,23 @@ width and the longest string in LIST."
     (forward-line direction)
     (beginning-of-line)))
 
     (forward-line direction)
     (beginning-of-line)))
 
+(defun ibuffer-customize ()
+  "Begin customizing Ibuffer interactively."
+  (interactive)
+  (customize-group 'ibuffer))
+
 (defun ibuffer-backward-line (&optional arg skip-group-names)
   "Move backwards ARG lines, wrapping around the list if necessary."
   (interactive "P")
 (defun ibuffer-backward-line (&optional arg skip-group-names)
   "Move backwards ARG lines, wrapping around the list if necessary."
   (interactive "P")
-  (unless arg
-    (setq arg 1))
+  (or arg (setq arg 1))
   (beginning-of-line)
   (while (> arg 0)
     (forward-line -1)
     (when (and ibuffer-movement-cycle
               (or (get-text-property (point) 'ibuffer-title)
                   (and skip-group-names
   (beginning-of-line)
   (while (> arg 0)
     (forward-line -1)
     (when (and ibuffer-movement-cycle
               (or (get-text-property (point) 'ibuffer-title)
                   (and skip-group-names
-                       (get-text-property (point) 'ibuffer-filter-group-name))))
+                       (get-text-property (point)
+                                          'ibuffer-filter-group-name))))
       (goto-char (point-max))
       (beginning-of-line))
     (ibuffer-skip-properties (append '(ibuffer-summary)
       (goto-char (point-max))
       (beginning-of-line))
     (ibuffer-skip-properties (append '(ibuffer-summary)
@@ -922,8 +1002,7 @@ width and the longest string in LIST."
 (defun ibuffer-forward-line (&optional arg skip-group-names)
   "Move forward ARG lines, wrapping around the list if necessary."
   (interactive "P")
 (defun ibuffer-forward-line (&optional arg skip-group-names)
   "Move forward ARG lines, wrapping around the list if necessary."
   (interactive "P")
-  (unless arg
-    (setq arg 1))
+  (or arg (setq arg 1))
   (beginning-of-line)
   (when (and ibuffer-movement-cycle
             (or (eobp)
   (beginning-of-line)
   (when (and ibuffer-movement-cycle
             (or (eobp)
@@ -1030,16 +1109,16 @@ a new window in the current frame, splitting vertically."
                 (> (length marked-bufs) 3)
                 (not (y-or-n-p (format "Really create a new frame for %s buffers? "
                                        (length marked-bufs)))))
                 (> (length marked-bufs) 3)
                 (not (y-or-n-p (format "Really create a new frame for %s buffers? "
                                        (length marked-bufs)))))
-     (set-buffer-modified-p nil)
+      (set-buffer-modified-p nil)
       (delete-other-windows)
       (switch-to-buffer (pop marked-bufs))
       (let ((height (/ (1- (if (eq type 'horizontally) (frame-width)
       (delete-other-windows)
       (switch-to-buffer (pop marked-bufs))
       (let ((height (/ (1- (if (eq type 'horizontally) (frame-width)
-                              (frame-height)))
+                            (frame-height)))
                       (1+ (length marked-bufs)))))
        (mapcar (if (eq type 'other-frame)
                    #'(lambda (buf)
                        (let ((curframe (selected-frame)))
                       (1+ (length marked-bufs)))))
        (mapcar (if (eq type 'other-frame)
                    #'(lambda (buf)
                        (let ((curframe (selected-frame)))
-                         (select-frame (new-frame))
+                         (select-frame (make-frame))
                          (switch-to-buffer buf)
                          (select-frame curframe)))
                  #'(lambda (buf)
                          (switch-to-buffer buf)
                          (select-frame curframe)))
                  #'(lambda (buf)
@@ -1073,7 +1152,7 @@ a new window in the current frame, splitting vertically."
            (ibuffer-columnize-and-insert-list names)
            (goto-char (point-min))
            (setq buffer-read-only t))
            (ibuffer-columnize-and-insert-list names)
            (goto-char (point-min))
            (setq buffer-read-only t))
-         (let ((lastwin (car (last (ibuffer-window-list)))))
+         (let ((lastwin (car (last (window-list nil 'nomini)))))
            ;; Now attempt to display the buffer...
            (save-window-excursion
              (select-window lastwin)
            ;; Now attempt to display the buffer...
            (save-window-excursion
              (select-window lastwin)
@@ -1090,11 +1169,11 @@ a new window in the current frame, splitting vertically."
                     ;; Handle a failure
                     (if (or (> (incf attempts) 4)
                             (and (stringp (cadr err))
                     ;; Handle a failure
                     (if (or (> (incf attempts) 4)
                             (and (stringp (cadr err))
-              ;; This definitely falls in the ghetto hack category...
+                                 ;; This definitely falls in the
+                                 ;; ghetto hack category...
                                  (not (string-match "too small" (cadr err)))))
                         (apply #'signal err)
                       (enlarge-window 3))))))
                                  (not (string-match "too small" (cadr err)))))
                         (apply #'signal err)
                       (enlarge-window 3))))))
-             ;; This part doesn't work correctly sometimes under XEmacs.
              (select-window (next-window))
              (switch-to-buffer buf)
              (unwind-protect
              (select-window (next-window))
              (switch-to-buffer buf)
              (unwind-protect
@@ -1111,7 +1190,7 @@ a new window in the current frame, splitting vertically."
 (defun ibuffer-buffer-names-with-mark (mark)
   (let ((ibuffer-buffer-names-with-mark-result nil))
     (ibuffer-map-lines-nomodify
 (defun ibuffer-buffer-names-with-mark (mark)
   (let ((ibuffer-buffer-names-with-mark-result nil))
     (ibuffer-map-lines-nomodify
-     #'(lambda (buf mk) 
+     #'(lambda (buf mk)
         (when (char-equal mark mk)
           (push (buffer-name buf)
                 ibuffer-buffer-names-with-mark-result))))
         (when (char-equal mark mk)
           (push (buffer-name buf)
                 ibuffer-buffer-names-with-mark-result))))
@@ -1127,7 +1206,7 @@ a new window in the current frame, splitting vertically."
   (if all
       (ibuffer-map-lines-nomodify
        #'(lambda (buf mark)
   (if all
       (ibuffer-map-lines-nomodify
        #'(lambda (buf mark)
-          (not (char-equal mark ? ))))
+          (not (char-equal mark ?\s))))
     (ibuffer-map-lines-nomodify
      #'(lambda (buf mark)
         (char-equal mark ibuffer-marked-char)))))
     (ibuffer-map-lines-nomodify
      #'(lambda (buf mark)
         (char-equal mark ibuffer-marked-char)))))
@@ -1201,18 +1280,18 @@ a new window in the current frame, splitting vertically."
      ((char-equal mark ibuffer-marked-char)
       (ibuffer-map-marked-lines
        #'(lambda (buf mark)
      ((char-equal mark ibuffer-marked-char)
       (ibuffer-map-marked-lines
        #'(lambda (buf mark)
-          (ibuffer-set-mark-1 ? )
+          (ibuffer-set-mark-1 ?\s)
           t)))
      ((char-equal mark ibuffer-deletion-char)
       (ibuffer-map-deletion-lines
        #'(lambda (buf mark)
           t)))
      ((char-equal mark ibuffer-deletion-char)
       (ibuffer-map-deletion-lines
        #'(lambda (buf mark)
-          (ibuffer-set-mark-1 ? )
+          (ibuffer-set-mark-1 ?\s)
           t)))
      (t
       (ibuffer-map-lines
        #'(lambda (buf mark)
           t)))
      (t
       (ibuffer-map-lines
        #'(lambda (buf mark)
-          (when (not (char-equal mark ? ))
-            (ibuffer-set-mark-1 ? ))
+          (when (not (char-equal mark ?\s))
+            (ibuffer-set-mark-1 ?\s))
           t)))))
   (ibuffer-redisplay t))
 
           t)))))
   (ibuffer-redisplay t))
 
@@ -1229,9 +1308,9 @@ group."
         (ibuffer-map-lines
          #'(lambda (buf mark)
              (cond ((eq mark ibuffer-marked-char)
         (ibuffer-map-lines
          #'(lambda (buf mark)
              (cond ((eq mark ibuffer-marked-char)
-                    (ibuffer-set-mark-1 ? )
+                    (ibuffer-set-mark-1 ?\s)
                     nil)
                     nil)
-                   ((eq mark ? )
+                   ((eq mark ?\s)
                     (ibuffer-set-mark-1 ibuffer-marked-char)
                     t)
                    (t
                     (ibuffer-set-mark-1 ibuffer-marked-char)
                     t)
                    (t
@@ -1250,24 +1329,23 @@ If point is on a group name, this function operates on that group."
   "Unmark the buffer on this line, and move forward ARG lines.
 If point is on a group name, this function operates on that group."
   (interactive "P")
   "Unmark the buffer on this line, and move forward ARG lines.
 If point is on a group name, this function operates on that group."
   (interactive "P")
-  (ibuffer-mark-interactive arg ?  1))
+  (ibuffer-mark-interactive arg ?\s 1))
 
 (defun ibuffer-unmark-backward (arg)
   "Unmark the buffer on this line, and move backward ARG lines.
 If point is on a group name, this function operates on that group."
   (interactive "P")
 
 (defun ibuffer-unmark-backward (arg)
   "Unmark the buffer on this line, and move backward ARG lines.
 If point is on a group name, this function operates on that group."
   (interactive "P")
-  (ibuffer-mark-interactive arg ?  -1))
+  (ibuffer-mark-interactive arg ?\s -1))
 
 (defun ibuffer-mark-interactive (arg mark movement)
   (assert (eq major-mode 'ibuffer-mode))
 
 (defun ibuffer-mark-interactive (arg mark movement)
   (assert (eq major-mode 'ibuffer-mode))
-  (unless arg
-    (setq arg 1))
+  (or arg (setq arg 1))
   (ibuffer-forward-line 0)
   (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
       (progn
        (require 'ibuf-ext)
        (ibuffer-mark-on-buffer #'identity mark it))
   (ibuffer-forward-line 0)
   (ibuffer-aif (get-text-property (point) 'ibuffer-filter-group-name)
       (progn
        (require 'ibuf-ext)
        (ibuffer-mark-on-buffer #'identity mark it))
-    (ibuffer-forward-line 0 t) 
+    (ibuffer-forward-line 0 t)
     (let ((inhibit-read-only t))
       (while (> arg 0)
        (ibuffer-set-mark mark)
     (let ((inhibit-read-only t))
       (while (> arg 0)
        (ibuffer-set-mark mark)
@@ -1334,38 +1412,38 @@ If point is on a group name, this function operates on that group."
                  (if uncompiledp
                      ibuffer-filter-format-alist
                    ibuffer-compiled-filter-formats))))))
                  (if uncompiledp
                      ibuffer-filter-format-alist
                    ibuffer-compiled-filter-formats))))))
-       
+
 (defun ibuffer-current-format (&optional uncompiledp)
   (or ibuffer-current-format
       (setq ibuffer-current-format 0))
 (defun ibuffer-current-format (&optional uncompiledp)
   (or ibuffer-current-format
       (setq ibuffer-current-format 0))
-  (nth ibuffer-current-format (ibuffer-current-formats uncompiledp)))  
+  (nth ibuffer-current-format (ibuffer-current-formats uncompiledp)))
 
 (defun ibuffer-expand-format-entry (form)
   (if (or (consp form)
          (symbolp form))
 
 (defun ibuffer-expand-format-entry (form)
   (if (or (consp form)
          (symbolp form))
-    (let ((sym (intern (concat "ibuffer-make-column-"
-                              (symbol-name (if (consp form)
-                                               (car form)
-                                             form))))))
-      (unless (or (fboundp sym)
-                 (assq sym ibuffer-inline-columns))
-       (error "Unknown column %s in ibuffer-formats" form))
-      (let (min max align elide)
-       (if (consp form)
-           (setq min (or (nth 1 form) 0)
-                 max (or (nth 2 form) -1)
-                 align (or (nth 3 form) :left)
-                 elide (or (nth 4 form) nil))
-         (setq min 0
-               max -1
-               align :left
-               elide nil))
-       (list sym min max align elide)))
+      (let ((sym (intern (concat "ibuffer-make-column-"
+                                (symbol-name (if (consp form)
+                                                 (car form)
+                                               form))))))
+       (unless (or (fboundp sym)
+                   (assq sym ibuffer-inline-columns))
+         (error "Unknown column %s in ibuffer-formats" form))
+       (let (min max align elide)
+         (if (consp form)
+             (setq min (or (nth 1 form) 0)
+                   max (or (nth 2 form) -1)
+                   align (or (nth 3 form) :left)
+                   elide (or (nth 4 form) nil))
+           (setq min 0
+                 max -1
+                 align :left
+                 elide nil))
+         (list sym min max align elide)))
     form))
     form))
-  
+
 (defun ibuffer-compile-make-eliding-form (strvar elide from-end-p)
   (let ((ellipsis (propertize ibuffer-eliding-string 'font-lock-face 'bold)))
 (defun ibuffer-compile-make-eliding-form (strvar elide from-end-p)
   (let ((ellipsis (propertize ibuffer-eliding-string 'font-lock-face 'bold)))
-    (if (or elide ibuffer-elide-long-columns)
+    (if (or elide (with-no-warnings ibuffer-elide-long-columns))
        `(if (> strlen 5)
             ,(if from-end-p
                  `(concat ,ellipsis
        `(if (> strlen 5)
             ,(if from-end-p
                  `(concat ,ellipsis
@@ -1384,8 +1462,8 @@ If point is on a group name, this function operates on that group."
     `(substring ,strvar 0 ,maxvar)))
 
 (defun ibuffer-compile-make-format-form (strvar widthform alignment)
     `(substring ,strvar 0 ,maxvar)))
 
 (defun ibuffer-compile-make-format-form (strvar widthform alignment)
-  (let* ((left `(make-string tmp2 ? ))
-         (right `(make-string (- tmp1 tmp2) ? )))
+  (let* ((left `(make-string tmp2 ?\s))
+        (right `(make-string (- tmp1 tmp2) ?\s)))
     `(progn
        (setq tmp1 ,widthform
             tmp2 (/ tmp1 2))
     `(progn
        (setq tmp1 ,widthform
             tmp2 (/ tmp1 2))
@@ -1462,19 +1540,19 @@ If point is on a group name, this function operates on that group."
                    ;; into our generated code.  Otherwise, we just
                    ;; generate a call to the column function.
                    (ibuffer-aif (assq sym ibuffer-inline-columns)
                    ;; into our generated code.  Otherwise, we just
                    ;; generate a call to the column function.
                    (ibuffer-aif (assq sym ibuffer-inline-columns)
-                                (nth 1 it)
-                                `(,sym buffer mark)))
+                       (nth 1 it)
+                     `(,sym buffer mark)))
                   ;; You're not expected to understand this.  Hell, I
                   ;; don't even understand it, and I wrote it five
                   ;; minutes ago.
                   (insertgenfn (ibuffer-aif (get sym 'ibuffer-column-summarizer)
                   ;; You're not expected to understand this.  Hell, I
                   ;; don't even understand it, and I wrote it five
                   ;; minutes ago.
                   (insertgenfn (ibuffer-aif (get sym 'ibuffer-column-summarizer)
-                                 ;; I really, really wish Emacs Lisp had closures.
-                                 (lambda (arg sym)
-                                   `(insert
-                                     (let ((ret ,arg))
-                                       (put ',sym 'ibuffer-column-summary
-                                            (cons ret (get ',sym 'ibuffer-column-summary)))
-                                       ret)))
+                                   ;; I really, really wish Emacs Lisp had closures.
+                                   (lambda (arg sym)
+                                     `(insert
+                                       (let ((ret ,arg))
+                                         (put ',sym 'ibuffer-column-summary
+                                              (cons ret (get ',sym 'ibuffer-column-summary)))
+                                         ret)))
                                  (lambda (arg sym)
                                    `(insert ,arg))))
                   (mincompform `(< strlen ,(if (integerp min)
                                  (lambda (arg sym)
                                    `(insert ,arg))))
                   (mincompform `(< strlen ,(if (integerp min)
@@ -1483,40 +1561,40 @@ If point is on a group name, this function operates on that group."
                   (maxcompform `(> strlen ,(if (integerp max)
                                                max
                                              'max))))
                   (maxcompform `(> strlen ,(if (integerp max)
                                                max
                                              'max))))
-                (if (or min-used max-used)
-                    ;; The complex case, where we have to limit the
-                    ;; form to a maximum or minimum size.
-                    (progn
-                      (when (and min-used (not (integerp min)))
-                        (push `(min ,min) letbindings))
-                      (when (and max-used (not (integerp max)))
-                        (push `(max ,max) letbindings))
-                      (push 
-                       (if (and min-used max-used)
-                           `(if ,mincompform
-                                ,minform
-                              (if ,maxcompform
-                                  ,maxform))
-                         (if min-used
-                             `(when ,mincompform
-                                ,minform)
-                           `(when ,maxcompform
-                              ,maxform)))
-                       outforms)
-                      (push (append 
-                             `(setq str ,callform)
-                             (when strlen-used
-                               `(strlen (length str))))
-                            outforms)
-                      (setq outforms
-                            (append outforms (list (funcall insertgenfn 'str sym)))))
-                  ;; The simple case; just insert the string.
-                  (push (funcall insertgenfn callform sym) outforms))
-                ;; Finally, return a `let' form which binds the
-                ;; variables in `letbindings', and contains all the
-                ;; code in `outforms'.
-                `(let ,letbindings
-                   ,@outforms)))))
+              (if (or min-used max-used)
+                  ;; The complex case, where we have to limit the
+                  ;; form to a maximum or minimum size.
+                  (progn
+                    (when (and min-used (not (integerp min)))
+                      (push `(min ,min) letbindings))
+                    (when (and max-used (not (integerp max)))
+                      (push `(max ,max) letbindings))
+                    (push
+                     (if (and min-used max-used)
+                         `(if ,mincompform
+                              ,minform
+                            (if ,maxcompform
+                                ,maxform))
+                       (if min-used
+                           `(when ,mincompform
+                              ,minform)
+                         `(when ,maxcompform
+                            ,maxform)))
+                     outforms)
+                    (push (append
+                           `(setq str ,callform)
+                           (when strlen-used
+                             `(strlen (length str))))
+                          outforms)
+                    (setq outforms
+                          (append outforms (list (funcall insertgenfn 'str sym)))))
+                ;; The simple case; just insert the string.
+                (push (funcall insertgenfn callform sym) outforms))
+              ;; Finally, return a `let' form which binds the
+              ;; variables in `letbindings', and contains all the
+              ;; code in `outforms'.
+              `(let ,letbindings
+                 ,@outforms)))))
        result))
     (setq result
          ;; We don't want to unconditionally load the byte-compiler.
        result))
     (setq result
          ;; We don't want to unconditionally load the byte-compiler.
@@ -1538,16 +1616,11 @@ If point is on a group name, this function operates on that group."
                                            '(tmp2)))
                              ,@(nreverse result))))))))
 
                                            '(tmp2)))
                              ,@(nreverse result))))))))
 
-(defvar ibuffer-compiled-formats nil)
-(defvar ibuffer-cached-formats nil)
-(defvar ibuffer-cached-eliding-string nil)
-(defvar ibuffer-cached-elide-long-columns 0)
-
 (defun ibuffer-recompile-formats ()
   "Recompile `ibuffer-formats'."
   (interactive)
   (setq ibuffer-compiled-formats
 (defun ibuffer-recompile-formats ()
   "Recompile `ibuffer-formats'."
   (interactive)
   (setq ibuffer-compiled-formats
-         (mapcar #'ibuffer-compile-format ibuffer-formats))
+       (mapcar #'ibuffer-compile-format ibuffer-formats))
   (when (boundp 'ibuffer-filter-format-alist)
     (setq ibuffer-compiled-filter-formats
          (mapcar #'(lambda (entry)
   (when (boundp 'ibuffer-filter-format-alist)
     (setq ibuffer-compiled-filter-formats
          (mapcar #'(lambda (entry)
@@ -1562,7 +1635,7 @@ If point is on a group name, this function operates on that group."
     (ibuffer-awhen (and (consp form)
                        (get (car form) 'ibuffer-column-summarizer))
       (put (car form) 'ibuffer-column-summary nil))))
     (ibuffer-awhen (and (consp form)
                        (get (car form) 'ibuffer-column-summarizer))
       (put (car form) 'ibuffer-column-summary nil))))
-  
+
 (defun ibuffer-check-formats ()
   (when (null ibuffer-formats)
     (error "No formats!"))
 (defun ibuffer-check-formats ()
   (when (null ibuffer-formats)
     (error "No formats!"))
@@ -1574,7 +1647,7 @@ If point is on a group name, this function operates on that group."
              (not (equal ibuffer-cached-eliding-string ibuffer-eliding-string))
              (eql 0 ibuffer-cached-elide-long-columns)
              (not (eql ibuffer-cached-elide-long-columns
              (not (equal ibuffer-cached-eliding-string ibuffer-eliding-string))
              (eql 0 ibuffer-cached-elide-long-columns)
              (not (eql ibuffer-cached-elide-long-columns
-                       ibuffer-elide-long-columns))
+                       (with-no-warnings ibuffer-elide-long-columns)))
              (and ext-loaded
                   (not (eq ibuffer-cached-filter-formats
                            ibuffer-filter-format-alist))
              (and ext-loaded
                   (not (eq ibuffer-cached-filter-formats
                            ibuffer-filter-format-alist))
@@ -1584,7 +1657,7 @@ If point is on a group name, this function operates on that group."
       (ibuffer-recompile-formats)
       (setq ibuffer-cached-formats ibuffer-formats
            ibuffer-cached-eliding-string ibuffer-eliding-string
       (ibuffer-recompile-formats)
       (setq ibuffer-cached-formats ibuffer-formats
            ibuffer-cached-eliding-string ibuffer-eliding-string
-           ibuffer-cached-elide-long-columns ibuffer-elide-long-columns)
+           ibuffer-cached-elide-long-columns (with-no-warnings ibuffer-elide-long-columns))
       (when ext-loaded
        (setq ibuffer-cached-filter-formats ibuffer-filter-format-alist))
       (message "Formats have changed, recompiling...done"))))
       (when ext-loaded
        (setq ibuffer-cached-filter-formats ibuffer-filter-format-alist))
       (message "Formats have changed, recompiling...done"))))
@@ -1596,7 +1669,7 @@ If point is on a group name, this function operates on that group."
 
 (define-ibuffer-column read-only (:name "R" :inline t)
   (if buffer-read-only
 
 (define-ibuffer-column read-only (:name "R" :inline t)
   (if buffer-read-only
-      "%"
+      (string ibuffer-read-only-char)
     " "))
 
 (define-ibuffer-column modified (:name "M" :inline t)
     " "))
 
 (define-ibuffer-column modified (:name "M" :inline t)
@@ -1604,48 +1677,106 @@ If point is on a group name, this function operates on that group."
       (string ibuffer-modified-char)
     " "))
 
       (string ibuffer-modified-char)
     " "))
 
-(define-ibuffer-column name (:inline t
-                            :props
-                            ('mouse-face 'highlight 'keymap ibuffer-name-map
-                             'ibuffer-name-column t
-                             'help-echo "mouse-1: mark this buffer\nmouse-2: select this buffer\nmouse-3: operate on this buffer"))
+(define-ibuffer-column name
+  (:inline t
+   :header-mouse-map ibuffer-name-header-map
+   :props
+   ('mouse-face 'highlight 'keymap ibuffer-name-map
+               'ibuffer-name-column t
+               'help-echo '(if tooltip-mode
+                               "mouse-1: mark this buffer\nmouse-2: select this buffer\nmouse-3: operate on this buffer"
+                             "mouse-1: mark buffer   mouse-2: select buffer   mouse-3: operate"))
+   :summarizer
+   (lambda (strings)
+     (let ((bufs (length strings)))
+       (cond ((zerop bufs) "No buffers")
+            ((= 1 bufs) "1 buffer")
+            (t (format "%s buffers" bufs))))))
   (propertize (buffer-name) 'font-lock-face (ibuffer-buffer-name-face buffer mark)))
   (propertize (buffer-name) 'font-lock-face (ibuffer-buffer-name-face buffer mark)))
-  
-(define-ibuffer-column size (:inline t)
+
+(define-ibuffer-column size
+  (:inline t
+   :header-mouse-map ibuffer-size-header-map
+   :summarizer
+   (lambda (column-strings)
+     (let ((total 0))
+       (dolist (string column-strings)
+        (setq total
+              ;; like, ewww ...
+              (+ (float (string-to-number string))
+                 total)))
+       (format "%.0f" total))))
   (format "%s" (buffer-size)))
 
   (format "%s" (buffer-size)))
 
-(define-ibuffer-column mode (:inline t
-                            :props
-                            ('mouse-face 'highlight
-                             'keymap ibuffer-mode-name-map
-                             'help-echo "mouse-2: filter by this mode"))
+(define-ibuffer-column mode
+  (:inline t
+   :header-mouse-map ibuffer-mode-header-map
+   :props
+   ('mouse-face 'highlight
+               'keymap ibuffer-mode-name-map
+               'help-echo "mouse-2: filter by this mode"))
   (format "%s" mode-name))
 
   (format "%s" mode-name))
 
-(define-ibuffer-column process ()
+(define-ibuffer-column process
+  (:summarizer
+   (lambda (strings)
+     (let ((total (length (delete "" strings))))
+       (cond ((zerop total) "No processes")
+            ((= 1 total) "1 process")
+            (t (format "%d processes" total))))))
   (ibuffer-aif (get-buffer-process buffer)
       (format "(%s %s)" it (process-status it))
   (ibuffer-aif (get-buffer-process buffer)
       (format "(%s %s)" it (process-status it))
-    "none"))
-
-(define-ibuffer-column filename ()
+    ""))
+
+(define-ibuffer-column filename
+  (:summarizer
+   (lambda (strings)
+     (let ((total (length (delete "" strings))))
+       (cond ((zerop total) "No files")
+            ((= 1 total) "1 file")
+            (t (format "%d files" total))))))
   (let ((directory-abbrev-alist ibuffer-directory-abbrev-alist))
     (abbreviate-file-name
      (or buffer-file-name
         (and (boundp 'dired-directory)
   (let ((directory-abbrev-alist ibuffer-directory-abbrev-alist))
     (abbreviate-file-name
      (or buffer-file-name
         (and (boundp 'dired-directory)
-             dired-directory)
+             (if (stringp dired-directory)
+                 dired-directory
+               (car dired-directory)))
         ""))))
 
         ""))))
 
-(define-ibuffer-column filename-and-process (:name "Filename/Process")
+(define-ibuffer-column filename-and-process
+  (:name "Filename/Process"
+   :summarizer
+   (lambda (strings)
+     (setq strings (delete "" strings))
+     (let ((procs 0)
+          (files 0))
+       (dolist (string strings)
+        (if (string-match "\\(\?:\\`(\[\[:ascii:\]\]\+)\\)" string)
+            (progn (setq procs (1+ procs))
+                   (if (< (match-end 0) (length string))
+                       (setq files (1+ files))))
+          (setq files (1+ files))))
+       (concat (cond ((zerop files) "No files")
+                    ((= 1 files) "1 file")
+                    (t (format "%d files" files)))
+              ", "
+              (cond ((zerop procs) "no processes")
+                    ((= 1 procs) "1 process")
+                    (t (format "%d processes" procs)))))))
   (let ((proc (get-buffer-process buffer))
        (filename (ibuffer-make-column-filename buffer mark)))
     (if proc
   (let ((proc (get-buffer-process buffer))
        (filename (ibuffer-make-column-filename buffer mark)))
     (if proc
-       (concat (propertize (format "(%s %s) " proc (process-status proc))
+       (concat (propertize (format "(%s %s)" proc (process-status proc))
                            'font-lock-face 'italic)
                            'font-lock-face 'italic)
-               filename)
+               (if (> (length filename) 0)
+                   (format " %s" filename)
+                 ""))
       filename)))
 
 (defun ibuffer-format-column (str width alignment)
       filename)))
 
 (defun ibuffer-format-column (str width alignment)
-  (let ((left (make-string (/ width 2) ? ))
-       (right (make-string (- width (/ width 2)) ? )))
+  (let ((left (make-string (/ width 2) ?\s))
+       (right (make-string (- width (/ width 2)) ?\s)))
     (case alignment
       (:right (concat left right str))
       (:center (concat left str right))
     (case alignment
       (:right (concat left right str))
       (:center (concat left str right))
@@ -1694,7 +1825,7 @@ If point is on a group name, this function operates on that group."
             (ibuffer-current-format)))
          (when ibuffer-shrink-to-minimum-size
            (ibuffer-shrink-to-fit)))))))
             (ibuffer-current-format)))
          (when ibuffer-shrink-to-minimum-size
            (ibuffer-shrink-to-fit)))))))
-   
+
 (defun ibuffer-map-on-mark (mark func)
   (ibuffer-map-lines
    #'(lambda (buf mk)
 (defun ibuffer-map-on-mark (mark func)
   (ibuffer-map-lines
    #'(lambda (buf mk)
@@ -1704,13 +1835,13 @@ If point is on a group name, this function operates on that group."
 
 (defun ibuffer-map-lines (function &optional nomodify group)
   "Call FUNCTION for each buffer.
 
 (defun ibuffer-map-lines (function &optional nomodify group)
   "Call FUNCTION for each buffer.
-Don't set the ibuffer modification flag iff NOMODIFY is non-nil.
+Set the ibuffer modification flag unless NOMODIFY is non-nil.
 
 If optional argument GROUP is non-nil, then only call FUNCTION on
 buffers in filtering group GROUP.
 
 
 If optional argument GROUP is non-nil, then only call FUNCTION on
 buffers in filtering group GROUP.
 
- FUNCTION is called with four arguments: the buffer object itself, the
-current mark symbol, and the beginning and ending line positions."
+FUNCTION is called with two arguments:
+the buffer object itself and the current mark symbol."
   (assert (eq major-mode 'ibuffer-mode))
   (ibuffer-forward-line 0)
   (let* ((orig-target-line (1+ (count-lines (save-excursion
   (assert (eq major-mode 'ibuffer-mode))
   (ibuffer-forward-line 0)
   (let* ((orig-target-line (1+ (count-lines (save-excursion
@@ -1725,7 +1856,7 @@ current mark symbol, and the beginning and ending line positions."
        (progn
          (setq buffer-read-only nil)
          (goto-char (point-min))
        (progn
          (setq buffer-read-only nil)
          (goto-char (point-min))
-         (ibuffer-forward-line 0 t)      
+         (ibuffer-forward-line 0 t)
          (while (and (not (eobp))
                      (not (get-text-property (point) 'ibuffer-summary))
                      (progn
          (while (and (not (eobp))
                      (not (get-text-property (point) 'ibuffer-summary))
                      (progn
@@ -1755,7 +1886,7 @@ current mark symbol, and the beginning and ending line positions."
                                    (1+ (line-end-position)))
                     (incf ibuffer-map-lines-count)
                     (when (< ibuffer-map-lines-total
                                    (1+ (line-end-position)))
                     (incf ibuffer-map-lines-count)
                     (when (< ibuffer-map-lines-total
-                              orig-target-line)
+                             orig-target-line)
                       (decf target-line-offset)))
                    (t
                     (incf ibuffer-map-lines-count)
                       (decf target-line-offset)))
                    (t
                     (incf ibuffer-map-lines-count)
@@ -1801,7 +1932,7 @@ the value of point at the beginning of the line for that buffer."
     (mapcar #'(lambda (buf) (let ((e (assq buf bufs)))
                              (if e
                                  e
     (mapcar #'(lambda (buf) (let ((e (assq buf bufs)))
                              (if e
                                  e
-                               (cons buf ? ))))
+                               (cons buf ?\s))))
            curbufs)))
 
 (defun ibuffer-buf-matches-predicates (buf predicates)
            curbufs)))
 
 (defun ibuffer-buf-matches-predicates (buf predicates)
@@ -1813,7 +1944,7 @@ the value of point at the beginning of the line for that buffer."
              (funcall pred buf))
        (setq hit t)))
     hit))
              (funcall pred buf))
        (setq hit t)))
     hit))
-  
+
 (defun ibuffer-filter-buffers (ibuffer-buf last bmarklist all)
   (let ((ext-loaded (featurep 'ibuf-ext)))
     (delq nil
 (defun ibuffer-filter-buffers (ibuffer-buf last bmarklist all)
   (let ((ext-loaded (featurep 'ibuf-ext)))
     (delq nil
@@ -1824,11 +1955,11 @@ the value of point at the beginning of the line for that buffer."
                 (when
                     ;; This takes precedence over anything else
                     (or (and ibuffer-always-show-last-buffer
                 (when
                     ;; This takes precedence over anything else
                     (or (and ibuffer-always-show-last-buffer
-                               (eq last buf))
-                          (funcall (if ext-loaded
-                                       #'ibuffer-ext-visible-p
-                                     #'ibuffer-visible-p)
-                                   buf all ibuffer-buf))
+                             (eq last buf))
+                        (funcall (if ext-loaded
+                                     #'ibuffer-ext-visible-p
+                                   #'ibuffer-visible-p)
+                                 buf all ibuffer-buf))
                   e)))
           bmarklist))))
 
                   e)))
           bmarklist))))
 
@@ -1837,16 +1968,16 @@ the value of point at the beginning of the line for that buffer."
           (not
            (ibuffer-buf-matches-predicates buf ibuffer-maybe-show-predicates)))
        (or ibuffer-view-ibuffer
           (not
            (ibuffer-buf-matches-predicates buf ibuffer-maybe-show-predicates)))
        (or ibuffer-view-ibuffer
-          (and ibuffer-buf 
+          (and ibuffer-buf
                (not (eq ibuffer-buf buf))))))
 
 ;; This function is a special case; it's not defined by
                (not (eq ibuffer-buf buf))))))
 
 ;; This function is a special case; it's not defined by
-;; `ibuffer-define-sorter'.
+;; `define-ibuffer-sorter'.
 (defun ibuffer-do-sort-by-recency ()
   "Sort the buffers by last view time."
   (interactive)
   (setq ibuffer-sorting-mode 'recency)
 (defun ibuffer-do-sort-by-recency ()
   "Sort the buffers by last view time."
   (interactive)
   (setq ibuffer-sorting-mode 'recency)
-  (ibuffer-redisplay t))
+  (ibuffer-update nil t))
 
 (defun ibuffer-update-format ()
   (when (null ibuffer-current-format)
 
 (defun ibuffer-update-format ()
   (when (null ibuffer-current-format)
@@ -1889,17 +2020,23 @@ the value of point at the beginning of the line for that buffer."
                    (min (cadr element))
                    ;; (max (caddr element))
                    (align (cadddr element)))
                    (min (cadr element))
                    ;; (max (caddr element))
                    (align (cadddr element)))
-              ;; Ignore a negative min when we're inserting the title
+               ;; Ignore a negative min when we're inserting the title
                (when (minusp min)
                  (setq min (- min)))
                (let* ((name (or (get sym 'ibuffer-column-name)
                                 (error "Unknown column %s in ibuffer-formats" sym)))
                (when (minusp min)
                  (setq min (- min)))
                (let* ((name (or (get sym 'ibuffer-column-name)
                                 (error "Unknown column %s in ibuffer-formats" sym)))
-                      (len (length name)))
-                 (if (< len min)
-                     (ibuffer-format-column name
-                                            (- min len)
-                                            align)
-                   name))))))
+                      (len (length name))
+                      (hmap (get sym 'header-mouse-map))
+                      (strname (if (< len min)
+                                   (ibuffer-format-column name
+                                                          (- min len)
+                                                          align)
+                                 name)))
+                 (when hmap
+                   (setq
+                    strname 
+                    (propertize strname 'mouse-face 'highlight 'keymap hmap)))
+                 strname)))))
         (add-text-properties opos (point) `(ibuffer-title-header t))
         (insert "\n")
         ;; Add the underlines
         (add-text-properties opos (point) `(ibuffer-title-header t))
         (insert "\n")
         ;; Add the underlines
@@ -1909,10 +2046,10 @@ the value of point at the beginning of the line for that buffer."
                      (buffer-substring (point) (line-end-position)))))
           (apply #'insert (mapcar
                            #'(lambda (c)
                      (buffer-substring (point) (line-end-position)))))
           (apply #'insert (mapcar
                            #'(lambda (c)
-                               (if (not (or (char-equal c ? )
+                               (if (not (or (char-equal c ?\s)
                                             (char-equal c ?\n)))
                                    ?-
                                             (char-equal c ?\n)))
                                    ?-
-                                 ? ))
+                                 ?\s))
                            str)))
         (insert "\n"))
        (point))
                            str)))
         (insert "\n"))
        (point))
@@ -1923,34 +2060,35 @@ the value of point at the beginning of the line for that buffer."
        (delete-region (previous-single-property-change
                        (point-max) 'ibuffer-summary)
                       (point-max)))
        (delete-region (previous-single-property-change
                        (point-max) 'ibuffer-summary)
                       (point-max)))
-    (add-text-properties
-     (point)
-     (progn
-       (insert "\n")
-       (dolist (element format)
-        (insert
-         (if (stringp element)
-             (make-string (length element) ? )
-           (let ((sym (car element)))
-             (let ((min (cadr element))
-                   ;; (max (caddr element))
-                   (align (cadddr element)))
-               ;; Ignore a negative min when we're inserting the title
-               (when (minusp min)
-                 (setq min (- min)))
-               (let* ((summary (if (get sym 'ibuffer-column-summarizer)
-                                   (funcall (get sym 'ibuffer-column-summarizer)
-                                            (get sym 'ibuffer-column-summary))
-                                 (make-string (length (get sym 'ibuffer-column-name))
-                                              ? )))
-                      (len (length summary)))
-                 (if (< len min)
-                     (ibuffer-format-column summary
-                                            (- min len)
-                                            align)
-                   summary)))))))
-       (point))
-     `(ibuffer-summary t))))
+    (if ibuffer-display-summary
+       (add-text-properties
+        (point)
+        (progn
+          (insert "\n")
+          (dolist (element format)
+            (insert
+             (if (stringp element)
+                 (make-string (length element) ?\s)
+               (let ((sym (car element)))
+                 (let ((min (cadr element))
+                       ;; (max (caddr element))
+                       (align (cadddr element)))
+                   ;; Ignore a negative min when we're inserting the title
+                   (when (minusp min)
+                     (setq min (- min)))
+                   (let* ((summary (if (get sym 'ibuffer-column-summarizer)
+                                       (funcall (get sym 'ibuffer-column-summarizer)
+                                                (get sym 'ibuffer-column-summary))
+                                     (make-string (length (get sym 'ibuffer-column-name))
+                                                  ?\s)))
+                          (len (length summary)))
+                     (if (< len min)
+                         (ibuffer-format-column summary
+                                                (- min len)
+                                                align)
+                       summary)))))))
+          (point))
+        `(ibuffer-summary t)))))
 
 (defun ibuffer-update-mode-name ()
   (setq mode-name (format "Ibuffer by %s" (if ibuffer-sorting-mode
 
 (defun ibuffer-update-mode-name ()
   (setq mode-name (format "Ibuffer by %s" (if ibuffer-sorting-mode
@@ -1999,11 +2137,15 @@ If optional arg SILENT is non-nil, do not display progress messages."
 
 (defun ibuffer-update (arg &optional silent)
   "Regenerate the list of all buffers.
 
 (defun ibuffer-update (arg &optional silent)
   "Regenerate the list of all buffers.
-Display buffers whose name matches one of `ibuffer-maybe-show-predicates'
-iff arg ARG is non-nil.  
+
+Prefix arg non-nil means to toggle whether buffers that match
+`ibuffer-maybe-show-predicates' should be displayed.
 
 If optional arg SILENT is non-nil, do not display progress messages."
   (interactive "P")
 
 If optional arg SILENT is non-nil, do not display progress messages."
   (interactive "P")
+  (if arg
+      (setq ibuffer-display-maybe-show-predicates
+           (not ibuffer-display-maybe-show-predicates)))
   (ibuffer-forward-line 0)
   (let* ((bufs (buffer-list))
         (blist (ibuffer-filter-buffers
   (ibuffer-forward-line 0)
   (let* ((bufs (buffer-list))
         (blist (ibuffer-filter-buffers
@@ -2016,7 +2158,7 @@ If optional arg SILENT is non-nil, do not display progress messages."
                     (caddr bufs)
                   (cadr bufs))
                 (ibuffer-current-buffers-with-marks bufs)
                     (caddr bufs)
                   (cadr bufs))
                 (ibuffer-current-buffers-with-marks bufs)
-                arg)))
+                ibuffer-display-maybe-show-predicates)))
     (when (null blist)
       (if (and (featurep 'ibuf-ext)
               ibuffer-filtering-qualifiers)
     (when (null blist)
       (if (and (featurep 'ibuf-ext)
               ibuffer-filtering-qualifiers)
@@ -2059,7 +2201,14 @@ If optional arg SILENT is non-nil, do not display progress messages."
      font-lock-face ,ibuffer-filter-group-name-face
      keymap ,ibuffer-mode-filter-group-map
      mouse-face highlight
      font-lock-face ,ibuffer-filter-group-name-face
      keymap ,ibuffer-mode-filter-group-map
      mouse-face highlight
-     help-echo ,(concat filter-string "mouse-1: toggle marks in this group\nmouse-2: hide/show this filtering group ")))
+     help-echo ,(let ((echo '(if tooltip-mode
+                                "mouse-1: toggle marks in this group\nmouse-2: hide/show this filtering group"
+                              "mouse-1: toggle marks  mouse-2: hide/show")))
+                 (if (> (length filter-string) 0)
+                     `(concat ,filter-string
+                              (if tooltip-mode "\n" " ")
+                              ,echo)
+                   echo))))
   (insert "\n")
   (when bmarklist
     (put-text-property
   (insert "\n")
   (when bmarklist
     (put-text-property
@@ -2071,7 +2220,7 @@ If optional arg SILENT is non-nil, do not display progress messages."
      'ibuffer-filter-group
      name)))
 
      'ibuffer-filter-group
      name)))
 
-(defun ibuffer-redisplay-engine (bmarklist &optional all)
+(defun ibuffer-redisplay-engine (bmarklist &optional ignore)
   (assert (eq major-mode 'ibuffer-mode))
   (let* ((--ibuffer-insert-buffers-and-marks-format
          (ibuffer-current-format))
   (assert (eq major-mode 'ibuffer-mode))
   (let* ((--ibuffer-insert-buffers-and-marks-format
          (ibuffer-current-format))
@@ -2097,6 +2246,7 @@ If optional arg SILENT is non-nil, do not display progress messages."
                                  (member name ibuffer-hidden-filter-groups)))
                   (bmarklist (cdr group)))
              (unless (and (null bmarklist)
                                  (member name ibuffer-hidden-filter-groups)))
                   (bmarklist (cdr group)))
              (unless (and (null bmarklist)
+                          (not disabled)
                           ext-loaded
                           (null ibuffer-show-empty-filter-groups))
                (ibuffer-insert-filter-group
                           ext-loaded
                           (null ibuffer-show-empty-filter-groups))
                (ibuffer-insert-filter-group
@@ -2117,13 +2267,14 @@ If optional arg SILENT is non-nil, do not display progress messages."
 
 (defun ibuffer-quit ()
   "Quit this `ibuffer' session.
 
 (defun ibuffer-quit ()
   "Quit this `ibuffer' session.
-Delete the current window iff `ibuffer-delete-window-on-quit' is non-nil."
+Try to restore the previous window configuration if
+`ibuffer-restore-window-config-on-quit' is non-nil."
   (interactive)
   (interactive)
-  (if ibuffer-delete-window-on-quit
+  (if ibuffer-restore-window-config-on-quit
       (progn
        (bury-buffer)
        (unless (= (count-windows) 1)
       (progn
        (bury-buffer)
        (unless (= (count-windows) 1)
-         (delete-window)))
+         (set-window-configuration ibuffer-prev-window-config)))
     (bury-buffer)))
 
 ;;;###autoload
     (bury-buffer)))
 
 ;;;###autoload
@@ -2147,28 +2298,27 @@ buffers which are visiting a file."
 ;;;###autoload
 (defun ibuffer (&optional other-window-p name qualifiers noselect
                          shrink filter-groups formats)
 ;;;###autoload
 (defun ibuffer (&optional other-window-p name qualifiers noselect
                          shrink filter-groups formats)
-  "Begin using `ibuffer' to edit a list of buffers.
+  "Begin using Ibuffer to edit a list of buffers.
 Type 'h' after entering ibuffer for more information.
 
 Type 'h' after entering ibuffer for more information.
 
-Optional argument OTHER-WINDOW-P says to use another window.
-Optional argument NAME specifies the name of the buffer; it defaults
-to \"*Ibuffer*\".
-Optional argument QUALIFIERS is an initial set of filtering qualifiers
-to use; see `ibuffer-filtering-qualifiers'.
-Optional argument NOSELECT means don't select the Ibuffer buffer.
-Optional argument SHRINK means shrink the buffer to minimal size.  The
-special value `onewindow' means always use another window.
-Optional argument FILTER-GROUPS is an initial set of filtering
-groups to use; see `ibuffer-filter-groups'.
-Optional argument FORMATS is the value to use for `ibuffer-formats'.
-If specified, then the variable `ibuffer-formats' will have that value
-locally in this buffer."
+All arguments are optional.
+OTHER-WINDOW-P says to use another window.
+NAME specifies the name of the buffer (defaults to \"*Ibuffer*\").
+QUALIFIERS is an initial set of filtering qualifiers to use;
+  see `ibuffer-filtering-qualifiers'.
+NOSELECT means don't select the Ibuffer buffer.
+SHRINK means shrink the buffer to minimal size.  The special
+  value `onewindow' means always use another window.
+FILTER-GROUPS is an initial set of filtering groups to use;
+  see `ibuffer-filter-groups'.
+FORMATS is the value to use for `ibuffer-formats'.
+  If specified, then the variable `ibuffer-formats' will have
+  that value locally in this buffer."
   (interactive "P")
   (when ibuffer-use-other-window
     (setq other-window-p t))
   (interactive "P")
   (when ibuffer-use-other-window
     (setq other-window-p t))
-  (let* ((buf (get-buffer-create (or name "*Ibuffer*")))
-        (already-in (eq (current-buffer) buf))
-        (need-update nil))
+  (setq ibuffer-prev-window-config (current-window-configuration))
+  (let ((buf (get-buffer-create (or name "*Ibuffer*"))))
     (if other-window-p
        (funcall (if noselect #'(lambda (buf) (display-buffer buf t)) #'pop-to-buffer) buf)
       (funcall (if noselect #'display-buffer #'switch-to-buffer) buf))
     (if other-window-p
        (funcall (if noselect #'(lambda (buf) (display-buffer buf t)) #'pop-to-buffer) buf)
       (funcall (if noselect #'display-buffer #'switch-to-buffer) buf))
@@ -2176,11 +2326,10 @@ locally in this buffer."
       (save-selected-window
        ;; We switch to the buffer's window in order to be able
        ;; to modify the value of point
       (save-selected-window
        ;; We switch to the buffer's window in order to be able
        ;; to modify the value of point
-       (select-window (get-buffer-window buf))
-       (unless (eq major-mode 'ibuffer-mode)
-         (ibuffer-mode)
-         (setq need-update t))
-       (setq ibuffer-delete-window-on-quit other-window-p)
+       (select-window (get-buffer-window buf 0))
+       (or (eq major-mode 'ibuffer-mode)
+           (ibuffer-mode))
+       (setq ibuffer-restore-window-config-on-quit other-window-p)
        (when shrink
          (setq ibuffer-shrink-to-minimum-size shrink))
        (when qualifiers
        (when shrink
          (setq ibuffer-shrink-to-minimum-size shrink))
        (when qualifiers
@@ -2205,7 +2354,7 @@ locally in this buffer."
 (put 'ibuffer-mode 'mode-class 'special)
 (defun ibuffer-mode ()
   "A major mode for viewing a list of buffers.
 (put 'ibuffer-mode 'mode-class 'special)
 (defun ibuffer-mode ()
   "A major mode for viewing a list of buffers.
-In ibuffer, you can conveniently perform many operations on the
+In Ibuffer, you can conveniently perform many operations on the
 currently open buffers, in addition to filtering your view to a
 particular subset of them, and sorting by various criteria.
 
 currently open buffers, in addition to filtering your view to a
 particular subset of them, and sorting by various criteria.
 
@@ -2296,7 +2445,7 @@ Filter group commands:
   '\\[ibuffer-save-filter-groups]' - Save the current groups with a name.
   '\\[ibuffer-switch-to-saved-filter-groups]' - Restore previously saved groups.
   '\\[ibuffer-delete-saved-filter-groups]' - Delete previously saved groups.
   '\\[ibuffer-save-filter-groups]' - Save the current groups with a name.
   '\\[ibuffer-switch-to-saved-filter-groups]' - Restore previously saved groups.
   '\\[ibuffer-delete-saved-filter-groups]' - Delete previously saved groups.
-    
+
 Sorting commands:
 
   '\\[ibuffer-toggle-sorting-mode]' - Rotate between the various sorting modes.
 Sorting commands:
 
   '\\[ibuffer-toggle-sorting-mode]' - Rotate between the various sorting modes.
@@ -2308,10 +2457,13 @@ Sorting commands:
 
 Other commands:
 
 
 Other commands:
 
+  '\\[ibuffer-update]' - Regenerate the list of all buffers.
+          Prefix arg means to toggle whether buffers that match
+          `ibuffer-maybe-show-predicates' should be displayed.
+
   '\\[ibuffer-switch-format]' - Change the current display format.
   '\\[forward-line]' - Move point to the next line.
   '\\[previous-line]' - Move point to the previous line.
   '\\[ibuffer-switch-format]' - Change the current display format.
   '\\[forward-line]' - Move point to the next line.
   '\\[previous-line]' - Move point to the previous line.
-  '\\[ibuffer-update]' - As above, but add new buffers to the list.
   '\\[ibuffer-quit]' - Bury the Ibuffer buffer.
   '\\[describe-mode]' - This help.
   '\\[ibuffer-diff-with-file]' - View the differences between this buffer
   '\\[ibuffer-quit]' - Bury the Ibuffer buffer.
   '\\[describe-mode]' - This help.
   '\\[ibuffer-diff-with-file]' - View the differences between this buffer
@@ -2387,6 +2539,9 @@ will be inserted before the group at point."
   ;; This makes things less ugly for Emacs 21 users with a non-nil
   ;; `show-trailing-whitespace'.
   (setq show-trailing-whitespace nil)
   ;; This makes things less ugly for Emacs 21 users with a non-nil
   ;; `show-trailing-whitespace'.
   (setq show-trailing-whitespace nil)
+  ;; disable `show-paren-mode' buffer-locally
+  (if (bound-and-true-p show-paren-mode)
+      (set (make-local-variable 'show-paren-mode) nil))
   (set (make-local-variable 'revert-buffer-function)
        #'ibuffer-update)
   (set (make-local-variable 'ibuffer-sorting-mode)
   (set (make-local-variable 'revert-buffer-function)
        #'ibuffer-update)
   (set (make-local-variable 'ibuffer-sorting-mode)
@@ -2395,6 +2550,8 @@ will be inserted before the group at point."
        ibuffer-default-sorting-reversep)
   (set (make-local-variable 'ibuffer-shrink-to-minimum-size)
        ibuffer-default-shrink-to-minimum-size)
        ibuffer-default-sorting-reversep)
   (set (make-local-variable 'ibuffer-shrink-to-minimum-size)
        ibuffer-default-shrink-to-minimum-size)
+  (set (make-local-variable 'ibuffer-display-maybe-show-predicates)
+       ibuffer-default-display-maybe-show-predicates)
   (set (make-local-variable 'ibuffer-filtering-qualifiers) nil)
   (set (make-local-variable 'ibuffer-filter-groups) nil)
   (set (make-local-variable 'ibuffer-filter-group-kill-ring) nil)
   (set (make-local-variable 'ibuffer-filtering-qualifiers) nil)
   (set (make-local-variable 'ibuffer-filter-groups) nil)
   (set (make-local-variable 'ibuffer-filter-group-kill-ring) nil)
@@ -2404,8 +2561,7 @@ will be inserted before the group at point."
   (set (make-local-variable 'ibuffer-cached-eliding-string) nil)
   (set (make-local-variable 'ibuffer-cached-elide-long-columns) nil)
   (set (make-local-variable 'ibuffer-current-format) nil)
   (set (make-local-variable 'ibuffer-cached-eliding-string) nil)
   (set (make-local-variable 'ibuffer-cached-elide-long-columns) nil)
   (set (make-local-variable 'ibuffer-current-format) nil)
-  (set (make-local-variable 'ibuffer-did-modifiction) nil)
-  (set (make-local-variable 'ibuffer-delete-window-on-quit) nil)
+  (set (make-local-variable 'ibuffer-restore-window-config-on-quit) nil)
   (set (make-local-variable 'ibuffer-did-modification) nil)
   (set (make-local-variable 'ibuffer-tmp-hide-regexps) nil)
   (set (make-local-variable 'ibuffer-tmp-show-regexps) nil)
   (set (make-local-variable 'ibuffer-did-modification) nil)
   (set (make-local-variable 'ibuffer-tmp-hide-regexps) nil)
   (set (make-local-variable 'ibuffer-tmp-show-regexps) nil)
@@ -2415,14 +2571,17 @@ will be inserted before the group at point."
   (when ibuffer-default-directory
     (setq default-directory ibuffer-default-directory))
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
   (when ibuffer-default-directory
     (setq default-directory ibuffer-default-directory))
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
-  (run-hooks 'ibuffer-mode-hook)
+  (run-mode-hooks 'ibuffer-mode-hook)
   ;; called after mode hooks to allow the user to add filters
   (ibuffer-update-mode-name))
 
 (provide 'ibuffer)
 
   ;; called after mode hooks to allow the user to add filters
   (ibuffer-update-mode-name))
 
 (provide 'ibuffer)
 
+(run-hooks 'ibuffer-load-hook)
+
 ;; Local Variables:
 ;; coding: iso-8859-1
 ;; End:
 
 ;; Local Variables:
 ;; coding: iso-8859-1
 ;; End:
 
+;;; arch-tag: 72581688-0603-4954-b8cf-837c700f62e8
 ;;; ibuffer.el ends here
 ;;; ibuffer.el ends here