Instantly share code, notes, and snippets.

@Jared314 /ohm.clj
Last active Dec 20, 2015

Embed
What would you like to do?
(ns ohm
(:require [clojure.string :as string]
[clojure.java.io :refer [as-file]])
(:import [java.io File]))
(defrecord Leaf [nss declares fns])
(defn parse-value [value]
value)
(defn compare-value [v1 v2]
(compare (parse-value v1) (parse-value v2)))
(defn insert! [data item]
(if (nil? data)
(Leaf. [(:ns item)] [(:name item)] (sorted-set-by compare-value (:source item)))
(let [nss (conj (:nss data) (:ns item))
declares (conj (:declares data) (:name item))
fns (conj (:fns data) (:source item))]
(assoc data :nss nss :declares declares :fns fns))))
(defn parse-ns-name [value]
(string/split value #"\."))
(defn parse [base key namespace value]
(update-in base
(concat [key] (parse-ns-name namespace))
#(insert! % value)))
;;;;;;;;;;;;
; Output
;;;;;;;;;;;;
(defn layout-data [data]
(if (not (instance? Leaf data))
(list data)
(lazy-cat (map #(:source %) (:nss data)) ; ns
(map #(str "(declare " % ")") (:declares data)) ; declare
(:fns data))))
(defn format-name [value] (string/replace value "-" "_"))
(defn write! [base-path data]
(let [keys (keys data)
leaves (filter #(instance? Leaf (data %)) keys)
nodes (filter #(not (instance? Leaf (data %))) keys)
base-file (as-file base-path)]
(dorun (map #(spit (str base-path File/separator (format-name %) ".clj")
(string/join "\n" (layout-data (data %))))
leaves))
(for [n nodes]
(let [new-path (str base-path File/separator (format-name n))
new-file (as-file new-path)]
(if (not (.exists new-file)) (.mkdir new-file))
(write! new-path (data n))))))
; Usage
(def project (map->Leaf {:fns ["(defproject tester1 \"0.1.0-SNAPSHOT\" :dependencies [[org.clojure/clojure \"1.5.1\"]])"]}))
(def base {"src" {}
"test" {}
"project" project})
(def ns1 {:name "tester1.core" :source "(ns tester1.core)"})
(def ns2 {:name "tester1.server" :source "(ns tester1.server (:require [tester1.core :as c]))"})
(def fn1 {:name "thing1" :source "(defn thing1 [] true)" :ns ns1})
(def fn2 {:name "thing2" :source "(defn thing2 [] true)" :ns ns1})
(def fn3 {:name "thing3" :source "(defn thing3 [] true)" :ns ns2})
(def data [fn1 fn2 fn3])
(def result
(reduce #(parse %1 "src" (:name (:ns %2)) %2)
base
data))
;(write! "/Users/user1/Desktop/tester1" result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment