;;; ibuf-ext.el --- extensions for ibuffer
-;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2014 Free Software Foundation, Inc.
;; Author: Colin Walters <walters@verbum.org>
;; Maintainer: John Paul Wallington <jpw@gnu.org>
;; Created: 2 Dec 2001
;; Keywords: buffer, convenience
+;; Package: ibuffer
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; These functions should be automatically loaded when called, but you
-;; can explicity (require 'ibuf-ext) in your ~/.emacs to have them
+;; can explicitly (require 'ibuf-ext) in your ~/.emacs to have them
;; preloaded.
;;; Code:
(eval-when-compile
(require 'ibuf-macs)
- (require 'cl))
+ (require 'cl-lib))
;;; Utility functions
(defun ibuffer-delete-alist (key alist)
(defvar ibuffer-tmp-show-regexps nil
"A list of regexps which should match buffer names to always show.")
-(defvar ibuffer-auto-mode nil
- "If non-nil, Ibuffer auto-mode should be enabled for this buffer.
-Do not set this variable directly! Use the function
-`ibuffer-auto-mode' instead.")
-
(defvar ibuffer-auto-buffers-changed nil)
(defcustom ibuffer-saved-filters '(("gnus"
See also the variables `ibuffer-filter-groups',
`ibuffer-filtering-qualifiers', `ibuffer-filtering-alist', and the
-functions `ibuffer-switch-to-saved-filter-group',
-`ibuffer-save-filter-group'."
+functions `ibuffer-switch-to-saved-filter-groups',
+`ibuffer-save-filter-groups'."
:type '(repeat sexp)
:group 'ibuffer)
(ibuffer-included-in-filters-p buf ibuffer-filtering-qualifiers)
(ibuffer-buf-matches-predicates buf ibuffer-always-show-predicates)))))
-(defun ibuffer-auto-update-changed ()
- (when (frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed)
- (mapcar #'(lambda (buf)
- (ignore-errors
- (with-current-buffer buf
- (when (and ibuffer-auto-mode
- (eq major-mode 'ibuffer-mode))
- (ibuffer-update nil t)))))
- (buffer-list))))
-
;;;###autoload
-(defun ibuffer-auto-mode (&optional arg)
- "Toggle use of Ibuffer's auto-update facility.
-With numeric ARG, enable auto-update if and only if ARG is positive."
- (interactive)
- (unless (eq major-mode 'ibuffer-mode)
+(define-minor-mode ibuffer-auto-mode
+ "Toggle use of Ibuffer's auto-update facility (Ibuffer Auto mode).
+With a prefix argument ARG, enable Ibuffer Auto mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil."
+ nil nil nil
+ (unless (derived-mode-p 'ibuffer-mode)
(error "This buffer is not in Ibuffer mode"))
- (set (make-local-variable 'ibuffer-auto-mode)
- (if arg
- (plusp arg)
- (not ibuffer-auto-mode)))
- (frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed)
- (add-hook 'post-command-hook 'ibuffer-auto-update-changed)
- (ibuffer-update-mode-name))
+ (frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed) ; Initialize state vector
+ (add-hook 'post-command-hook 'ibuffer-auto-update-changed))
+
+(defun ibuffer-auto-update-changed ()
+ (when (frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed)
+ (dolist (buf (buffer-list))
+ (ignore-errors
+ (with-current-buffer buf
+ (when (and ibuffer-auto-mode
+ (derived-mode-p 'ibuffer-mode))
+ (ibuffer-update nil t)))))))
;;;###autoload
(defun ibuffer-mouse-filter-by-mode (event)
(if (assq 'mode ibuffer-filtering-qualifiers)
(setq ibuffer-filtering-qualifiers
(ibuffer-delete-alist 'mode ibuffer-filtering-qualifiers))
- (ibuffer-push-filter (cons 'mode
- (with-current-buffer buf
- major-mode)))))
+ (ibuffer-push-filter (cons 'mode (buffer-local-value 'major-mode buf)))))
(ibuffer-update nil t))
;;;###autoload
:modifier-p :maybe)
(revert-buffer t t))
+;;;###autoload (autoload 'ibuffer-do-isearch "ibuf-ext")
+(define-ibuffer-op ibuffer-do-isearch ()
+ "Perform a `isearch-forward' in marked buffers."
+ (:interactive ()
+ :opstring "searched in"
+ :complex t
+ :modifier-p :maybe)
+ (multi-isearch-buffers (ibuffer-get-marked-buffers)))
+
+;;;###autoload (autoload 'ibuffer-do-isearch-regexp "ibuf-ext")
+(define-ibuffer-op ibuffer-do-isearch-regexp ()
+ "Perform a `isearch-forward-regexp' in marked buffers."
+ (:interactive ()
+ :opstring "searched regexp in"
+ :complex t
+ :modifier-p :maybe)
+ (multi-isearch-buffers-regexp (ibuffer-get-marked-buffers)))
+
;;;###autoload (autoload 'ibuffer-do-replace-regexp "ibuf-ext")
(define-ibuffer-op replace-regexp (from-str to-str)
"Perform a `replace-regexp' in marked buffers."
(defun ibuffer-included-in-filter-p-1 (buf filter)
(not
(not
- (case (car filter)
- (or
+ (pcase (car filter)
+ (`or
(memq t (mapcar #'(lambda (x)
(ibuffer-included-in-filter-p buf x))
(cdr filter))))
- (saved
+ (`saved
(let ((data
(assoc (cdr filter)
ibuffer-saved-filters)))
(unless data
- (ibuffer-filter-disable)
+ (ibuffer-filter-disable t)
(error "Unknown saved filter %s" (cdr filter)))
(ibuffer-included-in-filters-p buf (cadr data))))
- (t
- (let ((filterdat (assq (car filter)
- ibuffer-filtering-alist)))
- ;; filterdat should be like (TYPE DESCRIPTION FUNC)
- ;; just a sanity check
- (unless filterdat
- (ibuffer-filter-disable)
- (error "Undefined filter %s" (car filter)))
- (not
- (not
- (funcall (caddr filterdat)
- buf
- (cdr filter))))))))))
+ (_
+ (pcase-let ((`(,_type ,_desc ,func)
+ (assq (car filter) ibuffer-filtering-alist)))
+ (unless func
+ (ibuffer-filter-disable t)
+ (error "Undefined filter %s" (car filter)))
+ (funcall func buf (cdr filter))))))))
(defun ibuffer-generate-filter-groups (bmarklist &optional noempty nodefault)
(let ((filter-group-alist (if nodefault
(i 0))
(dolist (filtergroup filter-group-alist)
(let ((filterset (cdr filtergroup)))
- (multiple-value-bind (hip-crowd lamers)
- (ibuffer-split-list (lambda (bufmark)
- (ibuffer-included-in-filters-p (car bufmark)
- filterset))
- bmarklist)
+ (cl-multiple-value-bind (hip-crowd lamers)
+ (cl-values-list
+ (ibuffer-split-list (lambda (bufmark)
+ (ibuffer-included-in-filters-p (car bufmark)
+ filterset))
+ bmarklist))
(aset vec i hip-crowd)
- (incf i)
+ (cl-incf i)
(setq bmarklist lamers))))
(let (ret)
(dotimes (j i ret)
(cons (format "%s" mode) `((mode . ,mode))))
(let ((modes
(ibuffer-remove-duplicates
- (mapcar (lambda (buf)
- (with-current-buffer buf major-mode))
+ (mapcar (lambda (buf)
+ (buffer-local-value 'major-mode buf))
(buffer-list)))))
(if ibuffer-view-ibuffer
modes
;;;###autoload
(defun ibuffer-decompose-filter-group (group)
"Decompose the filter group GROUP into active filters."
- (interactive
+ (interactive
(list (ibuffer-read-filter-group-name "Decompose filter group: " t)))
(let ((data (cdr (assoc group ibuffer-filter-groups))))
(setq ibuffer-filter-groups (ibuffer-delete-alist
;;;###autoload
(defun ibuffer-jump-to-filter-group (name)
"Move point to the filter group whose name is NAME."
- (interactive
+ (interactive
(list (ibuffer-read-filter-group-name "Jump to filter group: ")))
(ibuffer-aif (assoc name (ibuffer-current-filter-groups-with-position))
(goto-char (cdr it))
(if (equal (car groups) group)
(setq found t
groups nil)
- (incf res)
+ (cl-incf res)
(setq groups (cdr groups))))
res)))
(cond ((not found)
(ibuffer-aif (assoc name ibuffer-saved-filter-groups)
(setcdr it groups)
(push (cons name groups) ibuffer-saved-filter-groups))
- (ibuffer-maybe-save-stuff)
- (ibuffer-update-mode-name))
+ (ibuffer-maybe-save-stuff))
;;;###autoload
(defun ibuffer-delete-saved-filter-groups (name)
;;;###autoload
(defun ibuffer-switch-to-saved-filter-groups (name)
"Set this buffer's filter groups to saved version with NAME.
-The value from `ibuffer-saved-filters' is used.
-If prefix argument ADD is non-nil, then add the saved filters instead
-of replacing the current filters."
+The value from `ibuffer-saved-filter-groups' is used."
(interactive
(list
- (if (null ibuffer-saved-filter-groups)
- (error "No saved filters")
- (completing-read "Switch to saved filter group: "
- ibuffer-saved-filter-groups nil t))))
+ (cond ((null ibuffer-saved-filter-groups)
+ (error "No saved filters"))
+ ;; `ibuffer-saved-filter-groups' is a user variable that defaults
+ ;; to nil. We assume that with one element in this list the user
+ ;; knows what she wants. See bug#12331.
+ ((null (cdr ibuffer-saved-filter-groups))
+ (caar ibuffer-saved-filter-groups))
+ (t
+ (completing-read "Switch to saved filter group: "
+ ibuffer-saved-filter-groups nil t)))))
(setq ibuffer-filter-groups (cdr (assoc name ibuffer-saved-filter-groups))
ibuffer-hidden-filter-groups nil)
(ibuffer-update nil t))
;;;###autoload
-(defun ibuffer-filter-disable ()
- "Disable all filters currently in effect in this buffer."
+(defun ibuffer-filter-disable (&optional delete-filter-groups)
+ "Disable all filters currently in effect in this buffer.
+With optional arg DELETE-FILTER-GROUPS non-nil, delete all filter
+group definitions by setting `ibuffer-filter-groups' to nil."
(interactive)
(setq ibuffer-filtering-qualifiers nil)
+ (if delete-filter-groups
+ (setq ibuffer-filter-groups nil))
(let ((buf (ibuffer-current-buffer)))
(ibuffer-update nil t)
(when buf
(when (null ibuffer-filtering-qualifiers)
(error "No filters in effect"))
(let ((lim (pop ibuffer-filtering-qualifiers)))
- (case (car lim)
- (or
+ (pcase (car lim)
+ (`or
(setq ibuffer-filtering-qualifiers (append
(cdr lim)
ibuffer-filtering-qualifiers)))
- (saved
+ (`saved
(let ((data
(assoc (cdr lim)
ibuffer-saved-filters)))
(setq ibuffer-filtering-qualifiers (append
(cadr data)
ibuffer-filtering-qualifiers))))
- (not
+ (`not
(push (cdr lim)
ibuffer-filtering-qualifiers))
- (t
+ (_
(error "Filter type %s is not compound" (car lim)))))
(ibuffer-update nil t))
(not (eq 'or (caar ibuffer-filtering-qualifiers))))
(error "Top filter is not an OR"))
(let ((lim (pop ibuffer-filtering-qualifiers)))
- (setq ibuffer-filtering-qualifiers
+ (setq ibuffer-filtering-qualifiers
(nconc (cdr lim) ibuffer-filtering-qualifiers))))
(when (< (length ibuffer-filtering-qualifiers) 2)
(error "Need two filters to OR"))
(ibuffer-aif (assoc name ibuffer-saved-filters)
(setcdr it filters)
(push (list name filters) ibuffer-saved-filters))
- (ibuffer-maybe-save-stuff)
- (ibuffer-update-mode-name))
+ (ibuffer-maybe-save-stuff))
;;;###autoload
(defun ibuffer-delete-saved-filters (name)
;;;###autoload
(defun ibuffer-switch-to-saved-filters (name)
- "Set this buffer's filters to filters with NAME from `ibuffer-saved-filters'.
-If prefix argument ADD is non-nil, then add the saved filters instead
-of replacing the current filters."
+ "Set this buffer's filters to filters with NAME from `ibuffer-saved-filters'."
(interactive
(list
(if (null ibuffer-saved-filters)
(ibuffer-format-qualifier-1 qualifier)))
(defun ibuffer-format-qualifier-1 (qualifier)
- (case (car qualifier)
- (saved
+ (pcase (car qualifier)
+ (`saved
(concat " [filter: " (cdr qualifier) "]"))
- (or
+ (`or
(concat " [OR" (mapconcat #'ibuffer-format-qualifier
(cdr qualifier) "") "]"))
- (t
+ (_
(let ((type (assq (car qualifier) ibuffer-filtering-alist)))
(unless qualifier
(error "Ibuffer: bad qualifier %s" qualifier))
(concat " [" (cadr type) ": " (format "%s]" (cdr qualifier)))))))
-(defun ibuffer-list-buffer-modes ()
- "Create an alist of buffer modes currently in use.
-The list returned will be of the form (\"MODE-NAME\" . MODE-SYMBOL)."
- (let ((bufs (buffer-list))
- (modes)
- (this-mode))
- (while bufs
- (setq this-mode
- (with-current-buffer
- (car bufs)
- major-mode)
- bufs (cdr bufs))
- (add-to-list
- 'modes
- `(,(symbol-name this-mode) .
- ,this-mode)))
- modes))
+(defun ibuffer-list-buffer-modes (&optional include-parents)
+ "Create a completion table of buffer modes currently in use.
+If INCLUDE-PARENTS is non-nil then include parent modes."
+ (let ((modes))
+ (dolist (buf (buffer-list))
+ (let ((this-mode (buffer-local-value 'major-mode buf)))
+ (while (and this-mode (not (memq this-mode modes)))
+ (push this-mode modes)
+ (setq this-mode (and include-parents
+ (get this-mode 'derived-mode-parent))))))
+ (mapcar #'symbol-name modes)))
;;; Extra operation definitions
"Toggle current view to buffers with major mode QUALIFIER."
(:description "major mode"
:reader
- (intern
- (completing-read "Filter by major mode: " obarray
- #'(lambda (e)
- (string-match "-mode$"
- (symbol-name e)))
- t
- (let ((buf (ibuffer-current-buffer)))
- (if (and buf (buffer-live-p buf))
- (with-current-buffer buf
- (symbol-name major-mode))
- "")))))
- (eq qualifier (with-current-buffer buf major-mode)))
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (intern
+ (completing-read
+ (if default
+ (format "Filter by major mode (default %s): " default)
+ "Filter by major mode: ")
+ obarray
+ #'(lambda (e)
+ (string-match "-mode\\'" (symbol-name e)))
+ t nil nil default))))
+ (eq qualifier (buffer-local-value 'major-mode buf)))
;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext")
(define-ibuffer-filter used-mode
Called interactively, this function allows selection of modes
currently used by buffers."
(:description "major mode in use"
+ :reader
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (intern
+ (completing-read
+ (if default
+ (format "Filter by major mode (default %s): " default)
+ "Filter by major mode: ")
+ (ibuffer-list-buffer-modes) nil t nil nil default))))
+ (eq qualifier (buffer-local-value 'major-mode buf)))
+
+;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
+(define-ibuffer-filter derived-mode
+ "Toggle current view to buffers whose major mode inherits from QUALIFIER."
+ (:description "derived mode"
:reader
(intern
- (completing-read "Filter by major mode: "
- (ibuffer-list-buffer-modes)
- nil
- t
- (let ((buf (ibuffer-current-buffer)))
- (if (and buf (buffer-live-p buf))
- (with-current-buffer buf
- (symbol-name major-mode))
- "")))))
- (eq qualifier (with-current-buffer buf major-mode)))
+ (completing-read "Filter by derived mode: "
+ (ibuffer-list-buffer-modes t)
+ nil t)))
+ (with-current-buffer buf (derived-mode-p qualifier)))
;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext")
(define-ibuffer-filter name
"Toggle current view to buffers with filename matching QUALIFIER."
(:description "filename"
:reader (read-from-minibuffer "Filter by filename (regexp): "))
- (ibuffer-awhen (with-current-buffer buf
- (or buffer-file-name
- (and (boundp 'dired-directory)
- (let ((dired-dir
- (if (stringp dired-directory)
- dired-directory
- (car dired-directory))))
- (and dired-dir
- (expand-file-name dired-dir))))))
+ (ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name))
(string-match qualifier it)))
;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext")
Ordering is lexicographic."
(:description "major mode")
(string-lessp (downcase
- (symbol-name (with-current-buffer
- (car a)
- major-mode)))
+ (symbol-name (buffer-local-value 'major-mode (car a))))
(downcase
- (symbol-name (with-current-buffer
- (car b)
- major-mode)))))
+ (symbol-name (buffer-local-value 'major-mode (car b))))))
;;;###autoload (autoload 'ibuffer-do-sort-by-mode-name "ibuf-ext")
(define-ibuffer-sorter mode-name
Ordering is lexicographic."
(:description "major mode name")
(string-lessp (downcase
- (with-current-buffer
- (car a)
- mode-name))
+ (with-current-buffer
+ (car a)
+ (format-mode-line mode-name)))
(downcase
(with-current-buffer
(car b)
- mode-name))))
+ (format-mode-line mode-name)))))
;;;###autoload (autoload 'ibuffer-do-sort-by-alphabetic "ibuf-ext")
(define-ibuffer-sorter alphabetic
(with-current-buffer (car b)
(buffer-size))))
+;;;###autoload (autoload 'ibuffer-do-sort-by-filename/process "ibuf-ext")
+(define-ibuffer-sorter filename/process
+ "Sort the buffers by their file name/process name."
+ (:description "file name")
+ (string-lessp
+ ;; FIXME: For now just compare the file name and the process name
+ ;; (if it exists). Is there a better way to do this?
+ (or (buffer-file-name (car a))
+ (let ((pr-a (get-buffer-process (car a))))
+ (and (processp pr-a) (process-name pr-a))))
+ (or (buffer-file-name (car b))
+ (let ((pr-b (get-buffer-process (car b))))
+ (and (processp pr-b) (process-name pr-b))))))
+
;;; Functions to emulate bs.el
;;;###autoload
(setq direction 1))
;; Skip the title
(ibuffer-forward-line 0)
- (let ((opos (point))
- curmark)
+ (let ((opos (point)))
(ibuffer-forward-line direction)
(while (not (or (= (point) opos)
- (eq (setq curmark (ibuffer-current-mark))
- mark)))
+ (eq (ibuffer-current-mark) mark)))
(ibuffer-forward-line direction))
(when (and (= (point) opos)
(not (eq (ibuffer-current-mark) mark)))
(message "No buffers marked; use 'm' to mark a buffer")
(let ((count
(ibuffer-map-marked-lines
- #'(lambda (buf mark)
+ #'(lambda (_buf _mark)
'kill))))
(message "Killed %s lines" count))))
(let (buf-point)
;; Blindly search for our buffer: it is very likely that it is
;; not in a hidden filter group.
- (ibuffer-map-lines #'(lambda (buf marks)
+ (ibuffer-map-lines #'(lambda (buf _marks)
(when (string= (buffer-name buf) name)
(setq buf-point (point))
nil))
(dolist (group ibuffer-hidden-filter-groups)
(ibuffer-jump-to-filter-group group)
(ibuffer-toggle-filter-group)
- (ibuffer-map-lines #'(lambda (buf marks)
+ (ibuffer-map-lines #'(lambda (buf _marks)
(when (string= (buffer-name buf) name)
(setq buf-point (point))
nil))
(error "No buffer with name %s" name)
(goto-char buf-point)))))
+(declare-function diff-sentinel "diff"
+ (code &optional old-temp-file new-temp-file))
+
+(defun ibuffer-diff-buffer-with-file-1 (buffer)
+ (let ((bufferfile (buffer-local-value 'buffer-file-name buffer))
+ (tempfile (make-temp-file "buffer-content-")))
+ (when bufferfile
+ (unwind-protect
+ (progn
+ (with-current-buffer buffer
+ (write-region nil nil tempfile nil 'nomessage))
+ (let* ((old (expand-file-name bufferfile))
+ (new (expand-file-name tempfile))
+ (oldtmp (file-local-copy old))
+ (newtmp (file-local-copy new))
+ (switches diff-switches)
+ (command
+ (mapconcat
+ 'identity
+ `(,diff-command
+ ;; Use explicitly specified switches
+ ,@(if (listp switches) switches (list switches))
+ ,@(if (or old new)
+ (list "-L" (shell-quote-argument old)
+ "-L" (shell-quote-argument
+ (format "Buffer %s" (buffer-name buffer)))))
+ ,(shell-quote-argument (or oldtmp old))
+ ,(shell-quote-argument (or newtmp new)))
+ " ")))
+ (let ((inhibit-read-only t))
+ (insert command "\n")
+ (diff-sentinel
+ (call-process shell-file-name nil
+ (current-buffer) nil
+ shell-command-switch command))
+ (insert "\n")))))
+ (sit-for 0)
+ (when (file-exists-p tempfile)
+ (delete-file tempfile)))))
+
;;;###autoload
(defun ibuffer-diff-with-file ()
- "View the differences between this buffer and its associated file.
+ "View the differences between marked buffers and their associated files.
+If no buffers are marked, use buffer at point.
This requires the external program \"diff\" to be in your `exec-path'."
(interactive)
- (let ((buf (ibuffer-current-buffer)))
- (unless (buffer-live-p buf)
- (error "Buffer %s has been killed" buf))
- (diff-buffer-with-file buf)))
+ (require 'diff)
+ (let ((marked-bufs (ibuffer-get-marked-buffers)))
+ (when (null marked-bufs)
+ (setq marked-bufs (list (ibuffer-current-buffer t))))
+ (with-current-buffer (get-buffer-create "*Ibuffer Diff*")
+ (setq buffer-read-only nil)
+ (buffer-disable-undo (current-buffer))
+ (erase-buffer)
+ (buffer-enable-undo (current-buffer))
+ (diff-mode)
+ (dolist (buf marked-bufs)
+ (unless (buffer-live-p buf)
+ (error "Buffer %s has been killed" buf))
+ (ibuffer-diff-buffer-with-file-1 buf))
+ (setq buffer-read-only t)))
+ (switch-to-buffer "*Ibuffer Diff*"))
;;;###autoload
(defun ibuffer-copy-filename-as-kill (&optional arg)
With no prefix arg, use the filename sans its directory of each marked file.
With a zero prefix arg, use the complete filename of each marked file.
With \\[universal-argument], use the filename of each marked file relative
-to `ibuffer-default-directory' iff non-nil, otherwise `default-directory'.
+to `ibuffer-default-directory' if non-nil, otherwise `default-directory'.
You can then feed the file name(s) to other commands with \\[yank]."
(interactive "p")
(t
'name))))
(ibuffer-map-marked-lines
- #'(lambda (buf mark)
+ #'(lambda (buf _mark)
(setq ibuffer-copy-filename-as-kill-result
(concat ibuffer-copy-filename-as-kill-result
(let ((name (buffer-file-name buf)))
(if name
- (case type
- (full
+ (pcase type
+ (`full
name)
- (relative
+ (`relative
(file-relative-name
name (or ibuffer-default-directory
default-directory)))
- (t
+ (_
(file-name-nondirectory name)))
""))
" "))))
(defun ibuffer-mark-on-buffer (func &optional ibuffer-mark-on-buffer-mark group)
(let ((count
(ibuffer-map-lines
- #'(lambda (buf mark)
+ #'(lambda (buf _mark)
(when (funcall func buf)
(ibuffer-set-mark-1 (or ibuffer-mark-on-buffer-mark
ibuffer-marked-char))
nil
group)))
(ibuffer-redisplay t)
- (message "Marked %s buffers" count)))
+ (unless (eq ibuffer-mark-on-buffer-mark ?\s)
+ (message "Marked %s buffers" count))))
;;;###autoload
(defun ibuffer-mark-by-name-regexp (regexp)
(ibuffer-mark-on-buffer
#'(lambda (buf)
(with-current-buffer buf
- (string-match regexp mode-name)))))
+ (string-match regexp (format-mode-line mode-name nil nil buf))))))
;;;###autoload
(defun ibuffer-mark-by-file-name-regexp (regexp)
(defun ibuffer-mark-by-mode (mode)
"Mark all buffers whose major mode equals MODE."
(interactive
- (list (intern (completing-read "Mark by major mode: " obarray
- #'(lambda (e)
- ;; kind of a hack...
- (and (fboundp e)
- (string-match "-mode$"
- (symbol-name e))))
- t
- (let ((buf (ibuffer-current-buffer)))
- (if (and buf (buffer-live-p buf))
- (with-current-buffer buf
- (cons (symbol-name major-mode)
- 0))
- ""))))))
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (list (intern
+ (completing-read
+ (if default
+ (format "Mark by major mode (default %s): " default)
+ "Mark by major mode: ")
+ (ibuffer-list-buffer-modes) nil t nil nil default)))))
(ibuffer-mark-on-buffer
#'(lambda (buf)
- (with-current-buffer buf
- (eq major-mode mode)))))
+ (eq (buffer-local-value 'major-mode buf) mode))))
;;;###autoload
(defun ibuffer-mark-modified-buffers ()
"Mark all modified buffers that have an associated file."
(interactive)
(ibuffer-mark-on-buffer
- #'(lambda (buf) (and (with-current-buffer buf buffer-file-name)
+ #'(lambda (buf) (and (buffer-local-value 'buffer-file-name buf)
(buffer-modified-p buf)))))
;;;###autoload
;;;###autoload
(defun ibuffer-mark-help-buffers ()
- "Mark buffers like *Help*, *Apropos*, *Info*."
+ "Mark buffers whose major mode is in variable `ibuffer-help-buffer-modes'."
(interactive)
(ibuffer-mark-on-buffer
#'(lambda (buf)
;;;###autoload
(defun ibuffer-mark-old-buffers ()
- "Mark buffers which have not been viewed in `ibuffer-old-time' days."
+ "Mark buffers which have not been viewed in `ibuffer-old-time' hours."
(interactive)
(ibuffer-mark-on-buffer
#'(lambda (buf)
(with-current-buffer buf
;; hacked from midnight.el
(when buffer-display-time
- (let* ((tm (current-time))
- (now (+ (* (float (ash 1 16)) (car tm))
- (float (cadr tm)) (* 0.0000001 (caddr tm))))
- (then (+ (* (float (ash 1 16))
- (car buffer-display-time))
- (float (cadr buffer-display-time))
- (* 0.0000001 (caddr buffer-display-time)))))
+ (let* ((now (float-time))
+ (then (float-time buffer-display-time)))
(> (- now then) (* 60 60 ibuffer-old-time))))))))
;;;###autoload
"Mark all read-only buffers."
(interactive)
(ibuffer-mark-on-buffer
- #'(lambda (buf)
- (with-current-buffer buf
- buffer-read-only))))
+ #'(lambda (buf) (buffer-local-value 'buffer-read-only buf))))
;;;###autoload
(defun ibuffer-mark-dired-buffers ()
"Mark all `dired' buffers."
(interactive)
(ibuffer-mark-on-buffer
- #'(lambda (buf)
- (with-current-buffer buf
- (eq major-mode 'dired-mode)))))
+ #'(lambda (buf) (eq (buffer-local-value 'major-mode buf) 'dired-mode))))
;;;###autoload
(defun ibuffer-do-occur (regexp &optional nlines)
(let ((ibuffer-do-occur-bufs nil))
;; Accumulate a list of marked buffers
(ibuffer-map-marked-lines
- #'(lambda (buf mark)
+ #'(lambda (buf _mark)
(push buf ibuffer-do-occur-bufs)))
(occur-1 regexp nlines ibuffer-do-occur-bufs)))
(provide 'ibuf-ext)
-;;; arch-tag: 9af21953-deda-4c30-b76d-f81d9128e76d
+;; Local Variables:
+;; generated-autoload-file: "ibuffer.el"
+;; End:
+
;;; ibuf-ext.el ends here