2010-07-12 23:27:35 +00:00
|
|
|
(ns path-to-enlightenment
|
2011-04-30 03:54:49 +00:00
|
|
|
(:use [fresh.core :only [clj-files-in freshener]]
|
|
|
|
|
[clojure.java.io :only [file]])
|
2011-01-12 22:38:04 +00:00
|
|
|
(:require [clojure.set]
|
2011-04-19 14:00:59 +00:00
|
|
|
[clojure.string]
|
2011-04-30 03:54:49 +00:00
|
|
|
[clojure.test])
|
|
|
|
|
(:import
|
|
|
|
|
[java.util.concurrent ScheduledThreadPoolExecutor TimeUnit]))
|
2010-01-24 03:28:43 +00:00
|
|
|
|
2011-02-03 18:26:58 +00:00
|
|
|
(def __ :fill-in-the-blank)
|
|
|
|
|
(def ___ (fn [& args] __))
|
2010-01-24 03:28:43 +00:00
|
|
|
|
2010-02-06 16:49:53 +00:00
|
|
|
(defmacro meditations [& forms]
|
2011-04-30 03:54:49 +00:00
|
|
|
(let [pairs (conj (partition 2 forms)
|
2011-04-19 14:00:59 +00:00
|
|
|
["Bootstrap for file/line reporting"
|
|
|
|
|
'(clojure.test/is (= 0 0))])
|
|
|
|
|
tests (map (fn [[doc# code#]]
|
2011-04-30 03:54:49 +00:00
|
|
|
`(clojure.test/is ~code# ~doc#))
|
2011-04-19 14:00:59 +00:00
|
|
|
pairs)]
|
2011-04-30 03:54:49 +00:00
|
|
|
`(and ~@tests)))
|
2010-02-05 18:57:38 +00:00
|
|
|
|
2010-07-12 23:19:54 +00:00
|
|
|
(def ordered-koans
|
|
|
|
|
["equalities"
|
2010-07-12 23:11:15 +00:00
|
|
|
"lists"
|
|
|
|
|
"vectors"
|
|
|
|
|
"sets"
|
|
|
|
|
"maps"
|
|
|
|
|
"functions"
|
|
|
|
|
"conditionals"
|
|
|
|
|
"higher_order_functions"
|
|
|
|
|
"runtime_polymorphism"
|
2011-03-31 13:11:27 +00:00
|
|
|
"lazy_sequences"
|
2010-07-12 23:11:15 +00:00
|
|
|
"sequence_comprehensions"
|
2010-11-17 04:23:33 +00:00
|
|
|
"creating_functions"
|
2010-11-06 22:38:31 +00:00
|
|
|
"recursion"
|
2010-11-10 02:19:10 +00:00
|
|
|
"destructuring"
|
2011-02-08 11:51:11 +00:00
|
|
|
"refs"
|
2011-03-31 12:44:54 +00:00
|
|
|
"atoms"
|
2011-02-11 01:13:52 +00:00
|
|
|
"macros"
|
|
|
|
|
"datatypes"])
|
2010-07-11 21:04:37 +00:00
|
|
|
|
2011-01-11 22:48:26 +00:00
|
|
|
(defn require-version [[required-major required-minor]]
|
|
|
|
|
(let [{:keys [major minor]} *clojure-version*]
|
|
|
|
|
(if (or (< major required-major)
|
|
|
|
|
(and (== major required-major) (< minor required-minor)))
|
|
|
|
|
(throw (Exception. (str "Clojure version " required-major "."
|
|
|
|
|
required-minor " or higher required."))))))
|
|
|
|
|
|
2011-01-12 22:38:04 +00:00
|
|
|
(defn parse-required-version []
|
|
|
|
|
(let [rdr (clojure.lang.LineNumberingPushbackReader.
|
|
|
|
|
(java.io.FileReader. (java.io.File. "project.clj")))
|
|
|
|
|
project-form (read rdr)
|
|
|
|
|
version-string (->> project-form
|
|
|
|
|
(drop 3)
|
|
|
|
|
(apply hash-map)
|
|
|
|
|
:dependencies
|
2011-04-14 00:19:50 +00:00
|
|
|
(map (fn [xs] (vec (take 2 xs))))
|
2011-01-12 22:38:04 +00:00
|
|
|
(into {})
|
|
|
|
|
('org.clojure/clojure))]
|
|
|
|
|
(map read-string
|
|
|
|
|
(take 3 (clojure.string/split version-string #"[\.\-]")))))
|
|
|
|
|
|
2011-04-30 03:54:49 +00:00
|
|
|
(defn files-to-keep-fresh []
|
|
|
|
|
(clj-files-in (file "src" "koans")))
|
|
|
|
|
|
|
|
|
|
(defn- tests-pass? [file-path]
|
|
|
|
|
(use 'path-to-enlightenment)
|
|
|
|
|
(load-file file-path))
|
|
|
|
|
|
|
|
|
|
(defn- among-paths? [files]
|
|
|
|
|
(into #{} (map #(.getCanonicalPath %) files)))
|
|
|
|
|
|
|
|
|
|
(defn- ordered-koan-paths []
|
|
|
|
|
(map (fn [koan-name]
|
|
|
|
|
(.getCanonicalPath (file "src" "koans" (str koan-name ".clj"))))
|
|
|
|
|
ordered-koans))
|
|
|
|
|
|
|
|
|
|
(defn- next-koan-path [last-koan-path]
|
|
|
|
|
(loop [[this-koan & more :as koan-paths] (ordered-koan-paths)]
|
|
|
|
|
(when (seq more)
|
|
|
|
|
(if (= last-koan-path this-koan)
|
|
|
|
|
(first more)
|
|
|
|
|
(recur more)))))
|
|
|
|
|
|
|
|
|
|
(defn namaste []
|
|
|
|
|
(println "\nYou have achieved clojure enlightenment. Namaste."))
|
|
|
|
|
|
|
|
|
|
(defn report-refresh [report]
|
|
|
|
|
(when-let [refreshed-files (seq (:reloaded report))]
|
|
|
|
|
(let [these-koans (filter
|
|
|
|
|
(among-paths? refreshed-files)
|
|
|
|
|
(ordered-koan-paths))]
|
|
|
|
|
(println "Refreshing:" these-koans)
|
|
|
|
|
(when (every? tests-pass? these-koans)
|
|
|
|
|
(if-let [next-koan-file (file (next-koan-path (last these-koans)))]
|
|
|
|
|
(report-refresh {:reloaded [next-koan-file]})
|
|
|
|
|
(namaste))))
|
|
|
|
|
(println))
|
|
|
|
|
:refreshed)
|
|
|
|
|
|
|
|
|
|
(def refresh! (freshener files-to-keep-fresh report-refresh))
|
|
|
|
|
|
|
|
|
|
(def scheduler (ScheduledThreadPoolExecutor. 1))
|
|
|
|
|
|
|
|
|
|
(defn setup-freshener []
|
|
|
|
|
(.scheduleWithFixedDelay scheduler refresh! 0 500 TimeUnit/MILLISECONDS)
|
|
|
|
|
(.awaitTermination scheduler Long/MAX_VALUE TimeUnit/SECONDS))
|
|
|
|
|
|
2010-07-12 23:19:54 +00:00
|
|
|
(defn run []
|
2011-01-12 22:38:04 +00:00
|
|
|
(require-version (parse-required-version))
|
2011-04-30 03:54:49 +00:00
|
|
|
(setup-freshener))
|
|
|
|
|
|
|
|
|
|
|