J'ai eu un problème similaire, alors peut-être que cela aidera - je ne suis pas très familier avec l'exportation ou les org internes, mais je n'ai rien trouvé qui pourrait analyser un fichier org dans une arborescence. Mais étant donné un tampon comme
* england
** london
** bristol
* france
ça vous donnera
(org-get-header-tree) => ("england" ("london" "bristol") "france")
et peut également inclure d'autres informations de l'arbre.
Donc, étant donné une liste plate de niveaux, nous devons produire un arbre, par exemple (1 1 2 3 1) => (1 1 (2 (3)) 1). Je ne pouvais pas non plus trouver une fonction qui ferait cela, alors j'en ai écrit une après beaucoup de dessin de cellules contre - je suis sûr qu'il y a une meilleure façon de le faire mais cela fonctionne. La fonction unflatten
prend une liste plate et quelques fonctions pour extraire les informations souhaitées de la liste et des niveaux d'élément et produit une arborescence.
Dans org-get-header-list
vous pouvez ajouter plus d'informations que vous souhaitez extraire de chaque élément avec des appels à org-element-property
, puis org-get-header-tree
vous pouvez inclure des fonctions pour extraire les informations de la liste.
En l'état, cela n'inclut pas la gestion des listes de tirets, mais peut-être pourrait-il être adapté pour gérer celles-ci également sans trop de problèmes ...
(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
devrait faire ce que vous voulez.