Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
* org-parser-tree Building upon the awesome [[https://github.com/200ok-ch/org-parser][org-parser]], =org-parser-tree= provides utilities to create a Clojure tree structure from an org file ** Alpha-Status Currently only the following [[https://github.com/200ok-ch/org-parser/blob/master/resources/org.ebnf][line types]] of [[https://github.com/200ok-ch/org-parser][org-parser]] are implemented: - =:head-line= - =:content-line= - =:list-item-line= - =:drawer-begin-item= =org-parser-tree= is [[https://github.com/rollacaster/org-parser-tree#extensibility][extensible]] can add missing implementations or edit the existing ones ** [[https://clojure.org/reference/deps_and_cli][CLI/deps.edn]] dependency information: #+BEGIN_SRC clojurescript rollacaster/org-parser-tree {:git/url "https://github.com/rollacaster/org-parser-tree" :sha "e7510a6b3bc6abebfd4428c236e0e449c7be6ee1"} #+END_SRC ** Usage #+BEGIN_SRC clojurescript (ns hello-world.core (:require [tech.thomas-sojka.org-parser-tree.core :refer [parse-tree]])) (parse-tree " ,* 2019 ,** Unordered ,*** Sometime ,**** Clojure Spec basics :LEARN:TUTORIAL: ,** 2019-01 January ,*** KW01 ,**** Build a snowman :SOCIAL: ,**** Game night :SOCIAL:") #+END_SRC *** Result #+BEGIN_SRC clojurescript {: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 []})})})})} #+END_SRC #+DOWNLOADED: screenshot @ 2020-12-22 12:37:32 [[file:resources/org-parser-tree/2020-12-22_12-37-32_screenshot.png]] ** How it works During the creation of the tree structure three functions are called for each [[https://github.com/200ok-ch/org-parser/blob/master/resources/org.ebnf][line type]] of [[https://github.com/200ok-ch/org-parser][org-parser]]: - =transform=: Transform a line of [[https://github.com/200ok-ch/org-parser][org-parser]] to another Clojure data-structure - =post-transform=: Transform a line of =org-parser-tree= to another Clojure data-structure - =stratify=: Place a transformed line into the tree structure by using [[https://clojure.github.io/clojure/clojure.zip-api.html][clojure.zip]] It's possible to extend any part of the tree creation. ** Extensibility By using [[https://clojure.org/reference/multimethods][Multimethods]] it's possible to extend the generated data structure or add missing implementations dynamically *** post-transform You can extend how a parsed line from =org-parser-tree= is transformed #+BEGIN_SRC clojure (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)) (parse-tree " ,* KW01 ,** Build a [[https://en.wikipedia.org/wiki/Snowman][snowman]]") #+END_SRC **** Result #+BEGIN_SRC clojurescript {: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 []})})} #+END_SRC *** stratify You can extend how =org-parser-tree= builds the tree using the [[https://clojure.github.io/clojure/clojure.zip-api.html][clojure.zip API]] #+BEGIN_SRC clojurescript (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")) (parse-tree " ,**** 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=") #+END_SRC **** Result #+BEGIN_SRC clojurescript {: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"})} #+END_SRC *** transform You can add missing implementations of [[https://github.com/200ok-ch/org-parser/blob/master/resources/org.ebnf][line types]] from [[https://github.com/200ok-ch/org-parser][org-parser]] or replace existing ones #+BEGIN_SRC clojurescript (ns hello-word.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]] [tech.thomas-sojka.org-parser-tree.transform :refer [transform]])) (defmethod transform :keyword-line [[_ [_ keyword-key] [_ keyword-value]]] {:type :keyword-line :key keyword-key :value keyword-value}) (defmethod stratify :keyword-line [org-tree {:keys [key value]}] (z/replace org-tree (assoc (z/node org-tree) :keywords {(keyword key) value}))) (parse-tree "#+TAGS: WORK(w) ,* 2021") #+END_SRC **** Result #+BEGIN_SRC clojurescript {:children ({:tags #{}, :type :head-line, :title "2021", :level 1, :children []}), :title "root", :level 0, :keywords {:TAGS "WORK(w)"}} #+END_SRC