Tuve un problema similar, por lo que tal vez esto ayude: no estoy muy familiarizado con la exportación de org o los componentes internos de la organización, pero no pude encontrar nada que analizara un archivo de organización en una estructura de árbol. Pero dado un búfer como
* england
** london
** bristol
* france
te dará
(org-get-header-tree) => ("england" ("london" "bristol") "france")
y puede incluir otra información del árbol también.
Entonces, dada una lista plana de niveles, necesitamos producir un árbol, por ejemplo (1 1 2 3 1) => (1 1 (2 (3)) 1). No pude encontrar una función que hiciera esto, así que escribí una después de dibujar muchas celdas en contra. Estoy seguro de que hay una mejor manera de hacerlo, pero funciona. La función unflatten
toma una lista plana y un par de funciones para extraer la información que desea de la lista y los niveles de elementos y produce una estructura de árbol.
En org-get-header-list
podría agregar más información que desea extraer de cada elemento con llamadas org-element-property
, y luego org-get-header-tree
podría incluir funciones para extraer la información de la lista.
Tal como está, esto no incluye el manejo de listas de guiones, pero tal vez podría adaptarse para manejarlas también sin demasiados problemas ...
(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
deorg-element-map
debería hacer lo que quieras.