mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 08:43:40 -07:00
ibuffer: New filters and commands
Add several new filters and improve documentation. See discussion on: https://lists.gnu.org/archive/html/emacs-devel/2016-11/msg00399.html * lisp/ibuf-ext.el: Add paragraph to file commentary. (ibuffer-saved-filters, ibuffer-filtering-qualifiers) (ibuffer-filter-groups): Update doc string. (ibuffer-unary-operand): Add new function that transparently handles 'not' formats for compound filters. (ibuffer-included-in-filter-p): Handle 'not' fully; update doc string. (ibuffer-included-in-filter-p-1): Handle 'and' compound filters. (ibuffer-decompose-filter): Handle 'and' as well, and handle 'not' consistently with other uses. (ibuffer-and-filter): New defun analogous to 'ibuffer-or-filter'. (ibuffer--or-and-filter): New defun. (ibuffer-or-filter, ibuffer-and-filter): Use it. (ibuffer-format-qualifier): Handle 'and' filters as well. (ibuffer-filter-by-basename, ibuffer-filter-by-file-extension) (ibuffer-filter-by-directory, ibuffer-filter-by-starred-name) (ibuffer-filter-by-modified, ibuffer-filter-by-visiting-file): Add new pre-defined filters. (ibuffer-filter-chosen-by-completion): Add new interactive command for easily choosing a filter from the descriptions. * lisp/ibuffer.el (ibuffer-mode-map): Bind ibuffer-filter-by-basename, ibuffer-filter-by-file-extension, ibuffer-filter-by-starred-name, ibuffer-filter-by-modified, ibuffer-filter-by-visiting-file to '/b', '/.', '/*', '/i', '/v' respectively; bind 'ibuffer-or-filter', 'ibuffer-and-filter', 'ibuffer-pop-filter' ,'ibuffer-pop-filter-group' and 'ibuffer-filter-disable' to '/|', '/&', '/<up>', '/S-<up>' and '/ DEL' respectively. * test/lisp/ibuffer-tests.el (ibuffer-autoload): Add appropriate skip specification. Add menu entries for the new filters. (ibuffer-filter-inclusion-1, ibuffer-filter-inclusion-2 ibuffer-filter-inclusion-3, ibuffer-filter-inclusion-4 ibuffer-filter-inclusion-5, ibuffer-filter-inclusion-6 ibuffer-filter-inclusion-7, ibuffer-filter-inclusion-8 ibuffer-decompose-filter, ibuffer-and-filter ibuffer-or-filter): Add new tests; they are skipped unless ibuf-ext is loaded. ; * etc/NEWS: Add entries for new user-facing features.
This commit is contained in:
parent
f8072cd5c1
commit
35aaa6b6aa
4 changed files with 1009 additions and 81 deletions
21
etc/NEWS
21
etc/NEWS
|
|
@ -332,6 +332,27 @@ bound to 'Buffer-menu-unmark-all-buffers'.
|
|||
|
||||
** Ibuffer
|
||||
|
||||
---
|
||||
*** New filter commands `ibuffer-filter-by-basename',
|
||||
`ibuffer-filter-by-file-extension', `ibuffer-filter-by-directory',
|
||||
`ibuffer-filter-by-starred-name', `ibuffer-filter-by-modified'
|
||||
and `ibuffer-filter-by-visiting-file'; bound respectively
|
||||
to '/b', '/.', '//', '/*', '/i' and '/v'.
|
||||
|
||||
---
|
||||
*** Two new commands 'ibuffer-filter-chosen-by-completion'
|
||||
and `ibuffer-and-filter', the second bound to '/&'.
|
||||
|
||||
---
|
||||
*** The commands `ibuffer-pop-filter', `ibuffer-pop-filter-group',
|
||||
`ibuffer-or-filter' and `ibuffer-filter-disable' have the alternative
|
||||
bindings '/<up>', '/S-<up>', '/|' and '/DEL', respectively.
|
||||
|
||||
---
|
||||
*** The data format specifying filters has been extended to allow
|
||||
explicit logical 'and', and a more flexible form for logical 'not'.
|
||||
See 'ibuffer-filtering-qualifiers' doc string for full details.
|
||||
|
||||
---
|
||||
*** A new command 'ibuffer-copy-buffername-as-kill'; bound
|
||||
to 'B'.
|
||||
|
|
|
|||
347
lisp/ibuf-ext.el
347
lisp/ibuf-ext.el
|
|
@ -28,6 +28,13 @@
|
|||
;; These functions should be automatically loaded when called, but you
|
||||
;; can explicitly (require 'ibuf-ext) in your ~/.emacs to have them
|
||||
;; preloaded.
|
||||
;;
|
||||
;; For details on the structure of ibuffer filters and filter groups,
|
||||
;; see the documentation for variables `ibuffer-filtering-qualifiers',
|
||||
;; `ibuffer-filter-groups', and `ibuffer-saved-filters' in that order.
|
||||
;; The variable `ibuffer-filtering-alist' contains names and
|
||||
;; descriptions of the currently defined filters; also see the macro
|
||||
;; `define-ibuffer-filter'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
|
@ -139,19 +146,33 @@ Returns (OLD-FORMAT-DETECTED . UPDATED-SAVED-FILTERS-LIST)."
|
|||
(fixed (mapcar fix-filter filters)))
|
||||
(cons old-format-detected fixed))))
|
||||
|
||||
(defcustom ibuffer-saved-filters '(("gnus"
|
||||
(defcustom ibuffer-saved-filters '(("programming"
|
||||
(or (derived-mode . prog-mode)
|
||||
(mode . ess-mode)
|
||||
(mode . compilation-mode)))
|
||||
("text document"
|
||||
(and (derived-mode . text-mode)
|
||||
(not (starred-name))))
|
||||
("TeX"
|
||||
(or (derived-mode . tex-mode)
|
||||
(mode . latex-mode)
|
||||
(mode . context-mode)
|
||||
(mode . ams-tex-mode)
|
||||
(mode . bibtex-mode)))
|
||||
("web"
|
||||
(or (derived-mode . sgml-mode)
|
||||
(derived-mode . css-mode)
|
||||
(mode . javascript-mode)
|
||||
(mode . js2-mode)
|
||||
(mode . scss-mode)
|
||||
(derived-mode . haml-mode)
|
||||
(mode . sass-mode)))
|
||||
("gnus"
|
||||
(or (mode . message-mode)
|
||||
(mode . mail-mode)
|
||||
(mode . gnus-group-mode)
|
||||
(mode . gnus-summary-mode)
|
||||
(mode . gnus-article-mode)))
|
||||
("programming"
|
||||
(or (mode . emacs-lisp-mode)
|
||||
(mode . cperl-mode)
|
||||
(mode . c-mode)
|
||||
(mode . java-mode)
|
||||
(mode . idl-mode)
|
||||
(mode . lisp-mode))))
|
||||
(mode . gnus-article-mode))))
|
||||
|
||||
"An alist mapping saved filter names to filter specifications.
|
||||
|
||||
|
|
@ -214,8 +235,48 @@ Alternative ways to save the repaired value:
|
|||
"))
|
||||
|
||||
(defvar ibuffer-filtering-qualifiers nil
|
||||
"A list like (SYMBOL . QUALIFIER) which filters the current buffer list.
|
||||
See also `ibuffer-filtering-alist'.")
|
||||
"A list specifying the filters currently acting on the buffer list.
|
||||
|
||||
If this list is nil, then no filters are currently in
|
||||
effect. Otherwise, each element of this list specifies a single
|
||||
filter, and all of the specified filters in the list are applied
|
||||
successively to the buffer list.
|
||||
|
||||
Each filter specification can be of two types: simple or compound.
|
||||
|
||||
A simple filter specification has the form (SYMBOL . QUALIFIER),
|
||||
where SYMBOL is a key in the alist `ibuffer-filtering-alist' that
|
||||
determines the filter function to use and QUALIFIER is the data
|
||||
passed to that function (along with the buffer being considered).
|
||||
|
||||
A compound filter specification can have one of four forms:
|
||||
|
||||
-- (not FILTER-SPEC)
|
||||
|
||||
Represents the logical complement of FILTER-SPEC, which
|
||||
is any single filter specification, simple or compound.
|
||||
The form (not . FILTER-SPEC) is also accepted here.
|
||||
|
||||
-- (and FILTER-SPECS...)
|
||||
|
||||
Represents the logical-and of the filters defined by one or
|
||||
more filter specifications FILTER-SPECS..., where each
|
||||
specification can be simple or compound. Note that and is
|
||||
implicitly applied to the filters in the top-level list.
|
||||
|
||||
-- (or FILTER-SPECS...)
|
||||
|
||||
Represents the logical-or of the filters defined by one or
|
||||
more filter specifications FILTER-SPECS..., where each
|
||||
specification can be simple or compound.
|
||||
|
||||
-- (saved . \"NAME\")
|
||||
|
||||
Represents the filter saved under the string NAME
|
||||
in the alist `ibuffer-saved-filters'. It is an
|
||||
error to name a filter that has not been saved.
|
||||
|
||||
This variable is local to each ibuffer buffer.")
|
||||
|
||||
;; This is now frobbed by `define-ibuffer-filter'.
|
||||
(defvar ibuffer-filtering-alist nil
|
||||
|
|
@ -247,10 +308,18 @@ to this variable."
|
|||
(defvar ibuffer-compiled-filter-formats nil)
|
||||
|
||||
(defvar ibuffer-filter-groups nil
|
||||
"A list like ((\"NAME\" ((SYMBOL . QUALIFIER) ...) ...) which groups buffers.
|
||||
The SYMBOL should be one from `ibuffer-filtering-alist'.
|
||||
The QUALIFIER should be the same as QUALIFIER in
|
||||
`ibuffer-filtering-qualifiers'.")
|
||||
"An alist giving this buffer's active filter groups, or nil if none.
|
||||
|
||||
This alist maps filter group labels to filter specification
|
||||
lists. Each element has the form (\"LABEL\" FILTER-SPECS...),
|
||||
where FILTER-SPECS... represents one or more filter
|
||||
specifications of the same form as allowed as elements of
|
||||
`ibuffer-filtering-qualifiers'.
|
||||
|
||||
Each filter group is displayed as a separate section in the
|
||||
ibuffer list, headed by LABEL and displaying only the buffers
|
||||
that pass through all the filters associated with NAME in this
|
||||
list.")
|
||||
|
||||
(defcustom ibuffer-show-empty-filter-groups t
|
||||
"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
|
|||
(defcustom ibuffer-saved-filter-groups nil
|
||||
"An alist of filtering groups to switch between.
|
||||
|
||||
This variable should look like ((\"STRING\" QUALIFIERS)
|
||||
(\"STRING\" QUALIFIERS) ...), where
|
||||
QUALIFIERS is a list of the same form as
|
||||
`ibuffer-filtering-qualifiers'.
|
||||
Each element is of the form (\"NAME\" . FILTER-GROUP-LIST),
|
||||
where NAME is a unique but arbitrary name and FILTER-GROUP-LIST
|
||||
is a list of filter groups with the same structure as
|
||||
allowed for `ibuffer-filter-groups'.
|
||||
|
||||
See also the variables `ibuffer-filter-groups',
|
||||
`ibuffer-filtering-qualifiers', `ibuffer-filtering-alist', and the
|
||||
functions `ibuffer-switch-to-saved-filter-groups',
|
||||
`ibuffer-save-filter-groups'."
|
||||
See also the functions `ibuffer-save-filter-groups' and
|
||||
`ibuffer-switch-to-saved-filter-groups' for saving and switching
|
||||
between sets of filter groups, and the variable
|
||||
`ibuffer-save-with-custom' that affects how this information is
|
||||
saved."
|
||||
:type '(repeat sexp)
|
||||
:group 'ibuffer)
|
||||
|
||||
(defvar ibuffer-hidden-filter-groups nil
|
||||
"A list of filtering groups which are currently hidden.")
|
||||
"The list of filter groups that are currently hidden.")
|
||||
|
||||
(defvar ibuffer-filter-group-kill-ring nil)
|
||||
|
||||
|
|
@ -602,18 +672,38 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'."
|
|||
|
||||
;;;###autoload
|
||||
(defun ibuffer-included-in-filters-p (buf filters)
|
||||
"Return non-nil if BUF passes all FILTERS.
|
||||
|
||||
BUF is a lisp buffer object, and FILTERS is a list of filter
|
||||
specifications with the same structure as
|
||||
`ibuffer-filtering-qualifiers'."
|
||||
(not
|
||||
(memq nil ;; a filter will return nil if it failed
|
||||
(mapcar
|
||||
;; filter should be like (TYPE . QUALIFIER), or
|
||||
;; (or (TYPE . QUALIFIER) (TYPE . QUALIFIER) ...)
|
||||
#'(lambda (qual)
|
||||
(ibuffer-included-in-filter-p buf qual))
|
||||
filters))))
|
||||
(mapcar #'(lambda (filter)
|
||||
(ibuffer-included-in-filter-p buf filter))
|
||||
filters))))
|
||||
|
||||
(defun ibuffer-unary-operand (filter)
|
||||
"Extracts operand from a unary compound FILTER specification.
|
||||
|
||||
FILTER should be a cons cell of either form (f . d) or (f d),
|
||||
where operand d is itself a cons cell, or nil. Returns d."
|
||||
(let* ((tail (cdr filter))
|
||||
(maybe-q (car-safe tail)))
|
||||
(if (consp maybe-q) maybe-q tail)))
|
||||
|
||||
(defun ibuffer-included-in-filter-p (buf filter)
|
||||
"Return non-nil if BUF pass FILTER.
|
||||
|
||||
BUF is a lisp buffer object, and FILTER is a filter
|
||||
specification, with the same structure as an element of the list
|
||||
`ibuffer-filtering-qualifiers'."
|
||||
(if (eq (car filter) 'not)
|
||||
(not (ibuffer-included-in-filter-p-1 buf (cdr filter)))
|
||||
(let ((inner (ibuffer-unary-operand filter)))
|
||||
;; Allows (not (not ...)) etc, which may be overkill
|
||||
(if (eq (car inner) 'not)
|
||||
(ibuffer-included-in-filter-p buf (ibuffer-unary-operand inner))
|
||||
(not (ibuffer-included-in-filter-p-1 buf inner))))
|
||||
(ibuffer-included-in-filter-p-1 buf filter)))
|
||||
|
||||
(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'."
|
|||
(not
|
||||
(pcase (car filter)
|
||||
(`or
|
||||
;;; ATTN: Short-circuiting alternative with parallel structure w/`and
|
||||
;;(catch 'has-match
|
||||
;; (dolist (filter-spec (cdr filter) nil)
|
||||
;; (when (ibuffer-included-in-filter-p buf filter-spec)
|
||||
;; (throw 'has-match t))))
|
||||
(memq t (mapcar #'(lambda (x)
|
||||
(ibuffer-included-in-filter-p buf x))
|
||||
(cdr filter))))
|
||||
(ibuffer-included-in-filter-p buf x))
|
||||
(cdr filter))))
|
||||
(`and
|
||||
(catch 'no-match
|
||||
(dolist (filter-spec (cdr filter) t)
|
||||
(unless (ibuffer-included-in-filter-p buf filter-spec)
|
||||
(throw 'no-match nil)))))
|
||||
(`saved
|
||||
(let ((data (assoc (cdr filter) ibuffer-saved-filters)))
|
||||
(unless data
|
||||
|
|
@ -916,17 +1016,17 @@ group definitions by setting `ibuffer-filter-groups' to nil."
|
|||
(when buf
|
||||
(ibuffer-jump-to-buffer (buffer-name buf)))))
|
||||
|
||||
(defun ibuffer-push-filter (qualifier)
|
||||
"Add QUALIFIER to `ibuffer-filtering-qualifiers'."
|
||||
(push qualifier ibuffer-filtering-qualifiers))
|
||||
(defun ibuffer-push-filter (filter-specification)
|
||||
"Add FILTER-SPECIFICATION to `ibuffer-filtering-qualifiers'."
|
||||
(push filter-specification ibuffer-filtering-qualifiers))
|
||||
|
||||
;;;###autoload
|
||||
(defun ibuffer-decompose-filter ()
|
||||
"Separate the top compound filter (OR, NOT, or SAVED) in this buffer.
|
||||
"Separate this buffer's top compound filter (AND, OR, NOT, or SAVED).
|
||||
|
||||
This means that the topmost filter on the filtering stack, which must
|
||||
be a complex filter like (OR [name: foo] [mode: bar-mode]), will be
|
||||
turned into two separate filters [name: foo] and [mode: bar-mode]."
|
||||
turned into separate filters, like [name: foo] and [mode: bar-mode]."
|
||||
(interactive)
|
||||
(unless ibuffer-filtering-qualifiers
|
||||
(error "No filters in effect"))
|
||||
|
|
@ -935,14 +1035,14 @@ turned into two separate filters [name: foo] and [mode: bar-mode]."
|
|||
(tail (cdr filters))
|
||||
(value
|
||||
(pcase (caar filters)
|
||||
(`or (nconc head tail))
|
||||
((or `or 'and) (nconc head tail))
|
||||
(`saved
|
||||
(let ((data (assoc head ibuffer-saved-filters)))
|
||||
(unless data
|
||||
(ibuffer-filter-disable)
|
||||
(error "Unknown saved filter %s" head))
|
||||
(append (cdr data) tail)))
|
||||
(`not (cons head tail))
|
||||
(`not (cons (ibuffer-unary-operand (car filters)) tail))
|
||||
(_
|
||||
(error "Filter type %s is not compound" (caar filters))))))
|
||||
(setq ibuffer-filtering-qualifiers value))
|
||||
|
|
@ -971,31 +1071,36 @@ turned into two separate filters [name: foo] and [mode: bar-mode]."
|
|||
ibuffer-filtering-qualifiers))
|
||||
(ibuffer-update nil t))
|
||||
|
||||
(defun ibuffer--or-and-filter (op decompose)
|
||||
(if decompose
|
||||
(if (eq op (caar ibuffer-filtering-qualifiers))
|
||||
(ibuffer-decompose-filter)
|
||||
(error "Top filter is not an %s" (upcase (symbol-name op))))
|
||||
(when (< (length ibuffer-filtering-qualifiers) 2)
|
||||
(error "Need two filters to %s" (upcase (symbol-name op))))
|
||||
;; If either filter is an op, eliminate unnecessary nesting.
|
||||
(let ((first (pop ibuffer-filtering-qualifiers))
|
||||
(second (pop ibuffer-filtering-qualifiers)))
|
||||
(push (nconc (if (eq op (car first)) first (list op first))
|
||||
(if (eq op (car second)) (cdr second) (list second)))
|
||||
ibuffer-filtering-qualifiers)))
|
||||
(ibuffer-update nil t))
|
||||
|
||||
;;;###autoload
|
||||
(defun ibuffer-or-filter (&optional reverse)
|
||||
(defun ibuffer-or-filter (&optional decompose)
|
||||
"Replace the top two filters in this buffer with their logical OR.
|
||||
If optional argument REVERSE is non-nil, instead break the top OR
|
||||
If optional argument DECOMPOSE is non-nil, instead break the top OR
|
||||
filter into parts."
|
||||
(interactive "P")
|
||||
(if reverse
|
||||
(progn
|
||||
(when (or (null ibuffer-filtering-qualifiers)
|
||||
(not (eq 'or (caar ibuffer-filtering-qualifiers))))
|
||||
(error "Top filter is not an OR"))
|
||||
(let ((lim (pop ibuffer-filtering-qualifiers)))
|
||||
(setq ibuffer-filtering-qualifiers
|
||||
(nconc (cdr lim) ibuffer-filtering-qualifiers))))
|
||||
(when (< (length ibuffer-filtering-qualifiers) 2)
|
||||
(error "Need two filters to OR"))
|
||||
;; If the second filter is an OR, just add to it.
|
||||
(let ((first (pop ibuffer-filtering-qualifiers))
|
||||
(second (pop ibuffer-filtering-qualifiers)))
|
||||
(if (eq 'or (car second))
|
||||
(push (nconc (list 'or first) (cdr second))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'or first second)
|
||||
ibuffer-filtering-qualifiers))))
|
||||
(ibuffer-update nil t))
|
||||
(ibuffer--or-and-filter 'or decompose))
|
||||
|
||||
;;;###autoload
|
||||
(defun ibuffer-and-filter (&optional decompose)
|
||||
"Replace the top two filters in this buffer with their logical AND.
|
||||
If optional argument DECOMPOSE is non-nil, instead break the top AND
|
||||
filter into parts."
|
||||
(interactive "P")
|
||||
(ibuffer--or-and-filter 'and decompose))
|
||||
|
||||
(defun ibuffer-maybe-save-stuff ()
|
||||
(when ibuffer-save-with-custom
|
||||
|
|
@ -1069,7 +1174,9 @@ Interactively, prompt for NAME, and use the current filters."
|
|||
|
||||
(defun ibuffer-format-qualifier (qualifier)
|
||||
(if (eq (car-safe qualifier) 'not)
|
||||
(concat " [NOT" (ibuffer-format-qualifier-1 (cdr qualifier)) "]")
|
||||
(concat " [NOT"
|
||||
(ibuffer-format-qualifier-1 (ibuffer-unary-operand qualifier))
|
||||
"]")
|
||||
(ibuffer-format-qualifier-1 qualifier)))
|
||||
|
||||
(defun ibuffer-format-qualifier-1 (qualifier)
|
||||
|
|
@ -1078,14 +1185,16 @@ Interactively, prompt for NAME, and use the current filters."
|
|||
(concat " [filter: " (cdr qualifier) "]"))
|
||||
(`or
|
||||
(concat " [OR" (mapconcat #'ibuffer-format-qualifier
|
||||
(cdr qualifier) "") "]"))
|
||||
(cdr qualifier) "") "]"))
|
||||
(`and
|
||||
(concat " [AND" (mapconcat #'ibuffer-format-qualifier
|
||||
(cdr qualifier) "") "]"))
|
||||
(_
|
||||
(let ((type (assq (car qualifier) ibuffer-filtering-alist)))
|
||||
(unless qualifier
|
||||
(error "Ibuffer: bad qualifier %s" qualifier))
|
||||
(error "Ibuffer: bad qualifier %s" qualifier))
|
||||
(concat " [" (cadr type) ": " (format "%s]" (cdr qualifier)))))))
|
||||
|
||||
|
||||
(defun ibuffer-list-buffer-modes (&optional include-parents)
|
||||
"Create a completion table of buffer modes currently in use.
|
||||
If INCLUDE-PARENTS is non-nil then include parent modes."
|
||||
|
|
@ -1103,7 +1212,7 @@ If INCLUDE-PARENTS is non-nil then include parent modes."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-mode "ibuf-ext")
|
||||
(define-ibuffer-filter mode
|
||||
"Toggle current view to buffers with major mode QUALIFIER."
|
||||
"Limit current view to buffers with major mode QUALIFIER."
|
||||
(:description "major mode"
|
||||
:reader
|
||||
(let* ((buf (ibuffer-current-buffer))
|
||||
|
|
@ -1123,7 +1232,7 @@ If INCLUDE-PARENTS is non-nil then include parent modes."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-used-mode "ibuf-ext")
|
||||
(define-ibuffer-filter used-mode
|
||||
"Toggle current view to buffers with major mode QUALIFIER.
|
||||
"Limit current view to buffers with major mode QUALIFIER.
|
||||
Called interactively, this function allows selection of modes
|
||||
currently used by buffers."
|
||||
(:description "major mode in use"
|
||||
|
|
@ -1142,7 +1251,7 @@ currently used by buffers."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-derived-mode "ibuf-ext")
|
||||
(define-ibuffer-filter derived-mode
|
||||
"Toggle current view to buffers whose major mode inherits from QUALIFIER."
|
||||
"Limit current view to buffers whose major mode inherits from QUALIFIER."
|
||||
(:description "derived mode"
|
||||
:reader
|
||||
(intern
|
||||
|
|
@ -1153,22 +1262,73 @@ currently used by buffers."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-name "ibuf-ext")
|
||||
(define-ibuffer-filter name
|
||||
"Toggle current view to buffers with name matching QUALIFIER."
|
||||
"Limit current view to buffers with name matching QUALIFIER."
|
||||
(:description "buffer name"
|
||||
:reader (read-from-minibuffer "Filter by name (regexp): "))
|
||||
(string-match qualifier (buffer-name buf)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-starred-name "ibuf-ext")
|
||||
(define-ibuffer-filter starred-name
|
||||
"Limit current view to buffers with name beginning and ending
|
||||
with *, along with an optional suffix of the form digits or
|
||||
<digits>."
|
||||
(:description "starred buffer name"
|
||||
:reader nil)
|
||||
(string-match "\\`\\*[^*]+\\*\\(?:<[[:digit:]]+>\\)?\\'" (buffer-name buf)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-filename "ibuf-ext")
|
||||
(define-ibuffer-filter filename
|
||||
"Toggle current view to buffers with filename matching QUALIFIER."
|
||||
(:description "filename"
|
||||
:reader (read-from-minibuffer "Filter by filename (regexp): "))
|
||||
"Limit current view to buffers with full file name matching QUALIFIER.
|
||||
|
||||
For example, for a buffer associated with file '/a/b/c.d', this
|
||||
matches against '/a/b/c.d'."
|
||||
(:description "full file name"
|
||||
:reader (read-from-minibuffer "Filter by full file name (regexp): "))
|
||||
(ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name))
|
||||
(string-match qualifier it)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-basename "ibuf-ext")
|
||||
(define-ibuffer-filter basename
|
||||
"Limit current view to buffers with file basename matching QUALIFIER.
|
||||
|
||||
For example, for a buffer associated with file '/a/b/c.d', this
|
||||
matches against 'c.d'."
|
||||
(:description "file basename"
|
||||
:reader (read-from-minibuffer
|
||||
"Filter by file name, without directory part (regex): "))
|
||||
(ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name))
|
||||
(string-match qualifier (file-name-nondirectory it))))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-file-extension "ibuf-ext")
|
||||
(define-ibuffer-filter file-extension
|
||||
"Limit current view to buffers with filename extension matching QUALIFIER.
|
||||
|
||||
The separator character (typically `.') is not part of the
|
||||
pattern. For example, for a buffer associated with file
|
||||
'/a/b/c.d', this matches against 'd'."
|
||||
(:description "filename extension"
|
||||
:reader (read-from-minibuffer
|
||||
"Filter by filename extension without separator (regex): "))
|
||||
(ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name))
|
||||
(string-match qualifier (or (file-name-extension it) ""))))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-directory "ibuf-ext")
|
||||
(define-ibuffer-filter directory
|
||||
"Limit current view to buffers with directory matching QUALIFIER.
|
||||
|
||||
For a buffer associated with file '/a/b/c.d', this matches
|
||||
against '/a/b'. For a buffer not associated with a file, this
|
||||
matches against the value of `default-directory' in that buffer."
|
||||
(:description "directory name"
|
||||
:reader (read-from-minibuffer "Filter by directory name (regex): "))
|
||||
(ibuffer-aif (with-current-buffer buf (ibuffer-buffer-file-name))
|
||||
(let ((dirname (file-name-directory it)))
|
||||
(when dirname (string-match qualifier dirname)))
|
||||
(when default-directory (string-match qualifier default-directory))))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext")
|
||||
(define-ibuffer-filter size-gt
|
||||
"Toggle current view to buffers with size greater than QUALIFIER."
|
||||
"Limit current view to buffers with size greater than QUALIFIER."
|
||||
(:description "size greater than"
|
||||
:reader
|
||||
(string-to-number (read-from-minibuffer "Filter by size greater than: ")))
|
||||
|
|
@ -1177,16 +1337,30 @@ currently used by buffers."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-size-lt "ibuf-ext")
|
||||
(define-ibuffer-filter size-lt
|
||||
"Toggle current view to buffers with size less than QUALIFIER."
|
||||
"Limit current view to buffers with size less than QUALIFIER."
|
||||
(:description "size less than"
|
||||
:reader
|
||||
(string-to-number (read-from-minibuffer "Filter by size less than: ")))
|
||||
(< (with-current-buffer buf (buffer-size))
|
||||
qualifier))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-modified "ibuf-ext")
|
||||
(define-ibuffer-filter modified
|
||||
"Limit current view to buffers that are marked as modified."
|
||||
(:description "modified"
|
||||
:reader nil)
|
||||
(buffer-modified-p buf))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-visiting-file "ibuf-ext")
|
||||
(define-ibuffer-filter visiting-file
|
||||
"Limit current view to buffers that are visiting a file."
|
||||
(:description "visiting a file"
|
||||
:reader nil)
|
||||
(with-current-buffer buf (buffer-file-name)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-content "ibuf-ext")
|
||||
(define-ibuffer-filter content
|
||||
"Toggle current view to buffers whose contents match QUALIFIER."
|
||||
"Limit current view to buffers whose contents match QUALIFIER."
|
||||
(:description "content"
|
||||
:reader (read-from-minibuffer "Filter by content (regexp): "))
|
||||
(with-current-buffer buf
|
||||
|
|
@ -1196,12 +1370,33 @@ currently used by buffers."
|
|||
|
||||
;;;###autoload (autoload 'ibuffer-filter-by-predicate "ibuf-ext")
|
||||
(define-ibuffer-filter predicate
|
||||
"Toggle current view to buffers for which QUALIFIER returns non-nil."
|
||||
"Limit current view to buffers for which QUALIFIER returns non-nil."
|
||||
(:description "predicate"
|
||||
:reader (read-minibuffer "Filter by predicate (form): "))
|
||||
(with-current-buffer buf
|
||||
(eval qualifier)))
|
||||
|
||||
;;;###autoload (autoload 'ibuffer-filter-chosen-by-completion "ibuf-ext")
|
||||
(defun ibuffer-filter-chosen-by-completion ()
|
||||
"Select and apply filter chosen by completion against available filters.
|
||||
Indicates corresponding key sequences in echo area after filtering.
|
||||
|
||||
The completion matches against the filter description text of
|
||||
each filter in `ibuffer-filtering-alist'."
|
||||
(interactive)
|
||||
(let* ((filters (mapcar (lambda (x) (cons (cadr x) (car x)))
|
||||
ibuffer-filtering-alist))
|
||||
(match (completing-read "Filter by: " filters nil t))
|
||||
(filter (cdr (assoc match filters)))
|
||||
(command (intern (concat "ibuffer-filter-by-" (symbol-name filter)))))
|
||||
(call-interactively command)
|
||||
(message "%s can be run with key sequences: %s"
|
||||
command
|
||||
(mapconcat #'key-description
|
||||
(where-is-internal command ibuffer-mode-map nil t)
|
||||
"or "))))
|
||||
|
||||
|
||||
;;; Sorting
|
||||
|
||||
;;;###autoload
|
||||
|
|
|
|||
|
|
@ -518,26 +518,37 @@ directory, like `default-directory'."
|
|||
(define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process)
|
||||
(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-derived-mode)
|
||||
(define-key map (kbd "/ n") 'ibuffer-filter-by-name)
|
||||
(define-key map (kbd "/ *") 'ibuffer-filter-by-starred-name)
|
||||
(define-key map (kbd "/ f") 'ibuffer-filter-by-filename)
|
||||
(define-key map (kbd "/ b") 'ibuffer-filter-by-basename)
|
||||
(define-key map (kbd "/ .") 'ibuffer-filter-by-file-extension)
|
||||
(define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt)
|
||||
(define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt)
|
||||
(define-key map (kbd "/ i") 'ibuffer-filter-by-modified)
|
||||
(define-key map (kbd "/ v") 'ibuffer-filter-by-visiting-file)
|
||||
(define-key map (kbd "/ c") 'ibuffer-filter-by-content)
|
||||
(define-key map (kbd "/ e") 'ibuffer-filter-by-predicate)
|
||||
(define-key map (kbd "/ f") 'ibuffer-filter-by-filename)
|
||||
(define-key map (kbd "/ >") 'ibuffer-filter-by-size-gt)
|
||||
(define-key map (kbd "/ <") 'ibuffer-filter-by-size-lt)
|
||||
|
||||
(define-key map (kbd "/ r") 'ibuffer-switch-to-saved-filters)
|
||||
(define-key map (kbd "/ a") 'ibuffer-add-saved-filters)
|
||||
(define-key map (kbd "/ x") 'ibuffer-delete-saved-filters)
|
||||
(define-key map (kbd "/ d") 'ibuffer-decompose-filter)
|
||||
(define-key map (kbd "/ s") 'ibuffer-save-filters)
|
||||
(define-key map (kbd "/ p") 'ibuffer-pop-filter)
|
||||
(define-key map (kbd "/ <up>") 'ibuffer-pop-filter)
|
||||
(define-key map (kbd "/ !") 'ibuffer-negate-filter)
|
||||
(define-key map (kbd "/ t") 'ibuffer-exchange-filters)
|
||||
(define-key map (kbd "/ TAB") 'ibuffer-exchange-filters)
|
||||
(define-key map (kbd "/ o") 'ibuffer-or-filter)
|
||||
(define-key map (kbd "/ |") 'ibuffer-or-filter)
|
||||
(define-key map (kbd "/ &") 'ibuffer-and-filter)
|
||||
(define-key map (kbd "/ g") 'ibuffer-filters-to-filter-group)
|
||||
(define-key map (kbd "/ P") 'ibuffer-pop-filter-group)
|
||||
(define-key map (kbd "/ S-<up>") 'ibuffer-pop-filter-group)
|
||||
(define-key map (kbd "/ D") 'ibuffer-decompose-filter-group)
|
||||
(define-key map (kbd "/ /") 'ibuffer-filter-disable)
|
||||
|
||||
|
|
@ -657,13 +668,43 @@ directory, like `default-directory'."
|
|||
ibuffer-filter-by-derived-mode))
|
||||
(define-key-after map [menu-bar view filter filter-by-name]
|
||||
'(menu-item "Add filter by buffer name..." ibuffer-filter-by-name))
|
||||
(define-key-after map [menu-bar view filter filter-by-starred-name]
|
||||
'(menu-item "Add filter by starred buffer name..."
|
||||
ibuffer-filter-by-starred-name
|
||||
:help "List buffers whose names begin with a star"))
|
||||
(define-key-after map [menu-bar view filter filter-by-filename]
|
||||
'(menu-item "Add filter by filename..." ibuffer-filter-by-filename))
|
||||
'(menu-item "Add filter by full filename..." ibuffer-filter-by-filename
|
||||
:help
|
||||
(concat "For a buffer associated with file '/a/b/c.d', "
|
||||
"list buffer if a given pattern matches '/a/b/c.d'")))
|
||||
(define-key-after map [menu-bar view filter filter-by-basename]
|
||||
'(menu-item "Add filter by file basename..."
|
||||
ibuffer-filter-by-basename
|
||||
:help (concat "For a buffer associated with file '/a/b/c.d', "
|
||||
"list buffer if a given pattern matches 'c.d'")))
|
||||
(define-key-after map [menu-bar view filter filter-by-file-extension]
|
||||
'(menu-item "Add filter by file name extension..."
|
||||
ibuffer-filter-by-file-extension
|
||||
:help (concat "For a buffer associated with file '/a/b/c.d', "
|
||||
"list buffer if a given pattern matches 'd'")))
|
||||
(define-key-after map [menu-bar view filter filter-by-directory]
|
||||
'(menu-item "Add filter by filename's directory..."
|
||||
ibuffer-filter-by-directory
|
||||
:help
|
||||
(concat "For a buffer associated with file '/a/b/c.d', "
|
||||
"list buffer if a given pattern matches '/a/b'")))
|
||||
(define-key-after map [menu-bar view filter filter-by-size-lt]
|
||||
'(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt))
|
||||
(define-key-after map [menu-bar view filter filter-by-size-gt]
|
||||
'(menu-item "Add filter by size greater than..."
|
||||
ibuffer-filter-by-size-gt))
|
||||
(define-key-after map [menu-bar view filter filter-by-modified]
|
||||
'(menu-item "Add filter by modified buffer" ibuffer-filter-by-modified
|
||||
:help "List buffers that are marked as modified"))
|
||||
(define-key-after map [menu-bar view filter filter-by-visiting-file]
|
||||
'(menu-item "Add filter by buffer visiting a file"
|
||||
ibuffer-filter-by-visiting-file
|
||||
:help "List buffers that are visiting files"))
|
||||
(define-key-after map [menu-bar view filter filter-by-content]
|
||||
'(menu-item "Add filter by content (regexp)..."
|
||||
ibuffer-filter-by-content))
|
||||
|
|
@ -673,6 +714,12 @@ directory, like `default-directory'."
|
|||
(define-key-after map [menu-bar view filter pop-filter]
|
||||
'(menu-item "Remove top filter" ibuffer-pop-filter
|
||||
:enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
|
||||
(define-key-after map [menu-bar view filter and-filter]
|
||||
'(menu-item "AND top two filters" ibuffer-and-filter
|
||||
:enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
|
||||
(cdr ibuffer-filtering-qualifiers))
|
||||
:help
|
||||
"Create a new filter which is the logical AND of the top two filters"))
|
||||
(define-key-after map [menu-bar view filter or-filter]
|
||||
'(menu-item "OR top two filters" ibuffer-or-filter
|
||||
:enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
(require 'ibuf-macs))
|
||||
|
||||
(ert-deftest ibuffer-autoload ()
|
||||
"Tests to see whether reftex-auc has been autoloaded"
|
||||
"Tests to see whether ibuffer has been autoloaded"
|
||||
(skip-unless (not (featurep 'ibuf-ext)))
|
||||
(should
|
||||
(fboundp 'ibuffer-mark-unsaved-buffers))
|
||||
(should
|
||||
|
|
@ -138,5 +139,669 @@
|
|||
(should-not ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers filters))))
|
||||
|
||||
;; Test Filter Inclusion
|
||||
(let* (test-buffer-list ; accumulated buffers to clean up
|
||||
;; Utility functions without polluting the environment
|
||||
(set-buffer-mode
|
||||
(lambda (buffer mode)
|
||||
"Set BUFFER's major mode to MODE, a mode function, or fundamental."
|
||||
(with-current-buffer buffer
|
||||
(funcall (or mode #'fundamental-mode)))))
|
||||
(set-buffer-contents
|
||||
(lambda (buffer size include-content)
|
||||
"Add exactly SIZE bytes to BUFFER, including INCLUDE-CONTENT."
|
||||
(when (or size include-content)
|
||||
(let* ((unit "\n")
|
||||
(chunk "ccccccccccccccccccccccccccccccc\n")
|
||||
(chunk-size (length chunk))
|
||||
(size (if (and size include-content (stringp include-content))
|
||||
(- size (length include-content))
|
||||
size)))
|
||||
(unless (or (null size) (> size 0))
|
||||
(error "size argument must be nil or positive"))
|
||||
(with-current-buffer buffer
|
||||
(when include-content
|
||||
(insert include-content))
|
||||
(when size
|
||||
(dotimes (_ (floor size chunk-size))
|
||||
(insert chunk))
|
||||
(dotimes (_ (mod size chunk-size))
|
||||
(insert unit)))
|
||||
;; prevent query on cleanup
|
||||
(set-buffer-modified-p nil))))))
|
||||
(create-file-buffer
|
||||
(lambda (prefix &rest args-plist)
|
||||
"Create a file and buffer with designated properties.
|
||||
PREFIX is a string giving the beginning of the name, and ARGS-PLIST
|
||||
is a series of keyword-value pairs, with allowed keywords
|
||||
:suffix STRING, :size NUMBER, :mode MODE-FUNC, :include-content STRING.
|
||||
Returns the created buffer."
|
||||
(let* ((suffix (plist-get args-plist :suffix))
|
||||
(size (plist-get args-plist :size))
|
||||
(include (plist-get args-plist :include-content))
|
||||
(mode (plist-get args-plist :mode))
|
||||
(file (make-temp-file prefix nil suffix))
|
||||
(buf (find-file-noselect file t)))
|
||||
(push buf test-buffer-list) ; record for cleanup
|
||||
(funcall set-buffer-mode buf mode)
|
||||
(funcall set-buffer-contents buf size include)
|
||||
buf)))
|
||||
(create-non-file-buffer
|
||||
(lambda (prefix &rest args-plist)
|
||||
"Create a non-file and buffer with designated properties.
|
||||
PREFIX is a string giving the beginning of the name, and ARGS-PLIST
|
||||
is a series of keyword-value pairs, with allowed keywords
|
||||
:size NUMBER, :mode MODE-FUNC, :include-content STRING.
|
||||
Returns the created buffer."
|
||||
(let* ((size (plist-get args-plist :size))
|
||||
(include (plist-get args-plist :include-content))
|
||||
(mode (plist-get args-plist :mode))
|
||||
(buf (generate-new-buffer prefix)))
|
||||
(push buf test-buffer-list) ; record for cleanup
|
||||
(funcall set-buffer-mode buf mode)
|
||||
(funcall set-buffer-contents buf size include)
|
||||
buf)))
|
||||
(clean-up
|
||||
(lambda ()
|
||||
"Restore all emacs state modified during the tests"
|
||||
(while test-buffer-list ; created temporary buffers
|
||||
(let ((buf (pop test-buffer-list)))
|
||||
(with-current-buffer buf (bury-buffer)) ; ensure not selected
|
||||
(kill-buffer buf))))))
|
||||
;; Tests
|
||||
(ert-deftest ibuffer-filter-inclusion-1 ()
|
||||
"Tests inclusion using basic filter combinators with a single buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-file-buffer "ibuf-test-1" :size 100
|
||||
:include-content "One ring to rule them all\n")))
|
||||
(should (ibuffer-included-in-filters-p buf '((size-gt . 99))))
|
||||
(should (ibuffer-included-in-filters-p buf '((size-lt . 101))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((mode . fundamental-mode))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((content . "ring to rule them all"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (content . "ring to rule them all")))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (and (content . "ring to rule them all"))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (and (and (content . "ring to rule them all")))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((or (content . "ring to rule them all")))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (not (content . "ring to rule them all"))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (size-gt . 99)
|
||||
(content . "ring to rule them all")
|
||||
(mode . fundamental-mode)
|
||||
(basename . "\\`ibuf-test-1")))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (or (not (size-gt . 99))
|
||||
(not (content . "ring to rule them all"))
|
||||
(not (mode . fundamental-mode))
|
||||
(not (basename . "\\`ibuf-test-1")))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (or (size-gt . 99) (size-lt . 10))
|
||||
(and (content . "ring.*all")
|
||||
(content . "rule")
|
||||
(content . "them all")
|
||||
(content . "One"))
|
||||
(not (mode . text-mode))
|
||||
(basename . "\\`ibuf-test-1"))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-2 ()
|
||||
"Tests inclusion of basic filters in combination on a single buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-file-buffer "ibuf-test-2" :size 200
|
||||
:mode #'text-mode
|
||||
:include-content "and in the darkness find them\n")))
|
||||
(should (ibuffer-included-in-filters-p buf '((size-gt . 199))))
|
||||
(should (ibuffer-included-in-filters-p buf '((size-lt . 201))))
|
||||
(should (ibuffer-included-in-filters-p buf '((not size-gt . 200))))
|
||||
(should (ibuffer-included-in-filters-p buf '((not (size-gt . 200)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (size-gt . 199) (size-lt . 201)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((or (size-gt . 199) (size-gt . 201)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((or (size-gt . 201) (size-gt . 199)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((size-gt . 199) (mode . text-mode)
|
||||
(content . "darkness find them"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (size-gt . 199) (mode . text-mode)
|
||||
(content . "darkness find them")))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (or (not (size-gt . 199)) (not (mode . text-mode))
|
||||
(not (content . "darkness find them")))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((or (size-gt . 200) (content . "darkness find them")
|
||||
(derived-mode . emacs-lisp-mode)))))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
buf '((or (size-gt . 200) (content . "rule them all")
|
||||
(derived-mode . emacs-lisp-mode))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-3 ()
|
||||
"Tests inclusion with filename filters on specified buffers."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let* ((bufA
|
||||
(funcall create-file-buffer "ibuf-test-3.a" :size 50
|
||||
:mode #'text-mode
|
||||
:include-content "...but a multitude of drops?\n"))
|
||||
(bufB
|
||||
(funcall create-non-file-buffer "ibuf-test-3.b" :size 50
|
||||
:mode #'text-mode
|
||||
:include-content "...but a multitude of drops?\n"))
|
||||
(dirA (with-current-buffer bufA default-directory))
|
||||
(dirB (with-current-buffer bufB default-directory)))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA '((basename . "ibuf-test-3"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA '((basename . "test-3\\.a"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA '((file-extension . "a"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA (list (cons 'directory dirA))))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
bufB '((basename . "ibuf-test-3"))))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
bufB '((file-extension . "b"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufB (list (cons 'directory dirB))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA '((name . "ibuf-test-3"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufB '((name . "ibuf-test-3")))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-4 ()
|
||||
"Tests inclusion with various filters on a single buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-file-buffer "ibuf-test-4"
|
||||
:mode #'emacs-lisp-mode :suffix ".el"
|
||||
:include-content "(message \"--%s--\" 'emacs-rocks)\n")))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((file-extension . "el"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((derived-mode . prog-mode))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((used-mode . emacs-lisp-mode))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((mode . emacs-lisp-mode))))
|
||||
(with-current-buffer buf (set-buffer-modified-p t))
|
||||
(should (ibuffer-included-in-filters-p buf '((modified))))
|
||||
(with-current-buffer buf (set-buffer-modified-p nil))
|
||||
(should (ibuffer-included-in-filters-p buf '((not modified))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (file-extension . "el")
|
||||
(derived-mode . prog-mode)
|
||||
(not modified)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((or (file-extension . "tex")
|
||||
(derived-mode . prog-mode)
|
||||
(modified)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((file-extension . "el")
|
||||
(derived-mode . prog-mode)
|
||||
(not modified)))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-5 ()
|
||||
"Tests inclusion with various filters on a single buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-non-file-buffer "ibuf-test-5.el"
|
||||
:mode #'emacs-lisp-mode
|
||||
:include-content
|
||||
"(message \"--%s--\" \"It really does!\")\n")))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
buf '((file-extension . "el"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((size-gt . 18))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((predicate . (lambda ()
|
||||
(> (- (point-max) (point-min)) 18))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (mode . emacs-lisp-mode)
|
||||
(or (starred-name)
|
||||
(size-gt . 18))
|
||||
(and (not (size-gt . 100))
|
||||
(content . "[Ii]t *really does!")
|
||||
(or (name . "test-5")
|
||||
(not (filename . "test-5")))))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-6 ()
|
||||
"Tests inclusion using saved filters and DeMorgan's laws."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-non-file-buffer "*ibuf-test-6*" :size 65
|
||||
:mode #'text-mode))
|
||||
(buf2
|
||||
(funcall create-file-buffer "ibuf-test-6a" :suffix ".html"
|
||||
:mode #'html-mode
|
||||
:include-content
|
||||
"<HTML><BODY><H1>Hello, World!</H1></BODY></HTML>")))
|
||||
(should (ibuffer-included-in-filters-p buf '((starred-name))))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
buf '((saved . "text document"))))
|
||||
(should (ibuffer-included-in-filters-p buf2 '((saved . "web"))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf2 '((not (and (not (derived-mode . sgml-mode))
|
||||
(not (derived-mode . css-mode))
|
||||
(not (mode . javascript-mode))
|
||||
(not (mode . js2-mode))
|
||||
(not (mode . scss-mode))
|
||||
(not (derived-mode . haml-mode))
|
||||
(not (mode . sass-mode)))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((and (starred-name)
|
||||
(or (size-gt . 50) (filename . "foo"))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (or (not starred-name)
|
||||
(and (size-lt . 51)
|
||||
(not (filename . "foo")))))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-7 ()
|
||||
"Tests inclusion with various filters on a single buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((buf
|
||||
(funcall create-non-file-buffer "ibuf-test-7"
|
||||
:mode #'artist-mode)))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (starred-name)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not starred-name))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (not (not starred-name))))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (modified)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not modified))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
buf '((not (not (not modified)))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-filter-inclusion-8 ()
|
||||
"Tests inclusion with various filters."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((bufA
|
||||
(funcall create-non-file-buffer "ibuf-test-8a"
|
||||
:mode #'artist-mode))
|
||||
(bufB (funcall create-non-file-buffer "*ibuf-test-8b*" :size 32))
|
||||
(bufC (funcall create-file-buffer "ibuf-test8c" :suffix "*"
|
||||
:size 64))
|
||||
(bufD (funcall create-file-buffer "*ibuf-test8d" :size 128))
|
||||
(bufE (funcall create-file-buffer "*ibuf-test8e" :suffix "*<2>"
|
||||
:size 16))
|
||||
(bufF (and (funcall create-non-file-buffer "*ibuf-test8f*")
|
||||
(funcall create-non-file-buffer "*ibuf-test8f*"
|
||||
:size 8))))
|
||||
(with-current-buffer bufA (set-buffer-modified-p t))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufA '((and (not starred-name)
|
||||
(modified)
|
||||
(name . "test-8")
|
||||
(not (size-gt . 100))
|
||||
(mode . picture-mode)))))
|
||||
(with-current-buffer bufA (set-buffer-modified-p nil))
|
||||
(should-not (ibuffer-included-in-filters-p
|
||||
bufA '((or (starred-name) (visiting-file) (modified)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufB '((and (starred-name)
|
||||
(name . "test.*8b")
|
||||
(size-gt . 31)
|
||||
(not visiting-file)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufC '((and (not (starred-name))
|
||||
(visiting-file)
|
||||
(name . "8c[^*]*\\*")
|
||||
(size-lt . 65)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufD '((and (not (starred-name))
|
||||
(visiting-file)
|
||||
(name . "\\`\\*.*test8d")
|
||||
(size-lt . 129)
|
||||
(size-gt . 127)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufE '((and (starred-name)
|
||||
(visiting-file)
|
||||
(name . "8e.*?\\*<[[:digit:]]+>")
|
||||
(size-gt . 10)))))
|
||||
(should (ibuffer-included-in-filters-p
|
||||
bufF '((and (starred-name)
|
||||
(not (visiting-file))
|
||||
(name . "8f\\*<[[:digit:]]>")
|
||||
(size-lt . 10))))))
|
||||
(funcall clean-up))))
|
||||
|
||||
;; Test Filter Combination and Decomposition
|
||||
(let* (ibuffer-to-kill ; if non-nil, kill this buffer at cleanup
|
||||
(ibuffer-already 'check) ; existing ibuffer buffer to use but not kill
|
||||
;; Utility functions without polluting the environment
|
||||
(get-test-ibuffer
|
||||
(lambda ()
|
||||
"Returns a test ibuffer-mode buffer, creating one if necessary.
|
||||
If a new buffer is created, it is named \"*Test-Ibuffer*\" and is
|
||||
saved to `ibuffer-to-kill' for later cleanup."
|
||||
(when (eq ibuffer-already 'check)
|
||||
(setq ibuffer-already
|
||||
(catch 'found-buf
|
||||
(dolist (buf (buffer-list) nil)
|
||||
(when (with-current-buffer buf
|
||||
(derived-mode-p 'ibuffer-mode))
|
||||
(throw 'found-buf buf))))))
|
||||
(or ibuffer-already
|
||||
ibuffer-to-kill
|
||||
(let ((test-ibuf-name "*Test-Ibuffer*"))
|
||||
(ibuffer nil test-ibuf-name nil t)
|
||||
(setq ibuffer-to-kill (get-buffer test-ibuf-name))))))
|
||||
(clean-up
|
||||
(lambda ()
|
||||
"Restore all emacs state modified during the tests"
|
||||
(when ibuffer-to-kill ; created ibuffer
|
||||
(with-current-buffer ibuffer-to-kill
|
||||
(set-buffer-modified-p nil)
|
||||
(bury-buffer))
|
||||
(kill-buffer ibuffer-to-kill)
|
||||
(setq ibuffer-to-kill nil))
|
||||
(when (and ibuffer-already (not (eq ibuffer-already 'check)))
|
||||
;; restore existing ibuffer state
|
||||
(ibuffer-update nil t)))))
|
||||
;; Tests
|
||||
(ert-deftest ibuffer-decompose-filter ()
|
||||
"Tests `ibuffer-decompose-filter' for and, or, not, and saved."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((ibuf (funcall get-test-ibuffer)))
|
||||
(with-current-buffer ibuf
|
||||
(let ((ibuffer-filtering-qualifiers nil)
|
||||
(ibuffer-filter-groups nil)
|
||||
(filters '((size-gt . 100) (not (starred-name))
|
||||
(name . "foo"))))
|
||||
(progn
|
||||
(push (cons 'or filters) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal filters ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(progn
|
||||
(push (cons 'and filters) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal filters ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(progn
|
||||
(push (list 'not (car filters)) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal (list (car filters))
|
||||
ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(progn
|
||||
(push (cons 'not (car filters)) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal (list (car filters))
|
||||
ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(let ((gnus (assoc "gnus" ibuffer-saved-filters)))
|
||||
(push '(saved . "gnus") ibuffer-filtering-qualifiers)
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal (cdr gnus) ibuffer-filtering-qualifiers))
|
||||
(ibuffer-decompose-filter)
|
||||
(should (equal (cdr (cadr gnus)) ibuffer-filtering-qualifiers))
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(when (not (assoc "__unknown__" ibuffer-saved-filters))
|
||||
(push '(saved . "__uknown__") ibuffer-filtering-qualifiers)
|
||||
(should-error (ibuffer-decompose-filter) :type 'error)
|
||||
(setq ibuffer-filtering-qualifiers nil))
|
||||
(progn
|
||||
(push (car filters) ibuffer-filtering-qualifiers)
|
||||
(should-error (ibuffer-decompose-filter) :type 'error)
|
||||
(setq ibuffer-filtering-qualifiers nil)))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-and-filter ()
|
||||
"Tests `ibuffer-and-filter' in an Ibuffer buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((ibuf (funcall get-test-ibuffer)))
|
||||
(with-current-buffer ibuf
|
||||
(let ((ibuffer-filtering-qualifiers nil)
|
||||
(ibuffer-filter-groups nil)
|
||||
(filters [(size-gt . 100) (not (starred-name))
|
||||
(filename . "A") (mode . text-mode)]))
|
||||
(should-error (ibuffer-and-filter) :type 'error)
|
||||
(progn
|
||||
(push (aref filters 1) ibuffer-filtering-qualifiers)
|
||||
(should-error (ibuffer-and-filter) :type 'error))
|
||||
(should (progn
|
||||
(push (aref filters 0) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-and-filter)
|
||||
(and (equal (list 'and (aref filters 0) (aref filters 1))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(should (progn
|
||||
(ibuffer-and-filter 'decompose)
|
||||
(and (equal (aref filters 0)
|
||||
(pop ibuffer-filtering-qualifiers))
|
||||
(equal (aref filters 1)
|
||||
(pop ibuffer-filtering-qualifiers))
|
||||
(null ibuffer-filtering-qualifiers))))
|
||||
(should (progn
|
||||
(push (list 'and (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'and (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-and-filter)
|
||||
(and (equal (list 'and (aref filters 0) (aref filters 1)
|
||||
(aref filters 2) (aref filters 3))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'or (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'and (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-and-filter)
|
||||
(and (equal (list 'and (aref filters 0) (aref filters 1)
|
||||
(list 'or (aref filters 2)
|
||||
(aref filters 3)))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'and (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'or (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-and-filter)
|
||||
(and (equal (list 'and (list 'or (aref filters 0)
|
||||
(aref filters 1))
|
||||
(aref filters 2) (aref filters 3))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'or (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'or (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-and-filter)
|
||||
(and (equal (list 'and
|
||||
(list 'or (aref filters 0)
|
||||
(aref filters 1))
|
||||
(list 'or (aref filters 2)
|
||||
(aref filters 3)))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers))))))))
|
||||
(funcall clean-up)))
|
||||
|
||||
(ert-deftest ibuffer-or-filter ()
|
||||
"Tests `ibuffer-or-filter' in an Ibuffer buffer."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(unwind-protect
|
||||
(let ((ibuf (funcall get-test-ibuffer)))
|
||||
(with-current-buffer ibuf
|
||||
(let ((ibuffer-filtering-qualifiers nil)
|
||||
(ibuffer-filter-groups nil)
|
||||
(filters [(size-gt . 100) (not (starred-name))
|
||||
(filename . "A") (mode . text-mode)]))
|
||||
(should-error (ibuffer-or-filter) :type 'error)
|
||||
(progn
|
||||
(push (aref filters 1) ibuffer-filtering-qualifiers)
|
||||
(should-error (ibuffer-or-filter) :type 'error))
|
||||
(should (progn
|
||||
(push (aref filters 0) ibuffer-filtering-qualifiers)
|
||||
(ibuffer-or-filter)
|
||||
(and (equal (list 'or (aref filters 0) (aref filters 1))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(should (progn
|
||||
(ibuffer-or-filter 'decompose)
|
||||
(and (equal (aref filters 0)
|
||||
(pop ibuffer-filtering-qualifiers))
|
||||
(equal (aref filters 1)
|
||||
(pop ibuffer-filtering-qualifiers))
|
||||
(null ibuffer-filtering-qualifiers))))
|
||||
(should (progn
|
||||
(push (list 'or (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'or (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-or-filter)
|
||||
(and (equal (list 'or (aref filters 0) (aref filters 1)
|
||||
(aref filters 2) (aref filters 3))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'and (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'or (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-or-filter)
|
||||
(and (equal (list 'or (aref filters 0) (aref filters 1)
|
||||
(list 'and (aref filters 2)
|
||||
(aref filters 3)))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'or (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'and (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-or-filter)
|
||||
(and (equal (list 'or (list 'and (aref filters 0)
|
||||
(aref filters 1))
|
||||
(aref filters 2) (aref filters 3))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers)))))
|
||||
(pop ibuffer-filtering-qualifiers)
|
||||
(should (progn
|
||||
(push (list 'and (aref filters 2) (aref filters 3))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(push (list 'and (aref filters 0) (aref filters 1))
|
||||
ibuffer-filtering-qualifiers)
|
||||
(ibuffer-or-filter)
|
||||
(and (equal (list 'or
|
||||
(list 'and (aref filters 0)
|
||||
(aref filters 1))
|
||||
(list 'and (aref filters 2)
|
||||
(aref filters 3)))
|
||||
(car ibuffer-filtering-qualifiers))
|
||||
(null (cdr ibuffer-filtering-qualifiers))))))))
|
||||
(funcall clean-up))))
|
||||
|
||||
(ert-deftest ibuffer-format-qualifier ()
|
||||
"Tests string recommendation of filter from `ibuffer-format-qualifier'."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(let ((test1 '(mode . org-mode))
|
||||
(test2 '(size-lt . 100))
|
||||
(test3 '(derived-mode . prog-mode))
|
||||
(test4 '(or (size-gt . 10000)
|
||||
(and (not (starred-name))
|
||||
(directory . "\\<org\\>"))))
|
||||
(test5 '(or (filename . "scratch")
|
||||
(filename . "bonz")
|
||||
(filename . "temp")))
|
||||
(test6 '(or (mode . emacs-lisp-mode) (file-extension . "elc?")
|
||||
(and (starred-name) (name . "elisp"))
|
||||
(mode . lisp-interaction-mode)))
|
||||
(description (lambda (q)
|
||||
(cadr (assq q ibuffer-filtering-alist))))
|
||||
(tag (lambda (&rest args )
|
||||
(concat " [" (apply #'concat args) "]"))))
|
||||
(should (equal (ibuffer-format-qualifier test1)
|
||||
(funcall tag (funcall description 'mode)
|
||||
": " "org-mode")))
|
||||
(should (equal (ibuffer-format-qualifier test2)
|
||||
(funcall tag (funcall description 'size-lt)
|
||||
": " "100")))
|
||||
(should (equal (ibuffer-format-qualifier test3)
|
||||
(funcall tag (funcall description 'derived-mode)
|
||||
": " "prog-mode")))
|
||||
(should (equal (ibuffer-format-qualifier test4)
|
||||
(funcall tag "OR"
|
||||
(funcall tag (funcall description 'size-gt)
|
||||
": " (format "%s" 10000))
|
||||
(funcall tag "AND"
|
||||
(funcall tag "NOT"
|
||||
(funcall tag
|
||||
(funcall description
|
||||
'starred-name)
|
||||
": " "nil"))
|
||||
(funcall tag
|
||||
(funcall description 'directory)
|
||||
": " "\\<org\\>")))))
|
||||
(should (equal (ibuffer-format-qualifier test5)
|
||||
(funcall tag "OR"
|
||||
(funcall tag (funcall description 'filename)
|
||||
": " "scratch")
|
||||
(funcall tag (funcall description 'filename)
|
||||
": " "bonz")
|
||||
(funcall tag (funcall description 'filename)
|
||||
": " "temp"))))
|
||||
(should (equal (ibuffer-format-qualifier test6)
|
||||
(funcall tag "OR"
|
||||
(funcall tag (funcall description 'mode)
|
||||
": " "emacs-lisp-mode")
|
||||
(funcall tag (funcall description 'file-extension)
|
||||
": " "elc?")
|
||||
(funcall tag "AND"
|
||||
(funcall tag
|
||||
(funcall description 'starred-name)
|
||||
": " "nil")
|
||||
(funcall tag
|
||||
(funcall description 'name)
|
||||
": " "elisp"))
|
||||
(funcall tag (funcall description 'mode)
|
||||
": " "lisp-interaction-mode"))))))
|
||||
|
||||
(ert-deftest ibuffer-unary-operand ()
|
||||
"Tests `ibuffer-unary-operand': (not cell) or (not . cell) -> cell."
|
||||
(skip-unless (featurep 'ibuf-ext))
|
||||
(should (equal (ibuffer-unary-operand '(not . (mode "foo")))
|
||||
'(mode "foo")))
|
||||
(should (equal (ibuffer-unary-operand '(not (mode "foo")))
|
||||
'(mode "foo")))
|
||||
(should (equal (ibuffer-unary-operand '(not "cdr"))
|
||||
'("cdr")))
|
||||
(should (equal (ibuffer-unary-operand '(not)) nil))
|
||||
(should (equal (ibuffer-unary-operand '(not . a)) 'a)))
|
||||
|
||||
(provide 'ibuffer-tests)
|
||||
;; ibuffer-tests.el ends here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue