diff options
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ibuf-ext.el | 347 | ||||
| -rw-r--r-- | lisp/ibuffer.el | 55 |
2 files changed, 322 insertions, 80 deletions
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el index 9ce7b5a4846..7ebfecd3749 100644 --- a/lisp/ibuf-ext.el +++ b/lisp/ibuf-ext.el | |||
| @@ -28,6 +28,13 @@ | |||
| 28 | ;; These functions should be automatically loaded when called, but you | 28 | ;; These functions should be automatically loaded when called, but you |
| 29 | ;; can explicitly (require 'ibuf-ext) in your ~/.emacs to have them | 29 | ;; can explicitly (require 'ibuf-ext) in your ~/.emacs to have them |
| 30 | ;; preloaded. | 30 | ;; preloaded. |
| 31 | ;; | ||
| 32 | ;; For details on the structure of ibuffer filters and filter groups, | ||
| 33 | ;; see the documentation for variables `ibuffer-filtering-qualifiers', | ||
| 34 | ;; `ibuffer-filter-groups', and `ibuffer-saved-filters' in that order. | ||
| 35 | ;; The variable `ibuffer-filtering-alist' contains names and | ||
| 36 | ;; descriptions of the currently defined filters; also see the macro | ||
| 37 | ;; `define-ibuffer-filter'. | ||
| 31 | 38 | ||
| 32 | ;;; Code: | 39 | ;;; Code: |
| 33 | 40 | ||
| @@ -139,19 +146,33 @@ Returns (OLD-FORMAT-DETECTED . UPDATED-SAVED-FILTERS-LIST)." | |||
| 139 | (fixed (mapcar fix-filter filters))) | 146 | (fixed (mapcar fix-filter filters))) |
| 140 | (cons old-format-detected fixed)))) | 147 | (cons old-format-detected fixed)))) |
| 141 | 148 | ||
| 142 | (defcustom ibuffer-saved-filters '(("gnus" | 149 | (defcustom ibuffer-saved-filters '(("programming" |
| 150 | (or (derived-mode . prog-mode) | ||
| 151 | (mode . ess-mode) | ||
| 152 | (mode . compilation-mode))) | ||
| 153 | ("text document" | ||
| 154 | (and (derived-mode . text-mode) | ||
| 155 | (not (starred-name)))) | ||
| 156 | ("TeX" | ||
| 157 | (or (derived-mode . tex-mode) | ||
| 158 | (mode . latex-mode) | ||
| 159 | (mode . context-mode) | ||
| 160 | (mode . ams-tex-mode) | ||
| 161 | (mode . bibtex-mode))) | ||
| 162 | ("web" | ||
| 163 | (or (derived-mode . sgml-mode) | ||
| 164 | (derived-mode . css-mode) | ||
| 165 | (mode . javascript-mode) | ||
| 166 | (mode . js2-mode) | ||
| 167 | (mode . scss-mode) | ||
| 168 | (derived-mode . haml-mode) | ||
| 169 | (mode . sass-mode))) | ||
| 170 | ("gnus" | ||
| 143 | (or (mode . message-mode) | 171 | (or (mode . message-mode) |
| 144 | (mode . mail-mode) | 172 | (mode . mail-mode) |
| 145 | (mode . gnus-group-mode) | 173 | (mode . gnus-group-mode) |
| 146 | (mode . gnus-summary-mode) | 174 | (mode . gnus-summary-mode) |
| 147 | (mode . gnus-article-mode))) | 175 | (mode . gnus-article-mode)))) |
| 148 | ("programming" | ||
| 149 | (or (mode . emacs-lisp-mode) | ||
| 150 | (mode . cperl-mode) | ||
| 151 | (mode . c-mode) | ||
| 152 | (mode . java-mode) | ||
| 153 | (mode . idl-mode) | ||
| 154 | (mode . lisp-mode)))) | ||
| 155 | 176 | ||
| 156 | "An alist mapping saved filter names to filter specifications. | 177 | "An alist mapping saved filter names to filter specifications. |
| 157 | 178 | ||
| @@ -214,8 +235,48 @@ Alternative ways to save the repaired value: | |||
| 214 | ")) | 235 | ")) |
| 215 | 236 | ||
| 216 | (defvar ibuffer-filtering-qualifiers nil | 237 | (defvar ibuffer-filtering-qualifiers nil |
| 217 | "A list like (SYMBOL . QUALIFIER) which filters the current buffer list. | 238 | "A list specifying the filters currently acting on the buffer list. |
| 218 | See also `ibuffer-filtering-alist'.") | 239 | |
| 240 | If this list is nil, then no filters are currently in | ||
| 241 | effect. Otherwise, each element of this list specifies a single | ||
| 242 | filter, and all of the specified filters in the list are applied | ||
| 243 | successively to the buffer list. | ||
| 244 | |||
| 245 | Each filter specification can be of two types: simple or compound. | ||
| 246 | |||
| 247 | A simple filter specification has the form (SYMBOL . QUALIFIER), | ||
| 248 | where SYMBOL is a key in the alist `ibuffer-filtering-alist' that | ||
| 249 | determines the filter function to use and QUALIFIER is the data | ||
| 250 | passed to that function (along with the buffer being considered). | ||
| 251 | |||
| 252 | A compound filter specification can have one of four forms: | ||
| 253 | |||
| 254 | -- (not FILTER-SPEC) | ||
| 255 | |||
| 256 | Represents the logical complement of FILTER-SPEC, which | ||
| 257 | is any single filter specification, simple or compound. | ||
| 258 | The form (not . FILTER-SPEC) is also accepted here. | ||
| 259 | |||
| 260 | -- (and FILTER-SPECS...) | ||
| 261 | |||
| 262 | Represents the logical-and of the filters defined by one or | ||
| 263 | more filter specifications FILTER-SPECS..., where each | ||
| 264 | specification can be simple or compound. Note that and is | ||
| 265 | implicitly applied to the filters in the top-level list. | ||
| 266 | |||
| 267 | -- (or FILTER-SPECS...) | ||
| 268 | |||
| 269 | Represents the logical-or of the filters defined by one or | ||
| 270 | more filter specifications FILTER-SPECS..., where each | ||
| 271 | specification can be simple or compound. | ||
| 272 | |||
| 273 | -- (saved . \"NAME\") | ||
| 274 | |||
| 275 | Represents the filter saved under the string NAME | ||
| 276 | in the alist `ibuffer-saved-filters'. It is an | ||
| 277 | error to name a filter that has not been saved. | ||
| 278 | |||
| 279 | This variable is local to each ibuffer buffer.") | ||
| 219 | 280 | ||
| 220 | ;; This is now frobbed by `define-ibuffer-filter'. | 281 | ;; This is now frobbed by `define-ibuffer-filter'. |
| 221 | (defvar ibuffer-filtering-alist nil | 282 | (defvar ibuffer-filtering-alist nil |
| @@ -247,10 +308,18 @@ to this variable." | |||
| 247 | (defvar ibuffer-compiled-filter-formats nil) | 308 | (defvar ibuffer-compiled-filter-formats nil) |
| 248 | 309 | ||
| 249 | (defvar ibuffer-filter-groups nil | 310 | (defvar ibuffer-filter-groups nil |
| 250 | "A list like ((\"NAME\" ((SYMBOL . QUALIFIER) ...) ...) which groups buffers. | 311 | "An alist giving this buffer's active filter groups, or nil if none. |
| 251 | The SYMBOL should be one from `ibuffer-filtering-alist'. | 312 | |
| 252 | The QUALIFIER should be the same as QUALIFIER in | 313 | This alist maps filter group labels to filter specification |
| 253 | `ibuffer-filtering-qualifiers'.") | 314 | lists. Each element has the form (\"LABEL\" FILTER-SPECS...), |
| 315 | where FILTER-SPECS... represents one or more filter | ||
| 316 | specifications of the same form as allowed as elements of | ||
| 317 | `ibuffer-filtering-qualifiers'. | ||
| 318 | |||
| 319 | Each filter group is displayed as a separate section in the | ||
| 320 | ibuffer list, headed by LABEL and displaying only the buffers | ||
| 321 | that pass through all the filters associated with NAME in this | ||
| 322 | list.") | ||
| 254 | 323 | ||
| 255 | (defcustom ibuffer-show-empty-filter-groups t | 324 | (defcustom ibuffer-show-empty-filter-groups t |
| 256 | "If non-nil, then show the names of filter groups which are empty." | 325 | "If non-nil, then show the names of filter groups which are empty." |
| @@ -260,20 +329,21 @@ The QUALIFIER should be the same as QUALIFIER in | |||
| 260 | (defcustom ibuffer-saved-filter-groups nil | 329 | (defcustom ibuffer-saved-filter-groups nil |
| 261 | "An alist of filtering groups to switch between. | 330 | "An alist of filtering groups to switch between. |
| 262 | 331 | ||
| 263 | This variable should look like ((\"STRING\" QUALIFIERS) | 332 | Each element is of the form (\"NAME\" . FILTER-GROUP-LIST), |
| 264 | (\"STRING\" QUALIFIERS) ...), where | 333 | where NAME is a unique but arbitrary name and FILTER-GROUP-LIST |
| 265 | QUALIFIERS is a list of the same form as | 334 | is a list of filter groups with the same structure as |
| 266 | `ibuffer-filtering-qualifiers'. | 335 | allowed for `ibuffer-filter-groups'. |
| 267 | 336 | ||
| 268 | See also the variables `ibuffer-filter-groups', | 337 | See also the functions `ibuffer-save-filter-groups' and |
| 269 | `ibuffer-filtering-qualifiers', `ibuffer-filtering-alist', and the | 338 | `ibuffer-switch-to-saved-filter-groups' for saving and switching |
| 270 | functions `ibuffer-switch-to-saved-filter-groups', | 339 | between sets of filter groups, and the variable |
| 271 | `ibuffer-save-filter-groups'." | 340 | `ibuffer-save-with-custom' that affects how this information is |
| 341 | saved." | ||
| 272 | :type '(repeat sexp) | 342 | :type '(repeat sexp) |
| 273 | :group 'ibuffer) | 343 | :group 'ibuffer) |
| 274 | 344 | ||
| 275 | (defvar ibuffer-hidden-filter-groups nil | 345 | (defvar ibuffer-hidden-filter-groups nil |
| 276 | "A list of filtering groups which are currently hidden.") | 346 | "The list of filter groups that are currently hidden.") |
| 277 | 347 | ||
| 278 | (defvar ibuffer-filter-group-kill-ring nil) | 348 | (defvar ibuffer-filter-group-kill-ring nil) |
| 279 | 349 | ||
| @@ -602,18 +672,38 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'." | |||
| 602 | 672 | ||
| 603 | ;;;###autoload | 673 | ;;;###autoload |
| 604 | (defun ibuffer-included-in-filters-p (buf filters) | 674 | (defun ibuffer-included-in-filters-p (buf filters) |
| 675 | "Return non-nil if BUF passes all FILTERS. | ||
| 676 | |||
| 677 | BUF is a lisp buffer object, and FILTERS is a list of filter | ||
| 678 | specifications with the same structure as | ||
| 679 | `ibuffer-filtering-qualifiers'." | ||
| 605 | (not | 680 | (not |
| 606 | (memq nil ;; a filter will return nil if it failed | 681 | (memq nil ;; a filter will return nil if it failed |
| 607 | (mapcar | 682 | (mapcar #'(lambda (filter) |
| 608 | ;; filter should be like (TYPE . QUALIFIER), or | 683 | (ibuffer-included-in-filter-p buf filter)) |
| 609 | ;; (or (TYPE . QUALIFIER) (TYPE . QUALIFIER) ...) | 684 | filters)))) |
| 610 | #'(lambda (qual) | 685 | |
| 611 | (ibuffer-included-in-filter-p buf qual)) | 686 | (defun ibuffer-unary-operand (filter) |
| 612 | filters)))) | 687 | "Extracts operand from a unary compound FILTER specification. |
| 688 | |||
| 689 | FILTER should be a cons cell of either form (f . d) or (f d), | ||
| 690 | where operand d is itself a cons cell, or nil. Returns d." | ||
| 691 | (let* ((tail (cdr filter)) | ||
| 692 | (maybe-q (car-safe tail))) | ||
| 693 | (if (consp maybe-q) maybe-q tail))) | ||
| 613 | 694 | ||
| 614 | (defun ibuffer-included-in-filter-p (buf filter) | 695 | (defun ibuffer-included-in-filter-p (buf filter) |
| 696 | "Return non-nil if BUF pass FILTER. | ||
| 697 | |||
| 698 | BUF is a lisp buffer object, and FILTER is a filter | ||
| 699 | specification, with the same structure as an element of the list | ||
| 700 | `ibuffer-filtering-qualifiers'." | ||
| 615 | (if (eq (car filter) 'not) | 701 | (if (eq (car filter) 'not) |
| 616 | (not (ibuffer-included-in-filter-p-1 buf (cdr filter))) | 702 | (let ((inner (ibuffer-unary-operand filter))) |
| 703 | ;; Allows (not (not ...)) etc, which may be overkill | ||
| 704 | (if (eq (car inner) 'not) | ||
| 705 | (ibuffer-included-in-filter-p buf (ibuffer-unary-operand inner)) | ||
| 706 | (not (ibuffer-included-in-filter-p-1 buf inner)))) | ||
| 617 | (ibuffer-included-in-filter-p-1 buf filter))) | 707 | (ibuffer-included-in-filter-p-1 buf filter))) |
| 618 | 708 | ||
| 619 | (defun ibuffer-included-in-filter-p-1 (buf filter) | 709 | (defun ibuffer-included-in-filter-p-1 (buf filter) |
| @@ -621,9 +711,19 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'." | |||
| 621 | (not | 711 | (not |
| 622 | (pcase (car filter) | 712 | (pcase (car filter) |
| 623 | (`or | 713 | (`or |
| 714 | ;;; ATTN: Short-circuiting alternative with parallel structure w/`and | ||
| 715 | ;;(catch 'has-match | ||
| 716 | ;; (dolist (filter-spec (cdr filter) nil) | ||
| 717 | ;; (when (ibuffer-included-in-filter-p buf filter-spec) | ||
| 718 | ;; (throw 'has-match t)))) | ||
| 624 | (memq t (mapcar #'(lambda (x) | 719 | (memq t (mapcar #'(lambda (x) |
| 625 | (ibuffer-included-in-filter-p buf x)) | 720 | (ibuffer-included-in-filter-p buf x)) |
| 626 | (cdr filter)))) | 721 | (cdr filter)))) |
| 722 | (`and | ||
| 723 | (catch 'no-match | ||
| 724 | (dolist (filter-spec (cdr filter) t) | ||
| 725 | (unless (ibuffer-included-in-filter-p buf filter-spec) | ||
| 726 | (throw 'no-match nil))))) | ||
| 627 | (`saved | 727 | (`saved |
| 628 | (let ((data (assoc (cdr filter) ibuffer-saved-filters))) | 728 | (let ((data (assoc (cdr filter) ibuffer-saved-filters))) |
| 629 | (unless data | 729 | (unless data |
| @@ -916,17 +1016,17 @@ group definitions by setting `ibuffer-filter-groups' to nil." | |||
| 916 | (when buf | 1016 | (when buf |
| 917 | (ibuffer-jump-to-buffer (buffer-name buf))))) | 1017 | (ibuffer-jump-to-buffer (buffer-name buf))))) |
| 918 | 1018 | ||
| 919 | (defun ibuffer-push-filter (qualifier) | 1019 | (defun ibuffer-push-filter (filter-specification) |
| 920 | "Add QUALIFIER to `ibuffer-filtering-qualifiers'." | 1020 | "Add FILTER-SPECIFICATION to `ibuffer-filtering-qualifiers'." |
| 921 | (push qualifier ibuffer-filtering-qualifiers)) | 1021 | (push filter-specification ibuffer-filtering-qualifiers)) |
| 922 | 1022 | ||
| 923 | ;;;###autoload | 1023 | ;;;###autoload |
| 924 | (defun ibuffer-decompose-filter () | 1024 | (defun ibuffer-decompose-filter () |
| 925 | "Separate the top compound filter (OR, NOT, or SAVED) in this buffer. | 1025 | "Separate this buffer's top compound filter (AND, OR, NOT, or SAVED). |
| 926 | 1026 | ||
| 927 | This means that the topmost filter on the filtering stack, which must | 1027 | This means that the topmost filter on the filtering stack, which must |
| 928 | be a complex filter like (OR [name: foo] [mode: bar-mode]), will be | 1028 | be a complex filter like (OR [name: foo] [mode: bar-mode]), will be |
| 929 | turned into two separate filters [name: foo] and [mode: bar-mode]." | 1029 | turned into separate filters, like [name: foo] and [mode: bar-mode]." |
| 930 | (interactive) | 1030 | (interactive) |
| 931 | (unless ibuffer-filtering-qualifiers | 1031 | (unless ibuffer-filtering-qualifiers |
| 932 | (error "No filters in effect")) | 1032 | (error "No filters in effect")) |
| @@ -935,14 +1035,14 @@ turned into two separate filters [name: foo] and [mode: bar-mode]." | |||
| 935 | (tail (cdr filters)) | 1035 | (tail (cdr filters)) |
| 936 | (value | 1036 | (value |
| 937 | (pcase (caar filters) | 1037 | (pcase (caar filters) |
| 938 | (`or (nconc head tail)) | 1038 | ((or `or 'and) (nconc head tail)) |
| 939 | (`saved | 1039 | (`saved |
| 940 | (let ((data (assoc head ibuffer-saved-filters))) | 1040 | (let ((data (assoc head ibuffer-saved-filters))) |
| 941 | (unless data | 1041 | (unless data |
| 942 | (ibuffer-filter-disable) | 1042 | (ibuffer-filter-disable) |
| 943 | (error "Unknown saved filter %s" head)) | 1043 | (error "Unknown saved filter %s" head)) |
| 944 | (append (cdr data) tail))) | 1044 | (append (cdr data) tail))) |
| 945 | (`not (cons head tail)) | 1045 | (`not (cons (ibuffer-unary-operand (car filters)) tail)) |
| 946 | (_ | 1046 | (_ |
| 947 | (error "Filter type %s is not compound" (caar filters)))))) | 1047 | (error "Filter type %s is not compound" (caar filters)))))) |
| 948 | (setq ibuffer-filtering-qualifiers value)) | 1048 | (setq ibuffer-filtering-qualifiers value)) |
| @@ -971,31 +1071,36 @@ turned into two separate filters [name: foo] and [mode: bar-mode]." | |||
| 971 | ibuffer-filtering-qualifiers)) | 1071 | ibuffer-filtering-qualifiers)) |
| 972 | (ibuffer-update nil t)) | 1072 | (ibuffer-update nil t)) |
| 973 | 1073 | ||
| 1074 | (defun ibuffer--or-and-filter (op decompose) | ||
| 1075 | (if decompose | ||
| 1076 | (if (eq op (caar ibuffer-filtering-qualifiers)) | ||
| 1077 | (ibuffer-decompose-filter) | ||
| 1078 | (error "Top filter is not an %s" (upcase (symbol-name op)))) | ||
| 1079 | (when (< (length ibuffer-filtering-qualifiers) 2) | ||
| 1080 | (error "Need two filters to %s" (upcase (symbol-name op)))) | ||
| 1081 | ;; If either filter is an op, eliminate unnecessary nesting. | ||
| 1082 | (let ((first (pop ibuffer-filtering-qualifiers)) | ||
| 1083 | (second (pop ibuffer-filtering-qualifiers))) | ||
| 1084 | (push (nconc (if (eq op (car first)) first (list op first)) | ||
| 1085 | (if (eq op (car second)) (cdr second) (list second))) | ||
| 1086 | ibuffer-filtering-qualifiers))) | ||
| 1087 | (ibuffer-update nil t)) | ||
| 1088 | |||
| 974 | ;;;###autoload | 1089 | ;;;###autoload |
| 975 | (defun ibuffer-or-filter (&optional reverse) | 1090 | (defun ibuffer-or-filter (&optional decompose) |
| 976 | "Replace the top two filters in this buffer with their logical OR. | 1091 | "Replace the top two filters in this buffer with their logical OR. |
| 977 | If optional argument REVERSE is non-nil, instead break the top OR | 1092 | If optional argument DECOMPOSE is non-nil, instead break the top OR |
| 978 | filter into parts." | 1093 | filter into parts." |
| 979 | (interactive "P") | 1094 | (interactive "P") |
| 980 | (if reverse | 1095 | (ibuffer--or-and-filter 'or decompose)) |
| 981 | (progn | 1096 | |
| 982 | (when (or (null ibuffer-filtering-qualifiers) | 1097 | ;;;###autoload |
| 983 | (not (eq 'or (caar ibuffer-filtering-qualifiers)))) | 1098 | (defun ibuffer-and-filter (&optional decompose) |
| 984 | (error "Top filter is not an OR")) | 1099 | "Replace the top two filters in this buffer with their logical AND. |
| 985 | (let ((lim (pop ibuffer-filtering-qualifiers))) | 1100 | If optional argument DECOMPOSE is non-nil, instead break the top AND |
| 986 | (setq ibuffer-filtering-qualifiers | 1101 | filter into parts." |
| 987 | (nconc (cdr lim) ibuffer-filtering-qualifiers)))) | 1102 | (interactive "P") |
| 988 | (when (< (length ibuffer-filtering-qualifiers) 2) | 1103 | (ibuffer--or-and-filter 'and decompose)) |
| 989 | (error "Need two filters to OR")) | ||
| 990 | ;; If the second filter is an OR, just add to it. | ||
| 991 | (let ((first (pop ibuffer-filtering-qualifiers)) | ||
| 992 | (second (pop ibuffer-filtering-qualifiers))) | ||
| 993 | (if (eq 'or (car second)) | ||
| 994 | (push (nconc (list 'or first) (cdr second)) | ||
| 995 | ibuffer-filtering-qualifiers) | ||
| 996 | (push (list 'or first second) | ||
| 997 | ibuffer-filtering-qualifiers)))) | ||
| 998 | (ibuffer-update nil t)) | ||
| 999 | 1104 | ||
| 1000 | (defun ibuffer-maybe-save-stuff () | 1105 | (defun ibuffer-maybe-save-stuff () |
| 1001 | (when ibuffer-save-with-custom | 1106 | (when ibuffer-save-with-custom |
| @@ -1069,7 +1174,9 @@ Interactively, prompt for NAME, and use the current filters." | |||
| 1069 | 1174 | ||
| 1070 | (defun ibuffer-format-qualifier (qualifier) | 1175 | (defun ibuffer-format-qualifier (qualifier) |
| 1071 | (if (eq (car-safe qualifier) 'not) | 1176 | (if (eq (car-safe qualifier) 'not) |
| 1072 | (concat " [NOT" (ibuffer-format-qualifier-1 (cdr qualifier)) "]") | 1177 | (concat " [NOT" |
| 1178 | (ibuffer-format-qualifier-1 (ibuffer-unary-operand qualifier)) | ||
| 1179 | "]") | ||
| 1073 | (ibuffer-format-qualifier-1 qualifier))) | 1180 | (ibuffer-format-qualifier-1 qualifier))) |
| 1074 | 1181 | ||
| 1075 | (defun ibuffer-format-qualifier-1 (qualifier) | 1182 | (defun ibuffer-format-qualifier-1 (qualifier) |
| @@ -1078,14 +1185,16 @@ Interactively, prompt for NAME, and use the current filters." | |||
| 1078 | (concat " [filter: " (cdr qualifier) "]")) | 1185 | (concat " [filter: " (cdr qualifier) "]")) |
| 1079 | (`or | 1186 | (`or |
| 1080 | (concat " [OR" (mapconcat #'ibuffer-format-qualifier | 1187 | (concat " [OR" (mapconcat #'ibuffer-format-qualifier |
| 1081 | (cdr qualifier) "") "]")) | 1188 | (cdr qualifier) "") "]")) |
| 1189 | (`and | ||
| 1190 | (concat " [AND" (mapconcat #'ibuffer-format-qualifier | ||
| 1191 | (cdr qualifier) "") "]")) | ||
| 1082 | (_ | 1192 | (_ |
| 1083 | (let ((type (assq (car qualifier) ibuffer-filtering-alist))) | 1193 | (let ((type (assq (car qualifier) ibuffer-filtering-alist))) |
| 1084 | (unless qualifier | 1194 | (unless qualifier |
| 1085 | (error "Ibuffer: bad qualifier %s" qualifier)) | 1195 | (error "Ibuffer: bad qualifier %s" qualifier)) |
| 1086 | (concat " [" (cadr type) ": " (format "%s]" (cdr qualifier))))))) | 1196 | (concat " [" (cadr type) ": " (format "%s]" (cdr qualifier))))))) |
| 1087 | 1197 | ||
| 1088 | |||
| 1089 | (defun ibuffer-list-buffer-modes (&optional include-parents) | 1198 | (defun ibuffer-list-buffer-modes (&optional include-parents) |
| 1090 | "Create a completion table of buffer modes currently in use. | 1199 | "Create a completion table of buffer modes currently in use. |
| 1091 | If INCLUDE-PARENTS is non-nil then include parent modes." | 1200 | If INCLUDE-PARENTS is non-nil then include parent modes." |
| @@ -1103,7 +1212,7 @@ If INCLUDE-PARENTS is non-nil then include parent modes." | |||
| 1103 | 1212 | ||
| 1104 | ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext") | 1213 | ;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext") |
| 1105 | (define-ibuffer-filter mode | 1214 | (define-ibuffer-filter mode |
| 1106 | "Toggle current view to buffers with major mode QUALIFIER." | 1215 | "Limit current view to buffers with major mode QUALIFIER." |
| 1107 | (:description "major mode" | 1216 | (:description "major mode" |
| 1108 | :reader | 1217 | :reader |
| 1109 | (let* ((buf (ibuffer-current-buffer)) | 1218 | (let* ((buf (ibuffer-current-buffer)) |
| @@ -1123,7 +1232,7 @@ If INCLUDE-PARENTS is non-nil then include parent modes." | |||
| 1123 | 1232 | ||
| 1124 | ;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext") | 1233 | ;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext") |
| 1125 | (define-ibuffer-filter used-mode | 1234 | (define-ibuffer-filter used-mode |
| 1126 | "Toggle current view to buffers with major mode QUALIFIER. | 1235 | "Limit current view to buffers with major mode QUALIFIER. |
| 1127 | Called interactively, this function allows selection of modes | 1236 | Called interactively, this function allows selection of modes |
| 1128 | currently used by buffers." | 1237 | currently used by buffers." |
| 1129 | (:description "major mode in use" | 1238 | (:description "major mode in use" |
| @@ -1142,7 +1251,7 @@ currently used by buffers." | |||
| 1142 | 1251 | ||
| 1143 | ;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext") | 1252 | ;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext") |
| 1144 | (define-ibuffer-filter derived-mode | 1253 | (define-ibuffer-filter derived-mode |
| 1145 | "Toggle current view to buffers whose major mode inherits from QUALIFIER." | 1254 | "Limit current view to buffers whose major mode inherits from QUALIFIER." |
| 1146 | (:description "derived mode" | 1255 | (:description "derived mode" |
| 1147 | :reader | 1256 | :reader |
| 1148 | (intern | 1257 | (intern |
| @@ -1153,22 +1262,73 @@ currently used by buffers." | |||
| 1153 | 1262 | ||
| 1154 | ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext") | 1263 | ;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext") |
| 1155 | (define-ibuffer-filter name | 1264 | (define-ibuffer-filter name |
| 1156 | "Toggle current view to buffers with name matching QUALIFIER." | 1265 | "Limit current view to buffers with name matching QUALIFIER." |
| 1157 | (:description "buffer name" | 1266 | (:description "buffer name" |
| 1158 | :reader (read-from-minibuffer "Filter by name (regexp): ")) | 1267 | :reader (read-from-minibuffer "Filter by name (regexp): ")) |
| 1159 | (string-match qualifier (buffer-name buf))) | 1268 | (string-match qualifier (buffer-name buf))) |
| 1160 | 1269 | ||
| 1270 | ;;;###autoload (autoload 'ibuffer-filter-by-starred-name "ibuf-ext") | ||
| 1271 | (define-ibuffer-filter starred-name | ||
| 1272 | "Limit current view to buffers with name beginning and ending | ||
| 1273 | with *, along with an optional suffix of the form digits or | ||
| 1274 | <digits>." | ||
| 1275 | (:description "starred buffer name" | ||
| 1276 | :reader nil) | ||
| 1277 | (string-match "\\`\\*[^*]+\\*\\(?:<[[:digit:]]+>\\)?\\'" (buffer-name buf))) | ||
| 1278 | |||
| 1161 | ;;;###autoload (autoload 'ibuffer-filter-by-filename "ibuf-ext") | 1279 | ;;;###autoload (autoload 'ibuffer-filter-by-filename "ibuf-ext") |
| 1162 | (define-ibuffer-filter filename | 1280 | (define-ibuffer-filter filename |
| 1163 | "Toggle current view to buffers with filename matching QUALIFIER." | 1281 | "Limit current view to buffers with full file name matching QUALIFIER. |
| 1164 | (:description "filename" | 1282 | |
| 1165 | :reader (read-from-minibuffer "Filter by filename (regexp): ")) | 1283 | For example, for a buffer associated with file '/a/b/c.d', this |
| 1284 | matches against '/a/b/c.d'." | ||
| 1285 | (:description "full file name" | ||
| 1286 | :reader (read-from-minibuffer "Filter by full file name (regexp): ")) | ||
| 1166 | (ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name)) | 1287 | (ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name)) |
| 1167 | (string-match qualifier it))) | 1288 | (string-match qualifier it))) |
| 1168 | 1289 | ||
| 1290 | ;;;###autoload (autoload 'ibuffer-filter-by-basename "ibuf-ext") | ||
| 1291 | (define-ibuffer-filter basename | ||
| 1292 | "Limit current view to buffers with file basename matching QUALIFIER. | ||
| 1293 | |||
| 1294 | For example, for a buffer associated with file '/a/b/c.d', this | ||
| 1295 | matches against 'c.d'." | ||
| 1296 | (:description "file basename" | ||
| 1297 | :reader (read-from-minibuffer | ||
| 1298 | "Filter by file name, without directory part (regex): ")) | ||
| 1299 | (ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name)) | ||
| 1300 | (string-match qualifier (file-name-nondirectory it)))) | ||
| 1301 | |||
| 1302 | ;;;###autoload (autoload 'ibuffer-filter-by-file-extension "ibuf-ext") | ||
| 1303 | (define-ibuffer-filter file-extension | ||
| 1304 | "Limit current view to buffers with filename extension matching QUALIFIER. | ||
| 1305 | |||
| 1306 | The separator character (typically `.') is not part of the | ||
| 1307 | pattern. For example, for a buffer associated with file | ||
| 1308 | '/a/b/c.d', this matches against 'd'." | ||
| 1309 | (:description "filename extension" | ||
| 1310 | :reader (read-from-minibuffer | ||
| 1311 | "Filter by filename extension without separator (regex): ")) | ||
| 1312 | (ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name)) | ||
| 1313 | (string-match qualifier (or (file-name-extension it) "")))) | ||
| 1314 | |||
| 1315 | ;;;###autoload (autoload 'ibuffer-filter-by-directory "ibuf-ext") | ||
| 1316 | (define-ibuffer-filter directory | ||
| 1317 | "Limit current view to buffers with directory matching QUALIFIER. | ||
| 1318 | |||
| 1319 | For a buffer associated with file '/a/b/c.d', this matches | ||
| 1320 | against '/a/b'. For a buffer not associated with a file, this | ||
| 1321 | matches against the value of `default-directory' in that buffer." | ||
| 1322 | (:description "directory name" | ||
| 1323 | :reader (read-from-minibuffer "Filter by directory name (regex): ")) | ||
| 1324 | (ibuffer-aif (with-current-buffer buf (ibuffer-buffer-file-name)) | ||
| 1325 | (let ((dirname (file-name-directory it))) | ||
| 1326 | (when dirname (string-match qualifier dirname))) | ||
| 1327 | (when default-directory (string-match qualifier default-directory)))) | ||
| 1328 | |||
| 1169 | ;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext") | 1329 | ;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext") |
| 1170 | (define-ibuffer-filter size-gt | 1330 | (define-ibuffer-filter size-gt |
| 1171 | "Toggle current view to buffers with size greater than QUALIFIER." | 1331 | "Limit current view to buffers with size greater than QUALIFIER." |
| 1172 | (:description "size greater than" | 1332 | (:description "size greater than" |
| 1173 | :reader | 1333 | :reader |
| 1174 | (string-to-number (read-from-minibuffer "Filter by size greater than: "))) | 1334 | (string-to-number (read-from-minibuffer "Filter by size greater than: "))) |
| @@ -1177,16 +1337,30 @@ currently used by buffers." | |||
| 1177 | 1337 | ||
| 1178 | ;;;###autoload (autoload 'ibuffer-filter-by-size-lt "ibuf-ext") | 1338 | ;;;###autoload (autoload 'ibuffer-filter-by-size-lt "ibuf-ext") |
| 1179 | (define-ibuffer-filter size-lt | 1339 | (define-ibuffer-filter size-lt |
| 1180 | "Toggle current view to buffers with size less than QUALIFIER." | 1340 | "Limit current view to buffers with size less than QUALIFIER." |
| 1181 | (:description "size less than" | 1341 | (:description "size less than" |
| 1182 | :reader | 1342 | :reader |
| 1183 | (string-to-number (read-from-minibuffer "Filter by size less than: "))) | 1343 | (string-to-number (read-from-minibuffer "Filter by size less than: "))) |
| 1184 | (< (with-current-buffer buf (buffer-size)) | 1344 | (< (with-current-buffer buf (buffer-size)) |
| 1185 | qualifier)) | 1345 | qualifier)) |
| 1186 | 1346 | ||
| 1347 | ;;;###autoload (autoload 'ibuffer-filter-by-modified "ibuf-ext") | ||
| 1348 | (define-ibuffer-filter modified | ||
| 1349 | "Limit current view to buffers that are marked as modified." | ||
| 1350 | (:description "modified" | ||
| 1351 | :reader nil) | ||
| 1352 | (buffer-modified-p buf)) | ||
| 1353 | |||
| 1354 | ;;;###autoload (autoload 'ibuffer-filter-by-visiting-file "ibuf-ext") | ||
| 1355 | (define-ibuffer-filter visiting-file | ||
| 1356 | "Limit current view to buffers that are visiting a file." | ||
| 1357 | (:description "visiting a file" | ||
| 1358 | :reader nil) | ||
| 1359 | (with-current-buffer buf (buffer-file-name))) | ||
| 1360 | |||
| 1187 | ;;;###autoload (autoload 'ibuffer-filter-by-content "ibuf-ext") | 1361 | ;;;###autoload (autoload 'ibuffer-filter-by-content "ibuf-ext") |
| 1188 | (define-ibuffer-filter content | 1362 | (define-ibuffer-filter content |
| 1189 | "Toggle current view to buffers whose contents match QUALIFIER." | 1363 | "Limit current view to buffers whose contents match QUALIFIER." |
| 1190 | (:description "content" | 1364 | (:description "content" |
| 1191 | :reader (read-from-minibuffer "Filter by content (regexp): ")) | 1365 | :reader (read-from-minibuffer "Filter by content (regexp): ")) |
| 1192 | (with-current-buffer buf | 1366 | (with-current-buffer buf |
| @@ -1196,12 +1370,33 @@ currently used by buffers." | |||
| 1196 | 1370 | ||
| 1197 | ;;;###autoload (autoload 'ibuffer-filter-by-predicate "ibuf-ext") | 1371 | ;;;###autoload (autoload 'ibuffer-filter-by-predicate "ibuf-ext") |
| 1198 | (define-ibuffer-filter predicate | 1372 | (define-ibuffer-filter predicate |
| 1199 | "Toggle current view to buffers for which QUALIFIER returns non-nil." | 1373 | "Limit current view to buffers for which QUALIFIER returns non-nil." |
| 1200 | (:description "predicate" | 1374 | (:description "predicate" |
| 1201 | :reader (read-minibuffer "Filter by predicate (form): ")) | 1375 | :reader (read-minibuffer "Filter by predicate (form): ")) |
| 1202 | (with-current-buffer buf | 1376 | (with-current-buffer buf |
| 1203 | (eval qualifier))) | 1377 | (eval qualifier))) |
| 1204 | 1378 | ||
| 1379 | ;;;###autoload (autoload 'ibuffer-filter-chosen-by-completion "ibuf-ext") | ||
| 1380 | (defun ibuffer-filter-chosen-by-completion () | ||
| 1381 | "Select and apply filter chosen by completion against available filters. | ||
| 1382 | Indicates corresponding key sequences in echo area after filtering. | ||
| 1383 | |||
| 1384 | The completion matches against the filter description text of | ||
| 1385 | each filter in `ibuffer-filtering-alist'." | ||
| 1386 | (interactive) | ||
| 1387 | (let* ((filters (mapcar (lambda (x) (cons (cadr x) (car x))) | ||
| 1388 | ibuffer-filtering-alist)) | ||
| 1389 | (match (completing-read "Filter by: " filters nil t)) | ||
| 1390 | (filter (cdr (assoc match filters))) | ||
| 1391 | (command (intern (concat "ibuffer-filter-by-" (symbol-name filter))))) | ||
| 1392 | (call-interactively command) | ||
| 1393 | (message "%s can be run with key sequences: %s" | ||
| 1394 | command | ||
| 1395 | (mapconcat #'key-description | ||
| 1396 | (where-is-internal command ibuffer-mode-map nil t) | ||
| 1397 | "or ")))) | ||
| 1398 | |||
| 1399 | |||
| 1205 | ;;; Sorting | 1400 | ;;; Sorting |
| 1206 | 1401 | ||
| 1207 | ;;;###autoload | 1402 | ;;;###autoload |
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 94cee329d5a..5a740845bdf 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el | |||
| @@ -518,26 +518,37 @@ directory, like `default-directory'." | |||
| 518 | (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process) | 518 | (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process) |
| 519 | (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode) | 519 | (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode) |
| 520 | 520 | ||
| 521 | (define-key map (kbd "/ RET") 'ibuffer-filter-by-mode) | ||
| 521 | (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode) | 522 | (define-key map (kbd "/ m") 'ibuffer-filter-by-used-mode) |
| 522 | (define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode) | 523 | (define-key map (kbd "/ M") 'ibuffer-filter-by-derived-mode) |
| 523 | (define-key map (kbd "/ n") 'ibuffer-filter-by-name) | 524 | (define-key map (kbd "/ n") 'ibuffer-filter-by-name) |
| 524 | (define-key map (kbd "/ c") 'ibuffer-filter-by-content) | 525 | (define-key map (kbd "/ *") 'ibuffer-filter-by-starred-name) |
| 525 | (define-key map (kbd "/ e") 'ibuffer-filter-by-predicate) | ||
| 526 | (define-key map (kbd "/ f") 'ibuffer-filter-by-filename) | 526 | (define-key map (kbd "/ f") 'ibuffer-filter-by-filename) |
| 527 | (define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt) | 527 | (define-key map (kbd "/ b") 'ibuffer-filter-by-basename) |
| 528 | (define-key map (kbd "/ .") 'ibuffer-filter-by-file-extension) | ||
| 528 | (define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt) | 529 | (define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt) |
| 530 | (define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt) | ||
| 531 | (define-key map (kbd "/ i") 'ibuffer-filter-by-modified) | ||
| 532 | (define-key map (kbd "/ v") 'ibuffer-filter-by-visiting-file) | ||
| 533 | (define-key map (kbd "/ c") 'ibuffer-filter-by-content) | ||
| 534 | (define-key map (kbd "/ e") 'ibuffer-filter-by-predicate) | ||
| 535 | |||
| 529 | (define-key map (kbd "/ r") 'ibuffer-switch-to-saved-filters) | 536 | (define-key map (kbd "/ r") 'ibuffer-switch-to-saved-filters) |
| 530 | (define-key map (kbd "/ a") 'ibuffer-add-saved-filters) | 537 | (define-key map (kbd "/ a") 'ibuffer-add-saved-filters) |
| 531 | (define-key map (kbd "/ x") 'ibuffer-delete-saved-filters) | 538 | (define-key map (kbd "/ x") 'ibuffer-delete-saved-filters) |
| 532 | (define-key map (kbd "/ d") 'ibuffer-decompose-filter) | 539 | (define-key map (kbd "/ d") 'ibuffer-decompose-filter) |
| 533 | (define-key map (kbd "/ s") 'ibuffer-save-filters) | 540 | (define-key map (kbd "/ s") 'ibuffer-save-filters) |
| 534 | (define-key map (kbd "/ p") 'ibuffer-pop-filter) | 541 | (define-key map (kbd "/ p") 'ibuffer-pop-filter) |
| 542 | (define-key map (kbd "/ <up>") 'ibuffer-pop-filter) | ||
| 535 | (define-key map (kbd "/ !") 'ibuffer-negate-filter) | 543 | (define-key map (kbd "/ !") 'ibuffer-negate-filter) |
| 536 | (define-key map (kbd "/ t") 'ibuffer-exchange-filters) | 544 | (define-key map (kbd "/ t") 'ibuffer-exchange-filters) |
| 537 | (define-key map (kbd "/ TAB") 'ibuffer-exchange-filters) | 545 | (define-key map (kbd "/ TAB") 'ibuffer-exchange-filters) |
| 538 | (define-key map (kbd "/ o") 'ibuffer-or-filter) | 546 | (define-key map (kbd "/ o") 'ibuffer-or-filter) |
| 547 | (define-key map (kbd "/ |") 'ibuffer-or-filter) | ||
| 548 | (define-key map (kbd "/ &") 'ibuffer-and-filter) | ||
| 539 | (define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group) | 549 | (define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group) |
| 540 | (define-key map (kbd "/ P") 'ibuffer-pop-filter-group) | 550 | (define-key map (kbd "/ P") 'ibuffer-pop-filter-group) |
| 551 | (define-key map (kbd "/ S-<up>") 'ibuffer-pop-filter-group) | ||
| 541 | (define-key map (kbd "/ D") 'ibuffer-decompose-filter-group) | 552 | (define-key map (kbd "/ D") 'ibuffer-decompose-filter-group) |
| 542 | (define-key map (kbd "/ /") 'ibuffer-filter-disable) | 553 | (define-key map (kbd "/ /") 'ibuffer-filter-disable) |
| 543 | 554 | ||
| @@ -657,13 +668,43 @@ directory, like `default-directory'." | |||
| 657 | ibuffer-filter-by-derived-mode)) | 668 | ibuffer-filter-by-derived-mode)) |
| 658 | (define-key-after map [menu-bar view filter filter-by-name] | 669 | (define-key-after map [menu-bar view filter filter-by-name] |
| 659 | '(menu-item "Add filter by buffer name..." ibuffer-filter-by-name)) | 670 | '(menu-item "Add filter by buffer name..." ibuffer-filter-by-name)) |
| 671 | (define-key-after map [menu-bar view filter filter-by-starred-name] | ||
| 672 | '(menu-item "Add filter by starred buffer name..." | ||
| 673 | ibuffer-filter-by-starred-name | ||
| 674 | :help "List buffers whose names begin with a star")) | ||
| 660 | (define-key-after map [menu-bar view filter filter-by-filename] | 675 | (define-key-after map [menu-bar view filter filter-by-filename] |
| 661 | '(menu-item "Add filter by filename..." ibuffer-filter-by-filename)) | 676 | '(menu-item "Add filter by full filename..." ibuffer-filter-by-filename |
| 677 | :help | ||
| 678 | (concat "For a buffer associated with file '/a/b/c.d', " | ||
| 679 | "list buffer if a given pattern matches '/a/b/c.d'"))) | ||
| 680 | (define-key-after map [menu-bar view filter filter-by-basename] | ||
| 681 | '(menu-item "Add filter by file basename..." | ||
| 682 | ibuffer-filter-by-basename | ||
| 683 | :help (concat "For a buffer associated with file '/a/b/c.d', " | ||
| 684 | "list buffer if a given pattern matches 'c.d'"))) | ||
| 685 | (define-key-after map [menu-bar view filter filter-by-file-extension] | ||
| 686 | '(menu-item "Add filter by file name extension..." | ||
| 687 | ibuffer-filter-by-file-extension | ||
| 688 | :help (concat "For a buffer associated with file '/a/b/c.d', " | ||
| 689 | "list buffer if a given pattern matches 'd'"))) | ||
| 690 | (define-key-after map [menu-bar view filter filter-by-directory] | ||
| 691 | '(menu-item "Add filter by filename's directory..." | ||
| 692 | ibuffer-filter-by-directory | ||
| 693 | :help | ||
| 694 | (concat "For a buffer associated with file '/a/b/c.d', " | ||
| 695 | "list buffer if a given pattern matches '/a/b'"))) | ||
| 662 | (define-key-after map [menu-bar view filter filter-by-size-lt] | 696 | (define-key-after map [menu-bar view filter filter-by-size-lt] |
| 663 | '(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt)) | 697 | '(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt)) |
| 664 | (define-key-after map [menu-bar view filter filter-by-size-gt] | 698 | (define-key-after map [menu-bar view filter filter-by-size-gt] |
| 665 | '(menu-item "Add filter by size greater than..." | 699 | '(menu-item "Add filter by size greater than..." |
| 666 | ibuffer-filter-by-size-gt)) | 700 | ibuffer-filter-by-size-gt)) |
| 701 | (define-key-after map [menu-bar view filter filter-by-modified] | ||
| 702 | '(menu-item "Add filter by modified buffer" ibuffer-filter-by-modified | ||
| 703 | :help "List buffers that are marked as modified")) | ||
| 704 | (define-key-after map [menu-bar view filter filter-by-visiting-file] | ||
| 705 | '(menu-item "Add filter by buffer visiting a file" | ||
| 706 | ibuffer-filter-by-visiting-file | ||
| 707 | :help "List buffers that are visiting files")) | ||
| 667 | (define-key-after map [menu-bar view filter filter-by-content] | 708 | (define-key-after map [menu-bar view filter filter-by-content] |
| 668 | '(menu-item "Add filter by content (regexp)..." | 709 | '(menu-item "Add filter by content (regexp)..." |
| 669 | ibuffer-filter-by-content)) | 710 | ibuffer-filter-by-content)) |
| @@ -673,6 +714,12 @@ directory, like `default-directory'." | |||
| 673 | (define-key-after map [menu-bar view filter pop-filter] | 714 | (define-key-after map [menu-bar view filter pop-filter] |
| 674 | '(menu-item "Remove top filter" ibuffer-pop-filter | 715 | '(menu-item "Remove top filter" ibuffer-pop-filter |
| 675 | :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers))) | 716 | :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers))) |
| 717 | (define-key-after map [menu-bar view filter and-filter] | ||
| 718 | '(menu-item "AND top two filters" ibuffer-and-filter | ||
| 719 | :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers | ||
| 720 | (cdr ibuffer-filtering-qualifiers)) | ||
| 721 | :help | ||
| 722 | "Create a new filter which is the logical AND of the top two filters")) | ||
| 676 | (define-key-after map [menu-bar view filter or-filter] | 723 | (define-key-after map [menu-bar view filter or-filter] |
| 677 | '(menu-item "OR top two filters" ibuffer-or-filter | 724 | '(menu-item "OR top two filters" ibuffer-or-filter |
| 678 | :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers | 725 | :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers |