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