X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/052762262a0432217ba8b9329f2f44f54b290a8f..5fd6d89f46d4603757d5669904637201dd6677bb:/lisp/ibuf-ext.el diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el index baef4d0b20..9aef1ed95b 100644 --- a/lisp/ibuf-ext.el +++ b/lisp/ibuf-ext.el @@ -1,8 +1,9 @@ -;;; ibuf-ext.el --- extensions for ibuffer +;;; ibuf-ext.el --- extensions for ibuffer -;; 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: 2 Dec 2001 ;; Keywords: buffer, convenience @@ -20,8 +21,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: @@ -34,7 +35,6 @@ (require 'ibuffer) (eval-when-compile - (require 'derived) (require 'ibuf-macs) (require 'cl)) @@ -46,11 +46,22 @@ (setq alist (delete entry alist))) alist)) +;; borrowed from Gnus +(defun ibuffer-remove-duplicates (list) + "Return a copy of LIST with duplicate elements removed." + (let ((new nil) + (tail list)) + (while tail + (or (member (car tail) new) + (setq new (cons (car tail) new))) + (setq tail (cdr tail))) + (nreverse new))) + (defun ibuffer-split-list (ibuffer-split-list-fn ibuffer-split-list-elts) (let ((hip-crowd nil) (lamers nil)) (dolist (ibuffer-split-list-elt ibuffer-split-list-elts) - (if (funcall ibuffer-split-list-fn ibuffer-split-list-elt) + (if (funcall ibuffer-split-list-fn ibuffer-split-list-elt) (push ibuffer-split-list-elt hip-crowd) (push ibuffer-split-list-elt lamers))) ;; Too bad Emacs Lisp doesn't have multiple values. @@ -76,7 +87,7 @@ regardless of any active filters in this buffer." (defvar ibuffer-tmp-hide-regexps nil "A list of regexps which should match buffer names to not show.") - + (defvar ibuffer-tmp-show-regexps nil "A list of regexps which should match buffer names to always show.") @@ -91,16 +102,16 @@ Do not set this variable directly! Use the function ((or (mode . message-mode) (mode . mail-mode) (mode . gnus-group-mode) - (mode . gnus-summary-mode) + (mode . gnus-summary-mode) (mode . gnus-article-mode)))) ("programming" ((or (mode . emacs-lisp-mode) (mode . cperl-mode) (mode . c-mode) - (mode . java-mode) + (mode . java-mode) (mode . idl-mode) (mode . lisp-mode))))) - + "An alist of filter qualifiers to switch between. This variable should look like ((\"STRING\" QUALIFIERS) @@ -144,7 +155,7 @@ to this variable." :group 'ibuffer) (defvar ibuffer-cached-filter-formats nil) -(defvar ibuffer-compiled-filter-formats nil) +(defvar ibuffer-compiled-filter-formats nil) (defvar ibuffer-filter-groups nil "A list like ((\"NAME\" ((SYMBOL . QUALIFIER) ...) ...) which groups buffers. @@ -157,21 +168,7 @@ The QUALIFIER should be the same as QUALIFIER in :type 'boolean :group 'ibuffer) -(defcustom ibuffer-saved-filter-groups - '(("gnus" - ((or (mode . message-mode) - (mode . mail-mode) - (mode . gnus-group-mode) - (mode . gnus-summary-mode) - (mode . gnus-article-mode)))) - ("programming" - ((or (mode . emacs-lisp-mode) - (mode . cperl-mode) - (mode . c-mode) - (mode . java-mode) - (mode . idl-mode) - (mode . lisp-mode))))) - +(defcustom ibuffer-saved-filter-groups nil "An alist of filtering groups to switch between. This variable should look like ((\"STRING\" QUALIFIERS) @@ -202,7 +199,7 @@ functions `ibuffer-switch-to-saved-filter-group', (defcustom ibuffer-save-with-custom t "If non-nil, then use Custom to save interactively changed variables. Currently, this only applies to `ibuffer-saved-filters' and -`ibuffer-saved-filter-groups." +`ibuffer-saved-filter-groups'." :type 'boolean :group 'ibuffer) @@ -217,7 +214,7 @@ Currently, this only applies to `ibuffer-saved-filters' and (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)))) (or (ibuffer-included-in-filters-p buf ibuffer-filtering-qualifiers) @@ -269,7 +266,7 @@ With numeric ARG, enable auto-update if and only if ARG is positive." (if (assq 'mode ibuffer-filtering-qualifiers) (setq ibuffer-filtering-qualifiers (ibuffer-delete-alist 'mode ibuffer-filtering-qualifiers)) - (ibuffer-push-filter (cons 'mode + (ibuffer-push-filter (cons 'mode (with-current-buffer buf major-mode))))) (ibuffer-update nil t)) @@ -285,10 +282,10 @@ With numeric ARG, enable auto-update if and only if ARG is positive." ;;;###autoload (defun ibuffer-toggle-filter-group () "Toggle the display status of the filter group on this line." - (interactive) + (interactive) (ibuffer-toggle-filter-group-1 (point))) -(defun ibuffer-toggle-filter-group-1 (posn) +(defun ibuffer-toggle-filter-group-1 (posn) (let ((name (get-text-property posn 'ibuffer-filter-group-name))) (unless (stringp name) (error "No filtering group name present")) @@ -554,27 +551,55 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'." "Set the current filter groups to filter by mode." (interactive) (setq ibuffer-filter-groups - (mapcar (lambda (mode) - (cons (format "%s" mode) `((mode . ,mode)))) - (delete-duplicates - (mapcar (lambda (buf) (with-current-buffer buf major-mode)) - (buffer-list))))) + (mapcar (lambda (mode) + (cons (format "%s" mode) `((mode . ,mode)))) + (let ((modes + (ibuffer-remove-duplicates + (mapcar (lambda (buf) + (with-current-buffer buf major-mode)) + (buffer-list))))) + (if ibuffer-view-ibuffer + modes + (delq 'ibuffer-mode modes))))) (ibuffer-update nil t)) ;;;###autoload (defun ibuffer-pop-filter-group () - "Remove the first filtering group." + "Remove the first filter group." (interactive) (when (null ibuffer-filter-groups) - (error "No filtering groups active")) - (pop ibuffer-filter-groups) + (error "No filter groups active")) + (setq ibuffer-hidden-filter-groups + (delete (pop ibuffer-filter-groups) + ibuffer-hidden-filter-groups)) + (ibuffer-update nil t)) + +(defun ibuffer-read-filter-group-name (msg &optional nodefault noerror) + (when (and (not noerror) (null ibuffer-filter-groups)) + (error "No filter groups active")) + (let ((groups (mapcar #'car ibuffer-filter-groups))) + (completing-read msg (if nodefault + groups + (cons "Default" groups)) + nil t))) + +;;;###autoload +(defun ibuffer-decompose-filter-group (group) + "Decompose the filter group GROUP into active filters." + (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 + group ibuffer-filter-groups) + ibuffer-filtering-qualifiers data)) (ibuffer-update nil t)) ;;;###autoload (defun ibuffer-clear-filter-groups () - "Remove all filtering groups." + "Remove all filter groups." (interactive) - (setq ibuffer-filter-groups nil) + (setq ibuffer-filter-groups nil + ibuffer-hidden-filter-groups nil) (ibuffer-update nil t)) (defun ibuffer-current-filter-groups-with-position () @@ -596,67 +621,87 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'." ;;;###autoload (defun ibuffer-jump-to-filter-group (name) "Move point to the filter group whose name is NAME." - (interactive (list nil)) - (let ((table (ibuffer-current-filter-groups-with-position))) - (when (interactive-p) - (setq name (completing-read "Jump to filter group: " table nil t))) - (ibuffer-aif (assoc name table) - (goto-char (cdr it)) - (error "No filter group with name %s" name)))) + (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)) + (error "No filter group with name %s" name))) ;;;###autoload (defun ibuffer-kill-filter-group (name) - "Delete the filtering group named NAME." - (interactive (list nil)) - (when (interactive-p) - (setq name (completing-read "Kill filter group: " - ibuffer-filter-groups nil t))) + "Kill the filter group named NAME. +The group will be added to `ibuffer-filter-group-kill-ring'." + (interactive (list (ibuffer-read-filter-group-name "Kill filter group: " t))) + (when (equal name "Default") + (error "Can't kill default filter group")) (ibuffer-aif (assoc name ibuffer-filter-groups) - (setq ibuffer-filter-groups (ibuffer-delete-alist - name ibuffer-filter-groups)) + (progn + (push (copy-tree it) ibuffer-filter-group-kill-ring) + (setq ibuffer-filter-groups (ibuffer-delete-alist + name ibuffer-filter-groups)) + (setq ibuffer-hidden-filter-groups + (delete name ibuffer-hidden-filter-groups))) (error "No filter group with name \"%s\"" name)) (ibuffer-update nil t)) ;;;###autoload -(defun ibuffer-kill-line (&optional arg) - (interactive "P") +(defun ibuffer-kill-line (&optional arg interactive-p) + "Kill the filter group at point. +See also `ibuffer-kill-filter-group'." + (interactive "P\np") (ibuffer-aif (save-excursion (ibuffer-forward-line 0) (get-text-property (point) 'ibuffer-filter-group-name)) (progn - (when (equal it "Default") - (error "Can't kill default filtering group")) - (push (assoc it ibuffer-filter-groups) ibuffer-filter-group-kill-ring) (ibuffer-kill-filter-group it)) - (funcall (if (interactive-p) #'call-interactively #'funcall) + (funcall (if interactive-p #'call-interactively #'funcall) #'kill-line arg))) +(defun ibuffer-insert-filter-group-before (newgroup group) + (let* ((found nil) + (pos (let ((groups (mapcar #'car ibuffer-filter-groups)) + (res 0)) + (while groups + (if (equal (car groups) group) + (setq found t + groups nil) + (incf res) + (setq groups (cdr groups)))) + res))) + (cond ((not found) + (setq ibuffer-filter-groups + (nconc ibuffer-filter-groups (list newgroup)))) + ((zerop pos) + (push newgroup ibuffer-filter-groups)) + (t + (let ((cell (nthcdr pos ibuffer-filter-groups))) + (setf (cdr cell) (cons (car cell) (cdr cell))) + (setf (car cell) newgroup)))))) + ;;;###autoload -(defun ibuffer-yank (&optional arg) - (interactive "P") +(defun ibuffer-yank () + "Yank the last killed filter group before group at point." + (interactive) + (ibuffer-yank-filter-group + (or (get-text-property (point) 'ibuffer-filter-group-name) + (get-text-property (point) 'ibuffer-filter-group) + (error "No filter group at point")))) + +;;;###autoload +(defun ibuffer-yank-filter-group (name) + "Yank the last killed filter group before group named NAME." + (interactive (list (ibuffer-read-filter-group-name + "Yank filter group before group: "))) (unless ibuffer-filter-group-kill-ring - (error "ibuffer-filter-group-kill-ring is empty")) + (error "The Ibuffer filter group kill-ring is empty")) (save-excursion (ibuffer-forward-line 0) - (let* ((last-killed (pop ibuffer-filter-group-kill-ring)) - (all-groups ibuffer-filter-groups) - (cur (or (get-text-property (point) 'ibuffer-filter-group-name) - (get-text-property (point) 'ibuffer-filter-group) - (last all-groups))) - (pos (or (position cur (mapcar #'car all-groups) :test #'equal) - (1- (length all-groups))))) - (cond ((= pos 0) - (push last-killed ibuffer-filter-groups)) - ((= pos (1- (length all-groups))) - (nconc ibuffer-filter-groups (list last-killed))) - (t - (let ((cell (nthcdr pos ibuffer-filter-groups))) - (setf (cdr cell) (cons (car cell) (cdr cell))) - (setf (car cell) last-killed)))))) + (ibuffer-insert-filter-group-before (pop ibuffer-filter-group-kill-ring) + name)) (ibuffer-update nil t)) ;;;###autoload -(defun ibuffer-save-filter-groups (name groups) +(defun ibuffer-save-filter-groups (name groups) "Save all active filter groups GROUPS as NAME. They are added to `ibuffer-saved-filter-groups'. Interactively, prompt for NAME, and use the current filters." @@ -668,7 +713,7 @@ prompt for NAME, and use the current filters." ibuffer-filter-groups))) (ibuffer-aif (assoc name ibuffer-saved-filter-groups) (setcdr it groups) - (push (list name groups) ibuffer-saved-filter-groups)) + (push (cons name groups) ibuffer-saved-filter-groups)) (ibuffer-maybe-save-stuff) (ibuffer-update-mode-name)) @@ -679,8 +724,8 @@ They are removed from `ibuffer-saved-filter-groups'." (interactive (list (if (null ibuffer-saved-filter-groups) - (error "No saved filters") - (completing-read "Delete saved filters: " + (error "No saved filter groups") + (completing-read "Delete saved filter group: " ibuffer-saved-filter-groups nil t)))) (setq ibuffer-saved-filter-groups (ibuffer-delete-alist name ibuffer-saved-filter-groups)) @@ -699,7 +744,8 @@ of replacing the current filters." (error "No saved filters") (completing-read "Switch to saved filter group: " ibuffer-saved-filter-groups nil t)))) - (setq ibuffer-filter-groups (assoc name ibuffer-saved-filter-groups)) + (setq ibuffer-filter-groups (cdr (assoc name ibuffer-saved-filter-groups)) + ibuffer-hidden-filter-groups nil) (ibuffer-update nil t)) ;;;###autoload @@ -707,7 +753,10 @@ of replacing the current filters." "Disable all filters currently in effect in this buffer." (interactive) (setq ibuffer-filtering-qualifiers nil) - (ibuffer-update nil t)) + (let ((buf (ibuffer-current-buffer))) + (ibuffer-update nil t) + (when buf + (ibuffer-jump-to-buffer (buffer-name buf))))) ;;;###autoload (defun ibuffer-pop-filter () @@ -716,7 +765,10 @@ of replacing the current filters." (when (null ibuffer-filtering-qualifiers) (error "No filters in effect")) (pop ibuffer-filtering-qualifiers) - (ibuffer-update nil t)) + (let ((buf (ibuffer-current-buffer))) + (ibuffer-update nil t) + (when buf + (ibuffer-jump-to-buffer (buffer-name buf))))) (defun ibuffer-push-filter (qualifier) "Add QUALIFIER to `ibuffer-filtering-qualifiers'." @@ -731,7 +783,7 @@ be a complex filter like (OR [name: foo] [mode: bar-mode]), will be turned into two separate filters [name: foo] and [mode: bar-mode]." (interactive) (when (null ibuffer-filtering-qualifiers) - (error "No filters in effect")) + (error "No filters in effect")) (let ((lim (pop ibuffer-filtering-qualifiers))) (case (car lim) (or @@ -793,14 +845,16 @@ filter into parts." (not (eq 'or (caar ibuffer-filtering-qualifiers)))) (error "Top filter is not an OR")) (let ((lim (pop ibuffer-filtering-qualifiers))) - (setq ibuffer-filtering-qualifiers (nconc (cdr lim) 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")) ;; If the second filter is an OR, just add to it. (let ((first (pop ibuffer-filtering-qualifiers)) (second (pop ibuffer-filtering-qualifiers))) (if (eq 'or (car second)) - (push (nconc (list 'or first) (cdr second)) ibuffer-filtering-qualifiers) + (push (nconc (list 'or first) (cdr second)) + ibuffer-filtering-qualifiers) (push (list 'or first second) ibuffer-filtering-qualifiers)))) (ibuffer-update nil t)) @@ -870,7 +924,14 @@ of replacing the current filters." ibuffer-saved-filters nil t)))) (setq ibuffer-filtering-qualifiers (list (cons 'saved name))) (ibuffer-update nil t)) - + +(defun ibuffer-format-filter-group-data (filter) + (if (equal filter "Default") + "" + (concat "Filter:" (mapconcat #'ibuffer-format-qualifier + (cdr (assq filter ibuffer-filter-groups)) + " ")))) + (defun ibuffer-format-qualifier (qualifier) (if (eq (car-safe qualifier) 'not) (concat " [NOT" (ibuffer-format-qualifier-1 (cdr qualifier)) "]") @@ -888,11 +949,31 @@ of replacing the current filters." (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)) + + ;;; Extra operation definitions ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext.el") -(define-ibuffer-filter mode +(define-ibuffer-filter mode "Toggle current view to buffers with major mode QUALIFIER." (:description "major mode" :reader @@ -909,8 +990,27 @@ of replacing the current filters." ""))))) (eq qualifier (with-current-buffer buf major-mode))) +;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext.el") +(define-ibuffer-filter used-mode + "Toggle current view to buffers with major mode QUALIFIER. +Called interactively, this function allows selection of modes +currently used by buffers." + (:description "major mode in use" + :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))) + ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext.el") -(define-ibuffer-filter name +(define-ibuffer-filter name "Toggle current view to buffers with name matching QUALIFIER." (:description "buffer name" :reader (read-from-minibuffer "Filter by name (regexp): ")) @@ -921,11 +1021,17 @@ of replacing the current filters." "Toggle current view to buffers with filename matching QUALIFIER." (:description "filename" :reader (read-from-minibuffer "Filter by filename (regexp): ")) - (ibuffer-awhen (buffer-file-name buf) + (ibuffer-awhen (with-current-buffer buf + (or buffer-file-name + (and (boundp 'dired-directory) + (if (stringp dired-directory) + dired-directory + (car dired-directory)) + (expand-file-name dired-directory)))) (string-match qualifier it))) ;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext.el") -(define-ibuffer-filter size-gt +(define-ibuffer-filter size-gt "Toggle current view to buffers with size greater than QUALIFIER." (:description "size greater than" :reader @@ -934,7 +1040,7 @@ of replacing the current filters." qualifier)) ;;;###autoload (autoload 'ibuffer-filter-by-size-lt "ibuf-ext.el") -(define-ibuffer-filter size-lt +(define-ibuffer-filter size-lt "Toggle current view to buffers with size less than QUALIFIER." (:description "size less than" :reader @@ -1060,7 +1166,7 @@ Ordering is lexicographic." (defun ibuffer-add-to-tmp-hide (regexp) "Add REGEXP to `ibuffer-tmp-hide-regexps'. This means that buffers whose name matches REGEXP will not be shown -for this ibuffer session." +for this Ibuffer session." (interactive (list (read-from-minibuffer "Never show buffers matching: " @@ -1071,7 +1177,7 @@ for this ibuffer session." (defun ibuffer-add-to-tmp-show (regexp) "Add REGEXP to `ibuffer-tmp-show-regexps'. This means that buffers whose name matches REGEXP will always be shown -for this ibuffer session." +for this Ibuffer session." (interactive (list (read-from-minibuffer "Always show buffers matching: " @@ -1130,81 +1236,92 @@ to move by. The default is `ibuffer-marked-char'." ;;;###autoload (defun ibuffer-jump-to-buffer (name) - "Move point to the buffer whose name is NAME." - (interactive (list nil)) - (let ((table (mapcar #'(lambda (x) - (cons (buffer-name (car x)) - (caddr x))) - (ibuffer-current-state-list t)))) - (when (null table) - (error "No buffers!")) - (when (interactive-p) - (setq name (completing-read "Jump to buffer: " table nil t))) - (ibuffer-aif (assoc name table) - (goto-char (cdr it)) - (error "No buffer with name %s" name)))) + "Move point to the buffer whose name is NAME. + +If called interactively, prompt for a buffer name and go to the +corresponding line in the Ibuffer buffer. If said buffer is in a +hidden group filter, open it. + +If `ibuffer-jump-offer-only-visible-buffers' is non-nil, only offer +visible buffers in the completion list. Calling the command with +a prefix argument reverses the meaning of that variable." + (interactive (list + (let ((only-visible ibuffer-jump-offer-only-visible-buffers)) + (when current-prefix-arg + (setq only-visible (not only-visible))) + (if only-visible + (let ((table (mapcar #'(lambda (x) + (buffer-name (car x))) + (ibuffer-current-state-list)))) + (when (null table) + (error "No buffers!")) + (completing-read "Jump to buffer: " + table nil t)) + (read-buffer "Jump to buffer: " nil t))))) + (when (not (string= "" name)) + (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) + (when (string= (buffer-name buf) name) + (setq buf-point (point)) + nil)) + t nil) + (when (and + (null buf-point) + (not (null ibuffer-hidden-filter-groups))) + ;; We did not find our buffer. It must be in a hidden filter + ;; group, so go through all hidden filter groups to find it. + (catch 'found + (dolist (group ibuffer-hidden-filter-groups) + (ibuffer-jump-to-filter-group group) + (ibuffer-toggle-filter-group) + (ibuffer-map-lines #'(lambda (buf marks) + (when (string= (buffer-name buf) name) + (setq buf-point (point)) + nil)) + t group) + (if buf-point + (throw 'found nil) + (ibuffer-toggle-filter-group))))) + (if (null buf-point) + ;; Still not found even though we expanded all hidden filter + ;; groups: that must be because it's hidden by predicate: + ;; we won't bother trying to display it. + (error "No buffer with name %s" name) + (goto-char buf-point))))) ;;;###autoload (defun ibuffer-diff-with-file () "View the differences between this buffer and its associated file. This requires the external program \"diff\" to be in your `exec-path'." (interactive) - (let* ((buf (ibuffer-current-buffer)) - (buf-filename (with-current-buffer buf - buffer-file-name))) + (let ((buf (ibuffer-current-buffer))) (unless (buffer-live-p buf) (error "Buffer %s has been killed" buf)) - (unless buf-filename - (error "Buffer %s has no associated file" buf)) - (let ((diff-buf (get-buffer-create "*Ibuffer-diff*"))) - (with-current-buffer diff-buf - (setq buffer-read-only nil) - (erase-buffer)) - (let ((tempfile (make-temp-file "ibuffer-diff-"))) - (unwind-protect - (progn - (with-current-buffer buf - (write-region (point-min) (point-max) tempfile nil 'nomessage)) - (if (zerop - (apply #'call-process "diff" nil diff-buf nil - (append - (when (and (boundp 'ediff-custom-diff-options) - (stringp ediff-custom-diff-options)) - (list ediff-custom-diff-options)) - (list buf-filename tempfile)))) - (message "No differences found") - (progn - (with-current-buffer diff-buf - (goto-char (point-min)) - (if (fboundp 'diff-mode) - (diff-mode) - (fundamental-mode))) - (display-buffer diff-buf)))) - (when (file-exists-p tempfile) - (delete-file tempfile))))) - nil)) + (diff-buffer-with-file buf))) ;;;###autoload (defun ibuffer-copy-filename-as-kill (&optional arg) "Copy filenames of marked buffers into the kill ring. + The names are separated by a space. If a buffer has no filename, it is ignored. -With a zero prefix arg, use the complete pathname of each marked file. -You can then feed the file name(s) to other commands with C-y. +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'. - [ This docstring shamelessly stolen from the - `dired-copy-filename-as-kill' in \"dired-x\". ]" - ;; Add to docstring later: - ;; With C-u, use the relative pathname of each marked file. - (interactive "P") - (if (= (ibuffer-count-marked-lines) 0) +You can then feed the file name(s) to other commands with \\[yank]." + (interactive "p") + (if (zerop (ibuffer-count-marked-lines)) (message "No buffers marked; use 'm' to mark a buffer") (let ((ibuffer-copy-filename-as-kill-result "") - (type (cond ((eql arg 0) + (type (cond ((zerop arg) 'full) - ;; ((eql arg 4) - ;; 'relative) + ((= arg 4) + 'relative) (t 'name)))) (ibuffer-map-marked-lines @@ -1216,11 +1333,15 @@ You can then feed the file name(s) to other commands with C-y. (case type (full name) + (relative + (file-relative-name + name (or ibuffer-default-directory + default-directory))) (t (file-name-nondirectory name))) "")) " ")))) - (push ibuffer-copy-filename-as-kill-result kill-ring)))) + (kill-new ibuffer-copy-filename-as-kill-result)))) (defun ibuffer-mark-on-buffer (func &optional ibuffer-mark-on-buffer-mark group) (let ((count @@ -1380,7 +1501,7 @@ defaults to one." (interactive (occur-read-primary-args)) (if (or (not (integerp nlines)) (< nlines 0)) - (setq nlines 1)) + (setq nlines 0)) (when (zerop (ibuffer-count-marked-lines)) (ibuffer-set-mark ibuffer-marked-char)) (let ((ibuffer-do-occur-bufs nil)) @@ -1392,4 +1513,5 @@ defaults to one." (provide 'ibuf-ext) +;;; arch-tag: 9af21953-deda-4c30-b76d-f81d9128e76d ;;; ibuf-ext.el ends here