* 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-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
* 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
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.