소스 검색

Merge branch 'improve-consistency-in-filter-commands'

Carsten Dominik 6 년 전
부모
커밋
6f32e7af88
2개의 변경된 파일149개의 추가작업 그리고 133개의 파일을 삭제
  1. 37 45
      doc/org-manual.org
  2. 112 88
      lisp/org-agenda.el

+ 37 - 45
doc/org-manual.org

@@ -8928,12 +8928,10 @@ If you would like to have a special category for a single entry or
 a (sub)tree, give the entry a =CATEGORY= property with the special
 a (sub)tree, give the entry a =CATEGORY= property with the special
 category you want to apply as the value.
 category you want to apply as the value.
 
 
-The display in the agenda buffer looks best if the category is not
-longer than 10 characters.
-
 #+vindex: org-agenda-category-icon-alist
 #+vindex: org-agenda-category-icon-alist
-You can set up icons for category by customizing the
-~org-agenda-category-icon-alist~ variable.
+The display in the agenda buffer looks best if the category is not
+longer than 10 characters.  You can set up icons for category by
+customizing the ~org-agenda-category-icon-alist~ variable.
 
 
 *** Time-of-day specifications
 *** Time-of-day specifications
 :PROPERTIES:
 :PROPERTIES:
@@ -9039,20 +9037,16 @@ the estimated effort of an entry (see [[*Effort Estimates]]).
 #+vindex: org-agenda-tag-filter-preset
 #+vindex: org-agenda-tag-filter-preset
 #+vindex: org-agenda-effort-filter-preset
 #+vindex: org-agenda-effort-filter-preset
 #+vindex: org-agenda-regexp-filter-preset
 #+vindex: org-agenda-regexp-filter-preset
-Agenda built-in or customized commands are statically defined.  Agenda
-filters and limits provide two ways of narrowing down the list of
-agenda entries.
+Agenda built-in or custom commands are statically defined.  Agenda
+filters and limits allow to flexibly narrow down the list of agenda
+entries.
 
 
-Filters only change the visibility of items, are very fast and are
+/Filters/ only change the visibility of items, are very fast and are
 mostly used interactively[fn:96]. You can switch quickly between
 mostly used interactively[fn:96]. You can switch quickly between
-different filters without having to recreate the agenda.  If creating
-the agenda seems slow, one solution would be to create a view that
-contains everything you might want to work on for a while, and then
-use filtering to drill down.
-
-Limits on the other hand take effect before the agenda buffer is
-populated, so they are mostly useful when defined as local variables
-within custom agenda commands.
+different filters without having to recreate the agenda.  /Limits/ on
+the other hand take effect before the agenda buffer is populated, so
+they are mostly useful when defined as local variables within custom
+agenda commands.
 
 
 **** Filtering in the agenda
 **** Filtering in the agenda
 :PROPERTIES:
 :PROPERTIES:
@@ -9068,7 +9062,11 @@ within custom agenda commands.
 
 
 The general filtering command is ~org-agenda-filter~, bound to
 The general filtering command is ~org-agenda-filter~, bound to
 {{{kbd(/)}}}.  Before we introduce it, we describe commands for
 {{{kbd(/)}}}.  Before we introduce it, we describe commands for
-individual filter types.
+individual filter types.  All filtering commands handle prefix
+arguments in the same way:  A single {{{kbd(C-u)}}} prefix negates the
+filter, so it removes lines selected by the filter.  A double prefix
+adds the new filter condition to the one(s) already in place, so
+filter elements are accumulated.
 
 
 - {{{kbd(\)}}} (~org-agenda-filter-by-tag~) ::
 - {{{kbd(\)}}} (~org-agenda-filter-by-tag~) ::
 
 
@@ -9078,37 +9076,32 @@ individual filter types.
   Pressing {{{kbd(TAB)}}} at that prompt offers completion to select a
   Pressing {{{kbd(TAB)}}} at that prompt offers completion to select a
   tag, including any tags that do not have a selection character.  The
   tag, including any tags that do not have a selection character.  The
   command then hides all entries that do not contain or inherit this
   command then hides all entries that do not contain or inherit this
-  tag.  Call the command repeatedly to add several tags to the
-  filter. When called with prefix argument, remove the entries that
-  /do/ have the tag.  Pressing {{{kbd(+)}}} or {{{kbd(-)}}} at the
-  prompt also switches between filtering for and against the next tag.
-  {{{kbd(\)}}} at the prompt turns off the filter and shows any hidden
-  entries.
-
+  tag.  Pressing {{{kbd(+)}}} or {{{kbd(-)}}} at the prompt switches
+  between filtering for and against the next tag.  To clear the
+  filter, press {{{kbd(\)}}} twice (once to call the command again,
+  and once at the prompt).
 
 
 - {{{kbd(<)}}} (~org-agenda-filter-by-category~) ::
 - {{{kbd(<)}}} (~org-agenda-filter-by-category~) ::
 
 
   #+findex: org-agenda-filter-by-category
   #+findex: org-agenda-filter-by-category
   Filter by category of the line at point, and show only entries with
   Filter by category of the line at point, and show only entries with
-  this category.  Pressing {{{kbd(<)}}} again removes this filter.
-  When called with a prefix argument exclude the category of the item
-  at point from the agenda.
+  this category.  When called with a prefix argument, hide all entries
+  with the category at point.  To clear the filter, call this command
+  again by pressing {{{kbd(<)}}}.
 
 
 - {{{kbd(=)}}} (~org-agenda-filter-by-regexp~) ::
 - {{{kbd(=)}}} (~org-agenda-filter-by-regexp~) ::
 
 
   #+findex: org-agenda-filter-by-regexp
   #+findex: org-agenda-filter-by-regexp
   Filter the agenda view by a regular expression: only show agenda
   Filter the agenda view by a regular expression: only show agenda
-  entries matching the regular expression the user entered.  When
-  called with a prefix argument, it filters /out/ entries matching the
-  regexp.  Called in a regexp-filtered agenda view, remove the filter,
-  unless there are two universal prefix arguments, in which case
-  filters are accumulated.
+  entries matching the regular expression the user entered. To clear
+  the filter, call the command again by pressing {{{kbd(=)}}}.
 
 
 - {{{kbd(_)}}} (~org-agenda-filter-by-effort~) ::
 - {{{kbd(_)}}} (~org-agenda-filter-by-effort~) ::
 
 
   #+findex: org-agenda-filter-by-effort
   #+findex: org-agenda-filter-by-effort
-  Filter the agenda view with respect to effort estimates.  You first
-  need to set up allowed efforts globally, for example
+  Filter the agenda view with respect to effort estimates, so select
+  tasks that take the right amount of time.  You first need to set up
+  a list of efforts globally, for example
 
 
   #+begin_src emacs-lisp
   #+begin_src emacs-lisp
   (setq org-global-properties
   (setq org-global-properties
@@ -9123,18 +9116,16 @@ individual filter types.
   restricts to entries with effort smaller-or-equal, equal, or
   restricts to entries with effort smaller-or-equal, equal, or
   larger-or-equal than the selected value.  For application of the
   larger-or-equal than the selected value.  For application of the
   operator, entries without a defined effort are treated according to
   operator, entries without a defined effort are treated according to
-  the value of ~org-sort-agenda-noeffort-is-high~.
-
-  When called with a prefix argument, it removes entries matching the
-  condition.  With two universal prefix arguments, it clears effort
-  filters, which can be accumulated.
+  the value of ~org-sort-agenda-noeffort-is-high~.  To clear the
+  filter, press {{{kbd(_)}}} twice (once to call the command again,
+  and once at the first prompt).
 
 
 - {{{kbd(^)}}} (~org-agenda-filter-by-top-headline~) ::
 - {{{kbd(^)}}} (~org-agenda-filter-by-top-headline~) ::
 
 
   #+findex: org-agenda-filter-by-top-headline
   #+findex: org-agenda-filter-by-top-headline
   Filter the current agenda view and only display items that fall
   Filter the current agenda view and only display items that fall
-  under the same top-level headline as the current entry.  Press
-  {{{kbd(^)}}} again to turn this filter off.
+  under the same top-level headline as the current entry.  To clear
+  the filter, call this command again by pressing {{{kbd(^)}}}.
 
 
 - {{{kbd(/)}}} (~org-agenda-filter~) ::
 - {{{kbd(/)}}} (~org-agenda-filter~) ::
 
 
@@ -9155,9 +9146,10 @@ individual filter types.
   (tags will take priority).  If you reply to the prompt with the
   (tags will take priority).  If you reply to the prompt with the
   empty string, all filtering is removed.  If a filter is specified,
   empty string, all filtering is removed.  If a filter is specified,
   it replaces all current filters.  But if you call the command with a
   it replaces all current filters.  But if you call the command with a
-  prefix argument, or if you add an additional `+' (e.g. `++work') to
-  the front of the string, the new filter elements are added to the
-  active ones.
+  double prefix argument, or if you add an additional `+'
+  (e.g. `++work') to the front of the string, the new filter elements
+  are added to the active ones.  A single prefix argument applies the
+  entire filter in a negative sense.
 
 
 - {{{kbd(|)}}} (~org-agenda-filter-remove-all~) ::
 - {{{kbd(|)}}} (~org-agenda-filter-remove-all~) ::
 
 

+ 112 - 88
lisp/org-agenda.el

@@ -7468,8 +7468,8 @@ With a prefix argument, do so in all agenda buffers."
 (defun org-agenda-filter-by-category (strip)
 (defun org-agenda-filter-by-category (strip)
   "Filter lines in the agenda buffer that have a specific category.
   "Filter lines in the agenda buffer that have a specific category.
 The category is that of the current line.
 The category is that of the current line.
-Without prefix argument, keep only the lines of that category.
-With a prefix argument, exclude the lines of that category."
+With a `\\[universal-argument]' prefix argument, exclude the lines of that category.
+When there is already a category filter in place, this command removes the filter."
   (interactive "P")
   (interactive "P")
   (if (and org-agenda-filtered-by-category
   (if (and org-agenda-filtered-by-category
 	   org-agenda-category-filter)
 	   org-agenda-category-filter)
@@ -7499,7 +7499,8 @@ search from."
 (defvar org-agenda-filtered-by-top-headline nil)
 (defvar org-agenda-filtered-by-top-headline nil)
 (defun org-agenda-filter-by-top-headline (strip)
 (defun org-agenda-filter-by-top-headline (strip)
   "Keep only those lines that are descendants from the same top headline.
   "Keep only those lines that are descendants from the same top headline.
-The top headline is that of the current line."
+The top headline is that of the current line.  With prefix arg STRIP, hide
+all lines of the category at point."
   (interactive "P")
   (interactive "P")
   (if org-agenda-filtered-by-top-headline
   (if org-agenda-filtered-by-top-headline
       (progn
       (progn
@@ -7511,77 +7512,85 @@ The top headline is that of the current line."
         (error "No top-level headline at point")))))
         (error "No top-level headline at point")))))
 
 
 (defvar org-agenda-regexp-filter nil)
 (defvar org-agenda-regexp-filter nil)
-(defun org-agenda-filter-by-regexp (strip)
-  "Filter agenda entries by regular expressions.
-
-With one prefix argument, filter out entries matching the regexp.
-If there is already a regexp filter, remove it unless called with
-two prefix arguments."
+(defun org-agenda-filter-by-regexp (strip-or-accumulate)
+  "Filter agenda entries by a regular expressions.
+You will be prompted for the regular expresssion, and the agenda
+view will only show entires that are matched by that expression.
+
+With one `\\[universal-argument]' prefix argument, hide entries matching the regexp.
+When there is already a regexp filter active, this command removed the
+filter.  However, with two `\\[universal-argument]' prefix arguments, add a new condition to
+an already existing regexp filter."
   (interactive "P")
   (interactive "P")
-  (cond
-   ((and org-agenda-regexp-filter (not (equal strip '(16))))
-    (org-agenda-filter-show-all-re)
-    (message "Regexp filter removed"))
-   (t (let ((flt (concat (if (equal strip '(4)) "-" "+")
-			 (read-from-minibuffer
-			  (if (equal strip '(4))
-			      "Filter out entries matching regexp: "
-			    "Narrow to entries matching regexp: ")))))
-	(push flt org-agenda-regexp-filter)
-	(org-agenda-filter-apply org-agenda-regexp-filter 'regexp)))))
-
+  (let* ((strip (equal strip-or-accumulate '(4)))
+	 (accumulate (equal strip-or-accumulate '(16))))
+    (cond
+     ((and org-agenda-regexp-filter (not accumulate))
+      (org-agenda-filter-show-all-re)
+      (message "Regexp filter removed"))
+     (t (let ((flt (concat (if strip "-" "+")
+			   (read-from-minibuffer
+			    (if strip
+				"Hide entries matching regexp: "
+			      "Narrow to entries matching regexp: ")))))
+	  (push flt org-agenda-regexp-filter)
+	  (org-agenda-filter-apply org-agenda-regexp-filter 'regexp))))))
+  
 (defvar org-agenda-effort-filter nil)
 (defvar org-agenda-effort-filter nil)
-(defun org-agenda-filter-by-effort (strip)
+(defun org-agenda-filter-by-effort (strip-or-accumulate)
   "Filter agenda entries by effort.
   "Filter agenda entries by effort.
-With no prefix argument, keep entries matching the effort condition.
-With one prefix argument, filter out entries matching the condition.
-With two prefix arguments, remove the effort filters."
+With no `\\[universal-argument]' prefix argument, keep entries matching the effort condition.
+With one `\\[universal-argument]' prefix argument, filter out entries matching the condition.
+With two `\\[universal-argument]' prefix arguments, add a second condition to the existing filter.
+This last option is in practice not very useful, but it is available for
+consistency with the other filter commands."
   (interactive "P")
   (interactive "P")
-  (cond
-   ((member strip '(nil 4))
-    (let* ((efforts (split-string
-		     (or (cdr (assoc (concat org-effort-property "_ALL")
-				     org-global-properties))
-			 "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00")))
-	   ;; XXX: the following handles only up to 10 different
-	   ;; effort values.
-	   (allowed-keys (if (null efforts) nil
-			   (mapcar (lambda (n) (mod n 10)) ;turn 10 into 0
-				   (number-sequence 1 (length efforts)))))
-	   (op nil))
-      (while (not (memq op '(?< ?> ?= ?_)))
-	(setq op (read-char-exclusive "Effort operator? (> = or <)     or press `_' again to remove filter")))
-      ;; Select appropriate duration.  Ignore non-digit characters.
-      (if (eq op ?_)
-	  (progn
-	    (org-agenda-filter-show-all-effort)
-	    (message "Effort filter removed"))
-	(let ((prompt
-	       (apply #'format
-		      (concat "Effort %c "
-			      (mapconcat (lambda (s) (concat "[%d]" s))
-					 efforts
-					 " "))
-		      op allowed-keys))
-	      (eff -1))
-	  (while (not (memq eff allowed-keys))
-	    (message prompt)
-	    (setq eff (- (read-char-exclusive) 48)))
-	  (setq org-agenda-effort-filter
-		(list (concat (if strip "-" "+")
-			      (char-to-string op)
-			      ;; Numbering is 1 2 3 ... 9 0, but we want
-			      ;; 0 1 2 ... 8 9.
-			      (nth (mod (1- eff) 10) efforts)))))
-	(org-agenda-filter-apply org-agenda-effort-filter 'effort))))
-   (t (org-agenda-filter-show-all-effort)
-      (message "Effort filter removed"))))
-
-
-(defun org-agenda-filter (&optional keep)
+  (let* ((efforts (split-string
+		   (or (cdr (assoc (concat org-effort-property "_ALL")
+				   org-global-properties))
+		       "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00")))
+	 ;; XXX: the following handles only up to 10 different
+	 ;; effort values.
+	 (allowed-keys (if (null efforts) nil
+			 (mapcar (lambda (n) (mod n 10)) ;turn 10 into 0
+				 (number-sequence 1 (length efforts)))))
+	 (keep (equal strip-or-accumulate '(16)))
+	 (negative (equal strip-or-accumulate '(4)))
+	 (current org-agenda-effort-filter)
+	 (op nil))
+    (while (not (memq op '(?< ?> ?= ?_)))
+      (setq op (read-char-exclusive
+		"Effort operator? (> = or <)     or press `_' again to remove filter")))
+    ;; Select appropriate duration.  Ignore non-digit characters.
+    (if (eq op ?_)
+	(progn
+	  (org-agenda-filter-show-all-effort)
+	  (message "Effort filter removed"))
+      (let ((prompt
+	     (apply #'format
+		    (concat "Effort %c "
+			    (mapconcat (lambda (s) (concat "[%d]" s))
+				       efforts
+				       " "))
+		    op allowed-keys))
+	    (eff -1))
+	(while (not (memq eff allowed-keys))
+	  (message prompt)
+	  (setq eff (- (read-char-exclusive) 48)))
+	(org-agenda-filter-show-all-effort)
+	(setq org-agenda-effort-filter
+	      (append
+	       (list (concat (if negative "-" "+")
+			     (char-to-string op)
+			     ;; Numbering is 1 2 3 ... 9 0, but we want
+			     ;; 0 1 2 ... 8 9.
+			     (nth (mod (1- eff) 10) efforts)))
+	       (if keep current nil)))
+	(org-agenda-filter-apply org-agenda-effort-filter 'effort)))))
+
+
+(defun org-agenda-filter (&optional strip-or-accumulate)
   "Prompt for a general filter string and apply it to the agenda.
   "Prompt for a general filter string and apply it to the agenda.
-The new filter replaces all existing elements.  When called with a
-prefix arg KEEP, add the new elements to the existing filter.
 
 
 The string may contain filter elements like
 The string may contain filter elements like
 
 
@@ -7604,14 +7613,17 @@ values is offered.  Since the syntax for categories and tags is identical
 there should be no overlap between categoroes and tags.  If there is, tags
 there should be no overlap between categoroes and tags.  If there is, tags
 get priority.
 get priority.
 
 
-Instead of using the prefix argument to add to the current filter
-set, you can also add an additional leading `+' to filter string,
-like `+-John'.
+A single `\\[universal-argument]' prefix arg STRIP-OR-ACCUMULATE will negate the
+entire filter, which can be useful in connection with the prompt history.
 
 
-With a double prefix argument, execute the computed filtering defined in
+A double `\\[universal-argument] \\[universal-argument]' prefix arg will add the new filter elements to the
+existing ones. A shortcut for this is to add an additional `+' at the
+beginning of the string, like `+-John'.
+
+With a triple prefix argument, execute the computed filtering defined in
 the variable `org-agenda-auto-exclude-function'."
 the variable `org-agenda-auto-exclude-function'."
   (interactive "P")
   (interactive "P")
-  (if (equal keep '(16))
+  (if (equal strip-or-accumulate '(64))
       ;; Execute the auto-exclude action
       ;; Execute the auto-exclude action
       (if (not org-agenda-auto-exclude-function)
       (if (not org-agenda-auto-exclude-function)
 	  (user-error "`org-agenda-auto-exclude-function' is undefined")
 	  (user-error "`org-agenda-auto-exclude-function' is undefined")
@@ -7626,11 +7638,15 @@ the variable `org-agenda-auto-exclude-function'."
     ;; Prompt for a filter and act
     ;; Prompt for a filter and act
     (let* ((tag-list (org-agenda-get-represented-tags))
     (let* ((tag-list (org-agenda-get-represented-tags))
 	   (category-list (org-agenda-get-represented-categories))
 	   (category-list (org-agenda-get-represented-categories))
-	   (f-string (completing-read "Filter [+cat-tag<0:10-/regexp/]: "
-				      'org-agenda-filter-completion-function))
+	   (negate (equal strip-or-accumulate '(4)))
+	   (f-string (completing-read
+		      (concat
+		       (if negate "Negative filter" "Filter")
+		       " [+cat-tag<0:10-/regexp/]: ")
+		      'org-agenda-filter-completion-function))
 	   (keep (or (if (string-match "^+[-+]" f-string)
 	   (keep (or (if (string-match "^+[-+]" f-string)
 			 (progn (setq f-string (substring f-string 1)) t))
 			 (progn (setq f-string (substring f-string 1)) t))
-		     keep))
+		     (equal strip-or-accumulate '(16))))
 	   (fc (if keep org-agenda-category-filter))
 	   (fc (if keep org-agenda-category-filter))
 	   (ft (if keep org-agenda-tag-filter))
 	   (ft (if keep org-agenda-tag-filter))
 	   (fe (if keep org-agenda-effort-filter))
 	   (fe (if keep org-agenda-effort-filter))
@@ -7638,6 +7654,8 @@ the variable `org-agenda-auto-exclude-function'."
 	   pm s)
 	   pm s)
       (while (string-match "^[ \t]*\\([-+]\\)?\\(\\([^-+<>=/ \t]+\\)\\|\\([<>=][0-9:]+\\)\\|\\(/\\([^/]+\\)/?\\)\\)" f-string)
       (while (string-match "^[ \t]*\\([-+]\\)?\\(\\([^-+<>=/ \t]+\\)\\|\\([<>=][0-9:]+\\)\\|\\(/\\([^/]+\\)/?\\)\\)" f-string)
 	(setq pm (if (match-beginning 1) (match-string 1 f-string) "+"))
 	(setq pm (if (match-beginning 1) (match-string 1 f-string) "+"))
+	(when negate
+	  (setq pm (if (equal pm "+") "-" "+")))
 	(cond
 	(cond
 	 ((match-beginning 3)
 	 ((match-beginning 3)
 	  ;; category or tag
 	  ;; category or tag
@@ -7648,7 +7666,7 @@ the variable `org-agenda-auto-exclude-function'."
 	   ((member s category-list)
 	   ((member s category-list)
 	    (add-to-list 'fc (concat pm s) 'append 'equal))
 	    (add-to-list 'fc (concat pm s) 'append 'equal))
 	   (t (message
 	   (t (message
-	       "`%s%s' filter ignored tag/category is not represented"
+	       "`%s%s' filter ignored because tag/category is not represented"
 	       pm s))))
 	       pm s))))
 	 ((match-beginning 4)
 	 ((match-beginning 4)
 	  ;; effort
 	  ;; effort
@@ -7718,14 +7736,17 @@ which see."
     (org-agenda-filter-show-all-effort))
     (org-agenda-filter-show-all-effort))
   (org-agenda-finalize))
   (org-agenda-finalize))
 
 
-(defun org-agenda-filter-by-tag (arg &optional char exclude)
+(defun org-agenda-filter-by-tag (strip-or-accumulate &optional char exclude)
   "Keep only those lines in the agenda buffer that have a specific tag.
   "Keep only those lines in the agenda buffer that have a specific tag.
 
 
 The tag is selected with its fast selection letter, as configured.
 The tag is selected with its fast selection letter, as configured.
 
 
-With a `\\[universal-argument]' prefix, exclude the agenda search.
+With a `\\[universal-argument]' prefix, apply the filter negatively, stripping all matches.
+
+With a `\\[universal-argument] \\[universal-argument]' prefix, add the new tag to the existing filter
+instead of replacing it.
 
 
-With a `\\[universal-argument] \\[universal-argument]' prefix, filter the literal tag, \
+With a `\\[universal-argument] \\[universal-argument] \\[universal-argument]' prefix, filter the literal tag, \
 i.e. don't
 i.e. don't
 filter on all its group members.
 filter on all its group members.
 
 
@@ -7746,8 +7767,9 @@ also press `-' or `+' to switch between filtering and excluding."
 		     org-tag-alist-for-agenda ""))
 		     org-tag-alist-for-agenda ""))
 	 (valid-char-list (append '(?\t ?\r ?\\ ?. ?\s ?q)
 	 (valid-char-list (append '(?\t ?\r ?\\ ?. ?\s ?q)
 				  (string-to-list tag-chars)))
 				  (string-to-list tag-chars)))
-	 (exclude (or exclude (equal arg '(4))))
-	 (expand (not (equal arg '(16))))
+	 (exclude (or exclude (equal strip-or-accumulate '(4))))
+	 (accumulate (equal strip-or-accumulate '(16)))
+	 (expand (not (equal strip-or-accumulate '(64))))
 	 (inhibit-read-only t)
 	 (inhibit-read-only t)
 	 (current org-agenda-tag-filter)
 	 (current org-agenda-tag-filter)
 	 a n tag)
 	 a n tag)
@@ -7764,7 +7786,7 @@ also press `-' or `+' to switch between filtering and excluding."
 	(cond ((eq char ?-) (setq exclude t))
 	(cond ((eq char ?-) (setq exclude t))
 	      ((eq char ?+) (setq exclude nil)))))
 	      ((eq char ?+) (setq exclude nil)))))
     (when (eq char ?\t)
     (when (eq char ?\t)
-      (unless (local-variable-p 'org-global-tags-completion-table (current-buffer))
+      (unless (local-variable-p 'org-global-tags-completion-table)
 	(setq-local org-global-tags-completion-table
 	(setq-local org-global-tags-completion-table
 		    (org-global-tags-completion-table)))
 		    (org-global-tags-completion-table)))
       (let ((completion-ignore-case t))
       (let ((completion-ignore-case t))
@@ -7798,7 +7820,7 @@ also press `-' or `+' to switch between filtering and excluding."
       (setq tag (car a))
       (setq tag (car a))
       (setq org-agenda-tag-filter
       (setq org-agenda-tag-filter
 	    (cons (concat (if exclude "-" "+") tag)
 	    (cons (concat (if exclude "-" "+") tag)
-		  current))
+		  (if accumulate current nil)))
       (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))
       (org-agenda-filter-apply org-agenda-tag-filter 'tag expand))
      (t (error "Invalid tag selection character %c" char)))))
      (t (error "Invalid tag selection character %c" char)))))
 
 
@@ -7890,7 +7912,7 @@ function to set the right switches in the returned form."
     (dolist (x tags (cons (if (eq op ?-) 'and 'or) form))
     (dolist (x tags (cons (if (eq op ?-) 'and 'or) form))
       (let* ((tag (substring x 1))
       (let* ((tag (substring x 1))
 	     (f (cond
 	     (f (cond
-		 ((string= "" tag) '(not tags))
+		 ((string= "" tag) 'tags)
 		 ((and (string-match-p "\\`{" tag) (string-match-p "}\\'" tag))
 		 ((and (string-match-p "\\`{" tag) (string-match-p "}\\'" tag))
 		  ;; TAG is a regexp.
 		  ;; TAG is a regexp.
 		  (list 'org-match-any-p (substring tag 1 -1) 'tags))
 		  (list 'org-match-any-p (substring tag 1 -1) 'tags))
@@ -7945,7 +7967,8 @@ tags in the FILTER if any of the tags in FILTER are grouptags."
   ;; Deactivate `org-agenda-entry-text-mode' when filtering
   ;; Deactivate `org-agenda-entry-text-mode' when filtering
   (when org-agenda-entry-text-mode (org-agenda-entry-text-mode))
   (when org-agenda-entry-text-mode (org-agenda-entry-text-mode))
   (let (tags cat txt)
   (let (tags cat txt)
-    (setq org-agenda-filter-form (org-agenda-filter-make-matcher filter type expand))
+    (setq org-agenda-filter-form (org-agenda-filter-make-matcher
+				  filter type expand))
     ;; Only set `org-agenda-filtered-by-category' to t when a unique
     ;; Only set `org-agenda-filtered-by-category' to t when a unique
     ;; category is used as the filter:
     ;; category is used as the filter:
     (setq org-agenda-filtered-by-category
     (setq org-agenda-filtered-by-category
@@ -7998,7 +8021,8 @@ tags in the FILTER if any of the tags in FILTER are grouptags."
   (save-excursion
   (save-excursion
     (goto-char (point-min))
     (goto-char (point-min))
     (let ((inhibit-read-only t) pos)
     (let ((inhibit-read-only t) pos)
-      (while (setq pos (text-property-any (point) (point-max) 'org-filter-type type))
+      (while (setq pos (text-property-any (point) (point-max)
+					  'org-filter-type type))
 	(goto-char pos)
 	(goto-char pos)
 	(remove-text-properties
 	(remove-text-properties
 	 (point) (next-single-property-change (point) 'org-filter-type)
 	 (point) (next-single-property-change (point) 'org-filter-type)