diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 99304332..6f6674e4 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -415,7 +415,7 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.") (assoc opts-map :run fst :command-line-args (next args)))) opts-map))) -(defn parse-classpath [options] +(defn parse-global-opts [options] (when-let [f (first options)] (case f ("--classpath" "-cp") [(nnext options) (second options)] @@ -424,160 +424,162 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.") (defn parse-opts ([options] (parse-opts options nil)) ([options opts] - (let [[options classpath] (parse-classpath options) + (let [[options classpath] (parse-global-opts options) opts (if classpath (assoc opts :classpath classpath) opts) opt (first options) tasks (into #{} (map str) (keys (:tasks @common/bb-edn)))] (when opt - (cond (contains? tasks opt) - {:run opt - :classpath classpath - :command-line-args (rest options)} - (fs/regular-file? opt) - (if (str/ends-with? opt ".jar") - {:classpath classpath - :jar opt - :command-line-args (next options)} - {:classpath classpath - :file opt - :command-line-args (next options)}) - (command? opt) - (recur (cons (str "--" opt) (next options)) opts) - :else - (let [opts (loop [options options - opts-map opts] - (if options - (let [opt (first options)] - (case opt - ("--") (assoc opts-map :command-line-args (next options)) - ("--clojure") (assoc opts-map :clojure true - :command-line-args (rest options)) - ("--version") {:version true} - ("--help" "-h" "-?" "help") - {:help true - :command-line-args (rest options)} - ("--doc") - {:doc true - :command-line-args (rest options)} - ("--verbose") (recur (next options) - (assoc opts-map - :verbose? true)) - ("--describe") (recur (next options) - (assoc opts-map - :describe? true)) - ("--stream") (recur (next options) - (assoc opts-map - :stream? true)) - ("-i") (recur (next options) - (assoc opts-map - :shell-in true)) - ("-I") (recur (next options) - (assoc opts-map - :edn-in true)) - ("-o") (recur (next options) - (assoc opts-map - :shell-out true)) - ("-O") (recur (next options) - (assoc opts-map - :edn-out true)) - ("-io") (recur (next options) - (assoc opts-map - :shell-in true - :shell-out true)) - ("-iO") (recur (next options) - (assoc opts-map - :shell-in true - :edn-out true)) - ("-Io") (recur (next options) - (assoc opts-map - :edn-in true - :shell-out true)) - ("-IO") (recur (next options) - (assoc opts-map - :edn-in true - :edn-out true)) - ("--classpath", "-cp") - (let [options (next options)] - (recur (next options) - (assoc opts-map :classpath (first options)))) - ("--uberscript") - (let [options (next options)] - (recur (next options) - (assoc opts-map - :uberscript (first options)))) - ("--uberjar") - (let [options (next options)] - (recur (next options) - (assoc opts-map - :uberjar (first options)))) - ("-f" "--file") - (let [options (next options)] - (recur (next options) - (assoc opts-map - :file (first options)))) - ("--jar" "-jar") - (let [options (next options)] - (recur (next options) - (assoc opts-map - :jar (first options)))) - ("--repl") - (let [options (next options)] - (recur (next options) - (assoc opts-map - :repl true))) - ("--socket-repl") - (let [options (next options) - opt (first options) - opt (when (and opt (not (str/starts-with? opt "-"))) - opt) - options (if opt (next options) - options)] - (recur options - (assoc opts-map - :socket-repl (or opt "1666")))) - ("--nrepl-server") - (let [options (next options) - opt (first options) - opt (when (and opt (not (str/starts-with? opt "-"))) - opt) - options (if opt (next options) - options)] - (recur options - (assoc opts-map - :nrepl (or opt "1667")))) - ("--eval", "-e") - (let [options (next options)] - (recur (next options) - (update opts-map :expressions (fnil conj []) (first options)))) - ("--main", "-m",) - (let [options (next options)] - (recur (next options) - (assoc opts-map :main (first options)))) - ("--run") - (parse-run-opts opts-map (next options)) - ("--tasks") - (assoc opts-map :list-tasks true - :command-line-args (next options)) - ;; fallback - (if (and opts-map - (some opts-map [:file :jar :socket-repl :expressions :main :run])) + ;; FILE > TASK > SUBCOMMAND + (cond + (fs/regular-file? opt) + (if (str/ends-with? opt ".jar") + {:classpath classpath + :jar opt + :command-line-args (next options)} + {:classpath classpath + :file opt + :command-line-args (next options)}) + (contains? tasks opt) + {:run opt + :classpath classpath + :command-line-args (rest options)} + (command? opt) + (recur (cons (str "--" opt) (next options)) opts) + :else + (let [opts (loop [options options + opts-map opts] + (if options + (let [opt (first options)] + (case opt + ("--") (assoc opts-map :command-line-args (next options)) + ("--clojure") (assoc opts-map :clojure true + :command-line-args (rest options)) + ("--version") {:version true} + ("--help" "-h" "-?" "help") + {:help true + :command-line-args (rest options)} + ("--doc") + {:doc true + :command-line-args (rest options)} + ("--verbose") (recur (next options) + (assoc opts-map + :verbose? true)) + ("--describe") (recur (next options) + (assoc opts-map + :describe? true)) + ("--stream") (recur (next options) + (assoc opts-map + :stream? true)) + ("-i") (recur (next options) + (assoc opts-map + :shell-in true)) + ("-I") (recur (next options) + (assoc opts-map + :edn-in true)) + ("-o") (recur (next options) + (assoc opts-map + :shell-out true)) + ("-O") (recur (next options) + (assoc opts-map + :edn-out true)) + ("-io") (recur (next options) + (assoc opts-map + :shell-in true + :shell-out true)) + ("-iO") (recur (next options) + (assoc opts-map + :shell-in true + :edn-out true)) + ("-Io") (recur (next options) + (assoc opts-map + :edn-in true + :shell-out true)) + ("-IO") (recur (next options) + (assoc opts-map + :edn-in true + :edn-out true)) + ("--classpath", "-cp") + (let [options (next options)] + (recur (next options) + (assoc opts-map :classpath (first options)))) + ("--uberscript") + (let [options (next options)] + (recur (next options) + (assoc opts-map + :uberscript (first options)))) + ("--uberjar") + (let [options (next options)] + (recur (next options) + (assoc opts-map + :uberjar (first options)))) + ("-f" "--file") + (let [options (next options)] + (recur (next options) + (assoc opts-map + :file (first options)))) + ("--jar" "-jar") + (let [options (next options)] + (recur (next options) + (assoc opts-map + :jar (first options)))) + ("--repl") + (let [options (next options)] + (recur (next options) + (assoc opts-map + :repl true))) + ("--socket-repl") + (let [options (next options) + opt (first options) + opt (when (and opt (not (str/starts-with? opt "-"))) + opt) + options (if opt (next options) + options)] + (recur options + (assoc opts-map + :socket-repl (or opt "1666")))) + ("--nrepl-server") + (let [options (next options) + opt (first options) + opt (when (and opt (not (str/starts-with? opt "-"))) + opt) + options (if opt (next options) + options)] + (recur options + (assoc opts-map + :nrepl (or opt "1667")))) + ("--eval", "-e") + (let [options (next options)] + (recur (next options) + (update opts-map :expressions (fnil conj []) (first options)))) + ("--main", "-m",) + (let [options (next options)] + (recur (next options) + (assoc opts-map :main (first options)))) + ("--run") + (parse-run-opts opts-map (next options)) + ("--tasks") + (assoc opts-map :list-tasks true + :command-line-args (next options)) + ;; fallback + (if (and opts-map + (some opts-map [:file :jar :socket-repl :expressions :main :run])) + (assoc opts-map + :command-line-args options) + (let [trimmed-opt (str/triml opt) + c (.charAt trimmed-opt 0)] + (case c + (\( \{ \[ \* \@ \#) + (-> opts-map + (update :expressions (fnil conj []) (first options)) + (assoc :command-line-args (next options))) (assoc opts-map - :command-line-args options) - (let [trimmed-opt (str/triml opt) - c (.charAt trimmed-opt 0)] - (case c - (\( \{ \[ \* \@ \#) - (-> opts-map - (update :expressions (fnil conj []) (first options)) - (assoc :command-line-args (next options))) - (assoc opts-map - (if (str/ends-with? opt ".jar") - :jar - :file) opt - :command-line-args (next options))))))) - opts-map))] - opts)))))) + (if (str/ends-with? opt ".jar") + :jar + :file) opt + :command-line-args (next options))))))) + opts-map))] + opts)))))) (def env (atom {})) diff --git a/test/babashka/bb_edn_test.clj b/test/babashka/bb_edn_test.clj index a16fa234..4be0525c 100644 --- a/test/babashka/bb_edn_test.clj +++ b/test/babashka/bb_edn_test.clj @@ -1,6 +1,8 @@ (ns babashka.bb-edn-test (:require [babashka.fs :as fs] + [babashka.impl.common :as common] + [babashka.main :as main] [babashka.test-utils :as test-utils] [clojure.edn :as edn] [clojure.string :as str] @@ -107,6 +109,19 @@ (let [res (test-utils/bb nil "tasks")] (is (= "The following tasks are available:\n\ntask1 task1 doc\ntask2 task2 doc\n" res))))) +(deftest task-priority-test + (testing "FILE > TASK > SUBCOMMAND" + (is (= "foo.jar" (:uberjar (main/parse-opts ["uberjar" "foo.jar"])))) + (test-utils/with-config '{:tasks {uberjar (+ 1 2 3)}} + (vreset! common/bb-edn (edn/read-string (slurp test-utils/*bb-edn-path*))) + (is (= "uberjar" (:run (main/parse-opts ["uberjar"]))))) + (try + (test-utils/with-config '{:tasks {uberjar (+ 1 2 3)}} + (spit "uberjar" "#!/usr/bin/env bb\n(+ 1 2 3)") + (vreset! common/bb-edn (edn/read-string (slurp test-utils/*bb-edn-path*))) + (is (= "uberjar" (:file (main/parse-opts ["uberjar"]))))) + (finally (fs/delete "uberjar"))))) + ;; TODO: ;; Do we want to support the same parsing as the clj CLI? ;; Or do we want `--aliases :foo:bar`