Function: org-tags-expand
org-tags-expand is a byte-compiled function defined in org.el.gz.
Signature
(org-tags-expand MATCH &optional SINGLE-AS-LIST)
Documentation
Expand group tags in MATCH.
This replaces every group tag in MATCH with a regexp tag search. For example, a group tag "Work" defined as { Work : Lab Conf } will be replaced like this:
Work => {\<\(?:Work\|Lab\|Conf\)\>}
+Work => +{\<\(?:Work\|Lab\|Conf\)\>}
-Work => -{\<\(?:Work\|Lab\|Conf\)\>}
Replacing by a regexp preserves the structure of the match. E.g., this expansion
Work|Home => {\(?:Work\|Lab\|Conf\}|Home
will match anything tagged with "Lab" and "Home", or tagged with "Conf" and "Home" or tagged with "Work" and "Home".
A group tag in MATCH can contain regular expressions of its own. For example, a group tag "Proj" defined as { Proj : {P@.+} } will be replaced like this:
Proj => {\<\(?:Proj\)\>\|P@.+}
When the optional argument SINGLE-AS-LIST is non-nil, MATCH is assumed to be a single group tag, and the function will return the list of tags in this group.
Source Code
;; Defined in /usr/src/emacs/lisp/org/org.el.gz
(defun org-tags-expand (match &optional single-as-list)
"Expand group tags in MATCH.
This replaces every group tag in MATCH with a regexp tag search.
For example, a group tag \"Work\" defined as { Work : Lab Conf }
will be replaced like this:
Work => {\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
+Work => +{\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
-Work => -{\\<\\(?:Work\\|Lab\\|Conf\\)\\>}
Replacing by a regexp preserves the structure of the match.
E.g., this expansion
Work|Home => {\\(?:Work\\|Lab\\|Conf\\}|Home
will match anything tagged with \"Lab\" and \"Home\", or tagged
with \"Conf\" and \"Home\" or tagged with \"Work\" and \"Home\".
A group tag in MATCH can contain regular expressions of its own.
For example, a group tag \"Proj\" defined as { Proj : {P@.+} }
will be replaced like this:
Proj => {\\<\\(?:Proj\\)\\>\\|P@.+}
When the optional argument SINGLE-AS-LIST is non-nil, MATCH is
assumed to be a single group tag, and the function will return
the list of tags in this group."
(unless (org-string-nw-p match) (error "Invalid match tag: %S" match))
(let ((tag-groups
(or org-tag-groups-alist-for-agenda org-tag-groups-alist)))
(cond
(single-as-list (org--tags-expand-group (list match) tag-groups nil))
(org-group-tags
(let* ((case-fold-search t)
(group-keys (mapcar #'car tag-groups))
(key-regexp (concat "\\([+-]?\\)" (regexp-opt group-keys 'words)))
(return-match match))
;; Mark regexp-expressions in the match-expression so that we
;; do not replace them later on.
(let ((s 0))
(while (string-match "{.+?}" return-match s)
(setq s (match-end 0))
(add-text-properties
(match-beginning 0) (match-end 0) '(regexp t) return-match)))
;; For each tag token found in MATCH, compute a regexp and it
(with-syntax-table org-mode-tags-syntax-table
(replace-regexp-in-string
key-regexp
(lambda (m)
(if (get-text-property (match-beginning 2) 'regexp m)
m ;regexp tag: ignore
(let* ((operator (match-string 1 m))
(tag-token (let ((tag (match-string 2 m)))
(list tag)))
regexp-tags regular-tags)
;; Partition tags between regexp and regular tags.
;; Remove curly bracket syntax from regexp tags.
(dolist (tag (org--tags-expand-group tag-token tag-groups nil))
(save-match-data
(if (string-match "{\\(.+?\\)}" tag)
(push (match-string 1 tag) regexp-tags)
(push tag regular-tags))))
;; Replace tag token by the appropriate regexp.
;; Regular tags need to be regexp-quoted, whereas
;; regexp-tags are inserted as-is.
(let ((regular (regexp-opt regular-tags))
(regexp (mapconcat #'identity regexp-tags "\\|")))
(concat operator
(cond
((null regular-tags) (format "{%s}" regexp))
((null regexp-tags) (format "{\\<%s\\>}" regular))
(t (format "{\\<%s\\>\\|%s}" regular regexp))))))))
return-match
t t))))
(t match))))