Skip to content

Latest commit

 

History

History
363 lines (298 loc) · 13.2 KB

notes.org

File metadata and controls

363 lines (298 loc) · 13.2 KB

Plans

0.5

Release 0.5

  • [X] Check comment TODOs (using magit-todos).
  • [X] Check issues.
  • [X] Check plans (in this file).
  • [X] Check linters.
  • [X] Check tests.
  • [X] Update version numbers in file headers.
    • [X] org-make-toc.el
  • [X] Update changelog in README.org.
  • [X] Tag and sign new version (using Magit’s t r).
  • [X] Push master.
  • [X] Push tags.
  • [X] Post-release changes:
    • [X] Bump version numbers to n+1-pre:
      • [X] org-make-toc.el
      • [X] README.org

Notes

Get document tree

  • State “DONE” from “TODO” [2017-08-01 Tue 22:41]

There are different ways to get a tree of the document structure.

  • org-imenu-get-tree returns one that should be useful.
  • org-element-parse-buffer is more semantic and is probably better for my uses. It looks like it returns metadata, while org-imenu-get-tree is bare-bones, just what imenu needs.

Yeah, looks like org-element-parse-buffer is the way to go.

org-element-parse-buffer

(org-element-parse-buffer 'headline)

The structure of this appears to be like:

  • ‘headline
    • List of properties
    • List for child heading
      • ‘headline
      • List of properties

Walk tree

  • State “DONE” from “UNDERWAY” [2017-08-02 Wed 01:08]
  • State “UNDERWAY” from “DONE” [2017-08-02 Wed 00:08]

cl-loop

This works, but it helped me figure out how to use org-element-map, so I guess I’ll use that.

(defun org-walk-tree (tree element-pred)
  (cl-loop for element in tree
           when (eql 'headline (car element))
           when (funcall element-pred element)
           collect (list 'headline
                         :name (org-element-property :title element)
                         :children (org-walk-tree (cddr element) element-pred))))

(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/notes.org")
  (let ((tree (cddr (org-element-parse-buffer 'headline))))
    (org-walk-tree tree (lambda (element)
                          (not (string= (org-element-property :TOC element)
                                        "ignore"))))))

org-element-map

(defun org-walk-tree (tree element-pred)
  (cl-loop for element in tree
           when (eql 'headline (car element))
           when (funcall element-pred element)
           collect (list 'headline
                         :name (org-element-property :title element)
                         :children (org-walk-tree (cdddr element) element-pred))))

(defun argh (element)
  (unless (string= (org-element-property :TOC element)
                   "ignore")
    (list 'headline
          :name (org-element-property :title element)
          :children (org-element-map (cddr element) '(headline)
                             #'argh nil nil '(headline)))))

(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/notes.org")
  (let ((tree (cddr (org-element-parse-buffer 'headline))))
    (org-element-map tree '(headline) #'argh nil nil '(headline))))

Add :local to examples.org

Filter tree

Remove higher headings

  • State “DONE” from “TODO” [2017-08-02 Wed 03:42]

Get TOC level

  • State “DONE” from [2017-08-02 Wed 02:06]

Ugly, but it works. I guess the rather non-standard structure of the element tree makes this necessary. I tried to get treepy working with zippers, and I almost did…

(defun org-make-toc--first-in-tree (tree element-pred)
  (cl-loop for element in tree
           for type = (car element)
           if (eq 'headline type)
           for result = (funcall element-pred element)
           if result
           return result
           else
           for children = (cddr element)
           when children
           for result = (org-make-toc--first-in-tree children element-pred)
           when result
           return result))
(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (let* ((tree (cddr (org-element-parse-buffer 'headline)))
         (tree (org-make-toc--remove-ignored-entries tree))
         (toc-level (org-make-toc--first-in-tree tree
                                                 #'org-make-toc--is-toc-entry
                                                 #'org-make-toc--element-level)))
    toc-level))

Remove higher ones

  • State “DONE” from “TODO” [2017-08-02 Wed 03:41]
(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (let* ((tree (cddr (org-element-parse-buffer 'headline)))
         (tree (org-make-toc--remove-ignored-entries tree)))
    (org-make-toc--remove-higher-level-than-toc tree)))

Remove too-deep headings

  • State “MAYBE” from “TODO” [2017-08-02 Wed 01:08]

Use treepy to walk the tree

  • State “CANCELED” from “TODO” [2017-08-02 Wed 00:07]

I guess I’m just not smart enough to use treepy, because all I could get out of its walking functions were errors. Or maybe it’s just not suitable for the kind of structure org-element-map returns. I don’t know.

(require 'treepy)

(treepy-walk  #'identity (cddr (org-element-parse-buffer 'headline)))

Remove ignored headings

  • State “DONE” from “TODO” [2017-08-02 Wed 00:57]
(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (let ((tree (cddr (org-element-parse-buffer 'headline))))
    (org-make-toc--remove-ignored-entries tree)))

Use org-list-to-org from Org 9.1

Should be a nicer way to turn the ToC into the list string.

Check out orgpath

This looks really cool, although he seems to have abandoned it. I cloned a local copy to src/misc/org. Studying his functions that build a tree should be very helpful.

Transform tree to org list

  • State “UNDERWAY” from “TODO” [2017-08-02 Wed 04:16]

With each element being a link to the real heading. Need to support both GitHub links and Org links.

GitHub-style

  • State “DONE” from “TODO” [2017-08-02 Wed 04:16]
(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
    (let* ((tree (cddr (org-element-parse-buffer 'headline)))
           (tree (org-make-toc--remove-ignored-entries tree))
(tree (org-make-toc--remove-higher-level-than-toc tree)))
      (org-make-toc--tree-to-list tree)))

Replace TOC contents with list

(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (-when-let* ((tree (cddr (org-element-parse-buffer 'headline)))
               (tree (org-make-toc--remove-ignored-entries tree))
               (tree (org-make-toc--remove-higher-level-than-toc tree))
               (list (org-make-toc--tree-to-list tree))
               (pos (org-find-property "TOC" "this")))
    (org-make-toc--replace-entry-contents pos list)))

Treepy

(require 'treepy)

(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (let* ((tree (cddr (org-element-parse-buffer 'headline)))
         (zipper (treepy-zipper #'treepy-branch-p
                                #'treepy-children
                                #'treepy-make-node
                                tree)))
    (treepy-children zipper)))

(with-current-buffer (find-buffer-visiting "~/src/org-make-toc/test/data.org")
  (let* ((tree (cddr (org-element-parse-buffer 'headline)))
         (zipper (treepy-zipper (lambda (loc) (eql 'headline (car loc)))
                                (lambda (loc) (cddr loc))
                                (lambda (loc) (list 'headline (cdr loc) (cddr loc)))
                                tree)))
    zipper))

Checklists

Release

  • [ ] Check comment TODOs (using magit-todos).
  • [ ] Check issues.
  • [ ] Check plans (in this file).
  • [ ] Check linters.
  • [ ] Check tests.
  • [ ] Update version numbers in file headers.
    • [ ] org-make-toc.el
  • [ ] Update changelog in README.org.
  • [ ] Tag and sign new version (using Magit’s t r).
  • [ ] Push master.
  • [ ] Push tags.
  • [ ] Post-release changes:
    • [ ] Bump version numbers to n+1-pre:
      • [ ] org-make-toc.el
      • [ ] README.org