Skip to content

rollacaster/org-parser-tree

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 "7e27de6bb8bf52a2724f3bc243c0b6ef66611a9c"}

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

transform

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

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

(defmethod transform :list-item-line [[type & content]]
  (let [[_ [_ suffix] _] content]
    {:type type :list-item suffix}))

(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:",
   :list
   ["Use sets as function"
    "Use =list*= for nested cons"
    "Use =Constructor.= instead of =new="]})}

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]
             :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"})}

About

Create a Clojure tree structure from an org file

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published