This repository has been archived by the owner on Dec 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4a58710
Showing
14 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/target | ||
/classes | ||
/checkouts | ||
pom.xml | ||
pom.xml.asc | ||
*.jar | ||
*.class | ||
/.lein-* | ||
/.nrepl-port |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# lein-watch | ||
|
||
A Leiningen plugin to watch directories and run tasks automatically. | ||
|
||
## Usage | ||
|
||
Put `[lein-watch "0.1.0-SNAPSHOT"]` into the `:plugins` vector of your project.clj and | ||
add :watch configuration to your project.clj. | ||
|
||
Example configuration (run compile task when .clj files changes) : | ||
|
||
(defproject sample-project | ||
... | ||
:watch { | ||
:rate 500 ;; check file every 500ms (use 'watchtower' intanally) | ||
:watches { | ||
:compile { | ||
:watch-dirs ["src"] | ||
:file-patterns [#"\.clj"] | ||
:tasks ["compile"]}}} | ||
...) | ||
|
||
and just run watch task | ||
|
||
$ lein watch | ||
|
||
See [sample-project](http://github.com/runoshun/lein-watch/sample-project) for more complex usage. | ||
|
||
## License | ||
|
||
Distributed under the MIT License. | ||
|
||
Copyright © 2014 runoshun |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
(defproject lein-watch "0.0.1" | ||
:description "A Leiningen plugin to watch directories and run tasks automatically." | ||
:url "http://github.com/runoshun/lein-watch" | ||
:license {:name "MIT" | ||
:url "http://opensource.org/licenses/MIT"} | ||
:dependencies [[watchtower "0.1.1"]] | ||
:eval-in-leiningen true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/target | ||
/classes | ||
/checkouts | ||
pom.xml | ||
pom.xml.asc | ||
*.jar | ||
*.class | ||
/.lein-* | ||
/.nrepl-port |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# sample-project for lein-watch plugin | ||
|
||
See `project.clj` | ||
|
||
## License | ||
|
||
Distributed under the MIT License. | ||
|
||
Copyright © 2014 FIXME |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Introduction to test-watch | ||
|
||
TODO: write [great documentation](http://jacobian.org/writing/great-documentation/what-to-write/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
(defproject watch-sample "0.1.0-SNAPSHOT" | ||
:license {:name "Eclipse Public License" | ||
:url "http://www.eclipse.org/legal/epl-v10.html"} | ||
|
||
;; use 'lein-watch' plugin | ||
:plugins [[lein-watch "0.0.1"] | ||
[lein-garden "0.1.8"]] | ||
:dependencies [[org.clojure/clojure "1.5.1"]] | ||
|
||
;; profiles used in watch tasks | ||
:profiles {:garden {:source-paths ["src-garden"] | ||
:dependencies [[garden "1.1.5"]]} | ||
:hiccup {:source-paths ["src-hiccup"] | ||
:dependencies [[hiccup "1.0.5"]]}} | ||
|
||
:garden { | ||
:builds [{:id "screen" | ||
:stylesheet test-watch.css/screen | ||
:compiler {:output-to "resources/public/screen.css" | ||
:pretty-print true}}]} | ||
|
||
;; configuration for 'lein-watch' | ||
:watch { | ||
;; polling rate in 'ms' (it's directory passed to 'watchtower') | ||
:rate 300 | ||
|
||
;; watcher definition | ||
:watchers { | ||
;; run 'lein garden once' when *.clj file under the 'src-garden' changed. | ||
:garden {;; :watch-dirs (required) : vector of string | ||
;; Put directories that you want watch. | ||
:watch-dirs ["src-garden"] | ||
|
||
;; :file-patterns (optional) : vector of java.util.regex.Pattern | ||
;; If file name that changed is matched this patterns, tasks are executed. | ||
;; otherwise not executed. | ||
;; default : [#".*"]. | ||
:file-patterns [#"\.clj"] | ||
|
||
;; :tasks (required) : vector of (string|symbol) | ||
;; Put tasks that you want executed when file changed. | ||
;; If a value is string, it is evaluated as a leiningen task. | ||
;; If a value is symbol, it is called as a function in project context and | ||
;; is passed changed file as argument. | ||
:tasks ["garden once"] | ||
|
||
;; profiles (optional) : vector of keyword | ||
;; profile names used when executing tasks. | ||
;; default : [] | ||
:profiles [:garden]} | ||
;; call 'test-watch.hiccup/generate' (defined in 'src-hiccup/test_watch/hiccup.clj') | ||
;; when *.clj file under the 'src-hiccup' changed. | ||
:hiccup {:watch-dirs ["src-hiccup"] | ||
:profiles [:hiccup] | ||
:file-patterns [#"\.clj"] | ||
:tasks [test-watch.hiccup/generate]}}}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<html><head><link href="screen.css" rel="stylesheet" type="text/css" /></head><body><div><span>Hello world</span></div></body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
body { | ||
line-height: 1.5; | ||
font-size: 20px; | ||
font-family: sans-serif; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
(ns test-watch.css | ||
(:require [garden.def :refer [defstylesheet defstyles]] | ||
[garden.units :refer [px]])) | ||
|
||
(defstyles screen | ||
[:body | ||
{:font-family "sans-serif" | ||
:font-size (px 20) | ||
:line-height 1.5}]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
(ns test-watch.hiccup | ||
(:require [hiccup.core :refer [html]])) | ||
|
||
(defn generate [& _] | ||
(spit "resources/public/index.html" | ||
(html [:html | ||
[:head [:link {:rel "stylesheet" :type "text/css" :href "screen.css"}]] | ||
[:body [:div [:span "Hello world"]]]]))) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
(ns test-watch.core) | ||
|
||
(defn foo | ||
"I don't do a whole lot." | ||
[x] | ||
(println x "Hello, World!")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
(ns test-watch.core-test | ||
(:require [clojure.test :refer :all] | ||
[test-watch.core :refer :all])) | ||
|
||
(deftest a-test | ||
(testing "FIXME, I fail." | ||
(is (= 0 1)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
(ns leiningen.watch | ||
(:require [clojure.string :as string] | ||
[clojure.java.io :as io] | ||
[watchtower.core :as wt] | ||
[leiningen.core.eval :as lein-eval] | ||
[leiningen.core.main :as lein-main] | ||
[leiningen.core.project :as lein-project])) | ||
|
||
(def ^:private default-watcher-options | ||
{:file-patterns [#".*"] | ||
:profiles []}) | ||
|
||
(def ^:private default-global-settings | ||
{:rate 300}) | ||
|
||
(defn- non-nils [coll] (remove nil? coll)) | ||
|
||
(defn- ensure-regex [pat] | ||
(if (instance? java.util.regex.Pattern pat) | ||
pat | ||
(re-pattern pat))) | ||
|
||
(defn- match? [patterns file] | ||
(boolean (first (non-nils (map #(re-find % (str file)) | ||
(map ensure-regex patterns)))))) | ||
|
||
(defn- child? [parent child] | ||
(not (.isAbsolute (.relativize (.toURI (io/file parent)) | ||
(.toURI (io/file child)))))) | ||
|
||
(defn- make-route [dir patterns group] | ||
(fn [file] | ||
(if (and (child? dir file) (match? patterns file)) | ||
group | ||
nil))) | ||
|
||
(defn- make-router [watchers] | ||
(fn [file] | ||
(let [routes (mapcat (fn [group] | ||
(let [options (group watchers) | ||
patterns (-> options :file-patterns) | ||
dirs (-> options :watch-dirs)] | ||
(map (fn [dir] (make-route dir patterns group)) dirs))) | ||
(keys watchers))] | ||
(first (non-nils (map #(% file) routes)))))) | ||
|
||
(defn- separate-ns [sym] | ||
(let [syms (string/split (str sym) #"/")] | ||
(if (= 2 (count syms)) | ||
(symbol (first syms)) | ||
nil))) | ||
|
||
(defn- run-tasks [project watcher file] | ||
(let [project (lein-project/merge-profiles project (:profiles watcher)) | ||
tasks (:tasks watcher)] | ||
(println (str "[lein-watch] file changed : " file)) | ||
(println (str "[lein-watch] run-tasks : " tasks)) | ||
(doseq [task tasks] | ||
(cond | ||
(string? task) (lein-main/resolve-and-apply | ||
project | ||
(string/split (string/replace-first task #"%f" (str file)) #"\s+")) | ||
(symbol task) (let [ns (separate-ns task) | ||
file-str (.getAbsolutePath file) | ||
form (if ns | ||
`(do (require '~ns) (~task ~file-str)) | ||
`(~task ~file-str))] | ||
(lein-eval/eval-in-project project form)))))) | ||
|
||
(defn- ensure-slash [dir] | ||
(if-not (.endsWith dir "/") | ||
(str dir "/") | ||
dir)) | ||
|
||
(defn watch | ||
"Watch directories and run tasks when file changed." | ||
[project & args] | ||
(let [settings (:watch project) | ||
settings (merge default-global-settings settings) | ||
watchers (:watchers settings) | ||
watchers (reduce (fn [m [k v]] (assoc m k (merge default-watcher-options v))) {} watchers) | ||
router (make-router watchers) | ||
dirs (map ensure-slash (mapcat :watch-dirs (vals watchers))) | ||
process-event (fn [files] | ||
(doseq [file files] | ||
(run-tasks project (watchers (router file)) file)))] | ||
(if watchers | ||
(deref | ||
(wt/watcher dirs | ||
(wt/rate (:rate settings)) | ||
(wt/on-change process-event))) | ||
(println "no watcher found.")))) | ||
|
||
(comment | ||
(do | ||
(def project | ||
{:watch | ||
{:watchers | ||
{:garden {:watch-dirs ["src-garden"] | ||
:file-patterns [#".*"] | ||
:tasks ["garden once"]} | ||
:hiccup {:watch-dirs ["src-hiccup"] | ||
:file-patterns [#"\.txt"] | ||
:tasks ["hiccpu once"]}}}}) | ||
|
||
(def router (make-router (-> project :watch :watchers))) | ||
(assert (= (router (io/file "src-garden/foo")) :garden)) | ||
(assert (= (router "src-hiccup/bar") nil)) | ||
(assert (= (router "src-hiccup/bar.txt") :hiccup)) | ||
|
||
)) |