From 3644a48bcd52989a88eb959331185eaf5d230446 Mon Sep 17 00:00:00 2001 From: Colin Jones Date: Fri, 29 Apr 2011 22:54:49 -0500 Subject: [PATCH] Introduce the auto-refreshing runner via fresh. --- project.clj | 1 + src/path_to_answer_sheet.clj | 23 ++++++------ src/path_to_enlightenment.clj | 70 ++++++++++++++++++++++++++++------- 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/project.clj b/project.clj index 09b9890..adac171 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,5 @@ (defproject functional-koans "0.3.7" :description "The functional koans" :dependencies [[org.clojure/clojure "1.3.0-alpha6"] + [fresh "1.0.1"] [jline "0.9.94" :exclusions [junit]]]) diff --git a/src/path_to_answer_sheet.clj b/src/path_to_answer_sheet.clj index e9d56a4..c1ed4b4 100644 --- a/src/path_to_answer_sheet.clj +++ b/src/path_to_answer_sheet.clj @@ -212,18 +212,17 @@ (println (str "\n" koan ".clj is passing without filling in the blanks"))) (defn ensure-failing-without-answers [] - (binding [path-to-enlightenment/handle-problem - (constantly :correctly-failing-test) - clojure.test/*test-out* + (binding [clojure.test/*test-out* (java.io.PrintWriter. (java.io.ByteArrayOutputStream.))] - (dorun (map - (fn [koan] - (let [form (koan-text koan) - result (load-string form)] - (when (= :pass result) - (print-non-failing-error koan)))) - - ordered-koans)))) + (if (every? + (fn [koan] + (let [form (koan-text koan) + result (load-string form)] + (if result + (print-non-failing-error koan) + :pass))) + ordered-koans) + (println "\nTests all fail before the answers are filled in.")))) (defn ensure-passing-with-answers [] (try @@ -234,7 +233,7 @@ (fill-in-answers koan "__") (fill-in-answers koan "___")))) ordered-koans)) - (println "\nAll tests pass when the answers are filled in.") + (println "\nAll tests pass after the answers are filled in.") (catch Exception e (println "\nAnswer sheet fail: " e) diff --git a/src/path_to_enlightenment.clj b/src/path_to_enlightenment.clj index c1b814c..a4d0a88 100644 --- a/src/path_to_enlightenment.clj +++ b/src/path_to_enlightenment.clj @@ -1,26 +1,23 @@ (ns path-to-enlightenment - (:use [clojure.test]) + (:use [fresh.core :only [clj-files-in freshener]] + [clojure.java.io :only [file]]) (:require [clojure.set] [clojure.string] - [clojure.test])) + [clojure.test]) + (:import + [java.util.concurrent ScheduledThreadPoolExecutor TimeUnit])) (def __ :fill-in-the-blank) (def ___ (fn [& args] __)) -(defn ^:dynamic handle-problem [] - (System/exit 0)) - (defmacro meditations [& forms] - (let [pairs (partition 2 forms) - pairs (conj pairs + (let [pairs (conj (partition 2 forms) ["Bootstrap for file/line reporting" '(clojure.test/is (= 0 0))]) tests (map (fn [[doc# code#]] - `(if (is ~code# ~doc#) - :pass - (handle-problem))) + `(clojure.test/is ~code# ~doc#)) pairs)] - `(do ~@tests))) + `(and ~@tests))) (def ordered-koans ["equalities" @@ -63,7 +60,54 @@ (map read-string (take 3 (clojure.string/split version-string #"[\.\-]"))))) +(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)) + (defn run [] (require-version (parse-required-version)) - (doall (map (comp load (partial str "koans/")) ordered-koans)) - (println "You have achieved clojure enlightenment. Namaste.")) + (setup-freshener)) + +