From 55f38db119945aca51515e6ffd408a626abc75c1 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Tue, 16 Mar 2021 17:51:44 +0100 Subject: [PATCH] wip --- src/babashka/main.clj | 351 +++++++++++++++++++++--------------------- 1 file changed, 176 insertions(+), 175 deletions(-) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 19a4ebe4..4517ddca 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -522,189 +522,190 @@ Use -- to separate script command line args from bb command line args. sci/ns @sci/ns] (if-let [f (:exec opts)] (f) - (let [{version-opt :version - :keys [:shell-in :edn-in :shell-out :edn-out - :help? :file :command-line-args - :expressions :stream? - :repl :socket-repl :nrepl - :verbose? :classpath - :main :uberscript :describe? - :jar :uberjar :clojure] :as opts} - opts - _ (when clojure - (if-let [proc (deps/clojure (:opts opts))] - (-> @proc :exit (System/exit)) - (System/exit 0))) - _ (when verbose? (vreset! common/verbose? true)) - _ (do ;; set properties - (when main (System/setProperty "babashka.main" main)) - (System/setProperty "babashka.version" version)) - read-next (fn [*in*] - (if (pipe-signal-received?) - ::EOF - (if stream? - (if shell-in (or (read-line) ::EOF) - (edn/read {:readers edn-readers - :eof ::EOF} *in*)) - (delay (cond shell-in - (shell-seq *in*) - edn-in - (edn-seq *in*) - :else - (edn/read {:readers edn-readers} *in*)))))) - uberscript-sources (atom ()) - env (atom {}) - classpath (or classpath - (System/getenv "BABASHKA_CLASSPATH")) - _ (when classpath - (cp/add-classpath classpath)) - abs-path (when file - (let [abs-path (.getAbsolutePath (io/file file))] - (vars/bindRoot sci/file abs-path) - (System/setProperty "babashka.file" abs-path) - abs-path)) - _ (when jar - (cp/add-classpath jar)) - load-fn (fn [{:keys [:namespace :reload]}] - (when-let [{:keys [:loader]} - @cp/cp-state] - (if ;; ignore built-in namespaces when uberscripting, unless with :reload - (and uberscript - (not reload) - (or (contains? namespaces namespace) - (contains? sci-namespaces/namespaces namespace))) - "" - (let [res (cp/source-for-namespace loader namespace nil)] - (when uberscript (swap! uberscript-sources conj (:source res))) - res)))) - main (if (and jar (not main)) - (when-let [res (cp/getResource - (cp/loader jar) - ["META-INF/MANIFEST.MF"] {:url? true})] - (cp/main-ns res)) - main) + (if (:clojure opts) + (if-let [proc (deps/clojure (:opts opts))] + (-> @proc :exit) + 0) + (let [{version-opt :version + :keys [:shell-in :edn-in :shell-out :edn-out + :help? :file :command-line-args + :expressions :stream? + :repl :socket-repl :nrepl + :verbose? :classpath + :main :uberscript :describe? + :jar :uberjar]} + opts + _ (when verbose? (vreset! common/verbose? true)) + _ (do ;; set properties + (when main (System/setProperty "babashka.main" main)) + (System/setProperty "babashka.version" version)) + read-next (fn [*in*] + (if (pipe-signal-received?) + ::EOF + (if stream? + (if shell-in (or (read-line) ::EOF) + (edn/read {:readers edn-readers + :eof ::EOF} *in*)) + (delay (cond shell-in + (shell-seq *in*) + edn-in + (edn-seq *in*) + :else + (edn/read {:readers edn-readers} *in*)))))) + uberscript-sources (atom ()) + env (atom {}) + classpath (or classpath + (System/getenv "BABASHKA_CLASSPATH")) + _ (when classpath + (cp/add-classpath classpath)) + abs-path (when file + (let [abs-path (.getAbsolutePath (io/file file))] + (vars/bindRoot sci/file abs-path) + (System/setProperty "babashka.file" abs-path) + abs-path)) + _ (when jar + (cp/add-classpath jar)) + load-fn (fn [{:keys [:namespace :reload]}] + (when-let [{:keys [:loader]} + @cp/cp-state] + (if ;; ignore built-in namespaces when uberscripting, unless with :reload + (and uberscript + (not reload) + (or (contains? namespaces namespace) + (contains? sci-namespaces/namespaces namespace))) + "" + (let [res (cp/source-for-namespace loader namespace nil)] + (when uberscript (swap! uberscript-sources conj (:source res))) + res)))) + main (if (and jar (not main)) + (when-let [res (cp/getResource + (cp/loader jar) + ["META-INF/MANIFEST.MF"] {:url? true})] + (cp/main-ns res)) + main) - ;; TODO: pull more of these values to compile time - opts {:aliases aliases - :namespaces (-> namespaces - (assoc 'clojure.core - (assoc core-extras - '*command-line-args* - (sci/new-dynamic-var '*command-line-args* command-line-args) - '*warn-on-reflection* reflection-var - 'load-file load-file*)) - (assoc-in ['clojure.java.io 'resource] - (fn [path] - (when-let [{:keys [:loader]} @cp/cp-state] - (if (str/starts-with? path "/") nil ;; non-relative paths always return nil - (cp/getResource loader [path] {:url? true}))))) - (assoc-in ['user (with-meta '*input* - (when-not stream? - {:sci.impl/deref! true}))] input-var)) - :env env - :features #{:bb :clj} - :classes classes/class-map - :imports imports - :load-fn load-fn - :uberscript uberscript - :readers core/data-readers - :reify-fn reify-fn - :proxy-fn proxy-fn} - opts (addons/future opts) - sci-ctx (sci/init opts) - _ (vreset! common/ctx sci-ctx) - preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim)) - [expressions exit-code] - (cond expressions [expressions nil] - main [[(format "(ns user (:require [%1$s])) (apply %1$s/-main *command-line-args*)" - main)] nil] - file (try [[(read-file file)] nil] - (catch Exception e - (error-handler e {:expression expressions + ;; TODO: pull more of these values to compile time + opts {:aliases aliases + :namespaces (-> namespaces + (assoc 'clojure.core + (assoc core-extras + '*command-line-args* + (sci/new-dynamic-var '*command-line-args* command-line-args) + '*warn-on-reflection* reflection-var + 'load-file load-file*)) + (assoc-in ['clojure.java.io 'resource] + (fn [path] + (when-let [{:keys [:loader]} @cp/cp-state] + (if (str/starts-with? path "/") nil ;; non-relative paths always return nil + (cp/getResource loader [path] {:url? true}))))) + (assoc-in ['user (with-meta '*input* + (when-not stream? + {:sci.impl/deref! true}))] input-var)) + :env env + :features #{:bb :clj} + :classes classes/class-map + :imports imports + :load-fn load-fn + :uberscript uberscript + :readers core/data-readers + :reify-fn reify-fn + :proxy-fn proxy-fn} + opts (addons/future opts) + sci-ctx (sci/init opts) + _ (vreset! common/ctx sci-ctx) + preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim)) + [expressions exit-code] + (cond expressions [expressions nil] + main [[(format "(ns user (:require [%1$s])) (apply %1$s/-main *command-line-args*)" + main)] nil] + file (try [[(read-file file)] nil] + (catch Exception e + (error-handler e {:expression expressions + :verbose? verbose? + :preloads preloads + :loader (:loader @cp/cp-state)})))) + expression (str/join " " expressions) ;; this might mess with the locations... + exit-code + ;; handle preloads + (if exit-code exit-code + (do (when preloads + (sci/binding [sci/file ""] + (try + (sci/eval-string* sci-ctx preloads) + (catch Throwable e + (error-handler e {:expression expression :verbose? verbose? :preloads preloads - :loader (:loader @cp/cp-state)})))) - expression (str/join " " expressions) ;; this might mess with the locations... - exit-code - ;; handle preloads - (if exit-code exit-code - (do (when preloads - (sci/binding [sci/file ""] - (try - (sci/eval-string* sci-ctx preloads) - (catch Throwable e - (error-handler e {:expression expression - :verbose? verbose? - :preloads preloads - :loader (:loader @cp/cp-state)}))))) - nil)) - ;; socket REPL is start asynchronously. when no other args are - ;; provided, a normal REPL will be started as well, which causes the - ;; process to wait until SIGINT - _ (when socket-repl (start-socket-repl! socket-repl sci-ctx)) - exit-code - (or exit-code - (second - (cond version-opt - [(print-version) 0] - help? - [(print-help) 0] - describe? - [(print-describe) 0] - repl [(repl/start-repl! sci-ctx) 0] - nrepl [(start-nrepl! nrepl sci-ctx) 0] - uberjar [nil 0] - expressions - (sci/binding [sci/file abs-path] - (try - (loop [] - (let [in (read-next *in*)] - (if (identical? ::EOF in) - [nil 0] ;; done streaming - (let [res [(let [res - (sci/binding [sci/file (or @sci/file "") - input-var in] - (sci/eval-string* sci-ctx expression))] - (when (some? res) - (if-let [pr-f (cond shell-out println - edn-out prn)] - (if (coll? res) - (doseq [l res - :while (not (pipe-signal-received?))] - (pr-f l)) - (pr-f res)) - (prn res)))) 0]] - (if stream? - (recur) - res))))) - (catch Throwable e - (error-handler e {:expression expression - :verbose? verbose? - :preloads preloads - :loader (:loader @cp/cp-state)})))) - uberscript [nil 0] - :else [(repl/start-repl! sci-ctx) 0])) - 1)] - (flush) - (when uberscript - (let [uberscript-out uberscript] - (spit uberscript-out "") ;; reset file - (doseq [s (distinct @uberscript-sources)] - (spit uberscript-out s :append true)) - (spit uberscript-out preloads :append true) - (spit uberscript-out expression :append true))) - (when uberjar - (uberjar/run {:dest uberjar - :jar :uber - :classpath classpath - :main-class main - :verbose verbose?})) - exit-code))))) + :loader (:loader @cp/cp-state)}))))) + nil)) + ;; socket REPL is start asynchronously. when no other args are + ;; provided, a normal REPL will be started as well, which causes the + ;; process to wait until SIGINT + _ (when socket-repl (start-socket-repl! socket-repl sci-ctx)) + exit-code + (or exit-code + (second + (cond version-opt + [(print-version) 0] + help? + [(print-help) 0] + describe? + [(print-describe) 0] + repl [(repl/start-repl! sci-ctx) 0] + nrepl [(start-nrepl! nrepl sci-ctx) 0] + uberjar [nil 0] + expressions + (sci/binding [sci/file abs-path] + (try + (loop [] + (let [in (read-next *in*)] + (if (identical? ::EOF in) + [nil 0] ;; done streaming + (let [res [(let [res + (sci/binding [sci/file (or @sci/file "") + input-var in] + (sci/eval-string* sci-ctx expression))] + (when (some? res) + (if-let [pr-f (cond shell-out println + edn-out prn)] + (if (coll? res) + (doseq [l res + :while (not (pipe-signal-received?))] + (pr-f l)) + (pr-f res)) + (prn res)))) 0]] + (if stream? + (recur) + res))))) + (catch Throwable e + (error-handler e {:expression expression + :verbose? verbose? + :preloads preloads + :loader (:loader @cp/cp-state)})))) + uberscript [nil 0] + :else [(repl/start-repl! sci-ctx) 0])) + 1)] + (flush) + (when uberscript + (let [uberscript-out uberscript] + (spit uberscript-out "") ;; reset file + (doseq [s (distinct @uberscript-sources)] + (spit uberscript-out s :append true)) + (spit uberscript-out preloads :append true) + (spit uberscript-out expression :append true))) + (when uberjar + (uberjar/run {:dest uberjar + :jar :uber + :classpath classpath + :main-class main + :verbose verbose?})) + exit-code)))))) (defn main [& args] (let [opts (parse-opts args)] (if-let [do-opts (:do opts)] (reduce (fn [_ opts] +;; (prn :opts opts) (let [ret (exec opts)] (if (pos? ret) (reduced ret)