Function: org-element-map
org-element-map is a byte-compiled function defined in
org-element.el.gz.
Signature
(org-element-map DATA TYPES FUN &optional INFO FIRST-MATCH NO-RECURSION WITH-AFFILIATED)
Documentation
Map a function on selected elements or objects.
DATA is a parse tree (for example, returned by
org-element-parse-buffer), an element, an object, a string, or a
list of such constructs. TYPES is a symbol or list of symbols of
elements or object types (see org-element-all-elements and
org-element-all-objects for a complete list of types). FUN is the
function called on the matching element or object. It has to accept
one argument: the element or object itself.
When optional argument INFO is non-nil, it should be a plist holding export options. In that case, parts of the parse tree not exportable according to that property list will be skipped.
When optional argument FIRST-MATCH is non-nil, stop at the first match for which FUN doesn't return nil, and return that value.
Optional argument NO-RECURSION is a symbol or a list of symbols
representing elements or objects types. org-element-map won't
enter any recursive element or object whose type belongs to that
list. Though, FUN can still be applied on them.
When optional argument WITH-AFFILIATED is non-nil, FUN will also
apply to matching objects within parsed affiliated keywords (see
org-element-parsed-keywords).
Nil values returned from FUN do not appear in the results.
Examples:
---------
Assuming TREE is a variable containing an Org buffer parse tree,
the following example will return a flat list of all src-block
and example-block elements in it:
(setq tree (org-element-parse-buffer))
(org-element-map tree '(example-block src-block) #'identity)
The following snippet will find the first headline with a level of 1 and a "phone" tag, and will return its beginning position:
(org-element-map tree 'headline
(lambda (hl)
(and (= (org-element-property :level hl) 1)
(member "phone" (org-element-property :tags hl))
(org-element-property :begin hl)))
nil t)
The next example will return a flat list of all plain-list type
elements in TREE that are not a sub-list themselves:
(org-element-map tree 'plain-list #'identity nil nil 'plain-list)
Eventually, this example will return a flat list of all bold
type objects containing a latex-snippet type object, even
looking into captions:
(org-element-map tree 'bold
(lambda (b)
(and (org-element-map b 'latex-snippet #'identity nil t) b))
nil nil nil t)
Source Code
;; Defined in /usr/src/emacs/lisp/org/org-element.el.gz
(defun org-element-map
(data types fun &optional info first-match no-recursion with-affiliated)
"Map a function on selected elements or objects.
DATA is a parse tree (for example, returned by
`org-element-parse-buffer'), an element, an object, a string, or a
list of such constructs. TYPES is a symbol or list of symbols of
elements or object types (see `org-element-all-elements' and
`org-element-all-objects' for a complete list of types). FUN is the
function called on the matching element or object. It has to accept
one argument: the element or object itself.
When optional argument INFO is non-nil, it should be a plist
holding export options. In that case, parts of the parse tree
not exportable according to that property list will be skipped.
When optional argument FIRST-MATCH is non-nil, stop at the first
match for which FUN doesn't return nil, and return that value.
Optional argument NO-RECURSION is a symbol or a list of symbols
representing elements or objects types. `org-element-map' won't
enter any recursive element or object whose type belongs to that
list. Though, FUN can still be applied on them.
When optional argument WITH-AFFILIATED is non-nil, FUN will also
apply to matching objects within parsed affiliated keywords (see
`org-element-parsed-keywords').
Nil values returned from FUN do not appear in the results.
Examples:
---------
Assuming TREE is a variable containing an Org buffer parse tree,
the following example will return a flat list of all `src-block'
and `example-block' elements in it:
(setq tree (org-element-parse-buffer))
(org-element-map tree \\='(example-block src-block) #\\='identity)
The following snippet will find the first headline with a level
of 1 and a \"phone\" tag, and will return its beginning position:
(org-element-map tree \\='headline
(lambda (hl)
(and (= (org-element-property :level hl) 1)
(member \"phone\" (org-element-property :tags hl))
(org-element-property :begin hl)))
nil t)
The next example will return a flat list of all `plain-list' type
elements in TREE that are not a sub-list themselves:
(org-element-map tree \\='plain-list #\\='identity nil nil \\='plain-list)
Eventually, this example will return a flat list of all `bold'
type objects containing a `latex-snippet' type object, even
looking into captions:
(org-element-map tree \\='bold
(lambda (b)
(and (org-element-map b \\='latex-snippet #\\='identity nil t) b))
nil nil nil t)"
(declare (indent 2))
;; Ensure TYPES and NO-RECURSION are a list, even of one element.
(let* ((types (if (listp types) types (list types)))
(no-recursion (if (listp no-recursion) no-recursion
(list no-recursion)))
;; Recursion depth is determined by --CATEGORY.
(--category
(catch :--found
(let ((category 'greater-elements)
(all-objects (cons 'plain-text org-element-all-objects)))
(dolist (type types category)
(cond ((memq type all-objects)
;; If one object is found, the function has
;; to recurse into every object.
(throw :--found 'objects))
((not (memq type org-element-greater-elements))
;; If one regular element is found, the
;; function has to recurse, at least, into
;; every element it encounters.
(and (not (eq category 'elements))
(setq category 'elements))))))))
(--ignore-list (plist-get info :ignore-list))
--acc)
(letrec ((--walk-tree
(lambda (--data)
;; Recursively walk DATA. INFO, if non-nil, is a plist
;; holding contextual information.
(let ((--type (org-element-type --data)))
(cond
((not --data))
;; Ignored element in an export context.
((and info (memq --data --ignore-list)))
;; List of elements or objects.
((not --type) (mapc --walk-tree --data))
;; Unconditionally enter parse trees.
((eq --type 'org-data)
(mapc --walk-tree (org-element-contents --data)))
(t
;; Check if TYPE is matching among TYPES. If so,
;; apply FUN to --DATA and accumulate return value
;; into --ACC (or exit if FIRST-MATCH is non-nil).
(when (memq --type types)
(let ((result (funcall fun --data)))
(cond ((not result))
(first-match (throw :--map-first-match result))
(t (push result --acc)))))
;; If --DATA has a secondary string that can contain
;; objects with their type among TYPES, look inside.
(when (and (eq --category 'objects) (not (stringp --data)))
(dolist (p (cdr (assq --type
org-element-secondary-value-alist)))
(funcall --walk-tree (org-element-property p --data))))
;; If --DATA has any parsed affiliated keywords and
;; WITH-AFFILIATED is non-nil, look for objects in
;; them.
(when (and with-affiliated
(eq --category 'objects)
(eq (org-element-class --data) 'element))
(dolist (kwd-pair org-element--parsed-properties-alist)
(let ((kwd (car kwd-pair))
(value (org-element-property (cdr kwd-pair) --data)))
;; Pay attention to the type of parsed
;; keyword. In particular, preserve order for
;; multiple keywords.
(cond
((not value))
((member kwd org-element-dual-keywords)
(if (member kwd org-element-multiple-keywords)
(dolist (line (reverse value))
(funcall --walk-tree (cdr line))
(funcall --walk-tree (car line)))
(funcall --walk-tree (cdr value))
(funcall --walk-tree (car value))))
((member kwd org-element-multiple-keywords)
(mapc --walk-tree (reverse value)))
(t (funcall --walk-tree value))))))
;; Determine if a recursion into --DATA is possible.
(cond
;; --TYPE is explicitly removed from recursion.
((memq --type no-recursion))
;; --DATA has no contents.
((not (org-element-contents --data)))
;; Looking for greater elements but --DATA is
;; simply an element or an object.
((and (eq --category 'greater-elements)
(not (memq --type org-element-greater-elements))))
;; Looking for elements but --DATA is an object.
((and (eq --category 'elements)
(eq (org-element-class --data) 'object)))
;; In any other case, map contents.
(t (mapc --walk-tree (org-element-contents --data))))))))))
(catch :--map-first-match
(funcall --walk-tree data)
;; Return value in a proper order.
(nreverse --acc)))))