1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Ibuffer filter by modes: Accept several mode names

Extend all mode filters so that they handle >1 mode.
For instance, if the users want to filter all buffers in
C or C++ mode, then they can call the filter interactively
with input: 'c-mode,c++-mode' (Bug#32731).

* lisp/ibuf-macs.el(define-ibuffer-filter): Add key :accept-list.
If the value of this key is non-nil, then the filter accepts
either a single qualifier or a list of them; in the latter case,
the resultant filter is the `or' composition of the individual ones.

* lisp/ibuf-ext.el (ibuffer-filter-by-used-mode)
(ibuffer-filter-by-mode, ibuffer-filter-by-derived-mode)
Set :accept-list value non-nil.
Interactively, accept a comma separated list of mode names.

* etc/NEWS(Ibuffer): Announce this change.

Co-authored-by: Noam Postavsky <npostavs@gmail.com>
This commit is contained in:
Tino Calancha 2018-09-29 18:40:46 +09:00
parent 3bbe9e6091
commit 2296bf188f
3 changed files with 73 additions and 42 deletions

View file

@ -61,6 +61,11 @@ to reduce differences between developer and production builds.
** Ibuffer ** Ibuffer
---
*** All mode filters can now accept a list of symbols.
This means you can now easily filter several major modes, as well
as a single mode.
--- ---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'. *** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.

View file

@ -1228,28 +1228,33 @@ If INCLUDE-PARENTS is non-nil then include parent modes."
;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext") ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext")
(define-ibuffer-filter mode (define-ibuffer-filter mode
"Limit current view to buffers with major mode QUALIFIER." "Limit current view to buffers with major mode(s) specified by QUALIFIER.
QUALIFIER is the mode name as a symbol or a list of symbols.
Called interactively, accept a comma separated list of mode names."
(:description "major mode" (:description "major mode"
:reader :reader
(let* ((buf (ibuffer-current-buffer)) (let* ((buf (ibuffer-current-buffer))
(default (if (and buf (buffer-live-p buf)) (default (if (and buf (buffer-live-p buf))
(symbol-name (buffer-local-value (symbol-name (buffer-local-value
'major-mode buf))))) 'major-mode buf)))))
(intern (mapcar #'intern
(completing-read (completing-read-multiple
(if default (if default
(format "Filter by major mode (default %s): " default) (format "Filter by major mode (default %s): " default)
"Filter by major mode: ") "Filter by major mode: ")
obarray obarray
#'(lambda (e) (lambda (e)
(string-match "-mode\\'" (symbol-name e))) (string-match "-mode\\'" (if (symbolp e) (symbol-name e) e)))
t nil nil default)))) t nil nil default)))
:accept-list t)
(eq qualifier (buffer-local-value 'major-mode buf))) (eq qualifier (buffer-local-value 'major-mode buf)))
;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext") ;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext")
(define-ibuffer-filter used-mode (define-ibuffer-filter used-mode
"Limit current view to buffers with major mode QUALIFIER. "Limit current view to buffers with major mode(s) specified by QUALIFIER.
Called interactively, this function allows selection of modes QUALIFIER is the mode name as a symbol or a list of symbols.
Called interactively, accept a comma separated list of mode names
currently used by buffers." currently used by buffers."
(:description "major mode in use" (:description "major mode in use"
:reader :reader
@ -1257,23 +1262,29 @@ currently used by buffers."
(default (if (and buf (buffer-live-p buf)) (default (if (and buf (buffer-live-p buf))
(symbol-name (buffer-local-value (symbol-name (buffer-local-value
'major-mode buf))))) 'major-mode buf)))))
(intern (mapcar #'intern
(completing-read (completing-read-multiple
(if default (if default
(format "Filter by major mode (default %s): " default) (format "Filter by major mode (default %s): " default)
"Filter by major mode: ") "Filter by major mode: ")
(ibuffer-list-buffer-modes) nil t nil nil default)))) (ibuffer-list-buffer-modes) nil t nil nil default)))
:accept-list t)
(eq qualifier (buffer-local-value 'major-mode buf))) (eq qualifier (buffer-local-value 'major-mode buf)))
;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext") ;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
(define-ibuffer-filter derived-mode (define-ibuffer-filter derived-mode
"Limit current view to buffers whose major mode inherits from QUALIFIER." "Limit current view to buffers with major mode(s) specified by QUALIFIER.
QUALIFIER is the mode name as a symbol or a list of symbols.
Restrict the view to buffers whose major mode derivates
from modes specified by QUALIFIER.
Called interactively, accept a comma separated list of mode names."
(:description "derived mode" (:description "derived mode"
:reader :reader
(intern (mapcar #'intern
(completing-read "Filter by derived mode: " (completing-read-multiple "Filter by derived mode: "
(ibuffer-list-buffer-modes t) (ibuffer-list-buffer-modes t)
nil t))) nil t))
:accept-list t)
(with-current-buffer buf (derived-mode-p qualifier))) (with-current-buffer buf (derived-mode-p qualifier)))
;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext") ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext")

View file

@ -280,14 +280,18 @@ buffer object.
;;;###autoload ;;;###autoload
(cl-defmacro define-ibuffer-filter (name documentation (cl-defmacro define-ibuffer-filter (name documentation
(&key (&key
reader reader
description) description
&rest body) accept-list)
&rest body)
"Define a filter named NAME. "Define a filter named NAME.
DOCUMENTATION is the documentation of the function. DOCUMENTATION is the documentation of the function.
READER is a form which should read a qualifier from the user. READER is a form which should read a qualifier from the user.
DESCRIPTION is a short string describing the filter. DESCRIPTION is a short string describing the filter.
ACCEPT-LIST is a boolean; if non-nil, the filter accepts either
a single condition or a list of them; in the latter
case the filter is the `or' composition of the conditions.
BODY should contain forms which will be evaluated to test whether or BODY should contain forms which will be evaluated to test whether or
not a particular buffer should be displayed or not. The forms in BODY not a particular buffer should be displayed or not. The forms in BODY
@ -296,30 +300,41 @@ bound to the current value of the filter.
\(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" \(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)"
(declare (indent 2) (doc-string 2)) (declare (indent 2) (doc-string 2))
(let ((fn-name (intern (concat "ibuffer-filter-by-" (symbol-name name))))) (let ((fn-name (intern (concat "ibuffer-filter-by-" (symbol-name name))))
(filter (make-symbol "ibuffer-filter"))
(qualifier-str (make-symbol "ibuffer-qualifier-str")))
`(progn `(progn
(defun ,fn-name (qualifier) (defun ,fn-name (qualifier)
,(or documentation "This filter is not documented.") ,(or documentation "This filter is not documented.")
(interactive (list ,reader)) (interactive (list ,reader))
(if (null (ibuffer-push-filter (cons ',name qualifier))) (let ((,filter (cons ',name qualifier))
(message "%s" (,qualifier-str qualifier))
(format ,(concat (format "Filter by %s already applied: " description) ,(when accept-list
" %s") `(progn
qualifier)) (unless (listp qualifier) (setq qualifier (list qualifier)))
(message "%s" ;; Reject equivalent filters: (or f1 f2) is same as (or f2 f1).
(format ,(concat (format "Filter by %s added: " description) (setq qualifier (sort (delete-dups qualifier) #'string-lessp))
" %s") (setq ,filter (cons ',name (car qualifier)))
qualifier)) (setq ,qualifier-str
(ibuffer-update nil t))) (mapconcat (lambda (m) (if (symbolp m) (symbol-name m) m))
qualifier ","))
(when (cdr qualifier) ; Compose individual filters with `or'.
(setq ,filter `(or ,@(mapcar (lambda (m) (cons ',name m)) qualifier))))))
(if (null (ibuffer-push-filter ,filter))
(message ,(format "Filter by %s already applied: %%s" description)
,qualifier-str)
(message ,(format "Filter by %s added: %%s" description)
,qualifier-str)
(ibuffer-update nil t))))
(push (list ',name ,description (push (list ',name ,description
(lambda (buf qualifier) (lambda (buf qualifier)
(condition-case nil (condition-case nil
(progn ,@body) (progn ,@body)
(error (ibuffer-pop-filter) (error (ibuffer-pop-filter)
(when (eq ',name 'predicate) (when (eq ',name 'predicate)
(error "Wrong filter predicate: %S" (error "Wrong filter predicate: %S"
qualifier)))))) qualifier))))))
ibuffer-filtering-alist) ibuffer-filtering-alist)
:autoload-end))) :autoload-end)))
(provide 'ibuf-macs) (provide 'ibuf-macs)