X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/943949149f666ddd4569f12f620059176eb9b777..04ec34141ff9216131130a83777a2a42fde3255d:/lisp/ibuffer.el diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 3e47149809..7d6b72b06a 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -1,8 +1,10 @@ ;;; ibuffer.el --- operate on buffers like dired -;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 2000, 2001, 2002, 2003, 2004, +;; 2005 Free Software Foundation, Inc. ;; Author: Colin Walters +;; Maintainer: John Paul Wallington ;; Created: 8 Sep 2000 ;; Keywords: buffer, convenience @@ -20,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 -;; 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: @@ -36,17 +38,22 @@ (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'. @@ -54,10 +61,11 @@ 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) -(defcustom ibuffer-formats '((mark modified read-only " " (name 16 16 :left :elide) - " " (size 6 -1 :right) +(defcustom ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide) + " " (size 9 -1 :right) " " (mode 16 16 :right :elide) " " filename-and-process) (mark " " (name 16 -1) " " filename)) "A list of ways to display buffer lines. @@ -135,7 +143,9 @@ elisp byte-compiler." (defcustom ibuffer-fontification-alist `((10 buffer-read-only font-lock-constant-face) (15 (string-match "^*" (buffer-name)) font-lock-keyword-face) - (20 (string-match "^ " (buffer-name)) font-lock-warning-face) + (20 (and (string-match "^ " (buffer-name)) + (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)) "An alist describing how to fontify buffers. @@ -145,7 +155,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. -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") @@ -154,7 +164,7 @@ recreate it for the change to take effect." :group 'ibuffer) (defcustom ibuffer-use-other-window nil - "If non-nil, display the Ibuffer in another window by default." + "If non-nil, display Ibuffer in another window by default." :type 'boolean :group 'ibuffer) @@ -164,6 +174,11 @@ recreate it for the change to take effect." :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 @@ -177,8 +192,8 @@ recreate it for the change to take effect." (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) @@ -194,11 +209,12 @@ view of the buffers." (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) +(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." @@ -208,17 +224,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)))) - "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. -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) +(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 @@ -260,22 +286,27 @@ state, size, etc." :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) +(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. -This feature only works on Emacs 21 or later." + "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'." @@ -283,23 +314,30 @@ directory, like `default-directory'." 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) (defcustom ibuffer-hook nil - "Hooks run when `ibuffer' is called." + "Hook run when `ibuffer' is called." :type 'hook :group 'ibuffer) -(defvaralias 'ibuffer-hooks 'ibuffer-hook) +(define-obsolete-variable-alias 'ibuffer-hooks + 'ibuffer-hook "22.1") (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) -(defvaralias 'ibuffer-mode-hooks 'ibuffer-mode-hook) (defcustom ibuffer-marked-face 'font-lock-warning-face "Face used for displaying marked buffers." @@ -329,6 +367,7 @@ directory, like `default-directory'." (regexp :tag "To"))) :group 'ibuffer) + (defvar ibuffer-mode-map nil) (defvar ibuffer-mode-operate-map nil) (defvar ibuffer-mode-groups-popup nil) @@ -352,6 +391,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 "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) @@ -364,12 +404,12 @@ directory, like `default-directory'." (define-key map (kbd "* e") 'ibuffer-mark-dissociated-buffers) (define-key map (kbd "* h") 'ibuffer-mark-help-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) - + ;; immediate operations (define-key map (kbd "n") 'ibuffer-forward-line) (define-key map (kbd "") 'ibuffer-forward-line) @@ -425,7 +465,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 "q") 'ibuffer-quit) (define-key map (kbd "h") 'describe-mode) (define-key map (kbd "?") 'describe-mode) @@ -433,7 +473,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 "C-t") 'ibuffer-visit-tags-table) (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe) @@ -458,7 +498,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 "k") 'ibuffer-do-kill-lines) (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill) @@ -507,6 +547,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 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] @@ -556,7 +598,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 - :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 @@ -579,7 +621,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" - 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)) @@ -616,7 +658,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) - :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 @@ -637,8 +679,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 "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] @@ -682,10 +723,10 @@ directory, like `default-directory'." :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 mark-by-name-regexp] '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp :help "Mark buffers whose name matches a regexp")) @@ -743,51 +784,56 @@ 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")) - + (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] - '(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) - (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) - (setq ibuffer-mode-name-map map))) + 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) - (setq ibuffer-mode-filter-group-map map))) + map)) -(defvar ibuffer-mode-hooks nil) +(defvar ibuffer-restore-window-config-on-quit nil + "If non-nil, restore previous window configuration upon exiting `ibuffer'.") -(defvar ibuffer-delete-window-on-quit nil - "Whether or not to delete the window upon exiting `ibuffer'.") +(defvar ibuffer-prev-window-config nil + "Window configuration before starting Ibuffer.") (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. @@ -816,7 +862,7 @@ width and the longest string in 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))) @@ -839,7 +885,7 @@ width and the longest string in LIST." (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))) @@ -852,8 +898,8 @@ width and the longest string in LIST." 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." @@ -866,22 +912,25 @@ width and the longest string in LIST." (defun ibuffer-mouse-popup-menu (event) "Display a menu of operations." (interactive "e") - (let ((eventpt (save-excursion - (mouse-set-point event) - (point)))) + (let ((eventpt (posn-point (event-end event))) + (origpt (point))) (unwind-protect (if (get-text-property eventpt 'ibuffer-filter-group-name) - (popup-menu ibuffer-mode-groups-popup) + (progn + (goto-char eventpt) + (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))))) - (setq buffer-read-only t)))) + ;; 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) + (if (= eventpt (point)) + (goto-char origpt))))) (defun ibuffer-skip-properties (props direction) (while (and (not (eobp)) @@ -892,18 +941,23 @@ width and the longest string in LIST." (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") - (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 - (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) @@ -919,8 +973,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") - (unless arg - (setq arg 1)) + (or arg (setq arg 1)) (beginning-of-line) (when (and ibuffer-movement-cycle (or (eobp) @@ -951,7 +1004,6 @@ width and the longest string in LIST." (defun ibuffer-visit-buffer (&optional single) "Visit the buffer on this line. - If optional argument SINGLE is non-nil, then also ensure there is only one window." (interactive "P") @@ -1028,16 +1080,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))))) - (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) - (frame-height))) + (frame-height))) (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) @@ -1071,12 +1123,12 @@ a new window in the current frame, splitting vertically." (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) ;; The window might be too small to split; in that case, - ;; try a few times to increase its size before giving up. + ;; try a few times to increase its size before giving up. (let ((attempts 0) (trying t)) (while trying @@ -1088,11 +1140,11 @@ a new window in the current frame, splitting vertically." ;; 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)))))) - ;; This part doesn't work correctly sometimes under XEmacs. (select-window (next-window)) (switch-to-buffer buf) (unwind-protect @@ -1109,7 +1161,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 - #'(lambda (buf mk) + #'(lambda (buf mk) (when (char-equal mark mk) (push (buffer-name buf) ibuffer-buffer-names-with-mark-result)))) @@ -1125,7 +1177,7 @@ a new window in the current frame, splitting vertically." (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))))) @@ -1199,18 +1251,18 @@ a new window in the current frame, splitting vertically." ((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) - (ibuffer-set-mark-1 ? ) + (ibuffer-set-mark-1 ?\s) 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)) @@ -1227,9 +1279,9 @@ group." (ibuffer-map-lines #'(lambda (buf mark) (cond ((eq mark ibuffer-marked-char) - (ibuffer-set-mark-1 ? ) + (ibuffer-set-mark-1 ?\s) nil) - ((eq mark ? ) + ((eq mark ?\s) (ibuffer-set-mark-1 ibuffer-marked-char) t) (t @@ -1248,24 +1300,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") - (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") - (ibuffer-mark-interactive arg ? -1)) + (ibuffer-mark-interactive arg ?\s -1)) (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 t) + (ibuffer-forward-line 0 t) (let ((inhibit-read-only t)) (while (> arg 0) (ibuffer-set-mark mark) @@ -1332,38 +1383,38 @@ If point is on a group name, this function operates on that group." (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)) - (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)) - (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)) - + (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 @@ -1382,8 +1433,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) - (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)) @@ -1460,19 +1511,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) - (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) - ;; 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) @@ -1481,40 +1532,40 @@ If point is on a group name, this function operates on that group." (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. @@ -1536,16 +1587,11 @@ If point is on a group name, this function operates on that group." '(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 - (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) @@ -1560,7 +1606,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)))) - + (defun ibuffer-check-formats () (when (null ibuffer-formats) (error "No formats!")) @@ -1572,7 +1618,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 - ibuffer-elide-long-columns)) + (with-no-warnings ibuffer-elide-long-columns))) (and ext-loaded (not (eq ibuffer-cached-filter-formats ibuffer-filter-format-alist)) @@ -1582,7 +1628,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-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")))) @@ -1594,7 +1640,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 - "%" + (string ibuffer-read-only-char) " ")) (define-ibuffer-column modified (:name "M" :inline t) @@ -1602,48 +1648,103 @@ If point is on a group name, this function operates on that group." (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 + :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))) - -(define-ibuffer-column size (:inline t) + +(define-ibuffer-column size + (:inline t + :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))) -(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 + :props + ('mouse-face 'highlight + 'keymap ibuffer-mode-name-map + 'help-echo "mouse-2: filter by this mode")) (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)) - "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) - 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 - (concat (propertize (format "(%s %s) " proc (process-status proc)) + (concat (propertize (format "(%s %s)" proc (process-status proc)) 'font-lock-face 'italic) - filename) + (if (> (length filename) 0) + (format " %s" filename) + "")) 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)) @@ -1692,7 +1793,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))))))) - + (defun ibuffer-map-on-mark (mark func) (ibuffer-map-lines #'(lambda (buf mk) @@ -1707,8 +1808,8 @@ Don't set the ibuffer modification flag iff NOMODIFY is non-nil. 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 @@ -1723,7 +1824,7 @@ current mark symbol, and the beginning and ending line positions." (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 @@ -1753,7 +1854,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 - orig-target-line) + orig-target-line) (decf target-line-offset))) (t (incf ibuffer-map-lines-count) @@ -1799,7 +1900,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 - (cons buf ? )))) + (cons buf ?\s)))) curbufs))) (defun ibuffer-buf-matches-predicates (buf predicates) @@ -1811,7 +1912,7 @@ the value of point at the beginning of the line for that buffer." (funcall pred buf)) (setq hit t))) hit)) - + (defun ibuffer-filter-buffers (ibuffer-buf last bmarklist all) (let ((ext-loaded (featurep 'ibuf-ext))) (delq nil @@ -1822,11 +1923,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 - (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)))) @@ -1835,7 +1936,7 @@ 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 - (and ibuffer-buf + (and ibuffer-buf (not (eq ibuffer-buf buf)))))) ;; This function is a special case; it's not defined by @@ -1887,7 +1988,7 @@ the value of point at the beginning of the line for that buffer." (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) @@ -1907,10 +2008,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) - (if (not (or (char-equal c ? ) + (if (not (or (char-equal c ?\s) (char-equal c ?\n))) ?- - ? )) + ?\s)) str))) (insert "\n")) (point)) @@ -1921,34 +2022,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))) - (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 @@ -1976,10 +2078,9 @@ the value of point at the beginning of the line for that buffer." (defun ibuffer-redisplay (&optional silent) "Redisplay the current list of buffers. - This does not show new buffers; use `ibuffer-update' for that. -If SILENT is non-`nil', do not generate progress messages." +If optional arg SILENT is non-nil, do not display progress messages." (interactive) (ibuffer-forward-line 0) (unless silent @@ -1999,11 +2100,14 @@ If SILENT is non-`nil', do not generate progress messages." (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. -Do not display messages if SILENT is non-nil." +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 @@ -2012,12 +2116,11 @@ Do not display messages if SILENT is non-nil." (cadr bufs) (eq ibuffer-always-show-last-buffer :nomini) - (with-current-buffer (cadr bufs) - (minibufferp))) - (car (cddr bufs)) + (minibufferp (cadr 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) @@ -2060,7 +2163,14 @@ Do not display messages if SILENT is non-nil." 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 @@ -2072,7 +2182,7 @@ Do not display messages if SILENT is non-nil." '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)) @@ -2098,6 +2208,7 @@ Do not display messages if SILENT is non-nil." (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 @@ -2118,13 +2229,14 @@ Do not display messages if SILENT is non-nil." (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 iff +`ibuffer-restore-window-config-on-quit' is non-nil." (interactive) - (if ibuffer-delete-window-on-quit + (if ibuffer-restore-window-config-on-quit (progn (bury-buffer) (unless (= (count-windows) 1) - (delete-window))) + (set-window-configuration ibuffer-prev-window-config))) (bury-buffer))) ;;;###autoload @@ -2148,28 +2260,27 @@ buffers which are visiting a file." ;;;###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. -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)) - (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)) @@ -2178,10 +2289,9 @@ locally in this buffer." ;; 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) + (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 @@ -2198,7 +2308,7 @@ locally in this buffer." (unwind-protect (progn (setq buffer-read-only nil) - (run-hooks 'ibuffer-hooks)) + (run-hooks 'ibuffer-hook)) (setq buffer-read-only t)) (unless ibuffer-expert (message "Commands: m, u, t, RET, g, k, S, D, Q; q to quit; h for help")))))) @@ -2206,7 +2316,7 @@ locally in this buffer." (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. @@ -2297,7 +2407,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. - + Sorting commands: '\\[ibuffer-toggle-sorting-mode]' - Rotate between the various sorting modes. @@ -2388,6 +2498,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) + ;; 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) @@ -2396,6 +2509,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) + (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) @@ -2405,8 +2520,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-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) @@ -2415,14 +2529,18 @@ will be inserted before the group at point." (ibuffer-update-format) (when ibuffer-default-directory (setq default-directory ibuffer-default-directory)) - (run-hooks 'ibuffer-mode-hooks) + (add-hook 'change-major-mode-hook 'font-lock-defontify nil t) + (run-mode-hooks 'ibuffer-mode-hook) ;; 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: +;;; arch-tag: 72581688-0603-4954-b8cf-837c700f62e8 ;;; ibuffer.el ends here