Package: emacs;
Reported by: Tino Calancha <tino.calancha <at> gmail.com>
Date: Thu, 13 Sep 2018 18:20:02 UTC
Severity: wishlist
Found in version 26.1.50
Done: Tino Calancha <tino.calancha <at> gmail.com>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 32731 in the body.
You can then email your comments to 32731 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Thu, 13 Sep 2018 18:20:02 GMT) Full text and rfc822 format available.Tino Calancha <tino.calancha <at> gmail.com>
:bug-gnu-emacs <at> gnu.org
.
(Thu, 13 Sep 2018 18:20:02 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: bug-gnu-emacs <at> gnu.org Subject: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Fri, 14 Sep 2018 03:19:21 +0900
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 <at> 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
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Thu, 13 Sep 2018 19:10:02 GMT) Full text and rfc822 format available.Message #8 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Thu, 13 Sep 2018 15:09:41 -0400
On 13 September 2018 at 14:19, Tino Calancha <tino.calancha <at> 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)
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Thu, 13 Sep 2018 20:05:01 GMT) Full text and rfc822 format available.Message #11 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com> Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Fri, 14 Sep 2018 05:04:33 +0900 (JST)
On Thu, 13 Sep 2018, Noam Postavsky wrote: > On 13 September 2018 at 14:19, Tino Calancha <tino.calancha <at> 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
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Thu, 13 Sep 2018 20:39:02 GMT) Full text and rfc822 format available.Message #14 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Fri, 14 Sep 2018 05:38:39 +0900
Noam Postavsky <npostavs <at> 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 <at> 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 <at> 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 <at> 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---
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Thu, 13 Sep 2018 23:40:02 GMT) Full text and rfc822 format available.Message #17 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Thu, 13 Sep 2018 19:39:17 -0400
Tino Calancha <tino.calancha <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sat, 15 Sep 2018 09:16:01 GMT) Full text and rfc822 format available.Message #20 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 15 Sep 2018 18:15:18 +0900
Noam Postavsky <npostavs <at> gmail.com> writes: > Tino Calancha <tino.calancha <at> 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 <at> 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 <at> 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
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sat, 15 Sep 2018 12:44:01 GMT) Full text and rfc822 format available.Message #23 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 15 Sep 2018 08:42:54 -0400
Tino Calancha <tino.calancha <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 17 Sep 2018 17:45:01 GMT) Full text and rfc822 format available.Message #26 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 18 Sep 2018 02:44:28 +0900
Noam Postavsky <npostavs <at> 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 <at> 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 <at> 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---
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 17 Sep 2018 18:28:02 GMT) Full text and rfc822 format available.Message #29 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Mon, 17 Sep 2018 21:27:27 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com> > Date: Tue, 18 Sep 2018 02:44:28 +0900 > Cc: 32731 <at> debbugs.gnu.org > > Noam Postavsky <npostavs <at> 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?
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 17 Sep 2018 19:55:02 GMT) Full text and rfc822 format available.Message #32 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: 32731 <at> debbugs.gnu.org, npostavs <at> gmail.com, Tino Calancha <tino.calancha <at> gmail.com> Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 18 Sep 2018 04:53:56 +0900 (JST)
On Mon, 17 Sep 2018, Eli Zaretskii wrote: >> From: Tino Calancha <tino.calancha <at> gmail.com> >> Date: Tue, 18 Sep 2018 02:44:28 +0900 >> Cc: 32731 <at> debbugs.gnu.org >> >> Noam Postavsky <npostavs <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Tue, 18 Sep 2018 07:15:02 GMT) Full text and rfc822 format available.Message #35 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 18 Sep 2018 10:14:19 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com> > Date: Tue, 18 Sep 2018 04:53:56 +0900 (JST) > cc: Tino Calancha <tino.calancha <at> gmail.com>, npostavs <at> gmail.com, > 32731 <at> debbugs.gnu.org > > >> Noam Postavsky <npostavs <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Tue, 18 Sep 2018 23:20:01 GMT) Full text and rfc822 format available.Message #38 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 18 Sep 2018 19:19:34 -0400
Tino Calancha <tino.calancha <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Wed, 19 Sep 2018 09:25:01 GMT) Full text and rfc822 format available.Message #41 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Wed, 19 Sep 2018 18:23:52 +0900
Noam Postavsky <npostavs <at> gmail.com> writes: > Tino Calancha <tino.calancha <at> 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 <at> 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 <at> 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---
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Wed, 19 Sep 2018 09:43:02 GMT) Full text and rfc822 format available.Message #44 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Wed, 19 Sep 2018 12:42:28 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com> > Date: Wed, 19 Sep 2018 18:23:52 +0900 > Cc: 32731 <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Fri, 21 Sep 2018 08:38:02 GMT) Full text and rfc822 format available.Message #47 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Fri, 21 Sep 2018 17:37:39 +0900
Eli Zaretskii <eliz <at> gnu.org> writes: >> From: Tino Calancha <tino.calancha <at> gmail.com> >> Date: Wed, 19 Sep 2018 18:23:52 +0900 >> Cc: 32731 <at> 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 <at> 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 <at> 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
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sat, 22 Sep 2018 09:15:02 GMT) Full text and rfc822 format available.Message #50 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 22 Sep 2018 12:14:05 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com> > Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org > Date: Fri, 21 Sep 2018 17:37:39 +0900 > > Eli Zaretskii <eliz <at> gnu.org> writes: > > >> From: Tino Calancha <tino.calancha <at> gmail.com> > >> Date: Wed, 19 Sep 2018 18:23:52 +0900 > >> Cc: 32731 <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sat, 22 Sep 2018 13:01:02 GMT) Full text and rfc822 format available.Message #53 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: Eli Zaretskii <eliz <at> gnu.org>, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 22 Sep 2018 09:00:10 -0400
Tino Calancha <tino.calancha <at> gmail.com> writes: > commit 72e332c986304775e91020c88ded1ba9d7226023 > Author: Tino Calancha <tino.calancha <at> 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?).
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sun, 23 Sep 2018 03:10:03 GMT) Full text and rfc822 format available.Message #56 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Richard Stallman <rms <at> gnu.org> To: Noam Postavsky <npostavs <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org, tino.calancha <at> gmail.com Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 22 Sep 2018 21:37:27 -0400
[[[ 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)
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Sun, 23 Sep 2018 12:02:01 GMT) Full text and rfc822 format available.Message #59 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Noam Postavsky <npostavs <at> gmail.com> To: Richard Stallman <rms <at> gnu.org> Cc: 32731 <at> debbugs.gnu.org, tino.calancha <at> gmail.com Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sun, 23 Sep 2018 08:01:24 -0400
Richard Stallman <rms <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 24 Sep 2018 08:28:01 GMT) Full text and rfc822 format available.Message #62 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Richard Stallman <rms <at> gnu.org> Cc: 32731 <at> debbugs.gnu.org, Noam Postavsky <npostavs <at> gmail.com>, Tino Calancha <tino.calancha <at> gmail.com> Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Mon, 24 Sep 2018 17:27:42 +0900 (JST)
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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 24 Sep 2018 08:37:02 GMT) Full text and rfc822 format available.Message #65 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Noam Postavsky <npostavs <at> gmail.com> Cc: Eli Zaretskii <eliz <at> gnu.org>, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Mon, 24 Sep 2018 17:36:34 +0900
Noam Postavsky <npostavs <at> gmail.com> writes: > Tino Calancha <tino.calancha <at> gmail.com> writes: > >> commit 72e332c986304775e91020c88ded1ba9d7226023 >> Author: Tino Calancha <tino.calancha <at> 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 <at> 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 <at> 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---
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 24 Sep 2018 19:59:02 GMT) Full text and rfc822 format available.Message #68 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Richard Stallman <rms <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: 32731 <at> debbugs.gnu.org, npostavs <at> gmail.com, tino.calancha <at> gmail.com Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Mon, 24 Sep 2018 15:58:47 -0400
[[[ 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)
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 24 Sep 2018 20:49:02 GMT) Full text and rfc822 format available.Message #71 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: Richard Stallman <rms <at> gnu.org> Cc: 32731 <at> debbugs.gnu.org, npostavs <at> gmail.com, Tino Calancha <tino.calancha <at> gmail.com> Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST)
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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Mon, 24 Sep 2018 21:16:01 GMT) Full text and rfc822 format available.Message #74 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Tino Calancha <tino.calancha <at> gmail.com> Cc: npostavs <at> gmail.com, rms <at> gnu.org, 32731 <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 25 Sep 2018 00:14:54 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com> > Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST) > Cc: Tino Calancha <tino.calancha <at> gmail.com>, 32731 <at> debbugs.gnu.org, > npostavs <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Tue, 25 Sep 2018 08:15:02 GMT) Full text and rfc822 format available.Message #77 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Robert Pluim <rpluim <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org, rms <at> gnu.org, Tino Calancha <tino.calancha <at> gmail.com> Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 25 Sep 2018 10:14:11 +0200
Eli Zaretskii <eliz <at> gnu.org> writes: >> From: Tino Calancha <tino.calancha <at> gmail.com> >> Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST) >> Cc: Tino Calancha <tino.calancha <at> gmail.com>, 32731 <at> debbugs.gnu.org, >> npostavs <at> 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
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Tue, 25 Sep 2018 09:25:02 GMT) Full text and rfc822 format available.Message #80 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Robert Pluim <rpluim <at> gmail.com> Cc: npostavs <at> gmail.com, 32731 <at> debbugs.gnu.org, rms <at> gnu.org, tino.calancha <at> gmail.com Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 25 Sep 2018 12:24:22 +0300
> From: Robert Pluim <rpluim <at> gmail.com> > Cc: Tino Calancha <tino.calancha <at> gmail.com>, 32731 <at> debbugs.gnu.org, npostavs <at> gmail.com, rms <at> 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.
bug-gnu-emacs <at> gnu.org
:bug#32731
; Package emacs
.
(Tue, 25 Sep 2018 23:04:01 GMT) Full text and rfc822 format available.Message #83 received at 32731 <at> debbugs.gnu.org (full text, mbox):
From: Richard Stallman <rms <at> gnu.org> To: Eli Zaretskii <eliz <at> gnu.org> Cc: rpluim <at> gmail.com, 32731 <at> debbugs.gnu.org, npostavs <at> gmail.com, tino.calancha <at> gmail.com Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Tue, 25 Sep 2018 19:03:11 -0400
[[[ 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)
Tino Calancha <tino.calancha <at> gmail.com>
:Tino Calancha <tino.calancha <at> gmail.com>
:Message #88 received at 32731-done <at> debbugs.gnu.org (full text, mbox):
From: Tino Calancha <tino.calancha <at> gmail.com> To: 32731-done <at> debbugs.gnu.org Subject: Re: bug#32731: 26.1.50; Ibuffer filter by mode: Handle >1 mode names Date: Sat, 29 Sep 2018 18:49:03 +0900
Robert Pluim <rpluim <at> gmail.com> writes: > Eli Zaretskii <eliz <at> gnu.org> writes: > >>> From: Tino Calancha <tino.calancha <at> gmail.com> >>> Date: Tue, 25 Sep 2018 05:48:43 +0900 (JST) >>> Cc: Tino Calancha <tino.calancha <at> gmail.com>, 32731 <at> debbugs.gnu.org, >>> npostavs <at> 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)
Debbugs Internal Request <help-debbugs <at> gnu.org>
to internal_control <at> debbugs.gnu.org
.
(Sat, 27 Oct 2018 11:24:05 GMT) Full text and rfc822 format available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.