我正在尝试根据
org-mode
缓冲区的某些部分编写自定义 Elisp 函数来进行字数统计,我想知道 org-element
是否有一个好方法来解析与某个标签(或属性)匹配的所有标题。更具体地说,我有一个像这样的缓冲区:
#+TITLE: My manuscript
Authors, affiliations, etc.
* Abstract :abstract:
Text in the abstract.
* Introduction :body:
Some sample text goes here.
* Methods :body:
Some sample text goes here.
* Results :body:
Some sample text goes here.
* Discussion :body:
Some sample text goes here.
* References :refs:
References go here.
我想获取与
:body:
标签匹配的所有标题的字数(即 20)。到目前为止,我一直在使用这个答案中的函数,它在返回标题的字数方面做得很好:
(require 'cl-lib)
(require 'org-element)
(defun org-element-parse-headline (&optional granularity visible-only)
"Parse current headline.
GRANULARITY and VISIBLE-ONLY are like the args of `org-element-parse-buffer'."
(let ((level (org-current-level)))
(org-element-map
(org-element-parse-buffer granularity visible-only)
'headline
(lambda (el)
(and
(eq (org-element-property :level el) level)
(<= (org-element-property :begin el) (point))
(<= (point) (org-element-property :end el))
el))
nil 'first-match 'no-recursion)))
(cl-defun org+-count-words-of-heading (&key (worthy '(paragraph bold italic underline code footnote-reference link strike-through subscript superscript table table-row table-cell))
(no-recursion nil))
"Count words in the section of the current heading.
WORTHY is a list of things worthy to be counted.
This list should at least include the symbols:
paragraph, bold, italic, underline and strike-through.
If NO-RECURSION is non-nil don't count the words in subsections."
(interactive (and current-prefix-arg
(list :no-recursion t)))
(let ((word-count 0))
(org-element-map
(org-element-contents (org-element-parse-headline))
'(paragraph table)
(lambda (par)
(org-element-map
par
worthy
(lambda (el)
(cl-incf
word-count
(cl-loop
for txt in (org-element-contents el)
when (eq (org-element-type txt) 'plain-text)
sum
(with-temp-buffer
(insert txt)
(count-words (point-min) (point-max))))
))))
nil nil (and no-recursion 'headline)
)
(when (called-interactively-p 'any)
(message "Word count in section: %d" word-count))
word-count))
我想我必须调整
org-element-parse-headline
函数来匹配标签,而不是抓住标题,但有人知道如何做到这一点吗?谢谢!
要从整个缓冲区中获取结果,而不仅仅是当前点的标题,请设置
level
的值,例如。到 0
检查整个缓冲区。然后,要将匹配限制为具有特定标签的标题,请向 org-element-map
中的函数添加条件。
(defun my-org-element-parse-headline (&optional granularity visible-only)
(let ((level 0) ; or restrict level
(granularity (or granularity 'headline)))
(org-element-map
(org-element-parse-buffer granularity visible-only)
granularity
(lambda (el)
;; eg. restrict elements to levels greater than `level`
(when (< level (org-element-property :level el))
(and
(member "body" (org-element-property :tags el))
;; ...
el)))
;; dont set 'first-match if you want all the matches
nil nil 'no-recursion)))
;; eg. results from your example org file
(mapcar (lambda (el) (org-element-property :raw-value el)) (my-org-element-parse-headline))
;; ("Introduction" "Methods" "Results" "Discussion")