Skip to content

rollacaster/org-parser-tree

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

org-parser-tree

Building upon the awesome org-parser, org-parser-tree provides utilities to create a tree structure in clojure from an org file

Alpha-Status

Currently only the following line types of org-parser are implemented:

  • :head-line
  • :content-line
  • :list-item-line

But you can add missing implementations or edit the existing ones by using the Customizations

CLI/deps.edn dependency information:

rollacaster/org-parser-tree {:git/url "https://github.com/rollacaster/org-parser-tree" :sha "e7f0876fbb4b7793081bcdf7f94df39c440f9c1f"}

Usage

(ns hello-world.core
  (:require [tech.thomas-sojka.org-parser-tree.core :refer [parse-tree]]))

(let [journal "
* 2019
** Unordered
*** Sometime
**** Clojure Spec basics :LEARN:TUTORIAL:
** 2019-01 January
*** KW01
**** Build a snowman :SOCIAL:
**** Game night :SOCIAL:"]
  (parse-tree journal))

Result

{:title "root",
 :level 0,
 :children
 ({:title "2019",
   :type :head-line,
   :level 1,
   :tags #{},
   :children
   ({:title "Unordered",
     :type :head-line,
     :level 2,
     :tags #{},
     :children
     ({:title "Sometime",
       :type :head-line,
       :level 3,
       :tags #{},
       :children
       ({:title "Clojure Spec basics",
         :type :head-line,
         :level 4,
         :tags #{"LEARN" "TUTORIAL"},
         :children []})})}
    {:title "2019-01 January",
     :type :head-line,
     :level 2,
     :tags #{},
     :children
     ({:title "KW01",
       :type :head-line,
       :level 3,
       :tags #{},
       :children
       ({:title "Build a snowman",
         :type :head-line,
         :level 4,
         :tags #{"SOCIAL"},
         :children []}
        {:title "Game night",
         :type :head-line,
         :level 4,
         :tags #{"SOCIAL"},
         :children []})})})})}

resources/org-parser-tree/2020-12-22_12-37-32_screenshot.png

Customizations

By using Multimethods it’s possible to customize the generated data structure or add missing implementations dynamically

post-transform

You can customise how a parsed line from org-parser-tree is transformed

(ns hello-world.core
  (:require [clojure.string :as str]
            [tech.thomas-sojka.org-parser-tree.core :refer [parse-tree]]
            [tech.thomas-sojka.org-parser-tree.transform
             :refer
             [post-transform]]))

(defn transform-link [{:keys [title] :as headline}]
  (let [re-org-link #"\[\[(.*)\]\[(.*)\]\]"]
      (if (str/includes? title "[[")
        (let [[link description]
              (drop 1 (re-find (re-matcher re-org-link title)))]
          (-> headline
              (assoc :link link)
              (assoc :title (str/replace title re-org-link description))))
        headline)))

(defmethod post-transform :head-line [head-line]
  (transform-link head-line))

(let [journal "
* KW01
** Build a [[https://en.wikipedia.org/wiki/Snowman][snowman]]"]
  (parse-tree journal))

Result

{:title "root",
 :level 0,
 :children ({:title "KW01",
   :type :head-line,
   :level 1,
   :tags #{},
   :children
   ({:title "Build a snowman",
     :type :head-line,
     :level 2,
     :tags #{},
     :link "https://en.wikipedia.org/wiki/Snowman",
     :children []})})}

stratify

You can customise how org-parser-tree builds the tree using the clojure.zip API

(ns hello-world.core
  (:require [clojure.zip :as z]
            [tech.thomas-sojka.org-parser-tree.core :refer [parse-tree]]
            [tech.thomas-sojka.org-parser-tree.stratify :refer [stratify]]))

(defmethod stratify :list-item-line [org-tree list-item-line]
  (z/edit org-tree update :content str (:list-item list-item-line) "\n"))

(let [journal "
**** Learned new clojure tricks                                       :LEARN:
After reading the Clojure style guide I learned:
- Use sets as function
- Use =list*= for nested cons
- Use =Constructor.= instead of =new="]
  (parse-tree journal))

Result

{:title "root",
 :level 0,
 :children
 ({:title "Learned new clojure tricks",
   :type :head-line,
   :level 4,
   :tags #{"LEARN"},
   :children [],
   :content
   "After reading the Clojure style guide I learned:Use sets as function\nUse =list*= for nested cons\nUse =Constructor.= instead of =new=\n"})}

transform

You can add missing implementations of line types from org-parser or replace existing ones

(ns hello-world.core
  (:require [clojure.string :as str]
            [clojure.zip :as z]
            [tech.thomas-sojka.org-parser-tree.core :refer parse-tree]
            [tech.thomas-sojka.org-parser-tree.stratify :refer [stratify]]
            [tech.thomas-sojka.org-parser-tree.transform :refer [transform]]))

(defmethod transform :drawer-begin-line [[_ [_ drawer-name]]]
  {:type :drawer-begin-line
   :drawer (keyword (str/lower-case drawer-name))})
(defmethod stratify :drawer-begin-line [org-tree drawer-begin-line]
  (z/replace org-tree (assoc (z/node org-tree) (:drawer drawer-begin-line) [])))
(parse-tree "
* Test
:MY-DRAWER:
:END:")

Result

{:children
 ({:tags #{},
   :type :head-line,
   :title "Test",
   :level 1,
   :children [],
   :my-drawer [],
   :end []}),
 :title "root",
 :level 0}

About

Create a Clojure tree structure from an org file

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published