[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/org 55ba9f05a7 018/101: org-element-map: Refactor using
From: |
ELPA Syncer |
Subject: |
[elpa] externals/org 55ba9f05a7 018/101: org-element-map: Refactor using `org-element-ast-map' |
Date: |
Sat, 1 Jul 2023 09:59:00 -0400 (EDT) |
branch: externals/org
commit 55ba9f05a768e274e55b672b1c0ea1a672c5ffb7
Author: Ihor Radchenko <yantar92@posteo.net>
Commit: Ihor Radchenko <yantar92@posteo.net>
org-element-map: Refactor using `org-element-ast-map'
* lisp/org-element.el (org-element-map): Use `org-element-ast-map' to
traverse the AST. Update the docstring adding new features from
`org-element-ast-map' - FUN can now throw `:org-element-skip' signal
to skip current node and its child nodes. Clarify the structure of
INFO argument. Reverse the traverse order for dual keywords -
secondary value is now traversed after the main value.
* testing/lisp/test-org-element.el (test-org-element/map): Update the test
reflecting the change in dual keyword traversal order.
---
lisp/org-element.el | 129 +++++++++++----------------------------
testing/lisp/test-org-element.el | 2 +-
2 files changed, 36 insertions(+), 95 deletions(-)
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 5752b24ccf..6e8ce8933c 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4472,8 +4472,9 @@ 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.
+holding export options. In that case, elements of the parse tree
+\\(compared with `eq') not exportable according to `:ignore-list'
+property in 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.
@@ -4487,8 +4488,15 @@ When optional argument WITH-AFFILIATED is non-nil, FUN
will also
apply to matching objects within parsed affiliated keywords (see
`org-element-parsed-keywords').
+FUN may throw `:org-element-skip' signal. Then, `org-element-map'
+will not recurse into the current element.
+
Nil values returned from FUN do not appear in the results.
+When buffer parse tree is used, elements and objects are generally
+traversed in the same order they appear in text with a single
+exception of dual keywords where secondary value is traversed after
+the mail value.
Examples:
---------
@@ -4526,98 +4534,31 @@ looking into captions:
(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 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 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)))))
+ (ignore-list (plist-get info :ignore-list))
+ (objects?
+ (cl-intersection
+ (cons 'plain-text org-element-all-objects) types))
+ (no-recursion
+ (append
+ (if (listp no-recursion) no-recursion
+ (list no-recursion))
+ (unless objects?
+ org-element-all-objects)
+ (unless objects?
+ ;; Do not recurse into elements that can only contain
+ ;; objects.
+ (cl-set-difference
+ org-element-all-elements
+ org-element-greater-elements)))))
+ (org-element-ast-map
+ data types fun
+ ignore-list first-match
+ no-recursion
+ ;; Affiliated keywords may only contain objects.
+ (when (and with-affiliated objects?)
+ (mapcar #'cdr org-element--parsed-properties-alist))
+ ;; Secondary strings may only contain objects.
+ (not objects?))))
;; The following functions are internal parts of the parser.
;;
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 9c44bd340f..096e660f52 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -70,7 +70,7 @@ Some other text
;; Use WITH-AFFILIATED argument.
(should
(equal
- '("a" "1" "b" "2")
+ '("1" "a" "2" "b")
(org-test-with-temp-text "#+CAPTION[a]: 1\n#+CAPTION[b]: 2\nParagraph"
(org-element-map
(org-element-at-point) 'plain-text 'identity nil nil nil t)))))
- [elpa] externals/org 7c549f4841 060/101: org-babel-tangle-collect-blocks: Switch to org-element API, (continued)
- [elpa] externals/org 7c549f4841 060/101: org-babel-tangle-collect-blocks: Switch to org-element API, ELPA Syncer, 2023/07/01
- [elpa] externals/org b2482d9cc4 070/101: * testing/lisp/test-org-element.el: Add new tests, ELPA Syncer, 2023/07/01
- [elpa] externals/org b0a2deaec6 073/101: org-element--current-element: Faster property drawer check, ELPA Syncer, 2023/07/01
- [elpa] externals/org 110601ce74 074/101: org-element--current-element: Add FIXME, ELPA Syncer, 2023/07/01
- [elpa] externals/org 48e4a76b99 079/101: org-element: Avoid computing static regexps dynamically, ELPA Syncer, 2023/07/01
- [elpa] externals/org f895be1ad9 086/101: org-element--properties-mapc: Small refactoring, ELPA Syncer, 2023/07/01
- [elpa] externals/org a04e16bd11 082/101: lisp/org-macs.el: Restructure file outline, fixing compiler warning, ELPA Syncer, 2023/07/01
- [elpa] externals/org 5a3224a325 085/101: etc/ORG-NEWS: Document Org API changes, ELPA Syncer, 2023/07/01
- [elpa] externals/org 9249275738 089/101: fixup! etc/ORG-NEWS: Document Org API changes, ELPA Syncer, 2023/07/01
- [elpa] externals/org f97aeaa243 099/101: org-fold-core--isearch-setup: Use `add-function', ELPA Syncer, 2023/07/01
- [elpa] externals/org 55ba9f05a7 018/101: org-element-map: Refactor using `org-element-ast-map',
ELPA Syncer <=
- [elpa] externals/org 29cb0b370b 022/101: org-element-headline-parser: Defer property drawer values, ELPA Syncer, 2023/07/01
- [elpa] externals/org 44baf8f2b8 030/101: org-element-parse-buffer: New optional argument to not force undefer, ELPA Syncer, 2023/07/01
- [elpa] externals/org 13ae9b95f8 045/101: org-narrow-to-subtree: Use org-element API, ELPA Syncer, 2023/07/01
- [elpa] externals/org 3024e933c0 053/101: org-get-buffer-tags: Switch to org-element API, ELPA Syncer, 2023/07/01
- [elpa] externals/org def4bfa9c1 055/101: org-scan-tag: Switch to pure use of `org-element-cache-map', ELPA Syncer, 2023/07/01
- [elpa] externals/org 2efc7fcfdc 058/101: org-agenda-get-scheduled: Switch to org-element API, ELPA Syncer, 2023/07/01
- [elpa] externals/org 598d7bbcf2 062/101: Remove APPT_WARNTIME text property cache, ELPA Syncer, 2023/07/01
- [elpa] externals/org 39466ecf47 065/101: org-element-cache: Do not check for deferred :parent unnecessarily, ELPA Syncer, 2023/07/01
- [elpa] externals/org 9ed7956afd 080/101: org-element: Use constant values for fixed deferred properties, ELPA Syncer, 2023/07/01