From af71f1d529d0d9eee699139b48f15f075e9468a9 Mon Sep 17 00:00:00 2001 From: Colin Jones Date: Sat, 31 Jul 2010 15:41:24 -0500 Subject: [PATCH 1/4] more robust project-needed decision --- src/leiningen/core.clj | 8 ++++---- src/leiningen/interactive.clj | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/leiningen/core.clj b/src/leiningen/core.clj index 9d2e9e54..a8d8a966 100644 --- a/src/leiningen/core.clj +++ b/src/leiningen/core.clj @@ -61,8 +61,6 @@ "--version" "version" "überjar" "uberjar" "int" "interactive"})) -(def no-project-needed (atom #{"new" "help" "version"})) - (defn task-not-found [& _] (abort "That's not a task. Use \"lein help\" to list all tasks.")) @@ -104,11 +102,13 @@ (replace \_ \-) (replace \/ \.))) +(defn project-needed [taskname] + (some #{'project} (map first (:arglists (meta (resolve-task taskname)))))) + (defn -main ([& [task-name & args]] (let [task-name (or (@aliases task-name) task-name "help") - project (when-not (@no-project-needed task-name) - (read-project)) + project (if (project-needed task-name) (read-project)) compile-path (:compile-path project)] (when compile-path (.mkdirs (File. compile-path))) (binding [*compile-path* compile-path] diff --git a/src/leiningen/interactive.clj b/src/leiningen/interactive.clj index da3929d4..2ae943f3 100644 --- a/src/leiningen/interactive.clj +++ b/src/leiningen/interactive.clj @@ -1,6 +1,6 @@ (ns leiningen.interactive (:require [clojure.string :as string]) - (:use [leiningen.core :only [resolve-task no-project-needed]])) + (:use [leiningen.core :only [resolve-task project-needed]])) (defn not-found [& _] (println "That's not a task. Use \"lein help\" to list all tasks.")) @@ -18,7 +18,7 @@ (when input (let [[task-name & args] (string/split input #"\s") task (resolve-task task-name not-found)] - (if (@no-project-needed task-name) - (apply task args) - (apply task project args)) + (if (project-needed task-name) + (apply task project args) + (apply task args)) (recur)))))) From 7acdf16a2999ce5dd2d212db1b78740bba5860f8 Mon Sep 17 00:00:00 2001 From: Colin Jones Date: Sat, 31 Jul 2010 15:58:58 -0500 Subject: [PATCH 2/4] unifying interactive and normal task calling --- src/leiningen/core.clj | 19 +++++++++++-------- src/leiningen/interactive.clj | 9 +++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/leiningen/core.clj b/src/leiningen/core.clj index a8d8a966..51aea513 100644 --- a/src/leiningen/core.clj +++ b/src/leiningen/core.clj @@ -102,8 +102,16 @@ (replace \_ \-) (replace \/ \.))) -(defn project-needed [taskname] - (some #{'project} (map first (:arglists (meta (resolve-task taskname)))))) +(defn project-needed [task-name] + (some #{'project} (map first (:arglists (meta (resolve-task task-name)))))) + +(defn apply-task [task-name project args not-found] + ;; TODO: can we catch only task-level arity problems here? + ;; compare args and (:arglists (meta (resolve-task task)))? + (let [task (resolve-task task-name not-found)] + (if (project-needed task-name) + (apply task project args) + (apply task args)))) (defn -main ([& [task-name & args]] @@ -114,12 +122,7 @@ (binding [*compile-path* compile-path] (when project (load-hooks project)) - ;; TODO: can we catch only task-level arity problems here? - ;; compare args and (:arglists (meta (resolve-task task)))? - (let [task (resolve-task task-name) - value (apply task (if project - (cons project args) - args))] + (let [value (apply-task task-name project args task-not-found)] (when (integer? value) (System/exit value)))))) ([] (apply -main (or *command-line-args* ["help"])))) diff --git a/src/leiningen/interactive.clj b/src/leiningen/interactive.clj index 2ae943f3..19985600 100644 --- a/src/leiningen/interactive.clj +++ b/src/leiningen/interactive.clj @@ -1,6 +1,6 @@ (ns leiningen.interactive (:require [clojure.string :as string]) - (:use [leiningen.core :only [resolve-task project-needed]])) + (:use [leiningen.core :only [apply-task]])) (defn not-found [& _] (println "That's not a task. Use \"lein help\" to list all tasks.")) @@ -16,9 +16,6 @@ ;; TODO: integrate with tab-completion in jLine (let [input (.readLine *in*)] (when input - (let [[task-name & args] (string/split input #"\s") - task (resolve-task task-name not-found)] - (if (project-needed task-name) - (apply task project args) - (apply task args)) + (let [[task-name & args] (string/split input #"\s")] + (apply-task task-name project args not-found) (recur)))))) From dc4ae5191c169ae3147d9dbd7f4c0ee050fabb6a Mon Sep 17 00:00:00 2001 From: Colin Jones Date: Sat, 31 Jul 2010 16:30:55 -0500 Subject: [PATCH 3/4] task-level arity checking --- src/leiningen/core.clj | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/leiningen/core.clj b/src/leiningen/core.clj index 51aea513..869b7c36 100644 --- a/src/leiningen/core.clj +++ b/src/leiningen/core.clj @@ -102,21 +102,34 @@ (replace \_ \-) (replace \/ \.))) -(defn project-needed [task-name] - (some #{'project} (map first (:arglists (meta (resolve-task task-name)))))) +(defn arglists [task-name not-found] + (:arglists (meta (resolve-task task-name not-found)))) + +(defn project-needed [task-name not-found] + (some #{'project} (map first (arglists task-name not-found)))) + +(defn matching-arity [task-name project args not-found] + (let [arg-count (if (project-needed task-name not-found) + (inc (count args)) + (count args))] + (some (fn [defined-args] + (if (= '& (last (butlast defined-args))) + (>= arg-count (- (count defined-args) 2)) + (= arg-count (count defined-args)))) + (arglists task-name not-found)))) (defn apply-task [task-name project args not-found] - ;; TODO: can we catch only task-level arity problems here? - ;; compare args and (:arglists (meta (resolve-task task)))? (let [task (resolve-task task-name not-found)] - (if (project-needed task-name) - (apply task project args) - (apply task args)))) + (if (matching-arity task-name project args not-found) + (if (project-needed task-name not-found) + (apply task project args) + (apply task args)) + (not-found)))) (defn -main ([& [task-name & args]] (let [task-name (or (@aliases task-name) task-name "help") - project (if (project-needed task-name) (read-project)) + project (if (project-needed task-name task-not-found) (read-project)) compile-path (:compile-path project)] (when compile-path (.mkdirs (File. compile-path))) (binding [*compile-path* compile-path] From 76d3d6648282e2aafcc1af15e0b00c5840b879a0 Mon Sep 17 00:00:00 2001 From: Colin Jones Date: Sun, 1 Aug 2010 20:58:22 -0500 Subject: [PATCH 4/4] multiple tasks from the command line --- src/leiningen/core.clj | 23 ++++++++++++++++++++++- test/test_core.clj | 17 +++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/test_core.clj diff --git a/src/leiningen/core.clj b/src/leiningen/core.clj index 9d2e9e54..f8c9f6c0 100644 --- a/src/leiningen/core.clj +++ b/src/leiningen/core.clj @@ -1,5 +1,6 @@ (ns leiningen.core (:use [clojure.contrib.find-namespaces :only [find-namespaces-on-classpath]] + [clojure.string :only [split]] [clojure.walk :only [walk]]) (:import [java.io File]) (:gen-class)) @@ -104,6 +105,22 @@ (replace \_ \-) (replace \/ \.))) +(def arg-separator ",") +(defn ends-in-separator [s] + (re-matches (re-pattern (str ".*" arg-separator)) s)) + +(defn make-groups [args] + (if (some ends-in-separator args) + (remove #(= [arg-separator] %) + (partition-by #(= arg-separator %) + (flatten + (map (fn [arg] + (if (ends-in-separator arg) + [(apply str (butlast arg)) arg-separator] + arg)) + args)))) + [args])) + (defn -main ([& [task-name & args]] (let [task-name (or (@aliases task-name) task-name "help") @@ -122,4 +139,8 @@ args))] (when (integer? value) (System/exit value)))))) - ([] (apply -main (or *command-line-args* ["help"])))) + ([] + (let [arg-groups (make-groups *command-line-args*)] + (dorun (map + (fn [arg-group] (apply -main (or arg-group ["help"]))) + arg-groups))))) diff --git a/test/test_core.clj b/test/test_core.clj new file mode 100644 index 00000000..83946087 --- /dev/null +++ b/test/test_core.clj @@ -0,0 +1,17 @@ +(ns test-core + (:use [leiningen.core :only [make-groups]] :reload-all) + (:use [clojure.test])) + +(deftest test-make-groups-empty-args + (is (= [[]] (make-groups [])))) + +(deftest test-make-groups-single-task + (is (= [["pom"]] (make-groups ["pom"])))) + +(deftest test-make-groups-without-args + (is (= [["clean"] ["deps"] ["test"]] + (make-groups ["clean," "deps," "test"])))) + +(deftest test-make-groups-with-args + (is (= [["test" "test-core"] ["version"]] + (make-groups ["test" "test-core," "version"]))))