;;; 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 <walters@verbum.org>
+;; Maintainer: John Paul Wallington <jpw@gnu.org>
;; Created: 8 Sep 2000
;; Keywords: buffer, convenience
;; 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:
(require 'ibuf-macs)
(require 'dired))
-;;; 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))))
-
- (cond ((boundp 'global-font-lock-mode)
- (defsubst ibuffer-use-fontification ()
- (when (boundp 'font-lock-mode)
- font-lock-mode)))
- ((boundp 'font-lock-auto-fontify)
- (defsubst ibuffer-use-fontification ()
- font-lock-auto-fontify))
- (t
- (defsubst ibuffer-use-fontification ()
- nil))))
+(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'.
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)
- " " (mode 16 16 :right :elide) " " filename)
+(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.
:group 'ibuffer)
(defcustom ibuffer-fontification-alist
- `((10 buffer-read-only font-lock-reference-face)
+ `((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.
PRIORITY is an integer, FORM is an arbitrary form to evaluate in the
buffer, and FACE is the face to use for fontification. If the FORM
evaluates to non-nil, then FACE will be put on the buffer name. The
-element with the highest PRIORITY takes precedence."
+element with the highest PRIORITY takes precedence.
+
+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")
(sexp :tag "Test Form")
: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)
: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-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)
(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."
(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
+ "If non-nil, then forward and backwards movement commands cycle."
+ :type 'boolean
+ :group 'ibuffer)
+
(defcustom ibuffer-modified-char ?*
"The character to display for modified buffers."
:type 'character
: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'."
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-hooks nil
- "Hooks run when `ibuffer' is called."
+(defcustom ibuffer-hook nil
+ "Hook run when `ibuffer' is called."
:type 'hook
:group 'ibuffer)
+(define-obsolete-variable-alias 'ibuffer-hooks
+ 'ibuffer-hook "22.1")
-(defcustom ibuffer-mode-hooks nil
- "Hooks run upon entry into `ibuffer-mode'."
+(defcustom ibuffer-mode-hook nil
+ "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)
(regexp :tag "To")))
:group 'ibuffer)
+
(defvar ibuffer-mode-map nil)
(defvar ibuffer-mode-operate-map nil)
(defvar ibuffer-mode-groups-popup nil)
(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 "* 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 "<down>") 'ibuffer-forward-line)
(define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
(define-key map (kbd "/ m") 'ibuffer-filter-by-mode)
+ (define-key map (kbd "/ M") 'ibuffer-filter-by-used-mode)
(define-key map (kbd "/ n") 'ibuffer-filter-by-name)
(define-key map (kbd "/ c") 'ibuffer-filter-by-content)
(define-key map (kbd "/ e") 'ibuffer-filter-by-predicate)
(define-key map (kbd "/ o") 'ibuffer-or-filter)
(define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group)
(define-key map (kbd "/ P") 'ibuffer-pop-filter-group)
+ (define-key map (kbd "/ D") 'ibuffer-decompose-filter-group)
(define-key map (kbd "/ /") 'ibuffer-filter-disable)
(define-key map (kbd "M-n") 'ibuffer-forward-filter-group)
(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 "% 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 "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-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]
(cons "Filter" (make-sparse-keymap "Filter")))
(define-key-after map [menu-bar view filter filter-disable]
- '(menu-item "Disable all filtering" ibuffer-filter-disable))
+ '(menu-item "Disable all filtering" ibuffer-filter-disable
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
(define-key-after map [menu-bar view filter filter-by-mode]
'(menu-item "Add filter by major mode..." ibuffer-filter-by-mode))
+ (define-key-after map [menu-bar view filter filter-by-mode]
+ '(menu-item "Add filter by major mode in use..." ibuffer-filter-by-used-mode))
(define-key-after map [menu-bar view filter filter-by-name]
'(menu-item "Add filter by buffer name..." ibuffer-filter-by-name))
(define-key-after map [menu-bar view filter filter-by-filename]
(define-key-after map [menu-bar view filter filter-by-predicate]
'(menu-item "Add filter by Lisp predicate..." ibuffer-filter-by-predicate))
(define-key-after map [menu-bar view filter pop-filter]
- '(menu-item "Remove top filter" ibuffer-pop-filter))
+ '(menu-item "Remove top filter" ibuffer-pop-filter
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
(define-key-after map [menu-bar view filter or-filter]
'(menu-item "OR top two filters" ibuffer-or-filter
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
+ (cdr ibuffer-filtering-qualifiers))
:help "Create a new filter which is the logical OR of the top two filters"))
(define-key-after map [menu-bar view filter negate-filter]
- '(menu-item "Negate top filter" ibuffer-negate-filter))
+ '(menu-item "Negate top filter" ibuffer-negate-filter
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
(define-key-after map [menu-bar view filter decompose-filter]
'(menu-item "Decompose top filter" ibuffer-decompose-filter
+ :enable (and (featurep 'ibuf-ext) (memq (car ibuffer-filtering-qualifiers) '(or saved not)))
:help "Break down a complex filter like OR or NOT"))
(define-key-after map [menu-bar view filter exchange-filters]
- '(menu-item "Swap top two filters" ibuffer-exchange-filters))
+ '(menu-item "Swap top two filters" ibuffer-exchange-filters
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
+ (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)
: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
+ :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)
:help "Replace current filters with a saved stack"))
(define-key-after map [menu-bar view filter add-saved-filters]
'(menu-item "Add to permanently saved filters..." ibuffer-add-saved-filters
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
:help "Include already saved stack with current filters"))
(define-key-after map [menu-bar view filter delete-saved-filters]
'(menu-item "Delete permanently saved filters..."
- ibuffer-delete-saved-filters))
+ ibuffer-delete-saved-filters
+ :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)))
;; Filter groups
(define-key-after groups-map [filters-to-filter-group]
'(menu-item "Create filter group from current filters..."
- ibuffer-filters-to-filter-group))
+ ibuffer-filters-to-filter-group
+ :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
(define-key-after groups-map [forward-filter-group]
'(menu-item "Move point to the next filter group"
- ibuffer-forward-filter-group))
+ 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 [pop-filter-group]
'(menu-item "Remove top filter group"
ibuffer-pop-filter-group
- :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
+ :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
(define-key-after groups-map [clear-filter-groups]
'(menu-item "Remove all filter groups"
ibuffer-clear-filter-groups
- :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
+ :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
+ (define-key-after groups-map [pop-filter-group]
+ '(menu-item "Decompose filter group..."
+ ibuffer-pop-filter-group
+ :help "\"Unmake\" a filter group"
+ :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
(define-key-after groups-map [save-filter-groups]
'(menu-item "Save current filter groups permanently..."
ibuffer-save-filter-groups
+ :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)
:help "Use a mnemnonic name to store current filter groups"))
(define-key-after groups-map [switch-to-saved-filter-groups]
'(menu-item "Restore permanently saved filters..."
ibuffer-switch-to-saved-filter-groups
- :help "Replace current filters with a saved stack"))
+ :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)
+ :help "Replace current filters with a saved stack"))
(define-key-after groups-map [delete-saved-filter-groups]
'(menu-item "Delete permanently saved filter groups..."
- ibuffer-delete-saved-filter-groups))
+ ibuffer-delete-saved-filter-groups
+ :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)))
(define-key-after groups-map [set-filter-groups-by-mode]
'(menu-item "Set current filter groups to filter by mode"
ibuffer-set-filter-groups-by-mode))
'(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 "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"))
(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 groups-map)))
-
-(defvar ibuffer-name-map nil)
-(unless ibuffer-name-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)))
+(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
(let ((map (make-sparse-keymap)))
- (set-keymap-parent map ibuffer-mode-map)
(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)))
- (set-keymap-parent map ibuffer-mode-map)
(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)))
- (set-keymap-parent map ibuffer-mode-map)
(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.
(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)))
(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)))
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-popup-menu (event)
"Display a menu of operations."
(interactive "e")
- (let ((origline (count-lines (point-min) (point))))
+ (let ((eventpt (posn-point (event-end event)))
+ (origpt (point)))
(unwind-protect
- (progn
- (mouse-set-point event)
- (if (get-text-property (point) 'ibuffer-filter-group-name)
- (save-excursion
- (popup-menu ibuffer-mode-groups-popup))
- (setq buffer-read-only nil)
+ (if (get-text-property eventpt 'ibuffer-filter-group-name)
+ (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)
- (setq buffer-read-only nil)
- (ibuffer-set-mark ibuffer-marked-char)
- (setq buffer-read-only nil)
+ (save-excursion
+ (goto-char eventpt)
+ (ibuffer-set-mark ibuffer-marked-char))
(save-excursion
(popup-menu ibuffer-mode-operate-map)))))
- (progn
- (setq buffer-read-only t)
- (goto-line (1+ origline))))))
-
+ (setq buffer-read-only t)
+ (if (= eventpt (point))
+ (goto-char origpt)))))
+
(defun ibuffer-skip-properties (props direction)
(while (and (not (eobp))
(let ((hit nil))
(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 (or (get-text-property (point) 'ibuffer-title)
- (and skip-group-names
- (get-text-property (point) 'ibuffer-filter-group-name)))
+ (when (and ibuffer-movement-cycle
+ (or (get-text-property (point) 'ibuffer-title)
+ (and skip-group-names
+ (get-text-property (point)
+ 'ibuffer-filter-group-name))))
(goto-char (point-max))
(beginning-of-line))
(ibuffer-skip-properties (append '(ibuffer-summary)
(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 (or (eobp)
- (get-text-property (point) 'ibuffer-summary))
+ (when (and ibuffer-movement-cycle
+ (or (eobp)
+ (get-text-property (point) 'ibuffer-summary)))
(goto-char (point-min)))
(when (or (get-text-property (point) 'ibuffer-title)
(and skip-group-names
(ibuffer-backward-line (- arg))
(while (> arg 0)
(forward-line 1)
- (when (or (eobp)
- (get-text-property (point) 'ibuffer-summary))
+ (when (and ibuffer-movement-cycle
+ (or (eobp)
+ (get-text-property (point) 'ibuffer-summary)))
(goto-char (point-min)))
(decf arg)
(ibuffer-skip-properties (append '(ibuffer-title)
(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")
(> (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)
(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
;; 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
(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))))
(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)))))
(defsubst ibuffer-map-deletion-lines (func)
(ibuffer-map-on-mark ibuffer-deletion-char func))
-(define-ibuffer-op save ()
+(define-ibuffer-op ibuffer-do-save ()
"Save marked buffers as with `save-buffer'."
(:complex t
:opstring "saved"
(save-buffer))))
t)
-(define-ibuffer-op toggle-modified ()
+(define-ibuffer-op ibuffer-do-toggle-modified ()
"Toggle modification flag of marked buffers."
(:opstring "(un)marked as modified"
:modifier-p t)
(set-buffer-modified-p (not (buffer-modified-p))))
-(define-ibuffer-op toggle-read-only ()
+(define-ibuffer-op ibuffer-do-toggle-read-only ()
"Toggle read only status in marked buffers."
(:opstring "toggled read only status in"
:modifier-p t)
(toggle-read-only))
-(define-ibuffer-op delete ()
+(define-ibuffer-op ibuffer-do-delete ()
"Kill marked buffers as with `kill-this-buffer'."
(:opstring "killed"
:active-opstring "kill"
'kill
nil))
-(define-ibuffer-op kill-on-deletion-marks ()
+(define-ibuffer-op ibuffer-do-kill-on-deletion-marks ()
"Kill buffers marked for deletion as with `kill-this-buffer'."
(:opstring "killed"
:active-opstring "kill"
((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))
(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
"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)
(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 (if (ibuffer-use-fontification)
- (propertize ibuffer-eliding-string 'face 'bold)
- ibuffer-eliding-string)))
- (if (or elide ibuffer-elide-long-columns)
+ (let ((ellipsis (propertize ibuffer-eliding-string 'font-lock-face 'bold)))
+ (if (or elide (with-no-warnings ibuffer-elide-long-columns))
`(if (> strlen 5)
,(if from-end-p
`(concat ,ellipsis
`(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))
;; 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)
(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.
'(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)
(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!"))
(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))
(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"))))
(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)
(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"))
- (buffer-name))
-
-(define-ibuffer-column size (:inline t)
+(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
+ :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"
+ :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))
+ 'font-lock-face 'italic)
+ (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))
(t (concat str left right)))))
-(defun ibuffer-fontify-region-function (beg end &optional verbose)
- (when verbose (message "Fontifying..."))
- (let ((inhibit-read-only t))
- (save-excursion
- (goto-char beg)
- (beginning-of-line)
- (while (< (point) end)
- (if (get-text-property (point) 'ibuffer-title-header)
- (put-text-property (point) (line-end-position) 'face ibuffer-title-face)
- (if (get-text-property (point) 'ibuffer-filter-group-name)
- (put-text-property (point) (line-end-position) 'face
- ibuffer-filter-group-name-face)
- (unless (or (get-text-property (point) 'ibuffer-title)
- (get-text-property (point) 'ibuffer-summary))
- (multiple-value-bind (buf mark)
- (get-text-property (point) 'ibuffer-properties)
- (let* ((namebeg (next-single-property-change (point) 'ibuffer-name-column
- nil (line-end-position)))
- (nameend (next-single-property-change namebeg 'ibuffer-name-column
- nil (line-end-position))))
- (put-text-property namebeg
- nameend
- 'face
- (cond ((char-equal mark ibuffer-marked-char)
- ibuffer-marked-face)
- ((char-equal mark ibuffer-deletion-char)
- ibuffer-deletion-face)
- (t
- (let ((level -1)
- result)
- (dolist (e ibuffer-fontification-alist result)
- (when (and (> (car e) level)
- (with-current-buffer buf
- (eval (cadr e))))
- (setq level (car e)
- result
- (if (symbolp (caddr e))
- (if (facep (caddr e))
- (caddr e)
- (symbol-value (caddr e))))))))))))))))
- (forward-line 1))))
- (when verbose (message "Fontifying...done")))
-
-(defun ibuffer-unfontify-region-function (beg end)
- (let ((inhibit-read-only t))
- (remove-text-properties beg end '(face nil))))
+(defun ibuffer-buffer-name-face (buf mark)
+ (cond ((char-equal mark ibuffer-marked-char)
+ ibuffer-marked-face)
+ ((char-equal mark ibuffer-deletion-char)
+ ibuffer-deletion-face)
+ (t
+ (let ((level -1)
+ result)
+ (dolist (e ibuffer-fontification-alist result)
+ (when (and (> (car e) level)
+ (with-current-buffer buf
+ (eval (nth 1 e))))
+ (setq level (car e)
+ result (nth 2 e))))))))
(defun ibuffer-insert-buffer-line (buffer mark format)
"Insert a line describing BUFFER and MARK using FORMAT."
(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)
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
(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
(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)
(mapcar #'(lambda (buf) (let ((e (assq buf bufs)))
(if e
e
- (cons buf ? ))))
+ (cons buf ?\s))))
curbufs)))
(defun ibuffer-buf-matches-predicates (buf predicates)
(funcall pred buf))
(setq hit t)))
hit))
-
+
(defun ibuffer-filter-buffers (ibuffer-buf last bmarklist all)
(let ((ext-loaded (featurep 'ibuf-ext)))
(delq nil
(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))))
(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
(next-single-property-change
(point-min) 'ibuffer-title)))
(goto-char (point-min))
- (put-text-property
+ (add-text-properties
(point)
(progn
(let ((opos (point)))
(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)
(- min len)
align)
name))))))
- (put-text-property opos (point) 'ibuffer-title-header t)
+ (add-text-properties opos (point) `(ibuffer-title-header t))
(insert "\n")
;; Add the underlines
(let ((str (save-excursion
(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))
- 'ibuffer-title t)
+ `(ibuffer-title t font-lock-face ,ibuffer-title-face))
;; Now, insert the summary columns.
(goto-char (point-max))
(if (get-text-property (1- (point-max)) 'ibuffer-summary)
(delete-region (previous-single-property-change
(point-max) 'ibuffer-summary)
(point-max)))
- (put-text-property
- (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-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
(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
- (current-buffer)
- (if (and
- (cadr bufs)
- (eq ibuffer-always-show-last-buffer
- :nomini)
- ;; This is a hack.
- (string-match " \\*Minibuf"
- (buffer-name (cadr bufs))))
- (caddr bufs)
- (cadr bufs))
- (ibuffer-current-buffers-with-marks bufs)
- arg)))
+ (current-buffer)
+ (if (and
+ (cadr bufs)
+ (eq ibuffer-always-show-last-buffer
+ :nomini)
+ (minibufferp (cadr bufs)))
+ (caddr bufs)
+ (cadr bufs))
+ (ibuffer-current-buffers-with-marks bufs)
+ ibuffer-display-maybe-show-predicates)))
(when (null blist)
(if (and (featurep 'ibuf-ext)
ibuffer-filtering-qualifiers)
(nreverse result)
result))))
-(defun ibuffer-insert-filter-group (name display-name format bmarklist)
+(defun ibuffer-insert-filter-group (name display-name filter-string format bmarklist)
(add-text-properties
(point)
(progn
(insert "[ " display-name " ]")
(point))
- `(ibuffer-filter-group-name ,name keymap ,ibuffer-mode-filter-group-map
- mouse-face highlight
- help-echo "mouse-1: toggle marks in this group\nmouse-2: hide/show this filtering group "))
+ `(ibuffer-filter-group-name
+ ,name
+ font-lock-face ,ibuffer-filter-group-name-face
+ keymap ,ibuffer-mode-filter-group-map
+ mouse-face highlight
+ 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
'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))
(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
name
(if disabled (concat name " ...") name)
+ (if ext-loaded
+ (ibuffer-format-filter-group-data name)
+ "")
--ibuffer-insert-buffers-and-marks-format
(if disabled
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
;;;###autoload
(defun ibuffer (&optional other-window-p name qualifiers noselect
- shrink filter-groups)
- "Begin using `ibuffer' to edit a list of buffers.
+ shrink filter-groups formats)
+ "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'."
+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))
(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))
- (when (ibuffer-use-fontification)
- (require 'font-lock))
- (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 filter-groups
(require 'ibuf-ext)
(setq ibuffer-filter-groups filter-groups))
+ (when formats
+ (set (make-local-variable 'ibuffer-formats) formats))
(ibuffer-update nil)
;; Skip the group name by default.
(ibuffer-forward-line 0 t)
(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"))))))
(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.
Filtering commands:
'\\[ibuffer-filter-by-mode]' - Add a filter by major mode.
+ '\\[ibuffer-filter-by-used-mode]' - Add a filter by major mode now in use.
'\\[ibuffer-filter-by-name]' - Add a filter by buffer name.
'\\[ibuffer-filter-by-content]' - Add a filter by buffer content.
'\\[ibuffer-filter-by-filename]' - Add a filter by filename.
'\\[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.
;; This makes things less ugly for Emacs 21 users with a non-nil
;; `show-trailing-whitespace'.
(setq show-trailing-whitespace nil)
- ;; Dummy font-lock-defaults to make font-lock turn on. We want this
- ;; so we know when to enable ibuffer's internal fontification.
- (set (make-local-variable 'font-lock-defaults)
- '(nil t nil nil nil
- (font-lock-fontify-region-function . ibuffer-fontify-region-function)
- (font-lock-unfontify-region-function . ibuffer-unfontify-region-function)))
+ ;; 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)
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-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)
(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