branch: externals/org
commit 1323d5a6d192d2066c59e7c0c5f0dd533e2f47c5
Author: Ihor Radchenko <[email protected]>
Commit: Ihor Radchenko <[email protected]>

    org-element: Demand spaces before heading tags; fix regression from 
d7b662383
    
    * lisp/org-element.el (org-element--headline-parse-title): Make sure
    that we search through spaces before tags.  These spaces are
    mandatory.  Previous parser code actually made them optional,
    contradicting other parts of the code, the syntax spec, and the common
    sense.
    * lisp/org.el (org-tag--group-optional-re): Fix the docstring inaccuracy.
    * testing/lisp/test-org-element.el (test-org-element/headline-tags):
    New test.
    
    Reported-by: Kristoffer Balintona <[email protected]>
    Link: 
https://orgmode.org/list/CANVbq5=4raZbeTCn02jSpyb5Bbz68c6CjT+1Xt5uvQ7=fd_...@mail.gmail.com
---
 lisp/org-element.el              | 11 +++++++----
 lisp/org.el                      |  2 +-
 testing/lisp/test-org-element.el | 23 +++++++++++++++++++++++
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/lisp/org-element.el b/lisp/org-element.el
index be26eff4eb..5f64cc1c1d 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -1411,10 +1411,13 @@ Throw `:org-element-deferred-retry' signal at the end."
                     (goto-char (match-end 0))
                      (skip-chars-forward " \t"))))
             (title-start (point))
-            (tags (when (re-search-forward
-                          org-tag--group-enclosed-re
-                         (line-end-position)
-                         'move)
+            (tags (when (progn
+                           ;; `org-tag-group-re' includes spaces before tags.
+                           ;; Start search before preceding spaces, if any.
+                           ;; If there are no spaces before point here,
+                           ;; We are not looking at the tags.
+                           (skip-chars-backward " \t")
+                           (re-search-forward org-tag-group-re 
(line-end-position) 'move))
                     (goto-char (match-beginning 0))
                      (mapcar #'org-element--get-cached-string
                             (org-split-string (match-string-no-properties 1) 
":"))))
diff --git a/lisp/org.el b/lisp/org.el
index 86ae20233a..b3b319917d 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -697,7 +697,7 @@ colon.")
 (defconst org-tag--group-optional-re
   (concat "\\(?:[ \t]+" org-tag--group-enclosed-re "\\)?[ \t]*$")
   "Regexp matching an optional tag group at the end of a line.
-Regexp includes optional leading and trailing spaces.  If a tag group
+Regexp includes leading and optional trailing spaces.  If a tag group
 is present, group 1 is the full tag group (with colons), group 2 is
 the tag content (without colons).")
 
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 34a914ef3d..f1dd3c230b 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -1755,6 +1755,29 @@ CLOCK: [2023-10-13 Fri 14:40]--[2023-10-13 Fri 14:51] => 
 0:11"
   (org-test-with-temp-text "* COMMENT:tag:"
     (should-not (org-element-property :commentedp (org-element-at-point)))))
 
+(ert-deftest test-org-element/headline-tags ()
+  "Test tag recognition."
+  (org-test-with-temp-text "* Headline"
+    (should-not (org-element-property :tags (org-element-at-point))))
+  (org-test-with-temp-text "* Headline:notatag:"
+    (should-not (org-element-property :tags (org-element-at-point))))
+  (org-test-with-temp-text "* Headline :tag:"
+    (should (equal (list "tag") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* Headline :tag:tag2:"
+    (should (equal (list "tag" "tag2") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* Headline :tag_valid:"
+    (should (equal (list "tag_valid") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* Headline :tag_valid#1%%:"
+    (should (equal (list "tag_valid#1%%") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* Headline :tag^:"
+    (should-not (org-element-property :tags (org-element-at-point))))
+  (org-test-with-temp-text "* Headline :tag::"
+    (should (equal (list "tag" "") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* Headline :notatag: :tag:"
+    (should (equal (list "tag") (org-element-property :tags 
(org-element-at-point)))))
+  (org-test-with-temp-text "* :notatag: Headline"
+    (should-not (org-element-property :tags (org-element-at-point)))))
+
 (ert-deftest test-org-element/headline-comment-keyword ()
   "Test COMMENT keyword recognition."
   ;; Reference test.

Reply via email to