* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
@ 2018-09-13 18:19 Tino Calancha
2018-09-13 19:09 ` Noam Postavsky
0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-13 18:19 UTC (permalink / raw)
To: 32731
Severity: wishlist
Ibuffer filtering is a great feature.
If you just want to filter by 1 major, then it's quite straight.
/m [mode1-name] RET
Filtering by >1 major mode is still possible; you must
combine the individuals filters with `ibuffer-or-filter':
/m [mode1-name] RET
/m [mode2-name] RET
/|
/m [mode3-name] RET
/|
.
.
.
/m [modeN-name] RET
/|
This become a bit cumbersome with > 2 mode names; you also need to
remember how to combine filters, which I usually forget :-|
Following patch adds a new command `ibuffer-filter-by-used-modes',
similar as `ibuffer-filter-by-used-mode', to simplify this filtering.
The new command accepts a list of mode names, and it takes care
internally of the filter composition.
Interactively, it preserves the interface of `ibuffer-filter-by-used-mode',
with the only difference that the user might input a comma separated
list of mode names. For instance,
;; Following produces identical result as the original command
M-x ibuffer-filter-by-used-modes RET mode1-mode RET
;; This is equivalent to create the N filters + OR-compose them
M-x ibuffer-filter-by-used-modes RET mode1-mode,mode2-mode,...,modeN-mode RET
--8<-----------------------------cut here---------------start------------->8---
commit e36ff5779764e531cc149e4342e93cb6e37c30ee
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Fri Sep 14 03:10:11 2018 +0900
Ibuffer filter by mode: Handle >1 mode names
Extend used mode filtering so that we can input >1 mode.
For instance, if we want to filter all buffers in
C or C++ mode, then we can call the filter interactively
with input: 'c-mode,c++-mode'.
* lisp/ibuf-ext.el (ibuffer-filter-by-used-modes):
New command. Accept a list of mode names (symbols).
Interactively, accept a comma separated list of mode names.
* lisp/ibuffer.el(ibuffer-mode-map): Rebind '/ m' to
the new command.
* etc/NEWS(Ibuffer): Announce this change.
diff --git a/etc/NEWS b/etc/NEWS
index a54ac2db43..6ef6f20b05 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -48,6 +48,11 @@ often cause crashes. Set it to nil if you really need those fonts.
** Ibuffer
---
+*** The new command 'ibuffer-filter-by-used-modes', bound
+to '/ m', extends 'ibuffer-filter-by-used-mode'; it makes easy
+filtering buffers by a list of major modes.
+
+---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.
** Imenu
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index a3143e5e29..b7c3ae8030 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1265,6 +1265,34 @@ used-mode
(ibuffer-list-buffer-modes) nil t nil nil default))))
(eq qualifier (buffer-local-value 'major-mode buf)))
+;;;###autoload
+(defun ibuffer-filter-by-used-modes(modes)
+ "Limit current view to buffers with major mode in MODES.
+MODES is a list of mode names (symbols).
+When called interactively, accept the mode names separated by commas."
+ (interactive
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (list
+ (mapcar #'intern
+ (split-string
+ (completing-read
+ (if default
+ (format "Filter by major mode (default %s): " default)
+ "Filter by major mode: ")
+ (ibuffer-list-buffer-modes)
+ nil nil nil nil default)
+ "\\s-*,\\s-*" t)))))
+ (setq modes (delete-dups modes))
+ (mapc #'ibuffer-filter-by-used-mode modes)
+ (let ((nb_modes (length modes)))
+ (when (>= nb_modes 2)
+ (cl-loop repeat (- nb_modes 2) do (ibuffer-or-filter))
+ (message nil)
+ (ibuffer-or-filter))))
+
;;;###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."
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 08b0801cb5..f7c20d0da3 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -519,7 +519,7 @@ ibuffer-mode-map
(define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
(define-key map (kbd "/ RET") 'ibuffer-filter-by-mode)
- (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode)
+ (define-key map (kbd "/ m") 'ibuffer-filter-by-used-modes)
(define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode)
(define-key map (kbd "/ n") 'ibuffer-filter-by-name)
(define-key map (kbd "/ *") 'ibuffer-filter-by-starred-name)
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.1.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
of 2018-09-14 built
Repository revision: 41cdda22c78eb0b00612ce25cdb356dd64322fcc
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-13 18:19 bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Tino Calancha
@ 2018-09-13 19:09 ` Noam Postavsky
2018-09-13 20:04 ` Tino Calancha
2018-09-13 20:38 ` Tino Calancha
0 siblings, 2 replies; 28+ messages in thread
From: Noam Postavsky @ 2018-09-13 19:09 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731
On 13 September 2018 at 14:19, Tino Calancha <tino.calancha@gmail.com> wrote:
> +;;;###autoload
> +(defun ibuffer-filter-by-used-modes(modes)
> + "Limit current view to buffers with major mode in MODES.
> +MODES is a list of mode names (symbols).
> +When called interactively, accept the mode names separated by commas."
> + (interactive
> + (let* ((buf (ibuffer-current-buffer))
> + (default (if (and buf (buffer-live-p buf))
> + (symbol-name (buffer-local-value
> + 'major-mode buf)))))
> + (list
> + (mapcar #'intern
> + (split-string
> + (completing-read
> + (if default
> + (format "Filter by major mode (default %s): " default)
> + "Filter by major mode: ")
> + (ibuffer-list-buffer-modes)
> + nil nil nil nil default)
> + "\\s-*,\\s-*" t)))))
This will use completion only for the first mode, right? Perhaps
completing-read-multiple would make more sense here.
> + (setq modes (delete-dups modes))
> + (mapc #'ibuffer-filter-by-used-mode modes)
> + (let ((nb_modes (length modes)))
> + (when (>= nb_modes 2)
> + (cl-loop repeat (- nb_modes 2) do (ibuffer-or-filter))
> + (message nil)
What's this `message' call for?
> + (ibuffer-or-filter))))
Maybe it's simpler to construct the filter directly? As in:
(push `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes))
ibuffer-filtering-qualifiers)
(ibuffer-update nil t)
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-13 19:09 ` Noam Postavsky
@ 2018-09-13 20:04 ` Tino Calancha
2018-09-13 20:38 ` Tino Calancha
1 sibling, 0 replies; 28+ messages in thread
From: Tino Calancha @ 2018-09-13 20:04 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731, Tino Calancha
On Thu, 13 Sep 2018, Noam Postavsky wrote:
> On 13 September 2018 at 14:19, Tino Calancha <tino.calancha@gmail.com> wrote:
>
>> +;;;###autoload
>> +(defun ibuffer-filter-by-used-modes(modes)
>> + "Limit current view to buffers with major mode in MODES.
>> +MODES is a list of mode names (symbols).
>> +When called interactively, accept the mode names separated by commas."
>> + (interactive
>> + (let* ((buf (ibuffer-current-buffer))
>> + (default (if (and buf (buffer-live-p buf))
>> + (symbol-name (buffer-local-value
>> + 'major-mode buf)))))
>> + (list
>> + (mapcar #'intern
>> + (split-string
>> + (completing-read
>> + (if default
>> + (format "Filter by major mode (default %s): " default)
>> + "Filter by major mode: ")
>> + (ibuffer-list-buffer-modes)
>> + nil nil nil nil default)
>> + "\\s-*,\\s-*" t)))))
>
> This will use completion only for the first mode, right?
Yeah, that's right.
> Perhaps completing-read-multiple would make more sense here.
Hummmm, it sounds like a good idea. I will look on it.
>> + (setq modes (delete-dups modes))
>> + (mapc #'ibuffer-filter-by-used-mode modes)
>> + (let ((nb_modes (length modes)))
>> + (when (>= nb_modes 2)
>> + (cl-loop repeat (- nb_modes 2) do (ibuffer-or-filter))
>> + (message nil)
>
> What's this `message' call for?
To clean the minibuffer after the second filter fails;
before you do the composition, you have an implicit AND, so
you are requiring:
(and (eq major-mode mode1-mode) (eq major-mode mode2-mode))
;; This fails
;; after `ibuffer-or-filter' previous line is changed to:
(or (eq major-mode mode1-mode) (eq major-mode mode2-mode))
>> + (ibuffer-or-filter))))
>
> Maybe it's simpler to construct the filter directly? As in:
>
> (push `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes))
> ibuffer-filtering-qualifiers)
> (ibuffer-update nil t)
Right, much more elegant. Thank you!
I will update the patch accordingly
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-13 19:09 ` Noam Postavsky
2018-09-13 20:04 ` Tino Calancha
@ 2018-09-13 20:38 ` Tino Calancha
2018-09-13 23:39 ` Noam Postavsky
1 sibling, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-13 20:38 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731
Noam Postavsky <npostavs@gmail.com> writes:
> This will use completion only for the first mode, right? Perhaps
> completing-read-multiple would make more sense here.
This is very nice suggestion! I never used this nice defun before!
(`completing-read-multiple')
> Maybe it's simpler to construct the filter directly? As in:
>
> (push `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes))
> ibuffer-filtering-qualifiers)
> (ibuffer-update nil t)
I tried this way and I see 2 nits:
1) With just one mode you still get superflous `or'
[OR [major mode in use: mode1]]
2) Also, with just one mode, we miss the printout message
with the description:
"Filter by major mode in use added: mode1"
Less important but `define-ibuffer-filter' performs some checks
(there is a `condition-case').
Following is a patch on top of previous patch with all your suggestions:
--8<-----------------------------cut here---------------start------------->8---
commit 5a0657d2d06dd495090d49fae477dbc624b1c85b
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Fri Sep 14 05:22:32 2018 +0900
Use completing-read-multiple
* lisp/ibuf-ext.el (ibuffer-filter-by-used-modes): Construct
teh filter by hand, instead of callig `completing-read-multiple'.
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index b7c3ae8030..f2f9ce8bce 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1277,21 +1277,16 @@ ibuffer-filter-by-used-modes
'major-mode buf)))))
(list
(mapcar #'intern
- (split-string
- (completing-read
- (if default
- (format "Filter by major mode (default %s): " default)
- "Filter by major mode: ")
- (ibuffer-list-buffer-modes)
- nil nil nil nil default)
- "\\s-*,\\s-*" t)))))
+ (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 nil default)))))
(setq modes (delete-dups modes))
- (mapc #'ibuffer-filter-by-used-mode modes)
- (let ((nb_modes (length modes)))
- (when (>= nb_modes 2)
- (cl-loop repeat (- nb_modes 2) do (ibuffer-or-filter))
- (message nil)
- (ibuffer-or-filter))))
+ (push `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes))
+ ibuffer-filtering-qualifiers)
+ (ibuffer-update nil t))
;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
(define-ibuffer-filter derived-mode
--8<-----------------------------cut here---------------end--------------->8---
Next one just use `completing-read-multiple' (keeps calling
`'ibuffer-filter-by-used-mode'); I prefer this one:
--8<-----------------------------cut here---------------start------------->8---
commit af9471040740d351208da7bc929219b291674d67
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Fri Sep 14 05:36:35 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend mode filters so that we can input more than 1 mode.
For instance, if we want to filter all buffers in
C or C++ mode, then we can call the filter interactively
with input: 'c-mode,c++-mode'.
* lisp/ibuf-ext.el (ibuffer-filter-by-used-modes):
New command. Accept a list of mode names (symbols).
Interactively, accept a comma separated list of mode names.
* lisp/ibuffer.el(ibuffer-mode-map): Rebind '/ m' to
the new command.
* etc/NEWS(Ibuffer): Announce this change.
Co-authored-by: Noam Postavsky <npostavs@gmail.com>
diff --git a/etc/NEWS b/etc/NEWS
index a54ac2db43..6ef6f20b05 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -48,6 +48,11 @@ often cause crashes. Set it to nil if you really need those fonts.
** Ibuffer
---
+*** The new command 'ibuffer-filter-by-used-modes', bound
+to '/ m', extends 'ibuffer-filter-by-used-mode'; it makes easy
+filtering buffers by a list of major modes.
+
+---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.
** Imenu
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index a3143e5e29..048d0bc126 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1265,6 +1265,32 @@ used-mode
(ibuffer-list-buffer-modes) nil t nil nil default))))
(eq qualifier (buffer-local-value 'major-mode buf)))
+;;;###autoload
+(defun ibuffer-filter-by-used-modes(modes)
+ "Limit current view to buffers with major mode in MODES.
+MODES is a list of mode names (symbols).
+When called interactively, accept the mode names separated by commas."
+ (interactive
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (list
+ (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 nil default)))))
+ (setq modes (delete-dups modes))
+ (mapc #'ibuffer-filter-by-used-mode modes)
+ (let ((nb_modes (length modes)))
+ (when (>= nb_modes 2)
+ (cl-loop repeat (- nb_modes 2) do (ibuffer-or-filter))
+ (message nil)
+ (ibuffer-or-filter))))
+
;;;###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."
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 08b0801cb5..f7c20d0da3 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -519,7 +519,7 @@ ibuffer-mode-map
(define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
(define-key map (kbd "/ RET") 'ibuffer-filter-by-mode)
- (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode)
+ (define-key map (kbd "/ m") 'ibuffer-filter-by-used-modes)
(define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode)
(define-key map (kbd "/ n") 'ibuffer-filter-by-name)
(define-key map (kbd "/ *") 'ibuffer-filter-by-starred-name)
--8<-----------------------------cut here---------------end--------------->8---
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-13 20:38 ` Tino Calancha
@ 2018-09-13 23:39 ` Noam Postavsky
2018-09-15 9:15 ` Tino Calancha
0 siblings, 1 reply; 28+ messages in thread
From: Noam Postavsky @ 2018-09-13 23:39 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731
Tino Calancha <tino.calancha@gmail.com> writes:
>> Maybe it's simpler to construct the filter directly? As in:
>>
>> (push `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes))
>> ibuffer-filtering-qualifiers)
>> (ibuffer-update nil t)
> I tried this way and I see 2 nits:
> 1) With just one mode you still get superflous `or'
> [OR [major mode in use: mode1]]
>
> 2) Also, with just one mode, we miss the printout message
> with the description:
> "Filter by major mode in use added: mode1"
Yeah, we need special cases for lists of zero and one modes.
> Less important but `define-ibuffer-filter' performs some checks
> (there is a `condition-case').
The condition-case thing is in a lambda form which goes into
ibuffer-filtering-alist, so I don't think there is a need to explicitly
invoke it when constructing a filter of an existing type.
> Next one just use `completing-read-multiple' (keeps calling
> `'ibuffer-filter-by-used-mode'); I prefer this one:
I would be okay if it was just a matter of repeated ibuffer-filter-*
calls, but the fact that it produces error messages which then need to
be hidden makes it unacceptable, IMO.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-13 23:39 ` Noam Postavsky
@ 2018-09-15 9:15 ` Tino Calancha
2018-09-15 12:42 ` Noam Postavsky
0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-15 9:15 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731
Noam Postavsky <npostavs@gmail.com> writes:
> Tino Calancha <tino.calancha@gmail.com> writes:
>
> Yeah, we need special cases for lists of zero and one modes.
No problem.
>> Less important but `define-ibuffer-filter' performs some checks
>> (there is a `condition-case').
>
> The condition-case thing is in a lambda form which goes into
> ibuffer-filtering-alist, so I don't think there is a need to explicitly
> invoke it when constructing a filter of an existing type.
Absolutely. Sorry for the noise.
>> Next one just use `completing-read-multiple' (keeps calling
>> `'ibuffer-filter-by-used-mode'); I prefer this one:
>
> I would be okay if it was just a matter of repeated ibuffer-filter-*
> calls, but the fact that it produces error messages which then need to
> be hidden makes it unacceptable, IMO.
I agree with you: those messages must not be produced.
BTW, I've noticed following commit is missing in the release branch:
'Make ibuffer filters idempotent'
(ee6fe8378a28444cb4913abca4af742f736e9b45)
I suggest we backport it.
Then, I am OK with the next patch (which uses that commit):
--8<-----------------------------cut here---------------start------------->8---
commit c60a9bb36d4d4092866f36d1d8b246b79c1a2fd8
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Sat Sep 15 18:01:14 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend mode filters so that we can input more than 1 mode.
For instance, if we want to filter all buffers in
C or C++ mode, then we can call the filter interactively
with input: 'c-mode,c++-mode'.
* lisp/ibuf-ext.el (ibuffer-filter-by-used-modes):
New command. Accept a list of mode names (symbols).
Interactively, accept a comma separated list of mode names.
* lisp/ibuffer.el(ibuffer-mode-map): Rebind '/ m' to
the new command.
* etc/NEWS(Ibuffer): Announce this change.
Co-authored-by: Noam Postavsky <npostavs@gmail.com>
diff --git a/etc/NEWS b/etc/NEWS
index a54ac2db43..6ef6f20b05 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -48,6 +48,11 @@ often cause crashes. Set it to nil if you really need those fonts.
** Ibuffer
---
+*** The new command 'ibuffer-filter-by-used-modes', bound
+to '/ m', extends 'ibuffer-filter-by-used-mode'; it makes easy
+filtering buffers by a list of major modes.
+
+---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.
** Imenu
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index a3143e5e29..7094ae2674 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1265,6 +1265,35 @@ used-mode
(ibuffer-list-buffer-modes) nil t nil nil default))))
(eq qualifier (buffer-local-value 'major-mode buf)))
+;;;###autoload
+(defun ibuffer-filter-by-used-modes(modes)
+ "Limit current view to buffers with major mode in MODES.
+MODES is a list of mode names (symbols).
+When called interactively, accept the mode names separated by commas."
+ (interactive
+ (let* ((buf (ibuffer-current-buffer))
+ (default (if (and buf (buffer-live-p buf))
+ (symbol-name (buffer-local-value
+ 'major-mode buf)))))
+ (list
+ (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)))))
+ ;; Sort to avoid adding filter (or mode2 mode1) once we have (or mode1 mode2)
+ (setq modes (sort (delete-dups modes) #'string-lessp))
+ (cond ((null (cdr modes)) (ibuffer-filter-by-used-mode (car modes)))
+ (t (let ((composed-filter
+ `(or ,@(mapcar (lambda (m) `(used-mode . ,m)) modes)))
+ (mode-names (mapconcat #'symbol-name modes ",")))
+ (if (null (ibuffer-push-filter composed-filter))
+ (message "Filter by mode in use already applied: %s" mode-names)
+ (message "Filter by mode in use added: %s" mode-names)
+ (ibuffer-update nil t))))))
+
;;;###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."
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 08b0801cb5..f7c20d0da3 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -519,7 +519,7 @@ ibuffer-mode-map
(define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
(define-key map (kbd "/ RET") 'ibuffer-filter-by-mode)
- (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode)
+ (define-key map (kbd "/ m") 'ibuffer-filter-by-used-modes)
(define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode)
(define-key map (kbd "/ n") 'ibuffer-filter-by-name)
(define-key map (kbd "/ *") 'ibuffer-filter-by-starred-name)
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
Repository revision: 41cdda22c78eb0b00612ce25cdb356dd64322fcc
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-15 9:15 ` Tino Calancha
@ 2018-09-15 12:42 ` Noam Postavsky
2018-09-17 17:44 ` Tino Calancha
0 siblings, 1 reply; 28+ messages in thread
From: Noam Postavsky @ 2018-09-15 12:42 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731
Tino Calancha <tino.calancha@gmail.com> writes:
> BTW, I've noticed following commit is missing in the release branch:
> 'Make ibuffer filters idempotent'
> (ee6fe8378a28444cb4913abca4af742f736e9b45)
>
> I suggest we backport it.
> Then, I am OK with the next patch (which uses that commit):
Shouldn't this patch be going into master anyway (since it's adding a
new feature)?
> + (cond ((null (cdr modes)) (ibuffer-filter-by-used-mode (car modes)))
> + (t (let ((composed-filter
We should handle the (null modes) case too, but otherwise looks good to
me.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-15 12:42 ` Noam Postavsky
@ 2018-09-17 17:44 ` Tino Calancha
2018-09-17 18:27 ` Eli Zaretskii
2018-09-18 23:19 ` Noam Postavsky
0 siblings, 2 replies; 28+ messages in thread
From: Tino Calancha @ 2018-09-17 17:44 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731
Noam Postavsky <npostavs@gmail.com> writes:
>Shouldn't this patch be going into master anyway (since it's adding a
>new feature)?
I think is pretty tiny and safe new feature. We can ask Eli anyway
[probably he is reading this right now :-)]
>> + (cond ((null (cdr modes)) (ibuffer-filter-by-used-mode (car modes)))
>> + (t (let ((composed-filter
>
> We should handle the (null modes) case too, but otherwise looks good to
> me.
Yeah, that's right.
* I don't like much such new function
`ibuffer-filter-by-used-modes': isn't it better that
`ibuffer-filter-by-used-mode' handles both inputs?
* Why just 'used modes' and not the other 2
mode filters benefit from this feature?
Because I just use that filter, i.e. '/ m'. A bit selfish.
Please take a look in following patch.
* It allows filtering by >1 mode with the 3 mode filters.
* It moves most of the code inside the macro `define-ibuffer-filter'; no
need to add new functions.
--8<-----------------------------cut here---------------start------------->8---
commit 2079d7b656cef1e1d2c03f3c7e0c93ec135f348d
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Tue Sep 18 02:19:54 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend all mode filters so that they handle >1 mode.
For instance, if the user wants to filter all buffers in
C or C++ mode, then s?he can call the filter interactively
with input: 'c-mode,c++-mode'.
* lisp/ibuf-ext.el (ibuffer-filter-by-used-mode)
(ibuffer-filter-by-mode, ibuffer-filter-by-derived-mode)
Accept a mode name or a list of mode names.
Interactively, accept a comma separated list of mode names.
* lisp/ibuf-macs.el(define-ibuffer-filter): Adjust it to
handle QUALIFIER been a list of symbols.
* etc/NEWS(Ibuffer): Announce this change.
Co-authored-by: Noam Postavsky <npostavs@gmail.com>
diff --git a/etc/NEWS b/etc/NEWS
index fa93112c91..43d9a38b91 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -62,6 +62,10 @@ to reduce differences between developer and production builds.
** Ibuffer
---
+*** All mode filters accept a symbol or a list of symbols, i.e., you
+can filter several major modes with easy.
+
+---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.
** Gnus
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index d9949d2835..2b0292f2de 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1228,28 +1228,33 @@ ibuffer-list-buffer-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 in 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)))
+ (lambda (e)
+ (string-match "-mode\\'" (if (symbolp e) (symbol-name e) 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
- "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 in QUALIFIER.
+QUALIFIER is the mode name as a symbol or a list of symbols.
+
+Called interactively, accept a comma separated list of mode names.
+When called interactively, this function allows selection of modes
currently used by buffers."
(:description "major mode in use"
:reader
@@ -1257,8 +1262,8 @@ used-mode
(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: ")
@@ -1267,11 +1272,13 @@ used-mode
;;;###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 whose major mode inherits from 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 "derived mode"
:reader
- (intern
- (completing-read "Filter by derived mode: "
+ (mapcar #'intern
+ (completing-read-multiple "Filter by derived mode: "
(ibuffer-list-buffer-modes t)
nil t)))
(with-current-buffer buf (derived-mode-p qualifier)))
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 6a70a8341a..7893ec9cae 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -296,21 +296,34 @@ ibuffer-save-marks
\(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)))
+ (let ((,filter (cons ',name qualifier))
+ (,qualifier-str qualifier))
+ ;; The mode filters accept one symbol or a list of symbols; if the
+ ;; user inputs >1 mode, compose the individual filters with `or'.
+ ,(when (memq name (list 'mode 'used-mode 'derived-mode))
+ `(progn
+ (unless (listp qualifier) (setq qualifier (list qualifier)))
+ ;; Reject equivalent filters: (or m1 m2) is same as (or m2 m1).
+ (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)
+ (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
--8<-----------------------------cut here---------------end--------------->8---
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-17 17:44 ` Tino Calancha
@ 2018-09-17 18:27 ` Eli Zaretskii
2018-09-17 19:53 ` Tino Calancha
2018-09-18 23:19 ` Noam Postavsky
1 sibling, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-17 18:27 UTC (permalink / raw)
To: Tino Calancha; +Cc: npostavs, 32731
> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Tue, 18 Sep 2018 02:44:28 +0900
> Cc: 32731@debbugs.gnu.org
>
> Noam Postavsky <npostavs@gmail.com> writes:
>
> >Shouldn't this patch be going into master anyway (since it's adding a
> >new feature)?
> I think is pretty tiny and safe new feature.
"Tiny and safe feature" doesn't necessarily cut it. It has to be
something important. Is it?
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-17 18:27 ` Eli Zaretskii
@ 2018-09-17 19:53 ` Tino Calancha
2018-09-18 7:14 ` Eli Zaretskii
0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-17 19:53 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Tino Calancha, 32731, npostavs
On Mon, 17 Sep 2018, Eli Zaretskii wrote:
>> From: Tino Calancha <tino.calancha@gmail.com>
>> Date: Tue, 18 Sep 2018 02:44:28 +0900
>> Cc: 32731@debbugs.gnu.org
>>
>> Noam Postavsky <npostavs@gmail.com> writes:
>>
>>> Shouldn't this patch be going into master anyway (since it's adding a
>>> new feature)?
>> I think is pretty tiny and safe new feature.
>
> "Tiny and safe feature" doesn't necessarily cut it. It has to be
> something important. Is it?
It's not important; just for convenience.
It doesn't bring anything new: you can get the same result just typing
more keys.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-17 19:53 ` Tino Calancha
@ 2018-09-18 7:14 ` Eli Zaretskii
0 siblings, 0 replies; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-18 7:14 UTC (permalink / raw)
To: Tino Calancha; +Cc: npostavs, 32731
> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Tue, 18 Sep 2018 04:53:56 +0900 (JST)
> cc: Tino Calancha <tino.calancha@gmail.com>, npostavs@gmail.com,
> 32731@debbugs.gnu.org
>
> >> Noam Postavsky <npostavs@gmail.com> writes:
> >>
> >>> Shouldn't this patch be going into master anyway (since it's adding a
> >>> new feature)?
> >> I think is pretty tiny and safe new feature.
> >
> > "Tiny and safe feature" doesn't necessarily cut it. It has to be
> > something important. Is it?
> It's not important; just for convenience.
> It doesn't bring anything new: you can get the same result just typing
> more keys.
Then I think we had better put it on master.
Thanks.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-17 17:44 ` Tino Calancha
2018-09-17 18:27 ` Eli Zaretskii
@ 2018-09-18 23:19 ` Noam Postavsky
2018-09-19 9:23 ` Tino Calancha
1 sibling, 1 reply; 28+ messages in thread
From: Noam Postavsky @ 2018-09-18 23:19 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731
Tino Calancha <tino.calancha@gmail.com> writes:
> * I don't like much such new function
> `ibuffer-filter-by-used-modes': isn't it better that
> `ibuffer-filter-by-used-mode' handles both inputs?
In principle, I agree with this, but there is a drawback to be aware of:
fancier completion modes (e.g., icomplete, ido, etc) don't support
completing-read-multiple. So users of those modes could see this as a
regression.
> * It moves most of the code inside the macro `define-ibuffer-filter'; no
> need to add new functions.
I don't like that define-ibuffer-filter has special code for certain
filter types.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-18 23:19 ` Noam Postavsky
@ 2018-09-19 9:23 ` Tino Calancha
2018-09-19 9:42 ` Eli Zaretskii
0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-19 9:23 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731
Noam Postavsky <npostavs@gmail.com> writes:
> Tino Calancha <tino.calancha@gmail.com> writes:
>
>> * I don't like much such new function
>> `ibuffer-filter-by-used-modes': isn't it better that
>> `ibuffer-filter-by-used-mode' handles both inputs?
>
> In principle, I agree with this, but there is a drawback to be aware of:
> fancier completion modes (e.g., icomplete, ido, etc) don't support
> completing-read-multiple. So users of those modes could see this as a
> regression.
OK. Annotaded here for the records.
>> * It moves most of the code inside the macro `define-ibuffer-filter'; no
>> need to add new functions.
>
> I don't like that define-ibuffer-filter has special code for certain
> filter types.
Me either, but I don't like code duplication either: Macros are a
convenient way to avoid that. Unless you have something sound in mind...
Following patch adds a key :composable, which also serves as
documentation.
--8<-----------------------------cut here---------------start------------->8---
commit 5c6092b172209cb0261f36f423f508bddc4d0dcd
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Wed Sep 19 18:08:35 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend all mode filters so that they handle >1 mode.
For instance, if the user wants to filter all buffers in
C or C++ mode, then s?he can call the filter interactively
with input: 'c-mode,c++-mode'.
* lisp/ibuf-macs.el(define-ibuffer-filter): Add key :composable.
If the value of this key is non-nil, then the filter accepts
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)
Accept a mode name or a list of mode names.
Interactively, accept a comma separated list of mode names.
Set :composable value non-nil.
* etc/NEWS(Ibuffer): Announce this change.
Co-authored-by: Noam Postavsky <npostavs@gmail.com>
diff --git a/etc/NEWS b/etc/NEWS
index fa93112c91..43d9a38b91 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -62,6 +62,10 @@ to reduce differences between developer and production builds.
** Ibuffer
---
+*** All mode filters accept a symbol or a list of symbols, i.e., you
+can filter several major modes with easy.
+
+---
*** New toggle 'ibuffer-do-toggle-lock', bound to 'L'.
** Gnus
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index d9949d2835..fc2e21a77f 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1228,28 +1228,34 @@ ibuffer-list-buffer-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 in 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)))
+ :composable 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 in QUALIFIER.
+QUALIFIER is the mode name as a symbol or a list of symbols.
+
+Called interactively, accept a comma separated list of mode names.
+When called interactively, this function allows selection of modes
currently used by buffers."
(:description "major mode in use"
:reader
@@ -1257,23 +1263,27 @@ used-mode
(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)))
+ :composable 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 whose major mode inherits from 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 "derived mode"
:reader
- (intern
- (completing-read "Filter by derived mode: "
+ (mapcar #'intern
+ (completing-read-multiple "Filter by derived mode: "
(ibuffer-list-buffer-modes t)
- nil t)))
+ nil t))
+ :composable t)
(with-current-buffer buf (derived-mode-p qualifier)))
;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext")
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 6a70a8341a..1030096ec1 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -282,12 +282,16 @@ ibuffer-save-marks
(cl-defmacro define-ibuffer-filter (name documentation
(&key
reader
- description)
+ description
+ composable)
&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.
+COMPOSABLE is a boolean; if non-nil, the filter accepts both,
+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,21 +300,32 @@ ibuffer-save-marks
\(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)))
+ (let ((,filter (cons ',name qualifier))
+ (,qualifier-str qualifier))
+ ,(when composable
+ `(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
--8<-----------------------------cut here---------------end--------------->8---
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-19 9:23 ` Tino Calancha
@ 2018-09-19 9:42 ` Eli Zaretskii
2018-09-21 8:37 ` Tino Calancha
0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-19 9:42 UTC (permalink / raw)
To: Tino Calancha; +Cc: npostavs, 32731
> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Wed, 19 Sep 2018 18:23:52 +0900
> Cc: 32731@debbugs.gnu.org
>
> Following patch adds a key :composable, which also serves as
> documentation.
Thanks, a few nits to the documentation parts:
> ---
> +*** All mode filters accept a symbol or a list of symbols, i.e., you
> +can filter several major modes with easy.
Please try to keep the first line in a NEWS item a single complete
sentence, as much as possible: that allows for more convenient
browsing in Outline mode. In this case, I would break this into two
sentences: a short announcement and followup details:
*** 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.
> ;;;###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 in QUALIFIER.
> +QUALIFIER is the mode name as a symbol or a list of symbols.
In the first sentence, I'd suggest to rephrase:
Limit current view to buffers with major mode(s) specified by QUALIFIER.
because "in QUALIFIER" only covers the case of a list.
Similarly in other doc strings you modified the same way.
> +Called interactively, accept a comma separated list of mode names.
> +When called interactively, this function allows selection of modes
> currently used by buffers."
These two sentences seem to be in contradiction, so they probably need
to be merged or rephrased.
> (cl-defmacro define-ibuffer-filter (name documentation
> (&key
> reader
> - description)
> + description
> + composable)
> &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.
> +COMPOSABLE is a boolean; if non-nil, the filter accepts both,
^
That comma should be deleted, it gets in the way of understanding what
you mean. And I would actually rephrase
if non-nil, the filter accepts either a single condition or a list
of them
because "both" might be interpreted as meaning "and", not "or".
I also wonder whether "COMPOSABLE" is a good name for this argument;
how about ACCEPT-LIST instead?
Thanks for working on this.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-19 9:42 ` Eli Zaretskii
@ 2018-09-21 8:37 ` Tino Calancha
2018-09-22 9:14 ` Eli Zaretskii
2018-09-22 13:00 ` Noam Postavsky
0 siblings, 2 replies; 28+ messages in thread
From: Tino Calancha @ 2018-09-21 8:37 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: npostavs, 32731
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Tino Calancha <tino.calancha@gmail.com>
>> Date: Wed, 19 Sep 2018 18:23:52 +0900
>> Cc: 32731@debbugs.gnu.org
>>
>> Following patch adds a key :composable, which also serves as
>> documentation.
>
> Thanks, a few nits to the documentation parts:
Thank you.
I've amended the patch to address all the nits:
--8<-----------------------------cut here---------------start------------->8---
commit 72e332c986304775e91020c88ded1ba9d7226023
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Fri Sep 21 17:32:57 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend all mode filters so that they handle >1 mode.
For instance, if the user wants to filter all buffers in
C or C++ mode, then s?he 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>
diff --git a/etc/NEWS b/etc/NEWS
index 736955be0c..9f7e0544d5 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -62,6 +62,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'.
** Gnus
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index d9949d2835..e3e0d0b578 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1228,28 +1228,33 @@ ibuffer-list-buffer-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 @@ used-mode
(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)))
+ (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")
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 6a70a8341a..066d9ac2d9 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -282,12 +282,16 @@ ibuffer-save-marks
(cl-defmacro define-ibuffer-filter (name documentation
(&key
reader
- description)
+ 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,29 +300,40 @@ ibuffer-save-marks
\(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)))
+ (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))))))
+ (condition-case nil
+ (progn ,@body)
+ (error (ibuffer-pop-filter)
+ (when (eq ',name 'predicate)
+ (error "Wrong filter predicate: %S"
+ qualifier))))))
ibuffer-filtering-alist)
:autoload-end)))
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 27.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
Repository revision: 7f3877e83405a089b580fe9d0342dc0b6c08cbfc
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-21 8:37 ` Tino Calancha
@ 2018-09-22 9:14 ` Eli Zaretskii
2018-09-22 13:00 ` Noam Postavsky
1 sibling, 0 replies; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-22 9:14 UTC (permalink / raw)
To: Tino Calancha; +Cc: npostavs, 32731
> From: Tino Calancha <tino.calancha@gmail.com>
> Cc: npostavs@gmail.com, 32731@debbugs.gnu.org
> Date: Fri, 21 Sep 2018 17:37:39 +0900
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> >> From: Tino Calancha <tino.calancha@gmail.com>
> >> Date: Wed, 19 Sep 2018 18:23:52 +0900
> >> Cc: 32731@debbugs.gnu.org
> >>
> >> Following patch adds a key :composable, which also serves as
> >> documentation.
> >
> > Thanks, a few nits to the documentation parts:
> Thank you.
> I've amended the patch to address all the nits:
Thanks, this LGTM.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-21 8:37 ` Tino Calancha
2018-09-22 9:14 ` Eli Zaretskii
@ 2018-09-22 13:00 ` Noam Postavsky
2018-09-23 1:37 ` Richard Stallman
2018-09-24 8:36 ` Tino Calancha
1 sibling, 2 replies; 28+ messages in thread
From: Noam Postavsky @ 2018-09-22 13:00 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731
Tino Calancha <tino.calancha@gmail.com> writes:
> commit 72e332c986304775e91020c88ded1ba9d7226023
> Author: Tino Calancha <tino.calancha@gmail.com>
> Date: Fri Sep 21 17:32:57 2018 +0900
>
> Ibuffer filter by modes: Accept several mode names
>
> Extend all mode filters so that they handle >1 mode.
> For instance, if the user wants to filter all buffers in
> C or C++ mode, then s?he can call the filter interactively
If you'll pardon another nit, I suggest using "they" instead of "s?he"
which has the advantage of being a pronounceable English word.
> + (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))))
Since I'm here nitting anyway, I would tweak this code a bit:
(let ((,filter (cons ',name qualifier))
(,qualifier-desc qualifier))
,(when accept-list
`(when (listp qualifier)
(setq ,qualifier-desc
(mapconcat (lambda (m) (if (symbolp m) (symbol-name m) m))
qualifier ","))
(if (null (cdr qualifier))
(setf (cdr ,filter) (car qualifier)) ; Singleton list.
;; Reject equivalent filters: (or f1 f2) is same as (or f2 f1).
(setq qualifier (delete-consecutive-dups
(sort qualifier #'string-lessp)))
;; 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-desc)
(message ,(format "Filter by %s added: %%s" description)
,qualifier-desc)
(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))))))
> + (condition-case nil
> + (progn ,@body)
> + (error (ibuffer-pop-filter)
> + (when (eq ',name 'predicate)
> + (error "Wrong filter predicate: %S"
> + qualifier))))))
> ibuffer-filtering-alist)
> :autoload-end)))
I think this hunk is just changing spaces to tabs (shouldn't .dir-locals
be setting indent-tabs-mode to nil though?).
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-22 13:00 ` Noam Postavsky
@ 2018-09-23 1:37 ` Richard Stallman
2018-09-23 12:01 ` Noam Postavsky
2018-09-24 8:27 ` Tino Calancha
2018-09-24 8:36 ` Tino Calancha
1 sibling, 2 replies; 28+ messages in thread
From: Richard Stallman @ 2018-09-23 1:37 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731, tino.calancha
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> If you'll pardon another nit, I suggest using "they" instead of "s?he"
> which has the advantage of being a pronounceable English word.
Using "they" for a singular antecedent is confusing, and I always find
it jarring. I won't make a rule against, but I make a point of never
using that construction. "S?he" avoids the confusion because it is
clearly singular.
I use a different set of gender-neutral singular pronouns, which I
think fit better into English. See
https://stallman.org/articles/genderless-pronouns.html.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-23 1:37 ` Richard Stallman
@ 2018-09-23 12:01 ` Noam Postavsky
2018-09-24 8:27 ` Tino Calancha
1 sibling, 0 replies; 28+ messages in thread
From: Noam Postavsky @ 2018-09-23 12:01 UTC (permalink / raw)
To: Richard Stallman; +Cc: 32731, tino.calancha
Richard Stallman <rms@gnu.org> writes:
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> > If you'll pardon another nit, I suggest using "they" instead of "s?he"
> > which has the advantage of being a pronounceable English word.
>
> Using "they" for a singular antecedent is confusing, and I always find
> it jarring. I won't make a rule against, but I make a point of never
> using that construction. "S?he" avoids the confusion because it is
> clearly singular.
>
> I use a different set of gender-neutral singular pronouns, which I
> think fit better into English. See
> https://stallman.org/articles/genderless-pronouns.html.
I find "s?he" jarring due to its non-wordness and "per" confusing
because it's already a word which means something else (I end up having
to read the sentence from the beginning again to parse it right). I
expect it's mostly a matter of practice though.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-23 1:37 ` Richard Stallman
2018-09-23 12:01 ` Noam Postavsky
@ 2018-09-24 8:27 ` Tino Calancha
2018-09-24 19:58 ` Richard Stallman
1 sibling, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-24 8:27 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tino Calancha, 32731, Noam Postavsky
On Sat, 22 Sep 2018, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> > If you'll pardon another nit, I suggest using "they" instead of "s?he"
> > which has the advantage of being a pronounceable English word.
>
> Using "they" for a singular antecedent is confusing, and I always find
> it jarring. I won't make a rule against, but I make a point of never
> using that construction. "S?he" avoids the confusion because it is
> clearly singular.
>
> I use a different set of gender-neutral singular pronouns, which I
> think fit better into English. See
> https://stallman.org/articles/genderless-pronouns.html.
How about 'it'? This way we include robots: we shouldn't
discriminate them ;-)
I saw in your site 'he/she'. I rewrote as 'she/he',
otherwise, someone picky might complain about
males been prioritized.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-22 13:00 ` Noam Postavsky
2018-09-23 1:37 ` Richard Stallman
@ 2018-09-24 8:36 ` Tino Calancha
1 sibling, 0 replies; 28+ messages in thread
From: Tino Calancha @ 2018-09-24 8:36 UTC (permalink / raw)
To: Noam Postavsky; +Cc: 32731
Noam Postavsky <npostavs@gmail.com> writes:
> Tino Calancha <tino.calancha@gmail.com> writes:
>
>> commit 72e332c986304775e91020c88ded1ba9d7226023
>> Author: Tino Calancha <tino.calancha@gmail.com>
>> Date: Fri Sep 21 17:32:57 2018 +0900
>>
>> Ibuffer filter by modes: Accept several mode names
>>
>> Extend all mode filters so that they handle >1 mode.
>> For instance, if the user wants to filter all buffers in
>> C or C++ mode, then s?he can call the filter interactively
>
> If you'll pardon another nit, I suggest using "they" instead of "s?he"
> which has the advantage of being a pronounceable English word.
I changed to she/he.
> I think this hunk is just changing spaces to tabs (shouldn't .dir-locals
> be setting indent-tabs-mode to nil though?).
I droped my hand-added tabs (also those I added in ibuf-ext.el).
Actually I don't like tabs in source code (just added as a sign of
respect to the library author).
--8<-----------------------------cut here---------------start------------->8---
commit d385f8077ffed38046231bb29448598484352543
Author: Tino Calancha <tino.calancha@gmail.com>
Date: Mon Sep 24 17:29:48 2018 +0900
Ibuffer filter by modes: Accept several mode names
Extend all mode filters so that they handle >1 mode.
For instance, if the user wants to filter all buffers in
C or C++ mode, then she/he 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>
diff --git a/etc/NEWS b/etc/NEWS
index bc6791b05b..8126354ab8 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -62,6 +62,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'.
** Gnus
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index d9949d2835..32ec91db97 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1228,28 +1228,33 @@ ibuffer-list-buffer-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 @@ used-mode
(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")
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 6a70a8341a..72a35a5331 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -280,14 +280,18 @@ ibuffer-save-marks
;;;###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 @@ ibuffer-save-marks
\(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)
--8<-----------------------------cut here---------------end--------------->8---
^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-24 8:27 ` Tino Calancha
@ 2018-09-24 19:58 ` Richard Stallman
2018-09-24 20:48 ` Tino Calancha
0 siblings, 1 reply; 28+ messages in thread
From: Richard Stallman @ 2018-09-24 19:58 UTC (permalink / raw)
To: Tino Calancha; +Cc: tino.calancha, 32731, npostavs
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
"She/he" seems to exclude nonbinary genders.
"S?he" does not HAVE to mean "only she or he".
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-24 19:58 ` Richard Stallman
@ 2018-09-24 20:48 ` Tino Calancha
2018-09-24 21:14 ` Eli Zaretskii
0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2018-09-24 20:48 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tino Calancha, 32731, npostavs
On Mon, 24 Sep 2018, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> "She/he" seems to exclude nonbinary genders.
> "S?he" does not HAVE to mean "only she or he".
I don't feel excluded if I read "she". Maybe I have enough
self-confidence or I know the difference between
sex and gramatical genre.
Anyway, whatever Eli likes is fine for me.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-24 20:48 ` Tino Calancha
@ 2018-09-24 21:14 ` Eli Zaretskii
2018-09-25 8:14 ` Robert Pluim
0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-24 21:14 UTC (permalink / raw)
To: Tino Calancha; +Cc: 32731, npostavs, rms
> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST)
> Cc: Tino Calancha <tino.calancha@gmail.com>, 32731@debbugs.gnu.org,
> npostavs@gmail.com
>
> > "She/he" seems to exclude nonbinary genders.
> > "S?he" does not HAVE to mean "only she or he".
> I don't feel excluded if I read "she". Maybe I have enough
> self-confidence or I know the difference between
> sex and gramatical genre.
> Anyway, whatever Eli likes is fine for me.
I usually just rewrite the text to be in plural, like "the users"
instead of "the user". Then "they" is correct English.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-24 21:14 ` Eli Zaretskii
@ 2018-09-25 8:14 ` Robert Pluim
2018-09-25 9:24 ` Eli Zaretskii
2018-09-29 9:49 ` Tino Calancha
0 siblings, 2 replies; 28+ messages in thread
From: Robert Pluim @ 2018-09-25 8:14 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Tino Calancha, npostavs, rms, 32731
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Tino Calancha <tino.calancha@gmail.com>
>> Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST)
>> Cc: Tino Calancha <tino.calancha@gmail.com>, 32731@debbugs.gnu.org,
>> npostavs@gmail.com
>>
>> > "She/he" seems to exclude nonbinary genders.
>> > "S?he" does not HAVE to mean "only she or he".
>> I don't feel excluded if I read "she". Maybe I have enough
>> self-confidence or I know the difference between
>> sex and gramatical genre.
>> Anyway, whatever Eli likes is fine for me.
>
> I usually just rewrite the text to be in plural, like "the users"
> instead of "the user". Then "they" is correct English.
Point of order: singular they has been correct English for the last
700 years. Some people donʼt like it, but that doesnʼt make it wrong.
Robert
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-25 8:14 ` Robert Pluim
@ 2018-09-25 9:24 ` Eli Zaretskii
2018-09-25 23:03 ` Richard Stallman
2018-09-29 9:49 ` Tino Calancha
1 sibling, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2018-09-25 9:24 UTC (permalink / raw)
To: Robert Pluim; +Cc: tino.calancha, npostavs, rms, 32731
> From: Robert Pluim <rpluim@gmail.com>
> Cc: Tino Calancha <tino.calancha@gmail.com>, 32731@debbugs.gnu.org, npostavs@gmail.com, rms@gnu.org
> Date: Tue, 25 Sep 2018 10:14:11 +0200
>
> > I usually just rewrite the text to be in plural, like "the users"
> > instead of "the user". Then "they" is correct English.
>
> Point of order: singular they has been correct English for the last
> 700 years. Some people donʼt like it, but that doesnʼt make it wrong.
"Some people" seem to include Richard, who said a few messages ago:
> Using "they" for a singular antecedent is confusing, and I always find
> it jarring. I won't make a rule against, but I make a point of never
> using that construction.
Thus my preference to rewrite in plural.
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-25 9:24 ` Eli Zaretskii
@ 2018-09-25 23:03 ` Richard Stallman
0 siblings, 0 replies; 28+ messages in thread
From: Richard Stallman @ 2018-09-25 23:03 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: rpluim, tino.calancha, 32731, npostavs
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Thus my preference to rewrite in plural.
Please do that,
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names
2018-09-25 8:14 ` Robert Pluim
2018-09-25 9:24 ` Eli Zaretskii
@ 2018-09-29 9:49 ` Tino Calancha
1 sibling, 0 replies; 28+ messages in thread
From: Tino Calancha @ 2018-09-29 9:49 UTC (permalink / raw)
To: 32731-done
Robert Pluim <rpluim@gmail.com> writes:
> Eli Zaretskii <eliz@gnu.org> writes:
>
>>> From: Tino Calancha <tino.calancha@gmail.com>
>>> Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST)
>>> Cc: Tino Calancha <tino.calancha@gmail.com>, 32731@debbugs.gnu.org,
>>> npostavs@gmail.com
>>>
>>> > "She/he" seems to exclude nonbinary genders.
>>> > "S?he" does not HAVE to mean "only she or he".
>>> I don't feel excluded if I read "she". Maybe I have enough
>>> self-confidence or I know the difference between
>>> sex and gramatical genre.
>>> Anyway, whatever Eli likes is fine for me.
>>
>> I usually just rewrite the text to be in plural, like "the users"
>> instead of "the user". Then "they" is correct English.
>
> Point of order: singular they has been correct English for the last
> 700 years. Some people donʼt like it, but that doesnʼt make it wrong.
My grandmother used to say:
"You'll never go to bed without learning a new thing"
[I know, every grandmother says that; same as the best
food is the one prepared by the mother of the person you are asking.]
I will write it in plural. Thank you all for the feedback!
Implemented at master branch as commit
'Ibuffer filter by modes: Accept several mode names'
(2296bf188fc99d66306e71e6decd3d2e176b7ae6)
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2018-09-29 9:49 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-13 18:19 bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Tino Calancha
2018-09-13 19:09 ` Noam Postavsky
2018-09-13 20:04 ` Tino Calancha
2018-09-13 20:38 ` Tino Calancha
2018-09-13 23:39 ` Noam Postavsky
2018-09-15 9:15 ` Tino Calancha
2018-09-15 12:42 ` Noam Postavsky
2018-09-17 17:44 ` Tino Calancha
2018-09-17 18:27 ` Eli Zaretskii
2018-09-17 19:53 ` Tino Calancha
2018-09-18 7:14 ` Eli Zaretskii
2018-09-18 23:19 ` Noam Postavsky
2018-09-19 9:23 ` Tino Calancha
2018-09-19 9:42 ` Eli Zaretskii
2018-09-21 8:37 ` Tino Calancha
2018-09-22 9:14 ` Eli Zaretskii
2018-09-22 13:00 ` Noam Postavsky
2018-09-23 1:37 ` Richard Stallman
2018-09-23 12:01 ` Noam Postavsky
2018-09-24 8:27 ` Tino Calancha
2018-09-24 19:58 ` Richard Stallman
2018-09-24 20:48 ` Tino Calancha
2018-09-24 21:14 ` Eli Zaretskii
2018-09-25 8:14 ` Robert Pluim
2018-09-25 9:24 ` Eli Zaretskii
2018-09-25 23:03 ` Richard Stallman
2018-09-29 9:49 ` Tino Calancha
2018-09-24 8:36 ` Tino Calancha
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.