diff options
| author | Tino Calancha | 2018-09-29 18:40:46 +0900 |
|---|---|---|
| committer | Tino Calancha | 2018-09-29 18:40:46 +0900 |
| commit | 2296bf188fc99d66306e71e6decd3d2e176b7ae6 (patch) | |
| tree | bfc6c4d8afad29ee0204ce56801583ea7d97e403 | |
| parent | 3bbe9e609138ae88a4c98bcee0da8fcf8b4a3e80 (diff) | |
| download | emacs-2296bf188fc99d66306e71e6decd3d2e176b7ae6.tar.gz emacs-2296bf188fc99d66306e71e6decd3d2e176b7ae6.zip | |
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>
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/ibuf-ext.el | 45 | ||||
| -rw-r--r-- | lisp/ibuf-macs.el | 65 |
3 files changed, 73 insertions, 42 deletions
| @@ -62,6 +62,11 @@ to reduce differences between developer and production builds. | |||
| 62 | ** Ibuffer | 62 | ** Ibuffer |
| 63 | 63 | ||
| 64 | --- | 64 | --- |
| 65 | *** All mode filters can now accept a list of symbols. | ||
| 66 | This means you can now easily filter several major modes, as well | ||
| 67 | as a single mode. | ||
| 68 | |||
| 69 | --- | ||
| 65 | *** New toggle 'ibuffer-do-toggle-lock', bound to 'L'. | 70 | *** New toggle 'ibuffer-do-toggle-lock', bound to 'L'. |
| 66 | 71 | ||
| 67 | ** Gnus | 72 | ** Gnus |
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el index d9949d28352..32ec91db970 100644 --- a/lisp/ibuf-ext.el +++ b/lisp/ibuf-ext.el | |||
| @@ -1228,28 +1228,33 @@ If INCLUDE-PARENTS is non-nil then include parent modes." | |||
| 1228 | 1228 | ||
| 1229 | ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext") | 1229 | ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext") |
| 1230 | (define-ibuffer-filter mode | 1230 | (define-ibuffer-filter mode |
| 1231 | "Limit current view to buffers with major mode QUALIFIER." | 1231 | "Limit current view to buffers with major mode(s) specified by QUALIFIER. |
| 1232 | QUALIFIER is the mode name as a symbol or a list of symbols. | ||
| 1233 | Called interactively, accept a comma separated list of mode names." | ||
| 1232 | (:description "major mode" | 1234 | (:description "major mode" |
| 1233 | :reader | 1235 | :reader |
| 1234 | (let* ((buf (ibuffer-current-buffer)) | 1236 | (let* ((buf (ibuffer-current-buffer)) |
| 1235 | (default (if (and buf (buffer-live-p buf)) | 1237 | (default (if (and buf (buffer-live-p buf)) |
| 1236 | (symbol-name (buffer-local-value | 1238 | (symbol-name (buffer-local-value |
| 1237 | 'major-mode buf))))) | 1239 | 'major-mode buf))))) |
| 1238 | (intern | 1240 | (mapcar #'intern |
| 1239 | (completing-read | 1241 | (completing-read-multiple |
| 1240 | (if default | 1242 | (if default |
| 1241 | (format "Filter by major mode (default %s): " default) | 1243 | (format "Filter by major mode (default %s): " default) |
| 1242 | "Filter by major mode: ") | 1244 | "Filter by major mode: ") |
| 1243 | obarray | 1245 | obarray |
| 1244 | #'(lambda (e) | 1246 | (lambda (e) |
| 1245 | (string-match "-mode\\'" (symbol-name e))) | 1247 | (string-match "-mode\\'" (if (symbolp e) (symbol-name e) e))) |
| 1246 | t nil nil default)))) | 1248 | t nil nil default))) |
| 1249 | :accept-list t) | ||
| 1247 | (eq qualifier (buffer-local-value 'major-mode buf))) | 1250 | (eq qualifier (buffer-local-value 'major-mode buf))) |
| 1248 | 1251 | ||
| 1249 | ;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext") | 1252 | ;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext") |
| 1250 | (define-ibuffer-filter used-mode | 1253 | (define-ibuffer-filter used-mode |
| 1251 | "Limit current view to buffers with major mode QUALIFIER. | 1254 | "Limit current view to buffers with major mode(s) specified by QUALIFIER. |
| 1252 | Called interactively, this function allows selection of modes | 1255 | QUALIFIER is the mode name as a symbol or a list of symbols. |
| 1256 | |||
| 1257 | Called interactively, accept a comma separated list of mode names | ||
| 1253 | currently used by buffers." | 1258 | currently used by buffers." |
| 1254 | (:description "major mode in use" | 1259 | (:description "major mode in use" |
| 1255 | :reader | 1260 | :reader |
| @@ -1257,23 +1262,29 @@ currently used by buffers." | |||
| 1257 | (default (if (and buf (buffer-live-p buf)) | 1262 | (default (if (and buf (buffer-live-p buf)) |
| 1258 | (symbol-name (buffer-local-value | 1263 | (symbol-name (buffer-local-value |
| 1259 | 'major-mode buf))))) | 1264 | 'major-mode buf))))) |
| 1260 | (intern | 1265 | (mapcar #'intern |
| 1261 | (completing-read | 1266 | (completing-read-multiple |
| 1262 | (if default | 1267 | (if default |
| 1263 | (format "Filter by major mode (default %s): " default) | 1268 | (format "Filter by major mode (default %s): " default) |
| 1264 | "Filter by major mode: ") | 1269 | "Filter by major mode: ") |
| 1265 | (ibuffer-list-buffer-modes) nil t nil nil default)))) | 1270 | (ibuffer-list-buffer-modes) nil t nil nil default))) |
| 1271 | :accept-list t) | ||
| 1266 | (eq qualifier (buffer-local-value 'major-mode buf))) | 1272 | (eq qualifier (buffer-local-value 'major-mode buf))) |
| 1267 | 1273 | ||
| 1268 | ;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext") | 1274 | ;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext") |
| 1269 | (define-ibuffer-filter derived-mode | 1275 | (define-ibuffer-filter derived-mode |
| 1270 | "Limit current view to buffers whose major mode inherits from QUALIFIER." | 1276 | "Limit current view to buffers with major mode(s) specified by QUALIFIER. |
| 1277 | QUALIFIER is the mode name as a symbol or a list of symbols. | ||
| 1278 | Restrict the view to buffers whose major mode derivates | ||
| 1279 | from modes specified by QUALIFIER. | ||
| 1280 | Called interactively, accept a comma separated list of mode names." | ||
| 1271 | (:description "derived mode" | 1281 | (:description "derived mode" |
| 1272 | :reader | 1282 | :reader |
| 1273 | (intern | 1283 | (mapcar #'intern |
| 1274 | (completing-read "Filter by derived mode: " | 1284 | (completing-read-multiple "Filter by derived mode: " |
| 1275 | (ibuffer-list-buffer-modes t) | 1285 | (ibuffer-list-buffer-modes t) |
| 1276 | nil t))) | 1286 | nil t)) |
| 1287 | :accept-list t) | ||
| 1277 | (with-current-buffer buf (derived-mode-p qualifier))) | 1288 | (with-current-buffer buf (derived-mode-p qualifier))) |
| 1278 | 1289 | ||
| 1279 | ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext") | 1290 | ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext") |
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el index 6a70a8341a2..72a35a53315 100644 --- a/lisp/ibuf-macs.el +++ b/lisp/ibuf-macs.el | |||
| @@ -280,14 +280,18 @@ buffer object. | |||
| 280 | 280 | ||
| 281 | ;;;###autoload | 281 | ;;;###autoload |
| 282 | (cl-defmacro define-ibuffer-filter (name documentation | 282 | (cl-defmacro define-ibuffer-filter (name documentation |
| 283 | (&key | 283 | (&key |
| 284 | reader | 284 | reader |
| 285 | description) | 285 | description |
| 286 | &rest body) | 286 | accept-list) |
| 287 | &rest body) | ||
| 287 | "Define a filter named NAME. | 288 | "Define a filter named NAME. |
| 288 | DOCUMENTATION is the documentation of the function. | 289 | DOCUMENTATION is the documentation of the function. |
| 289 | READER is a form which should read a qualifier from the user. | 290 | READER is a form which should read a qualifier from the user. |
| 290 | DESCRIPTION is a short string describing the filter. | 291 | DESCRIPTION is a short string describing the filter. |
| 292 | ACCEPT-LIST is a boolean; if non-nil, the filter accepts either | ||
| 293 | a single condition or a list of them; in the latter | ||
| 294 | case the filter is the `or' composition of the conditions. | ||
| 291 | 295 | ||
| 292 | BODY should contain forms which will be evaluated to test whether or | 296 | BODY should contain forms which will be evaluated to test whether or |
| 293 | not a particular buffer should be displayed or not. The forms in BODY | 297 | 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. | |||
| 296 | 300 | ||
| 297 | \(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" | 301 | \(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" |
| 298 | (declare (indent 2) (doc-string 2)) | 302 | (declare (indent 2) (doc-string 2)) |
| 299 | (let ((fn-name (intern (concat "ibuffer-filter-by-" (symbol-name name))))) | 303 | (let ((fn-name (intern (concat "ibuffer-filter-by-" (symbol-name name)))) |
| 304 | (filter (make-symbol "ibuffer-filter")) | ||
| 305 | (qualifier-str (make-symbol "ibuffer-qualifier-str"))) | ||
| 300 | `(progn | 306 | `(progn |
| 301 | (defun ,fn-name (qualifier) | 307 | (defun ,fn-name (qualifier) |
| 302 | ,(or documentation "This filter is not documented.") | 308 | ,(or documentation "This filter is not documented.") |
| 303 | (interactive (list ,reader)) | 309 | (interactive (list ,reader)) |
| 304 | (if (null (ibuffer-push-filter (cons ',name qualifier))) | 310 | (let ((,filter (cons ',name qualifier)) |
| 305 | (message "%s" | 311 | (,qualifier-str qualifier)) |
| 306 | (format ,(concat (format "Filter by %s already applied: " description) | 312 | ,(when accept-list |
| 307 | " %s") | 313 | `(progn |
| 308 | qualifier)) | 314 | (unless (listp qualifier) (setq qualifier (list qualifier))) |
| 309 | (message "%s" | 315 | ;; Reject equivalent filters: (or f1 f2) is same as (or f2 f1). |
| 310 | (format ,(concat (format "Filter by %s added: " description) | 316 | (setq qualifier (sort (delete-dups qualifier) #'string-lessp)) |
| 311 | " %s") | 317 | (setq ,filter (cons ',name (car qualifier))) |
| 312 | qualifier)) | 318 | (setq ,qualifier-str |
| 313 | (ibuffer-update nil t))) | 319 | (mapconcat (lambda (m) (if (symbolp m) (symbol-name m) m)) |
| 320 | qualifier ",")) | ||
| 321 | (when (cdr qualifier) ; Compose individual filters with `or'. | ||
| 322 | (setq ,filter `(or ,@(mapcar (lambda (m) (cons ',name m)) qualifier)))))) | ||
| 323 | (if (null (ibuffer-push-filter ,filter)) | ||
| 324 | (message ,(format "Filter by %s already applied: %%s" description) | ||
| 325 | ,qualifier-str) | ||
| 326 | (message ,(format "Filter by %s added: %%s" description) | ||
| 327 | ,qualifier-str) | ||
| 328 | (ibuffer-update nil t)))) | ||
| 314 | (push (list ',name ,description | 329 | (push (list ',name ,description |
| 315 | (lambda (buf qualifier) | 330 | (lambda (buf qualifier) |
| 316 | (condition-case nil | 331 | (condition-case nil |
| 317 | (progn ,@body) | 332 | (progn ,@body) |
| 318 | (error (ibuffer-pop-filter) | 333 | (error (ibuffer-pop-filter) |
| 319 | (when (eq ',name 'predicate) | 334 | (when (eq ',name 'predicate) |
| 320 | (error "Wrong filter predicate: %S" | 335 | (error "Wrong filter predicate: %S" |
| 321 | qualifier)))))) | 336 | qualifier)))))) |
| 322 | ibuffer-filtering-alist) | 337 | ibuffer-filtering-alist) |
| 323 | :autoload-end))) | 338 | :autoload-end))) |
| 324 | 339 | ||
| 325 | (provide 'ibuf-macs) | 340 | (provide 'ibuf-macs) |