As a practice, I managed to illustrate Clojure files using illustrate.clj, but my original idea was to annotate org-mode files of blogs. It's not uncommon that a blog post has some code snippets.
But it missed the feature until last night, as I wasn't sure how to implement it appropriately before and didn't have enough time.
For example, I may have an org-mode like this:
sum of two numbers: #+begin_src clojure (+ 1 2) #+end_src
I want to have a result comment (
(;; => 3)) after each top-level form after using
sum of two numbers:
#+begin_src clojure (+ 1 2) ;; => 3 #+end_src
As I come from a background of C++ and Python, the common way to do that in these languages would be:
find the begin of source blocks (
#+begin_src), and find their corresponding ends.
extract and illustrate the source blocks
join the newly source blocks back with the previous content
The Clojure way here is similar, but using
split the file content into lines
reduct the lines to final content
Use a state to carry the content before a block and the source block along the way. if a source block ends, call
(illustrate-string)to illustrate it and append the result string to previous content.
The function is like this:
(defn illustrate-org-file "Add illustration comments to an org-mode file" [file new-file] (let [lines (clojure.string/split-lines (slurp file)) result (reduce (fn [state line] (let [content (nth state 0) prev-in-block? (nth state 1) src-block (nth state 2)] (if prev-in-block? (if (re-matches #"\s*#\+end_src" line) [(str content (illustrate-string src-block) line "\n") false ""] [content true (str src-block line "\n")]) ; append to the source block ;; not in a src block previously [(str content line "\n") (if (re-matches #"\s*#\+begin_src\s+clojure" line) true false) ""]))) ["" false ""] lines)] (spit new-file (nth result 0))))
Although it works, it's not as concise and elegant as I expected. Maybe I would improve the code in the future.
The complete code is at my babashka-tools repo.