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:
parent
3bbe9e6091
commit
2296bf188f
3 changed files with 73 additions and 42 deletions
5
etc/NEWS
5
etc/NEWS
|
@ -61,6 +61,11 @@ to reduce differences between developer and production builds.
|
|||
|
||||
** 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'.
|
||||
|
||||
|
|
|
@ -1228,28 +1228,33 @@ If INCLUDE-PARENTS is non-nil then include parent modes."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext")
|
||||
(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"
|
||||
: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
|
||||
(mapcar #'intern
|
||||
(completing-read-multiple
|
||||
(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))))
|
||||
(lambda (e)
|
||||
(string-match "-mode\\'" (if (symbolp e) (symbol-name e) e)))
|
||||
t nil nil default)))
|
||||
:accept-list t)
|
||||
(eq qualifier (buffer-local-value 'major-mode buf)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext")
|
||||
(define-ibuffer-filter used-mode
|
||||
"Limit current view to buffers with major mode QUALIFIER.
|
||||
Called interactively, this function allows selection of modes
|
||||
"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
|
||||
currently used by buffers."
|
||||
(:description "major mode in use"
|
||||
:reader
|
||||
|
@ -1257,23 +1262,29 @@ currently used by buffers."
|
|||
(default (if (and buf (buffer-live-p buf))
|
||||
(symbol-name (buffer-local-value
|
||||
'major-mode buf)))))
|
||||
(intern
|
||||
(completing-read
|
||||
(mapcar #'intern
|
||||
(completing-read-multiple
|
||||
(if default
|
||||
(format "Filter by major mode (default %s): " default)
|
||||
"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)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
|
||||
(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"
|
||||
:reader
|
||||
(intern
|
||||
(completing-read "Filter by derived mode: "
|
||||
(ibuffer-list-buffer-modes t)
|
||||
nil t)))
|
||||
:reader
|
||||
(mapcar #'intern
|
||||
(completing-read-multiple "Filter by derived mode: "
|
||||
(ibuffer-list-buffer-modes t)
|
||||
nil t))
|
||||
:accept-list t)
|
||||
(with-current-buffer buf (derived-mode-p qualifier)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext")
|
||||
|
|
|
@ -280,14 +280,18 @@ buffer object.
|
|||
|
||||
;;;###autoload
|
||||
(cl-defmacro define-ibuffer-filter (name documentation
|
||||
(&key
|
||||
reader
|
||||
description)
|
||||
&rest body)
|
||||
(&key
|
||||
reader
|
||||
description
|
||||
accept-list)
|
||||
&rest body)
|
||||
"Define a filter named NAME.
|
||||
DOCUMENTATION is the documentation of the function.
|
||||
READER is a form which should read a qualifier from the user.
|
||||
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
|
||||
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)"
|
||||
(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
|
||||
(defun ,fn-name (qualifier)
|
||||
,(or documentation "This filter is not documented.")
|
||||
(interactive (list ,reader))
|
||||
(if (null (ibuffer-push-filter (cons ',name qualifier)))
|
||||
(message "%s"
|
||||
(format ,(concat (format "Filter by %s already applied: " description)
|
||||
" %s")
|
||||
qualifier))
|
||||
(message "%s"
|
||||
(format ,(concat (format "Filter by %s added: " description)
|
||||
" %s")
|
||||
qualifier))
|
||||
(ibuffer-update nil t)))
|
||||
,(or documentation "This filter is not documented.")
|
||||
(interactive (list ,reader))
|
||||
(let ((,filter (cons ',name qualifier))
|
||||
(,qualifier-str qualifier))
|
||||
,(when accept-list
|
||||
`(progn
|
||||
(unless (listp qualifier) (setq qualifier (list qualifier)))
|
||||
;; Reject equivalent filters: (or f1 f2) is same as (or f2 f1).
|
||||
(setq qualifier (sort (delete-dups qualifier) #'string-lessp))
|
||||
(setq ,filter (cons ',name (car qualifier)))
|
||||
(setq ,qualifier-str
|
||||
(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
|
||||
(lambda (buf qualifier)
|
||||
(condition-case nil
|
||||
(progn ,@body)
|
||||
(error (ibuffer-pop-filter)
|
||||
(when (eq ',name 'predicate)
|
||||
(error "Wrong filter predicate: %S"
|
||||
qualifier))))))
|
||||
ibuffer-filtering-alist)
|
||||
(lambda (buf qualifier)
|
||||
(condition-case nil
|
||||
(progn ,@body)
|
||||
(error (ibuffer-pop-filter)
|
||||
(when (eq ',name 'predicate)
|
||||
(error "Wrong filter predicate: %S"
|
||||
qualifier))))))
|
||||
ibuffer-filtering-alist)
|
||||
:autoload-end)))
|
||||
|
||||
(provide 'ibuf-macs)
|
||||
|
|
Loading…
Add table
Reference in a new issue