diff --git a/CHANGELOG.md b/CHANGELOG.md index c43dda47..08e04422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased - ??? +- Add `-i` flag to janet binary to make it easier to run image files from the command line - Remove `thread/` module. - Add `(number ...)` pattern to peg for more efficient number parsing using Janet's scan-number function without immediate string creation. diff --git a/janet.1 b/janet.1 index bd4ee7f3..2bb8560a 100644 --- a/janet.1 +++ b/janet.1 @@ -3,7 +3,7 @@ janet \- run the Janet language abstract machine .SH SYNOPSIS .B janet -[\fB\-hvsrpnqk\fR] +[\fB\-hvsrpnqik\fR] [\fB\-e\fR \fISOURCE\fR] [\fB\-E\fR \fISOURCE ...ARGUMENTS\fR] [\fB\-l\fR \fIMODULE\fR] @@ -213,6 +213,11 @@ Precompiles Janet source code into an image, a binary dump that can be efficient Source should be a path to the Janet module to compile, and output should be the file path of resulting image. Output should usually end with the .jimage extension. +.TP +.BR \-i +When this flag is passed, a script passed to the interpreter will be treated as a janet image file +rather than a janet source file. + .TP .BR \-l\ lib Import a Janet module before running a script or repl. Multiple files can be loaded diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 94bc37ff..4e312b7e 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -3508,6 +3508,12 @@ # conditional compilation for reduced os (def- getenv-alias (if-let [entry (in root-env 'os/getenv)] (entry :value) (fn [&]))) +(defn- run-main + [env subargs arg] + (if-let [main (get (in env 'main) :value)] + (let [thunk (compile [main ;subargs] env arg)] + (if (function? thunk) (thunk) (error (thunk :error)))))) + (defn cli-main `Entrance for the Janet CLI tool. Call this function with the command line arguments as an array or tuple of strings to invoke the CLI interface.` @@ -3515,17 +3521,18 @@ (setdyn :args args) - (var *should-repl* false) - (var *no-file* true) - (var *quiet* false) - (var *raw-stdin* false) - (var *handleopts* true) - (var *exit-on-error* true) - (var *colorize* true) - (var *debug* false) - (var *compile-only* false) - (var *warn-level* nil) - (var *error-level* nil) + (var should-repl false) + (var no-file true) + (var quiet false) + (var raw-stdin false) + (var handleopts true) + (var exit-on-error true) + (var colorize true) + (var debug-flag false) + (var compile-only false) + (var warn-level nil) + (var error-level nil) + (var expect-image false) (if-let [jp (getenv-alias "JANET_PATH")] (setdyn :syspath jp)) (if-let [jprofile (getenv-alias "JANET_PROFILE")] (setdyn :profilepath jprofile)) @@ -3555,8 +3562,9 @@ -k : Compile scripts but do not execute (flycheck) -m syspath : Set system path for loading global modules -c source output : Compile janet source code into an image + -i : Load the script argument as an image file instead of source code -n : Disable ANSI color output in the REPL - -l lib : Import a module before processing more arguments + -l lib : Use a module before processing more arguments -w level : Set the lint warning level - default is "normal" -x level : Set the lint error level - default is "none" -- : Stop handling options @@ -3564,29 +3572,31 @@ (os/exit 0) 1) "v" (fn [&] (print janet/version "-" janet/build) (os/exit 0) 1) - "s" (fn [&] (set *raw-stdin* true) (set *should-repl* true) 1) - "r" (fn [&] (set *should-repl* true) 1) - "p" (fn [&] (set *exit-on-error* false) 1) - "q" (fn [&] (set *quiet* true) 1) - "k" (fn [&] (set *compile-only* true) (set *exit-on-error* false) 1) - "n" (fn [&] (set *colorize* false) 1) + "s" (fn [&] (set raw-stdin true) (set should-repl true) 1) + "r" (fn [&] (set should-repl true) 0) + "p" (fn [&] (set exit-on-error false) 1) + "q" (fn [&] (set quiet true) 1) + "i" (fn [&] (set expect-image true) 1) + "k" (fn [&] (set compile-only true) (set exit-on-error false) 1) + "n" (fn [&] (set colorize false) 1) "m" (fn [i &] (setdyn :syspath (in args (+ i 1))) 2) "c" (fn c-switch [i &] - (def e (dofile (in args (+ i 1)))) + (def path (in args (+ i 1))) + (def e (dofile path)) (spit (in args (+ i 2)) (make-image e)) - (set *no-file* false) + (set no-file false) 3) - "-" (fn [&] (set *handleopts* false) 1) + "-" (fn [&] (set handleopts false) 1) "l" (fn l-switch [i &] (import* (in args (+ i 1)) - :prefix "" :exit *exit-on-error*) + :prefix "" :exit exit-on-error) 2) "e" (fn e-switch [i &] - (set *no-file* false) + (set no-file false) (eval-string (in args (+ i 1))) 2) "E" (fn E-switch [i &] - (set *no-file* false) + (set no-file false) (def subargs (array/slice args (+ i 2))) (def src ~|,(parse (in args (+ i 1)))) (def thunk (compile src)) @@ -3594,9 +3604,9 @@ ((thunk) ;subargs) (error (get thunk :error))) math/inf) - "d" (fn [&] (set *debug* true) 1) - "w" (fn [i &] (set *warn-level* (get-lint-level i)) 2) - "x" (fn [i &] (set *error-level* (get-lint-level i)) 2) + "d" (fn [&] (set debug-flag true) 1) + "w" (fn [i &] (set warn-level (get-lint-level i)) 2) + "x" (fn [i &] (set error-level (get-lint-level i)) 2) "R" (fn [&] (setdyn :profilepath nil) 1)}) (defn- dohandler [n i &] @@ -3608,29 +3618,37 @@ (def lenargs (length args)) (while (< i lenargs) (def arg (in args i)) - (if (and *handleopts* (= "-" (string/slice arg 0 1))) + (if (and handleopts (= "-" (string/slice arg 0 1))) (+= i (dohandler (string/slice arg 1) i)) (do - (set *no-file* false) - (def env (make-env)) (def subargs (array/slice args i)) - (put env :args subargs) - (put env :lint-error *error-level*) - (put env :lint-warn *warn-level*) - (if *compile-only* - (flycheck arg :exit *exit-on-error* :env env) + (set no-file false) + (if expect-image (do - (dofile arg :exit *exit-on-error* :env env) - (if-let [main (get (in env 'main) :value)] - (let [thunk (compile [main ;(tuple/slice args i)] env arg)] - (if (function? thunk) (thunk) (error (thunk :error))))))) + (def env (load-image (slurp arg))) + (put env :args subargs) + (put env :lint-error error-level) + (put env :lint-warn warn-level) + (if debug-flag (put env :debug true)) + (run-main env subargs arg)) + (do + (def env (make-env)) + (put env :args subargs) + (put env :lint-error error-level) + (put env :lint-warn warn-level) + (if debug-flag (put env :debug true)) + (if compile-only + (flycheck arg :exit exit-on-error :env env) + (do + (dofile arg :exit exit-on-error :env env) + (run-main env subargs arg))))) (set i lenargs)))) - (if (or *should-repl* *no-file*) + (if (or should-repl no-file) (if - *compile-only* (flycheck stdin :source "stdin" :exit *exit-on-error*) + compile-only (flycheck stdin :source "stdin" :exit exit-on-error) (do - (if-not *quiet* + (if-not quiet (print "Janet " janet/version "-" janet/build " " (os/which) "/" (os/arch) " - '(doc)' for help")) (flush) (defn getprompt [p] @@ -3644,15 +3662,15 @@ (when-let [profile.janet (dyn :profilepath)] (def new-env (dofile profile.janet :exit true)) (merge-module env new-env "" false)) - (if *debug* (put env :debug true)) - (def getter (if *raw-stdin* getstdin getline)) + (if debug-flag (put env :debug true)) + (def getter (if raw-stdin getstdin getline)) (defn getchunk [buf p] (getter (getprompt p) buf env)) - (setdyn :pretty-format (if *colorize* "%.20Q" "%.20q")) - (setdyn :err-color (if *colorize* true)) - (setdyn :doc-color (if *colorize* true)) - (setdyn :lint-error *error-level*) - (setdyn :lint-warn *error-level*) + (setdyn :pretty-format (if colorize "%.20Q" "%.20q")) + (setdyn :err-color (if colorize true)) + (setdyn :doc-color (if colorize true)) + (setdyn :lint-error error-level) + (setdyn :lint-warn error-level) (repl getchunk nil env))))) ###