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))))