diff --git a/README.md b/README.md index b5f8b611..91cf9000 100644 --- a/README.md +++ b/README.md @@ -167,16 +167,17 @@ Check out the image on [Docker hub](https://hub.docker.com/r/borkdude/babashka/) ## Usage ``` shellsession -Usage: bb [ -i | -I ] [ -o | -O ] [ --stream ] [--verbose] - [ ( --classpath | -cp ) ] [ --uberscript ] - [ ( --main | -m ) | -e | -f | - --repl | --socket-repl [:] | --nrepl-server [:] ] - [ arg* ] +Babashka v0.0.90 -Options: +Options must appear in the order of groups mentioned below. + +Help: --help, -h or -? Print this help text. --version Print the current version of babashka. + --describe Print an EDN map with information about this version of babashka. + +In- and output flags: -i Bind *input* to a lazy seq of lines from stdin. -I Bind *input* to a lazy seq of EDN values from stdin. @@ -184,20 +185,25 @@ Options: -O Write EDN values to stdout. --verbose Print entire stacktrace in case of exception. --stream Stream over lines or EDN values from stdin. Combined with -i or -I *input* becomes a single value per iteration. + +Uberscript: + --uberscript Collect preloads, -e, -f and -m and all required namespaces from the classpath into a single executable file. +Evaluation: + -e, --eval Evaluate an expression. -f, --file Evaluate a file. -cp, --classpath Classpath to use. -m, --main Call the -main function from namespace with args. + +REPL: + --repl Start REPL. Use rlwrap for history. --socket-repl Start socket REPL. Specify port (e.g. 1666) or host and port separated by colon (e.g. 127.0.0.1:1666). --nrepl-server Start nREPL server. Specify port (e.g. 1667) or host and port separated by colon (e.g. 127.0.0.1:1667). - --time Print execution time before exiting. - -- Stop parsing args and pass everything after -- to *command-line-args* -If neither -e, -f, or --socket-repl are specified, then the first argument that is not parsed as a option is treated as a file if it exists, or as an expression otherwise. -Everything after that is bound to *command-line-args*. +If neither -e, -f, or --socket-repl are specified, then the first argument that is not parsed as a option is treated as a file if it exists, or as an expression otherwise. Everything after that is bound to *command-line-args*. Use -- to separate script command lin args from bb command line args. ``` The `clojure.core` functions are accessible without a namespace alias. diff --git a/src/babashka/main.clj b/src/babashka/main.clj index a591268d..2571752f 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -91,12 +91,12 @@ ("--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)) - ("--time") (recur (next options) - (assoc opts-map - :time? true)) ("-i") (recur (next options) (assoc opts-map :shell-in true)) @@ -204,24 +204,20 @@ (defn print-version [] (println (str "babashka v"(str/trim (slurp (io/resource "BABASHKA_VERSION")))))) -(def usage-string "Usage: bb [ -i | -I ] [ -o | -O ] [ --stream ] [--verbose] - [ ( --classpath | -cp ) ] [ --uberscript ] - [ ( --main | -m ) | -e | -f | - --repl | --socket-repl [:] | --nrepl-server [:] ] - [ arg* ]") -(defn print-usage [] - (println usage-string)) (defn print-help [] (println (str "Babashka v" (str/trim (slurp (io/resource "BABASHKA_VERSION"))))) ;; (println (str "sci v" (str/trim (slurp (io/resource "SCI_VERSION"))))) (println) - (print-usage) - (println) - (println "Options:") + (println "Options must appear in the order of groups mentioned below.") (println " +Help: + --help, -h or -? Print this help text. --version Print the current version of babashka. + --describe Print an EDN map with information about this version of babashka. + +In- and output flags: -i Bind *input* to a lazy seq of lines from stdin. -I Bind *input* to a lazy seq of EDN values from stdin. @@ -229,20 +225,50 @@ -O Write EDN values to stdout. --verbose Print entire stacktrace in case of exception. --stream Stream over lines or EDN values from stdin. Combined with -i or -I *input* becomes a single value per iteration. + +Uberscript: + --uberscript Collect preloads, -e, -f and -m and all required namespaces from the classpath into a single executable file. +Evaluation: + -e, --eval Evaluate an expression. -f, --file Evaluate a file. -cp, --classpath Classpath to use. -m, --main Call the -main function from namespace with args. + +REPL: + --repl Start REPL. Use rlwrap for history. --socket-repl Start socket REPL. Specify port (e.g. 1666) or host and port separated by colon (e.g. 127.0.0.1:1666). --nrepl-server Start nREPL server. Specify port (e.g. 1667) or host and port separated by colon (e.g. 127.0.0.1:1667). - --time Print execution time before exiting. - -- Stop parsing args and pass everything after -- to *command-line-args* -If neither -e, -f, or --socket-repl are specified, then the first argument that is not parsed as a option is treated as a file if it exists, or as an expression otherwise. -Everything after that is bound to *command-line-args*.")) +If neither -e, -f, or --socket-repl are specified, then the first argument that is not parsed as a option is treated as a file if it exists, or as an expression otherwise. Everything after that is bound to *command-line-args*. Use -- to separate script command lin args from bb command line args.")) + +(defn print-describe [] + (println + (format + (str/trim " +{:babashka/version \"%s\" + :feature/core-async %s + :feature/csv %s + :feature/java-nio %s + :feature/java-time %s + :feature/xml %s + :feature/yaml %s + :feature/jdbc %s + :feature/postgresql %s + :feature/hsqldb %s}") + (str/trim (slurp (io/resource "BABASHKA_VERSION"))) + features/core-async? + features/csv? + features/java-nio? + features/java-time? + features/xml? + features/yaml? + features/jdbc? + features/postgresql? + features/hsqldb?))) (defn read-file [file] (let [f (io/file file)] @@ -354,13 +380,12 @@ Everything after that is bound to *command-line-args*.")) (binding [*unrestricted* true] (sci/binding [reflection-var false sci/ns (vars/->SciNamespace 'user nil)] - (let [t0 (System/currentTimeMillis) - {:keys [:version :shell-in :edn-in :shell-out :edn-out + (let [{:keys [:version :shell-in :edn-in :shell-out :edn-out :help? :file :command-line-args - :expressions :stream? :time? + :expressions :stream? :repl :socket-repl :nrepl :verbose? :classpath - :main :uberscript] :as _opts} + :main :uberscript :describe?] :as _opts} (parse-opts args) _ (when main (System/setProperty "babashka.main" main)) read-next (fn [*in*] @@ -469,6 +494,8 @@ Everything after that is bound to *command-line-args*.")) [(print-version) 0] help? [(print-help) 0] + describe? + [(print-describe) 0] repl [(repl/start-repl! sci-ctx) 0] socket-repl [(start-socket-repl! socket-repl sci-ctx) 0] nrepl [(start-nrepl! nrepl sci-ctx) 0] @@ -497,8 +524,7 @@ Everything after that is bound to *command-line-args*.")) (error-handler* e verbose?))) uberscript [nil 0] :else [(repl/start-repl! sci-ctx) 0])) - 1) - t1 (System/currentTimeMillis)] + 1)] (flush) (when uberscript uberscript @@ -508,8 +534,6 @@ Everything after that is bound to *command-line-args*.")) (spit uberscript-out s :append true)) (spit uberscript-out preloads :append true) (spit uberscript-out expression :append true))) - (when time? (binding [*out* *err*] - (println "bb took" (str (- t1 t0) "ms.")))) exit-code)))) (defn -main diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index 8491427b..1947a1fa 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -37,7 +37,10 @@ (is (thrown-with-msg? Exception #"does not exist" (bb nil "foo.clj"))) (is (thrown-with-msg? Exception #"does not exist" (bb nil "-help")))) (is (= "1 2 3" (bb nil "-e" "(require '[clojure.string :as str1])" "-e" "(str1/join \" \" [1 2 3])"))) - (is (= '("-e" "1") (bb nil "-e" "*command-line-args*" "--" "-e" "1")))) + (is (= '("-e" "1") (bb nil "-e" "*command-line-args*" "--" "-e" "1"))) + (let [v (bb nil "--describe")] + (is (:babashka/version v)) + (is (:feature/xml v)))) (deftest print-error-test (is (thrown-with-msg? Exception #"java.lang.NullPointerException" @@ -111,9 +114,8 @@ exit-code (sci/with-bindings {sci/out out sci/err err} (binding [*out* out *err* err] - (main/main "--time" "(println \"Hello world!\") (System/exit 42)")))] + (main/main "(println \"Hello world!\") (System/exit 42)")))] (is (= (str out) "Hello world!\n")) - (is (re-find #"took" (str err))) (is (= 42 exit-code)))) (deftest malformed-command-line-args-test