aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Genovese2016-12-07 19:51:33 +0900
committerTino Calancha2016-12-07 19:51:33 +0900
commit20f5a5b386db878e69a4b6be565dc06d06b46ffd (patch)
tree24f855a48bdc8617f5800e40f743ad9b2da767c0
parent8e5a769965313a7a1c42b5992ed24e8b0ea71ead (diff)
downloademacs-20f5a5b386db878e69a4b6be565dc06d06b46ffd.tar.gz
emacs-20f5a5b386db878e69a4b6be565dc06d06b46ffd.zip
ibuffer-saved-filters: Remove extra nesting level
Fix Bug#25049. * lisp/ibuf-ext.el (ibuffer-saved-filters): Remove extra nesting level; add transparent setter to adjust old-format values; update doc string. (ibuffer-save-filters): Remove extra level of nesting in ibuffer-saved-filters values when saving new filters. (ibuffer-old-saved-filters-warning): New variable with clickable message with repair options to be displayed as a warning if 'ibuffer-repair-saved-filters' detects a format mismatch. (ibuffer-repair-saved-filters): Add new command to check and repair saved filters format. (ibuffer-included-in-filter-p, ibuffer-decompose-filter): Change access of saved filter data (cadr->cdr) to account for reduced nesting. * test/lisp/ibuffer-tests.el (ibuffer-save-filters): New test; check that filters are saved in the proper format.
-rw-r--r--lisp/ibuf-ext.el156
-rw-r--r--test/lisp/ibuffer-tests.el29
2 files changed, 150 insertions, 35 deletions
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index 5ef07469772..d1bf5769d8c 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -35,7 +35,8 @@
35 35
36(eval-when-compile 36(eval-when-compile
37 (require 'ibuf-macs) 37 (require 'ibuf-macs)
38 (require 'cl-lib)) 38 (require 'cl-lib)
39 (require 'subr-x))
39 40
40;;; Utility functions 41;;; Utility functions
41(defun ibuffer-delete-alist (key alist) 42(defun ibuffer-delete-alist (key alist)
@@ -119,32 +120,100 @@ Buffers whose major mode is in this list, are not searched."
119 120
120(defvar ibuffer-auto-buffers-changed nil) 121(defvar ibuffer-auto-buffers-changed nil)
121 122
122(defcustom ibuffer-saved-filters '(("gnus" 123(defun ibuffer-update-saved-filters-format (filters)
123 ((or (mode . message-mode) 124 "Transforms alist from old to new `ibuffer-saved-filters' format.
124 (mode . mail-mode) 125
125 (mode . gnus-group-mode) 126Specifically, converts old-format alist with values of the
126 (mode . gnus-summary-mode) 127form (STRING (FILTER-SPECS...)) to alist with values of the
127 (mode . gnus-article-mode)))) 128form (STRING FILTER-SPECS...), where each filter spec should be a
128 ("programming" 129cons cell with a symbol in the car. Any elements in the latter
129 ((or (mode . emacs-lisp-mode) 130form are kept as is.
130 (mode . cperl-mode) 131
131 (mode . c-mode) 132Returns (OLD-FORMAT-DETECTED . UPDATED-SAVED-FILTERS-LIST)."
132 (mode . java-mode) 133 (when filters
133 (mode . idl-mode) 134 (let* ((old-format-detected nil)
134 (mode . lisp-mode))))) 135 (fix-filter (lambda (filter-spec)
135 136 (if (symbolp (car (cadr filter-spec)))
136 "An alist of filter qualifiers to switch between. 137 filter-spec
138 (setq old-format-detected t) ; side-effect
139 (cons (car filter-spec) (cadr filter-spec)))))
140 (fixed (mapcar fix-filter filters)))
141 (cons old-format-detected fixed))))
137 142
138This variable should look like ((\"STRING\" QUALIFIERS) 143(defcustom ibuffer-saved-filters '(("gnus"
139 (\"STRING\" QUALIFIERS) ...), where 144 (or (mode . message-mode)
140QUALIFIERS is a list of the same form as 145 (mode . mail-mode)
141`ibuffer-filtering-qualifiers'. 146 (mode . gnus-group-mode)
142See also the variables `ibuffer-filtering-qualifiers', 147 (mode . gnus-summary-mode)
143`ibuffer-filtering-alist', and the functions 148 (mode . gnus-article-mode)))
144`ibuffer-switch-to-saved-filters', `ibuffer-save-filters'." 149 ("programming"
145 :type '(repeat sexp) 150 (or (mode . emacs-lisp-mode)
151 (mode . cperl-mode)
152 (mode . c-mode)
153 (mode . java-mode)
154 (mode . idl-mode)
155 (mode . lisp-mode))))
156
157 "An alist mapping saved filter names to filter specifications.
158
159Each element should look like (\"NAME\" . FILTER-LIST), where
160FILTER-LIST has the same structure as the variable
161`ibuffer-filtering-qualifiers', which see. The filters defined
162here are joined with an implicit logical `and' and associated
163with NAME. The combined specification can be used by name in
164other filter specifications via the `saved' qualifier (again, see
165`ibuffer-filtering-qualifiers'). They can also be switched to by
166name (see the functions `ibuffer-switch-to-saved-filters' and
167`ibuffer-save-filters'). The variable `ibuffer-save-with-custom'
168affects how this information is saved for future sessions. This
169variable can be set directly from lisp code."
170 :version "26.1"
171 :type '(alist :key-type (string :tag "Filter name")
172 :value-type (repeat :tag "Filter specification" sexp))
173 :set (lambda (symbol value)
174 ;; Just set-default but update legacy old-style format
175 (set-default symbol (cdr (ibuffer-update-saved-filters-format value))))
146 :group 'ibuffer) 176 :group 'ibuffer)
147 177
178(defvar ibuffer-old-saved-filters-warning
179 (concat "Deprecated format detected for variable `ibuffer-saved-filters'.
180
181The format has been repaired and the variable modified accordingly.
182You can save the current value through the customize system by
183either clicking or hitting return "
184 (make-text-button
185 "here" nil
186 'face '(:weight bold :inherit button)
187 'mouse-face '(:weight normal :background "gray50" :inherit button)
188 'follow-link t
189 'help-echo "Click or RET: save new value in customize"
190 'action (lambda (_)
191 (if (not (fboundp 'customize-save-variable))
192 (message "Customize not available; value not saved")
193 (customize-save-variable 'ibuffer-saved-filters
194 ibuffer-saved-filters)
195 (message "Saved updated ibuffer-saved-filters."))))
196 ". See below for
197an explanation and alternative ways to save the repaired value.
198
199Explanation: For the list variable `ibuffer-saved-filters',
200elements of the form (STRING (FILTER-SPECS...)) are deprecated
201and should instead have the form (STRING FILTER-SPECS...), where
202each filter spec is a cons cell with a symbol in the car. See
203`ibuffer-saved-filters' for details. The repaired value fixes
204this format without changing the meaning of the saved filters.
205
206Alternative ways to save the repaired value:
207
208 1. Do M-x customize-variable and entering `ibuffer-saved-filters'
209 when prompted.
210
211 2. Set the updated value manually by copying the
212 following emacs-lisp form to your emacs init file.
213
214%s
215"))
216
148(defvar ibuffer-filtering-qualifiers nil 217(defvar ibuffer-filtering-qualifiers nil
149 "A list like (SYMBOL . QUALIFIER) which filters the current buffer list. 218 "A list like (SYMBOL . QUALIFIER) which filters the current buffer list.
150See also `ibuffer-filtering-alist'.") 219See also `ibuffer-filtering-alist'.")
@@ -224,6 +293,28 @@ Currently, this only applies to `ibuffer-saved-filters' and
224 :type 'boolean 293 :type 'boolean
225 :group 'ibuffer) 294 :group 'ibuffer)
226 295
296(defun ibuffer-repair-saved-filters ()
297 "Updates `ibuffer-saved-filters' to its new-style format, if needed.
298
299If this list has any elements of the old-style format, a
300deprecation warning is raised, with a button allowing persistent
301update. Any updated filters retain their meaning in the new
302format. See `ibuffer-update-saved-filters-format' and
303`ibuffer-saved-filters' for details of the old and new formats."
304 (interactive)
305 (when (and (boundp 'ibuffer-saved-filters) ibuffer-saved-filters)
306 (let ((fixed (ibuffer-update-saved-filters-format ibuffer-saved-filters)))
307 (prog1
308 (setq ibuffer-saved-filters (cdr fixed))
309 (when-let (old-format-detected (car fixed))
310 (let ((warning-series t)
311 (updated-form
312 (with-output-to-string
313 (pp `(setq ibuffer-saved-filters ',ibuffer-saved-filters)))))
314 (display-warning
315 'ibuffer
316 (format ibuffer-old-saved-filters-warning updated-form))))))))
317
227(defun ibuffer-ext-visible-p (buf all &optional ibuffer-buf) 318(defun ibuffer-ext-visible-p (buf all &optional ibuffer-buf)
228 (or 319 (or
229 (ibuffer-buf-matches-predicates buf ibuffer-tmp-show-regexps) 320 (ibuffer-buf-matches-predicates buf ibuffer-tmp-show-regexps)
@@ -535,13 +626,11 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'."
535 (ibuffer-included-in-filter-p buf x)) 626 (ibuffer-included-in-filter-p buf x))
536 (cdr filter)))) 627 (cdr filter))))
537 (`saved 628 (`saved
538 (let ((data 629 (let ((data (assoc (cdr filter) ibuffer-saved-filters)))
539 (assoc (cdr filter)
540 ibuffer-saved-filters)))
541 (unless data 630 (unless data
542 (ibuffer-filter-disable t) 631 (ibuffer-filter-disable t)
543 (error "Unknown saved filter %s" (cdr filter))) 632 (error "Unknown saved filter %s" (cdr filter)))
544 (ibuffer-included-in-filters-p buf (cadr data)))) 633 (ibuffer-included-in-filters-p buf (cdr data))))
545 (_ 634 (_
546 (pcase-let ((`(,_type ,_desc ,func) 635 (pcase-let ((`(,_type ,_desc ,func)
547 (assq (car filter) ibuffer-filtering-alist))) 636 (assq (car filter) ibuffer-filtering-alist)))
@@ -849,15 +938,12 @@ turned into two separate filters [name: foo] and [mode: bar-mode]."
849 (cdr lim) 938 (cdr lim)
850 ibuffer-filtering-qualifiers))) 939 ibuffer-filtering-qualifiers)))
851 (`saved 940 (`saved
852 (let ((data 941 (let ((data (assoc (cdr lim) ibuffer-saved-filters)))
853 (assoc (cdr lim)
854 ibuffer-saved-filters)))
855 (unless data 942 (unless data
856 (ibuffer-filter-disable) 943 (ibuffer-filter-disable)
857 (error "Unknown saved filter %s" (cdr lim))) 944 (error "Unknown saved filter %s" (cdr lim)))
858 (setq ibuffer-filtering-qualifiers (append 945 (setq ibuffer-filtering-qualifiers
859 (cadr data) 946 (append (cdr data) ibuffer-filtering-qualifiers))))
860 ibuffer-filtering-qualifiers))))
861 (`not 947 (`not
862 (push (cdr lim) 948 (push (cdr lim)
863 ibuffer-filtering-qualifiers)) 949 ibuffer-filtering-qualifiers))
@@ -936,7 +1022,7 @@ Interactively, prompt for NAME, and use the current filters."
936 ibuffer-filtering-qualifiers))) 1022 ibuffer-filtering-qualifiers)))
937 (ibuffer-aif (assoc name ibuffer-saved-filters) 1023 (ibuffer-aif (assoc name ibuffer-saved-filters)
938 (setcdr it filters) 1024 (setcdr it filters)
939 (push (list name filters) ibuffer-saved-filters)) 1025 (push (cons name filters) ibuffer-saved-filters))
940 (ibuffer-maybe-save-stuff)) 1026 (ibuffer-maybe-save-stuff))
941 1027
942;;;###autoload 1028;;;###autoload
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index 3a4def3a2b0..6d5187a2b77 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -66,5 +66,34 @@
66 (mapc (lambda (buf) (when (buffer-live-p buf) 66 (mapc (lambda (buf) (when (buffer-live-p buf)
67 (kill-buffer buf))) (list buf1 buf2))))) 67 (kill-buffer buf))) (list buf1 buf2)))))
68 68
69(ert-deftest ibuffer-save-filters ()
70 "Tests that `ibuffer-save-filters' saves in the proper format."
71 (skip-unless (featurep 'ibuf-ext))
72 (let ((ibuffer-save-with-custom nil)
73 (ibuffer-saved-filters nil)
74 (test1 '((mode . org-mode)
75 (or (size-gt . 10000)
76 (and (not (starred-name))
77 (directory . "\<org\>")))))
78 (test2 '((or (mode . emacs-lisp-mode) (file-extension . "elc?")
79 (and (starred-name) (name . "elisp"))
80 (mode . lisp-interaction-mode))))
81 (test3 '((size-lt . 100) (derived-mode . prog-mode)
82 (or (filename . "scratch")
83 (filename . "bonz")
84 (filename . "temp")))))
85 (ibuffer-save-filters "test1" test1)
86 (should (equal (car ibuffer-saved-filters) (cons "test1" test1)))
87 (ibuffer-save-filters "test2" test2)
88 (should (equal (car ibuffer-saved-filters) (cons "test2" test2)))
89 (should (equal (cadr ibuffer-saved-filters) (cons "test1" test1)))
90 (ibuffer-save-filters "test3" test3)
91 (should (equal (car ibuffer-saved-filters) (cons "test3" test3)))
92 (should (equal (cadr ibuffer-saved-filters) (cons "test2" test2)))
93 (should (equal (car (cddr ibuffer-saved-filters)) (cons "test1" test1)))
94 (should (equal (cdr (assoc "test1" ibuffer-saved-filters)) test1))
95 (should (equal (cdr (assoc "test2" ibuffer-saved-filters)) test2))
96 (should (equal (cdr (assoc "test3" ibuffer-saved-filters)) test3))))
97
69(provide 'ibuffer-tests) 98(provide 'ibuffer-tests)
70;; ibuffer-tests.el ends here 99;; ibuffer-tests.el ends here