diff --git a/lisp/org-pcomplete.el b/lisp/org-pcomplete.el index d245f6981..062f38a7c 100644 --- a/lisp/org-pcomplete.el +++ b/lisp/org-pcomplete.el @@ -104,10 +104,11 @@ The return value is a string naming the thing at point." (char-before))) (cons "tex" nil)) ;; Tags on a headline. - ((and (org-at-heading-p) - (eq ?: (save-excursion - (skip-chars-backward "[:alnum:]_@#%") - (char-before)))) + ((and (org-match-line + (format "\\*+ \\(?:.+? \\)?\\(:\\)\\(\\(?::\\|%s\\)+\\)?[ \t]*$" + org-tag-re)) + (or (org-point-in-group (point) 2) + (= (point) (match-end 1)))) (cons "tag" nil)) ;; TODO keywords on an empty headline. ((and (string-match "^\\*+ +\\S-*$" line-to-here) @@ -372,7 +373,8 @@ This needs more work, to handle headings with lots of spaces in them." (setq lst (delete tag lst))) lst)) (and (string-match ".*:" pcomplete-stub) - (substring pcomplete-stub (match-end 0)))))) + (substring pcomplete-stub (match-end 0))) + t))) (defun pcomplete/org-mode/drawer () "Complete a drawer name, including \"PROPERTIES\"." diff --git a/testing/lisp/test-org-pcomplete.el b/testing/lisp/test-org-pcomplete.el index c9fa4c908..581eab549 100644 --- a/testing/lisp/test-org-pcomplete.el +++ b/testing/lisp/test-org-pcomplete.el @@ -125,6 +125,39 @@ (pcomplete) (buffer-string))))) +(ert-deftest test-org-pcomplete/tag () + "Test tag completion." + ;; Complete at end of line, according to `org-current-tag-alist'. + (should + (equal "* H :foo:" + (org-test-with-temp-text "* H :" + (let ((org-current-tag-alist '(("foo")))) (pcomplete)) + (buffer-string)))) + (should + (equal "* H :foo:bar:" + (org-test-with-temp-text "* H :foo:b" + (let ((org-current-tag-alist '(("bar")))) (pcomplete)) + (buffer-string)))) + ;; If `org-current-tag-alist' is non-nil, complete against tags in + ;; buffer. + (should + (equal "* H1 :bar:\n* H2 :bar:" + (org-test-with-temp-text "* H1 :bar:\n* H2 :" + (let ((org-current-tag-alist nil)) (pcomplete)) + (buffer-string)))) + ;; Do not complete in the middle of a line. + (should + (equal "* H :notag: :real:tags:" + (org-test-with-temp-text "* H :notag: :real:tags:" + (let ((org-current-tag-alist '(("foo")))) (pcomplete)) + (buffer-string)))) + ;; Complete even when there's a match on the line. + (should + (equal "* foo: :foo:" + (org-test-with-temp-text "* foo: :" + (let ((org-current-tag-alist '(("foo")))) (pcomplete)) + (buffer-string))))) + (ert-deftest test-org-pcomplete/todo () "Test TODO completion." (should