Browse Source

Properly handle `org-tag-persistent-alist'

* lisp/org.el (org-current-tag-alist): New variable.
(org-set-tags):
(org-global-tags-completion-table):
(org-agenda-prepare-buffers): Use new variable.
(org-set-regexps-and-options): Use new variable.  Handle STARTUP early
so that "#+STARTUP: noptag" is taken into consideration.

* lisp/org-agenda.el (org-agenda-bulk-action): Use new variable.

* lisp/org-mobile.el (org-mobile-create-index-file): `org-tag-alist' is
  no longer buffer-local.

* testing/lisp/test-org.el (test-org/set-regexps-and-options): Add
  tests.
Nicolas Goaziou 4 years ago
parent
commit
4743d43dd8
4 changed files with 95 additions and 53 deletions
  1. 7 6
      lisp/org-agenda.el
  2. 1 1
      lisp/org-mobile.el
  3. 31 25
      lisp/org.el
  4. 56 21
      testing/lisp/test-org.el

+ 7 - 6
lisp/org-agenda.el

@@ -86,10 +86,11 @@
 (declare-function org-add-archive-files "org-archive" (files))
 (declare-function org-capture "org-capture" (&optional goto keys))
 
-(defvar calendar-mode-map)                    ; defined in calendar.el
-(defvar org-clock-current-task nil)           ; defined in org-clock.el
-(defvar org-mobile-force-id-on-agenda-items)  ; defined in org-mobile.el
-(defvar org-habit-show-habits)                ; defined in org-habit.el
+(defvar calendar-mode-map)
+(defvar org-clock-current-task)
+(defvar org-current-tag-alist)
+(defvar org-mobile-force-id-on-agenda-items)
+(defvar org-habit-show-habits)
 (defvar org-habit-show-habits-only-for-today)
 (defvar org-habit-show-all-today)
 
@@ -9930,8 +9931,8 @@ The prefix arg is passed through to the command if possible."
 		     (format "Tag to %s: " (if (eq action ?+) "add" "remove"))
 		     (with-current-buffer (marker-buffer (car entries))
 		       (delq nil
-			     (mapcar (lambda (x)
-				       (if (stringp (car x)) x)) org-tag-alist)))))
+			     (mapcar (lambda (x) (and (stringp (car x)) x))
+				     org-current-tag-alist)))))
 	  (setq cmd `(org-agenda-set-tags ,tag ,(if (eq action ?+) ''on ''off))))
 
 	 ((memq action '(?s ?d))

+ 1 - 1
lisp/org-mobile.el

@@ -422,7 +422,7 @@ agenda view showing the flagged items."
   (let ((files-alist (sort (copy-sequence org-mobile-files-alist)
 			   (lambda (a b) (string< (cdr a) (cdr b)))))
 	(def-todo (default-value 'org-todo-keywords))
-	(def-tags (default-value 'org-tag-alist))
+	(def-tags org-tag-alist)
 	(target-file (expand-file-name org-mobile-index-file
 				       org-mobile-directory))
 	file link-name todo-kwds done-kwds tags entry kwds dwds twds)

+ 31 - 25
lisp/org.el

@@ -2581,6 +2581,10 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'."
   "Alist of all groups tags from all current agenda files.")
 (defvar-local org-tag-groups-alist nil)
 (defvar org-agenda-contributing-files nil)
+(defvar-local org-current-tag-alist nil
+  "Alist of all tag groups in current buffer.
+This variable takes into consideration `org-tag-alist',
+`org-tag-persistent-alist' and TAGS keywords in the buffer.")
 (defvar-local org-not-done-keywords nil)
 (defvar-local org-done-keywords nil)
 (defvar-local org-todo-heads nil)
@@ -4901,13 +4905,28 @@ related expressions."
 				'("ARCHIVE" "CATEGORY" "COLUMNS" "CONSTANTS"
 				  "LINK" "OPTIONS" "PRIORITIES" "PROPERTY"
 				  "SEQ_TODO" "STARTUP" "TODO" "TYP_TODO")))))))
+      ;; Startup options.  Get this early since it does change
+      ;; behavior for other options (e.g., tags).
+      (let ((startup (cdr (assq 'startup alist))))
+	(dolist (option startup)
+	  (let ((entry (assoc-string option org-startup-options t)))
+	    (when entry
+	      (let ((var (nth 1 entry))
+		    (val (nth 2 entry)))
+		(if (not (nth 3 entry)) (set (make-local-variable var) val)
+		  (unless (listp (symbol-value var))
+		    (set (make-local-variable var) nil))
+		  (add-to-list var val)))))))
       (setq-local org-file-tags
 		  (mapcar #'org-add-prop-inherited
 			  (cdr (assq 'filetags alist))))
-      (setq-local org-tag-alist
-		  (let ((tags (cdr (assq 'tags alist))))
-		    (if tags (org-tag-string-to-alist tags) org-tag-alist)))
-      (setq-local org-tag-groups-alist (org-tag-alist-to-groups org-tag-alist))
+      (setq org-current-tag-alist
+	    (append org-tag-persistent-alist
+		    (let ((tags (cdr (assq 'tags alist))))
+		      (if tags (org-tag-string-to-alist tags)
+			org-tag-alist))))
+      (setq org-tag-groups-alist
+	    (org-tag-alist-to-groups org-current-tag-alist))
       (unless tags-only
 	;; File properties.
 	(setq-local org-file-properties (cdr (assq 'property alist)))
@@ -4939,17 +4958,6 @@ related expressions."
 	(let ((scripts (assq 'scripts alist)))
 	  (when scripts
 	    (setq-local org-use-sub-superscripts (cdr scripts))))
-	;; Startup options.
-	(let ((startup (cdr (assq 'startup alist))))
-	  (dolist (option startup)
-	    (let ((entry (assoc-string option org-startup-options t)))
-	      (when entry
-		(let ((var (nth 1 entry))
-		      (val (nth 2 entry)))
-		  (if (not (nth 3 entry)) (set (make-local-variable var) val)
-		    (unless (listp (symbol-value var))
-		      (set (make-local-variable var) nil))
-		    (add-to-list var val)))))))
 	;; TODO keywords.
 	(setq-local org-todo-kwd-alist nil)
 	(setq-local org-todo-key-alist nil)
@@ -14364,16 +14372,15 @@ instead of the agenda files."
   (save-excursion
     (org-uniquify
      (delq nil
-	   (apply 'append
+	   (apply #'append
 		  (mapcar
 		   (lambda (file)
 		     (set-buffer (find-file-noselect file))
-		     (append (org-get-buffer-tags)
-			     (mapcar (lambda (x) (if (stringp (car-safe x))
-						     (list (car-safe x)) nil))
-				     org-tag-alist)))
-		   (if (and files (car files))
-		       files
+		     (mapcar (lambda (x)
+			       (and (stringp (car-safe x))
+				    (list (car-safe x))))
+			     (or org-current-tag-alist (org-get-buffer-tags))))
+		   (if (car-safe files) files
 		     (org-agenda-files))))))))
 
 (defun org-make-tags-matcher (match)
@@ -14937,7 +14944,7 @@ When JUST-ALIGN is non-nil, only align tags."
 			     org-last-tags-completion-table
 			     (append
 			      org-tag-persistent-alist
-			      (or org-tag-alist (org-get-buffer-tags))
+			      (or org-current-tag-alist (org-get-buffer-tags))
 			      (and
 			       org-complete-tags-always-offer-all-agenda-tags
 			       (org-global-tags-completion-table
@@ -18717,8 +18724,7 @@ When a buffer is unmodified, it is just killed.  When modified, it is saved
 	    (setq org-tag-alist-for-agenda
 		  (org-uniquify
 		   (append org-tag-alist-for-agenda
-			   org-tag-alist
-			   org-tag-persistent-alist)))
+			   org-current-tag-alist)))
 	    ;; Merge current file's tag groups into global
 	    ;; `org-tag-groups-alist-for-agenda'.
 	    (when org-group-tags

+ 56 - 21
testing/lisp/test-org.el

@@ -1656,41 +1656,76 @@ SCHEDULED: <2014-03-04 tue.>"
 (ert-deftest test-org/set-regexps-and-options ()
   "Test `org-set-regexps-and-options' specifications."
   ;; TAGS keyword.
+  (should
+   (equal '(("A"))
+	  (let ((org-tag-alist '(("A")))
+		(org-tag-persistent-alist nil))
+	    (org-test-with-temp-text ""
+	      (org-mode-restart)
+	      org-current-tag-alist))))
+  (should
+   (equal '(("B"))
+	  (let ((org-tag-alist '(("A")))
+		(org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: B"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
+  (should
+   (equal '(("C") ("B"))
+	  (let ((org-tag-alist '(("A")))
+		(org-tag-persistent-alist '(("C"))))
+	    (org-test-with-temp-text "#+TAGS: B"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
+  (should
+   (equal '(("B"))
+	  (let ((org-tag-alist '(("A")))
+		(org-tag-persistent-alist '(("C"))))
+	    (org-test-with-temp-text "#+STARTUP: noptag\n#+TAGS: B"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '(("A" . ?a) ("B") ("C"))
-	  (org-test-with-temp-text "#+TAGS: A(a) B C"
-	    (org-mode-restart)
-	    org-tag-alist)))
+	  (let ((org-tag-persistant-alist nil))
+	    (org-test-with-temp-text "#+TAGS: A(a) B C"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '(("A") (:newline) ("B"))
-	  (org-test-with-temp-text "#+TAGS: A\n#+TAGS: B"
-	    (org-mode-restart)
-	    org-tag-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: A\n#+TAGS: B"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '((:startgroup) ("A") ("B") (:endgroup) ("C"))
-	  (org-test-with-temp-text "#+TAGS: { A B } C"
-	    (org-mode-restart)
-	    org-tag-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: { A B } C"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '((:startgroup) ("A") (:grouptags) ("B") ("C") (:endgroup))
-	  (org-test-with-temp-text "#+TAGS: { A : B C }"
-	    (org-mode-restart)
-	    org-tag-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: { A : B C }"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '(("A" "B" "C"))
-	  (org-test-with-temp-text "#+TAGS: { A : B C }"
-	    (org-mode-restart)
-	    org-tag-groups-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: { A : B C }"
+	      (org-mode-restart)
+	      org-tag-groups-alist))))
   (should
    (equal '((:startgrouptag) ("A") (:grouptags) ("B") ("C") (:endgrouptag))
-	  (org-test-with-temp-text "#+TAGS: [ A : B C ]"
-	    (org-mode-restart)
-	    org-tag-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: [ A : B C ]"
+	      (org-mode-restart)
+	      org-current-tag-alist))))
   (should
    (equal '(("A" "B" "C"))
-	  (org-test-with-temp-text "#+TAGS: [ A : B C ]"
-	    (org-mode-restart)
-	    org-tag-groups-alist)))
+	  (let ((org-tag-persistent-alist nil))
+	    (org-test-with-temp-text "#+TAGS: [ A : B C ]"
+	      (org-mode-restart)
+	      org-tag-groups-alist))))
   ;; FILETAGS keyword.
   (should
    (equal '("A" "B" "C")