Tôi đã gặp một vấn đề tương tự, vì vậy có lẽ điều này sẽ giúp ích - tôi không rành lắm về org export hoặc org internals, nhưng tôi không thể tìm thấy bất cứ điều gì có thể phân tích tệp org thành cấu trúc cây. Nhưng được cung cấp một bộ đệm như
* england
** london
** bristol
* france
nó sẽ cho bạn
(org-get-header-tree) => ("england" ("london" "bristol") "france")
và có thể bao gồm các thông tin khác từ cây là tốt.
Vì vậy, đưa ra một danh sách các cấp độ phẳng, chúng ta cần tạo ra một cây, ví dụ (1 1 2 3 1) => (1 1 (2 (3)) 1). Tôi không thể tìm thấy một chức năng nào có thể làm được điều này vì vậy đã viết một cái sau khi vẽ nhiều ô khuyết điểm - tôi chắc chắn có cách tốt hơn để làm điều này nhưng nó hoạt động. Hàm unflatten
lấy một danh sách phẳng và một vài hàm để trích xuất thông tin bạn muốn từ danh sách và các mức vật phẩm và tạo ra cấu trúc cây.
Trong org-get-header-list
bạn có thể thêm nhiều thông tin bạn muốn trích xuất từ mỗi mục bằng các cuộc gọi đến org-element-property
, và sau đó trong org-get-header-tree
bạn có thể bao gồm các chức năng để trích xuất thông tin từ danh sách.
Vì nó không bao gồm việc xử lý danh sách gạch ngang, nhưng có lẽ nó có thể được điều chỉnh để xử lý những danh sách đó mà không gặp quá nhiều rắc rối ...
(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
củaorg-element-map
nên làm những gì bạn muốn.