ฉันมีปัญหาที่คล้ายกันดังนั้นอาจจะช่วยได้ - ฉันไม่คุ้นเคยกับการส่งออก org หรือ internals ภายใน แต่ฉันไม่พบสิ่งใดที่จะแยกไฟล์ org ไปยังโครงสร้างต้นไม้ แต่ให้บัฟเฟอร์เหมือน
* england
** london
** bristol
* france
มันจะให้คุณ
(org-get-header-tree) => ("england" ("london" "bristol") "france")
และสามารถรวมข้อมูลอื่น ๆ จากต้นไม้เช่นกัน
เมื่อได้รับรายการระดับที่คงที่เราต้องสร้างต้นไม้เช่น (1 1 2 3 1) => (1 1 (2 (3)) 1) ฉันไม่สามารถหาฟังก์ชั่นที่จะทำสิ่งนี้ได้ดังนั้นจึงต้องเขียนเซลล์ข้อเสียหนึ่งครั้งหลังจากนั้นฉันแน่ใจว่ามีวิธีที่ดีกว่าในการทำสิ่งนี้ แต่มันใช้งานได้ ฟังก์ชั่นนี้unflatten
ใช้ฟังก์ชั่นลิสต์แบบแบนและฟังก์ชั่นสองสามอย่างในการดึงข้อมูลที่คุณต้องการจากรายการและระดับรายการและสร้างโครงสร้างแบบต้นไม้
ในorg-get-header-list
คุณสามารถเพิ่มข้อมูลเพิ่มเติมที่คุณต้องการแยกจากแต่ละรายการที่มีการโทรorg-element-property
แล้วในนั้นorg-get-header-tree
คุณสามารถรวมฟังก์ชั่นเพื่อดึงข้อมูลจากรายการ
เนื่องจากมันไม่รวมถึงการจัดการรายการ dash แต่บางทีมันอาจถูกดัดแปลงเพื่อจัดการกับรายการเหล่านั้นโดยไม่มีปัญหามากเกินไป ...
(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
ควรทำสิ่งที่คุณต้องการ