我有一个类似的问题,所以也许会有所帮助-我对org导出或org内部结构不是很熟悉,但是我找不到将org文件解析为树形结构的任何东西。但是给定一个像
* england
** london
** bristol
* france
它会给你
(org-get-header-tree) => ("england" ("london" "bristol") "france")
并且还可以包含树中的其他信息。
因此,给定一个简单的级别列表,我们需要生成一棵树,例如(1 1 2 3 1)=>(1 1(2(3))1)。我也找不到能执行此操作的函数,因此在多次绘制cons单元后写了一个-我确定有更好的方法可以执行此操作,但是它可以工作。该函数unflatten
采用一个平面列表和几个函数来从列表和项目级别中提取所需的信息,并生成树形结构。
在中,org-get-header-list
您可以通过调用来添加要从每个项目中提取的更多信息org-element-property
,然后在中org-get-header-tree
可以包括从列表中提取信息的函数。
就目前而言,这不包括对破折号列表的处理,但是也许可以将其修改为处理那些破折号而没有太多麻烦。
(defun unflatten (xs &optional fn-value fn-level)
"Unflatten a list XS into a tree, e.g. (1 2 3 1) => (1 (2 (3)) 1).
FN-VALUE specifies how to extract the values from each element, which
are included in the output tree, FN-LEVEL tells how to extract the
level of each element. By default these are the `identity' function so
it will work on a list of numbers."
(let* ((level 1)
(tree (cons nil nil))
(start tree)
(stack nil)
(fn-value (or fn-value #'identity))
(fn-level (or fn-level #'identity)))
(dolist (x xs)
(let ((x-value (funcall fn-value x))
(x-level (funcall fn-level x)))
(cond ((> x-level level)
(setcdr tree (cons (cons x-value nil) nil))
(setq tree (cdr tree))
(push tree stack)
(setq tree (car tree))
(setq level x-level))
((= x-level level)
(setcdr tree (cons x-value nil))
(setq tree (cdr tree)))
((< x-level level)
(while (< x-level level)
(setq tree (pop stack))
(setq level (- level 1)))
(setcdr tree (cons x-value nil))
(setq tree (cdr tree))
(setq level x-level)))))
(cdr start)))
; eg (unflatten '(1 2 3 2 3 4)) => '(1 (2 (3) 2 (3 (4))))
(defun org-get-header-list (&optional buffer)
"Get the headers of an org buffer as a flat list of headers and levels.
Buffer will default to the current buffer."
(interactive)
(with-current-buffer (or buffer (current-buffer))
(let ((tree (org-element-parse-buffer 'headline)))
(org-element-map
tree
'headline
(lambda (el) (list
(org-element-property :raw-value el) ; get header title without tags etc
(org-element-property :level el) ; get depth
;; >> could add other properties here
))))))
; eg (org-get-header-list) => (("pok" 1) ("lkm" 1) (("cedar" 2) ("yr" 2)) ("kjn" 1))
(defun org-get-header-tree (&optional buffer)
"Get the headers of the given org buffer as a tree."
(interactive)
(let* ((headers (org-get-header-list buffer))
(header-tree (unflatten headers
(lambda (hl) (car hl)) ; extract information to include in tree
(lambda (hl) (cadr hl))))) ; extract item level
header-tree))
; eg (org-get-header-tree) => ("pok" "lkm" ("cedar" "yr") "kjn")
no-recursion
的org-element-map
应该做你想要什么。