From 933dc914694c14889af86c06ba0a8bbd88a316cf Mon Sep 17 00:00:00 2001 From: Allen Li Date: Thu, 8 Jul 2021 21:35:34 -0700 Subject: [PATCH] org: Use crm for completing tags Change various places which use `completing-read' to read tags using a custom completion function to instead use `completing-read-multiple' with a completion table instead. This makes tab completion play better with alternative completion frameworks such as vertico, selectrum, etc. `org-change-tag-in-region' only reads a single tag, so it is changed to use a completion table with `completing-read'. This also makes it play better with alternative completion frameworks. Note that there is still one use for `org-tags-completion-function', which is for completing tag matches. Completing tag matches is different from completing lists of tags since the separators (+, -, etc) have semantic meaning. This commit does not address that use case. * lisp/org-capture.el (org-capture-fill-template): Changed to use completing-read-multiple. * lisp/org.el (org-set-tags-command): Changed to use completing-read-multiple. (org-change-tag-in-region): Changed to use a simple completion table. * testing/lisp/test-org.el (test-org/set-tags-command): Fixed tests. * etc/ORG-NEWS (Tag completion now uses =completing-read-multiple=): Added news. --- etc/ORG-NEWS | 6 +++++ lisp/org-capture.el | 12 +++++----- lisp/org.el | 18 +++++++++------ testing/lisp/test-org.el | 50 ++++++++++++++++------------------------ 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 3f3971961..719ac3547 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -409,6 +409,12 @@ The function does not allow for a third optional parameter anymore. If a babel src block produces a raw LaTeX environment, it will now be recognised as a result, and so replaced when re-evaluated. +*** Tag completion now uses =completing-read-multiple= + +Tag completion now uses =completing-read-multiple= with a simple +completion table, which should allow better interoperability with +custom completion functions. + * Version 9.4 ** Incompatible changes *** Possibly broken internal file links: please check and fix diff --git a/lisp/org-capture.el b/lisp/org-capture.el index 5ecec6309..c51744680 100644 --- a/lisp/org-capture.el +++ b/lisp/org-capture.el @@ -69,6 +69,7 @@ (declare-function org-table-goto-line "org-table" (N)) (defvar dired-buffers) +(defvar crm-separator) (defvar org-end-time-was-given) (defvar org-keyword-properties) (defvar org-remember-default-headline) @@ -1739,12 +1740,11 @@ The template may still contain \"%?\" for cursor positioning." (org-add-colon-after-tag-completion t) (ins (mapconcat #'identity - (org-split-string - (completing-read - (if prompt (concat prompt ": ") "Tags: ") - 'org-tags-completion-function nil nil nil - 'org-tags-history) - "[^[:alnum:]_@#%]+") + (let ((crm-separator "[ \t]*:[ \t]*")) + (completing-read-multiple + (if prompt (concat prompt ": ") "Tags: ") + org-last-tags-completion-table nil nil nil + 'org-tags-history)) ":"))) (when (org-string-nw-p ins) (unless (eq (char-before) ?:) (insert ":")) diff --git a/lisp/org.el b/lisp/org.el index 4fd8b6fa6..ed3ee3a1c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -201,6 +201,8 @@ Stars are put in group 1 and the trimmed body in group 2.") ;; load languages based on value of `org-babel-load-languages' (defvar org-babel-load-languages) +(defvar crm-separator) ; dynamically scoped param + ;;;###autoload (defun org-babel-do-load-languages (sym value) "Load the languages defined in `org-babel-load-languages'." @@ -12054,12 +12056,14 @@ in Lisp code use `org-set-tags' instead." inherited-tags table (and org-fast-tag-selection-include-todo org-todo-key-alist)) - (let ((org-add-colon-after-tag-completion (< 1 (length table)))) - (org-trim (completing-read - "Tags: " - #'org-tags-completion-function - nil nil (org-make-tag-string current-tags) - 'org-tags-history))))))) + (let ((org-add-colon-after-tag-completion (< 1 (length table))) + (crm-separator "[ \t]*:[ \t]*")) + (string-join (completing-read-multiple + "Tags: " + org-last-tags-completion-table + nil nil (org-make-tag-string current-tags) + 'org-tags-history) + ":")))))) (org-set-tags tags))))) ;; `save-excursion' may not replace the point at the right ;; position. @@ -12139,7 +12143,7 @@ This works in the agenda, and also in an Org buffer." (org-global-tags-completion-table)) (org-global-tags-completion-table)))) (completing-read - "Tag: " 'org-tags-completion-function nil nil nil + "Tag: " org-last-tags-completion-table nil nil nil 'org-tags-history)) (progn (message "[s]et or [r]emove? ") diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 95ffb0a80..de3c6f3c9 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -6969,8 +6969,8 @@ Paragraph" (should (equal "* H1 :foo:" (org-test-with-temp-text "* H1" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -6979,8 +6979,8 @@ Paragraph" (should (equal "* H1 :foo:\nContents" (org-test-with-temp-text "* H1\nContents" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -6988,30 +6988,20 @@ Paragraph" (should-not (equal "* H1 :foo:\nContents2" (org-test-with-temp-text "* H1\nContents2" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) (org-at-heading-p)))) - ;; Strip all forbidden characters from user-entered tags. - (should - (equal "* H1 :foo:" - (org-test-with-temp-text "* H1" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ": foo *:"))) - (let ((org-use-fast-tag-selection nil) - (org-tags-column 1)) - (org-set-tags-command))) - (buffer-string)))) ;; When a region is active and ;; `org-loop-over-headlines-in-active-region' is non-nil, insert the ;; same value in all headlines in region. (should (equal "* H1 :foo:\nContents\n* H2 :foo:" (org-test-with-temp-text "* H1\nContents\n* H2" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-loop-over-headlines-in-active-region t) (org-tags-column 1)) @@ -7023,8 +7013,8 @@ Paragraph" (should (equal "* H1\nContents\n* H2 :foo:" (org-test-with-temp-text "* H1\nContents\n* H2" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-loop-over-headlines-in-active-region nil) (org-tags-column 1)) @@ -7043,8 +7033,8 @@ Paragraph" (should (equal ":foo:" (org-test-with-temp-text "* " - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -7053,8 +7043,8 @@ Paragraph" (should (equal "* H1 :foo:" (org-test-with-temp-text "* H1" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -7063,8 +7053,8 @@ Paragraph" (should (equal "* H1 :foo:" (org-test-with-temp-text "** H1" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -7073,8 +7063,8 @@ Paragraph" (should (equal " b :foo:" (org-test-with-temp-text "* a b" - (cl-letf (((symbol-function 'completing-read) - (lambda (&rest args) ":foo:"))) + (cl-letf (((symbol-function 'completing-read-multiple) + (lambda (&rest args) '("foo")))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) @@ -7083,9 +7073,9 @@ Paragraph" (should (equal "b :foo:" (org-test-with-temp-text "* a :foo:\n** b :foo:" - (cl-letf (((symbol-function 'completing-read) + (cl-letf (((symbol-function 'completing-read-multiple) (lambda (prompt coll &optional pred req initial &rest args) - initial))) + (list initial)))) (let ((org-use-fast-tag-selection nil) (org-tags-column 1)) (org-set-tags-command))) -- 2.32.0