조직 모드 트리를 어떻게 걸을 수 있습니까?


10

배경

Emacs를위한 프리젠 테이션 모드를 작성하고 있습니다. 조직 파일은 데이터에 적합하기 때문에 입력을 조직 파일로하고 싶습니다.

문제

조직 모드 파일을 반복 할 수있는 "슬라이드"데이터 구조 목록으로 변환해야합니다. 이렇게하려면 다음 org-mode 파일과 같은 것을 사용하고 싶습니다.

* this is the first headline, with a title property and no contents
* this is the second headline, with contents
- dash list nested under the second headline
  - further nested
** nested headline

걸을 수 있습니다. 나는 시도 (org-element-parse-buffer)했지만 그것이 요소 목록을 제공하지만 더 나아가는 방법을 알아내는 것은 어렵습니다. 예를 들어, 호출 (org-element-map (org-element-parse-buffer) 'headline #'identity)세 가지 요소 의 목록을 제공합니다 . 마지막은 "중첩 헤드 라인"을 나타냅니다. "중첩 제목"이 "내용이있는 두 번째 제목"의 자식이되기를 원합니다.

XY 문제 방지

나는 분명히 org-mode 파일을 Elisp 데이터 구조로 변환하는 다른 방법에 열려 있습니다. 나는하지 않는 생각 나는 결과를 포함하는 새로운 파일을 끝내고 싶지 않기 때문에 조직-수출, 나에게 적합한 도구이지만, 데이터 구조는 내가 통해 반복 할 수 있습니다. 내 순진한 방법은 "모든 최상위 헤드 라인을 제공 한 다음 속성 및 포함 된 요소 (예 : 일반 헤드 라인 또는 중첩 된 목록-추가 헤드 라인 또는 대시 목록)를 얻을 수 있습니다"와 같은 방식입니다.


2
나는 세 번째 선택적 인수 no-recursionorg-element-map원하는 것을해야 한다고 생각합니다 .
wvxvw

2
파일의 맨 아래로 이동 한 다음 뒤로 검색하여 제목을 찾고, 모든 것을 잡고, 파일의 맨 위에 도달 할 때까지 계속 진행합니다 (프로세스 반복)? 각 검색 후 점이 이미 머리글의 시작 부분에 있기 때문에 뒤로 이동하므로 머리글의 시작 부분으로 돌아가는 것보다 조금 더 효율적입니다. org-agenda가 작동하는 방식, 즉 org-agenda-list, org-search-view, org-tags-view가 있습니다.
lawlist

답변:


7

비슷한 문제가 있었기 때문에 이것이 도움이 될 것입니다. 조직 내보내기 또는 조직 내부에 익숙하지 않지만 조직 파일을 트리 구조로 구문 분석하는 것을 찾을 수 없습니다. 그러나 같은 버퍼가 주어졌습니다.

* 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")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.