diff --git a/CHANGES.md b/CHANGES.md index 04101839..e75cccb9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,10 +2,9 @@ ## Breaking changes -## v0.0.44 -- #173: Rename `*in*` to `` (in the `user` namespace). The name - was a poor choice for two reasons. It shadowed `clojure.core/*in*`. Also, the - value was not a dynamic var, but the earmuffs suggested otherwise. +## v0.0.44 - 0.0.45 +- #173: Rename `*in*` to `*input*` (in the `user` namespace). The reason for + this is that itt shadowed `clojure.core/*in*` when used unqualified. ## v0.0.43 - #160: Add support for `java.lang.ProcessBuilder`. See docs. This replaces the diff --git a/README.md b/README.md index f904be78..f2e977a9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A Clojure [babushka](https://en.wikipedia.org/wiki/Headscarf) for the grey areas ``` shellsession $ bash <(curl -s https://raw.githubusercontent.com/borkdude/babashka/master/install) -$ ls | bb --time -i '(filter #(-> % io/file .isDirectory) )' +$ ls | bb --time -i '(filter #(-> % io/file .isDirectory) *input*)' ("doc" "resources" "sci" "script" "src" "target" "test") bb took 4ms. ``` @@ -64,29 +64,29 @@ on [CHANGES.md](CHANGES.md) for a list of breaking changes. ## Examples ``` shellsession -$ ls | bb -i '' +$ ls | bb -i '*input*' ["LICENSE" "README.md" "bb" "doc" "pom.xml" "project.clj" "reflection.json" "resources" "script" "src" "target" "test"] -$ ls | bb -i '(count )' +$ ls | bb -i '(count *input*)' 12 -$ bb '(vec (dedupe ))' <<< '[1 1 1 1 2]' +$ bb '(vec (dedupe *input*))' <<< '[1 1 1 1 2]' [1 2] -$ bb '(filterv :foo )' <<< '[{:foo 1} {:bar 2}]' +$ bb '(filterv :foo *input*)' <<< '[{:foo 1} {:bar 2}]' [{:foo 1}] -$ bb '(#(+ %1 %2 %3) 1 2 )' <<< 3 +$ bb '(#(+ %1 %2 %3) 1 2 *input*)' <<< 3 6 -$ ls | bb -i '(filterv #(re-find #"reflection" %) )' +$ ls | bb -i '(filterv #(re-find #"reflection" %) *input*)' ["reflection.json"] $ bb '(run! #(shell/sh "touch" (str "/tmp/test/" %)) (range 100))' -$ ls /tmp/test | bb -i '' +$ ls /tmp/test | bb -i '*input*' ["0" "1" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "2" "20" "21" ...] -$ bb -O '(repeat "dude")' | bb --stream '(str "rino")' | bb -I '(take 3 )' +$ bb -O '(repeat "dude")' | bb --stream '(str *input* "rino")' | bb -I '(take 3 *input*)' ("duderino" "duderino" "duderino") ``` @@ -143,12 +143,12 @@ Options: --help, -h or -? Print this help text. --version Print the current version of babashka. - -i Bind to a lazy seq of lines from stdin. - -I Bind to a lazy seq of EDN values from stdin. + -i Bind *input* to a lazy seq of lines from stdin. + -I Bind *input* to a lazy seq of EDN values from stdin. -o Write lines to stdout. -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 becomes a single value per iteration. + --stream Stream over lines or EDN values from stdin. Combined with -i or -I *input* becomes a single value per iteration. -e, --eval Evaluate an expression. -f, --file Evaluate a file. -cp, --classpath Classpath to use. @@ -221,13 +221,13 @@ conditionals](#reader-conditionals) to maintain compatibility with JVM Clojure. ### Input and output flags -In one-liners the `` value may come in handy. It contains the input read from stdin as EDN by default. If you want to read in text, use the `-i` flag, which binds `` to a lazy seq of lines of text. If you want to read multiple EDN values, use the `-I` flag. The `-o` option prints the result as lines of text. The `-O` option prints the result as lines of EDN values. +In one-liners the `*input*` value may come in handy. It contains the input read from stdin as EDN by default. If you want to read in text, use the `-i` flag, which binds `*input*` to a lazy seq of lines of text. If you want to read multiple EDN values, use the `-I` flag. The `-o` option prints the result as lines of text. The `-O` option prints the result as lines of EDN values. The following table illustrates the combination of options for commands of the form - echo "{{Input}}" | bb {{Input flags}} {{Output flags}} "" + echo "{{Input}}" | bb {{Input flags}} {{Output flags}} "*input*" -| Input | Input flags | Output flag | `` | Output | +| Input | Input flags | Output flag | `*input*` | Output | |----------------|-------------|-------------|---------------|----------| | `{:a 1}`
`{:a 2}` | | | `{:a 1}` | `{:a 1}` | | hello
bye | `-i` | | `("hello" "bye")` | `("hello" "bye")` | @@ -238,7 +238,7 @@ The following table illustrates the combination of options for commands of the f When combined with the `--stream` option, the script is executed for each value in the input: ``` clojure -$ echo '{:a 1} {:a 2}' | bb --stream '' +$ echo '{:a 1} {:a 2}' | bb --stream '*input*' {:a 1} {:a 2} ``` @@ -361,7 +361,7 @@ export BABASHKA_PRELOADS Note that you can concatenate multiple expressions. Now you can use these functions in babashka: ``` shellsession -$ bb '(-> (foo ) bar)' <<< 1 +$ bb '(-> (foo *input*) bar)' <<< 1 6 ``` @@ -371,7 +371,7 @@ You can also preload an entire file using `load-file`: export BABASHKA_PRELOADS='(load-file "my_awesome_prelude.clj")' ``` -Note that `` is not available in preloads. +Note that `*input*` is not available in preloads. ## Classpath @@ -601,7 +601,7 @@ welcome! ### Delete a list of files returned by a Unix command ``` -find . | grep conflict | bb -i '(doseq [f ] (.delete (io/file f)))' +find . | grep conflict | bb -i '(doseq [f *input*] (.delete (io/file f)))' ``` ### Calculate aggregate size of directory @@ -635,7 +635,7 @@ $ cat /tmp/test.txt 3 Babashka 4 Goodbye -$ < /tmp/test.txt bb -io '(shuffle )' +$ < /tmp/test.txt bb -io '(shuffle *input*)' 3 Babashka 2 Clojure 4 Goodbye @@ -649,7 +649,7 @@ For converting JSON to EDN, see [jet](https://github.com/borkdude/jet). ``` shellsession $ curl -s https://api.github.com/repos/borkdude/babashka/tags | jet --from json --keywordize --to edn | -bb '(-> first :name (subs 1))' +bb '(-> *input* first :name (subs 1))' "0.0.4" ``` @@ -658,8 +658,8 @@ bb '(-> first :name (subs 1))' ``` shellsession $ curl -s https://api.github.com/repos/borkdude/babashka/releases | jet --from json --keywordize | -bb '(-> first :assets)' | -bb '(some #(re-find #".*linux.*" (:browser_download_url %)) )' +bb '(-> *input* first :assets)' | +bb '(some #(re-find #".*linux.*" (:browser_download_url %)) *input*)' "https://github.com/borkdude/babashka/releases/download/v0.0.4/babashka-0.0.4-linux-amd64.zip" ``` @@ -669,7 +669,7 @@ Contributed by [@plexus](https://github.com/plexus). ``` shellsession $ curl https://clojars.org/stats/all.edn | -bb -o '(for [[[group art] counts] ] (str (reduce + (vals counts)) " " group "/" art))' | +bb -o '(for [[[group art] counts] *input*] (str (reduce + (vals counts)) " " group "/" art))' | sort -rn | less 14113842 clojure-complete/clojure-complete @@ -722,7 +722,7 @@ Contributed by [@plexus](https://github.com/plexus). ``` shellsession $ cat project.clj | sed -e 's/#=//g' -e 's/~@//g' -e 's/~//g' | -bb '(let [{:keys [dependencies source-paths resource-paths]} (apply hash-map (drop 3 ))] +bb '(let [{:keys [dependencies source-paths resource-paths]} (apply hash-map (drop 3 *input*))] {:paths (into source-paths resource-paths) :deps (into {} (for [[d v] dependencies] [d {:mvn/version v}]))}) ' | jet --pretty > deps.edn diff --git a/sci b/sci index 76502d11..27893200 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 76502d1116701264e85b702e8c501c1631feba4b +Subproject commit 278932006626278a29b2ce4307d332531ff8af9d diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 8ee62708..2b8e26dc 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -138,12 +138,12 @@ (println " --help, -h or -? Print this help text. --version Print the current version of babashka. - -i Bind to a lazy seq of lines from stdin. - -I Bind to a lazy seq of EDN values from stdin. + -i Bind *input* to a lazy seq of lines from stdin. + -I Bind *input* to a lazy seq of EDN values from stdin. -o Write lines to stdout. -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 becomes a single value per iteration. + --stream Stream over lines or EDN values from stdin. Combined with -i or -I *input* becomes a single value per iteration. -e, --eval Evaluate an expression. -f, --file Evaluate a file. -cp, --classpath Classpath to use. @@ -176,16 +176,16 @@ Everything after that is bound to *command-line-args*.")) (defn start-repl! [ctx read-next] (let [ctx (update ctx :bindings assoc - (with-meta ' - {:sci/deref! true}) - (read-next))] + (with-meta '*input* + {:sci.impl/deref! true}) + (sci/new-dynamic-var '*input* (read-next)))] (repl/start-repl! ctx))) (defn start-socket-repl! [address ctx read-next] (let [ctx (update ctx :bindings assoc - (with-meta ' - {:sci/deref! true}) - (read-next))] + (with-meta '*input* + {:sci.impl/deref! true}) + (sci/new-dynamic-var '*input* (read-next)))] (socket-repl/start-repl! address ctx) ;; hang until SIGINT @(promise))) @@ -296,9 +296,10 @@ Everything after that is bound to *command-line-args*.")) (let [expr (if file (read-file file) expression)] (if expr (loop [in (read-next *in*)] - (let [ctx (update-in ctx [:namespaces 'user] assoc (with-meta ' + (let [ctx (update-in ctx [:namespaces 'user] assoc (with-meta '*input* (when-not stream? - {:sci/deref! true})) in)] + {:sci.impl/deref! true})) + (sci/new-dynamic-var '*input* in))] (if (identical? ::EOF in) [nil 0] ;; done streaming (let [res [(let [res (eval-string expr ctx)] diff --git a/test/babashka/impl/repl_test.clj b/test/babashka/impl/repl_test.clj index dfe49c74..9d49344c 100644 --- a/test/babashka/impl/repl_test.clj +++ b/test/babashka/impl/repl_test.clj @@ -7,8 +7,8 @@ (set! *warn-on-reflection* true) (defn repl! [] - (start-repl! {:bindings {(with-meta ' - {:sci/deref! true}) + (start-repl! {:bindings {(with-meta '*input* + {:sci.impl/deref! true}) (delay [1 2 3]) '*command-line-args* ["a" "b" "c"]} @@ -27,7 +27,7 @@ (assert-repl "1\n(dec *1)(+ *2 *2)" "2") (assert-repl "1\n(dec *1)(+ *2 *2)" "2") (assert-repl "*command-line-args*" "[\"a\" \"b\" \"c\"]") - (assert-repl "" "[1 2 3]")) + (assert-repl "*input*" "[1 2 3]")) ;;;; Scratch diff --git a/test/babashka/impl/socket_repl_test.clj b/test/babashka/impl/socket_repl_test.clj index ad04df74..9ff3f86d 100644 --- a/test/babashka/impl/socket_repl_test.clj +++ b/test/babashka/impl/socket_repl_test.clj @@ -31,8 +31,8 @@ (deftest socket-repl-test (try (if tu/jvm? - (start-repl! "0.0.0.0:1666" {:bindings {(with-meta ' - {:sci/deref! true}) + (start-repl! "0.0.0.0:1666" {:bindings {(with-meta '*input* + {:sci.impl/deref! true}) (delay [1 2 3]) '*command-line-args* ["a" "b" "c"]} @@ -47,8 +47,8 @@ (sh "bash" "-c" "lsof -t -i:1666")))))) (is (socket-command "(+ 1 2 3)" "user=> 6")) - (testing "" - (is (socket-command "" "[1 2 3]"))) + (testing "*input*" + (is (socket-command "*input*" "[1 2 3]"))) (testing "*command-line-args*" (is (socket-command '*command-line-args* "\"a\" \"b\" \"c\""))) (testing "&env" @@ -72,7 +72,7 @@ (dotimes [_ 1000] (t/run-tests)) (stop-repl!) - (start-repl! "0.0.0.0:1666" {:bindings {(with-meta ' + (start-repl! "0.0.0.0:1666" {:bindings {(with-meta '*input* {:sci/deref! true}) (delay [1 2 3]) '*command-line-args* diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index e4286ebd..e0ad025f 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -34,45 +34,45 @@ (deftest main-test (testing "-io behaves as identity" - (= "foo\nbar\n" (test-utils/bb "foo\nbar\n" "-io" ""))) + (= "foo\nbar\n" (test-utils/bb "foo\nbar\n" "-io" "*input*"))) (testing "if and when" - (is (= 1 (bb 0 '(if (zero? ) 1 2)))) - (is (= 2 (bb 1 '(if (zero? ) 1 2)))) - (is (= 1 (bb 0 '(when (zero? ) 1)))) - (is (nil? (bb 1 '(when (zero? ) 1))))) + (is (= 1 (bb 0 '(if (zero? *input*) 1 2)))) + (is (= 2 (bb 1 '(if (zero? *input*) 1 2)))) + (is (= 1 (bb 0 '(when (zero? *input*) 1)))) + (is (nil? (bb 1 '(when (zero? *input*) 1))))) (testing "and and or" - (is (= false (bb 0 '(and false true )))) - (is (= 0 (bb 0 '(and true true )))) - (is (= 1 (bb 1 '(or false false )))) - (is (= false (bb false '(or false false )))) - (is (= 3 (bb false '(or false false 3))))) + (is (= false (bb 0 '(and false true *input*)))) + (is (= 0 (bb 0 '(and true true *input*)))) + (is (= 1 (bb 1 '(or false false *input*)))) + (is (= false (bb false '(or false false *input*)))) + (is (= 3 (bb false '(or false false *input* 3))))) (testing "fn" - (is (= 2 (bb 1 "(#(+ 1 %) )"))) + (is (= 2 (bb 1 "(#(+ 1 %) *input*)"))) (is (= [1 2 3] (bb 1 "(map #(+ 1 %) [0 1 2])"))) - (is (= 1 (bb 1 "(#(when (odd? ) ))")))) + (is (= 1 (bb 1 "(#(when (odd? *input*) *input*))")))) (testing "map" (is (= [1 2 3] (bb 1 '(map inc [0 1 2]))))) (testing "keep" (is (= [false true false] (bb 1 '(keep odd? [0 1 2]))))) (testing "->" - (is (= 4 (bb 1 '(-> inc inc (inc)))))) + (is (= 4 (bb 1 '(-> *input* inc inc (inc)))))) (testing "->>" - (is (= 10 (edn/read-string (test-utils/bb "foo\n\baar\baaaaz" "-i" "(->> (map count) (apply max))"))))) + (is (= 10 (edn/read-string (test-utils/bb "foo\n\baar\baaaaz" "-i" "(->> *input* (map count) (apply max))"))))) (testing "literals" (is (= {:a 4 :b {:a 2} :c [1 1] :d #{1 2}} - (bb 1 '{:a (+ 1 2 ) - :b {:a (inc )} - :c [ ] - :d #{ (inc )}})))) + (bb 1 '{:a (+ 1 2 *input*) + :b {:a (inc *input*)} + :c [*input* *input*] + :d #{*input* (inc *input*)}})))) (testing "shuffle the contents of a file" (let [in "foo\n Clojure is nice. \nbar\n If you're nice to clojure. " in-lines (set (str/split in #"\n")) out (test-utils/bb in "-io" - (str '(shuffle ))) + (str '(shuffle *input*))) out-lines (set (str/split out #"\n"))] (is (= in-lines out-lines)))) (testing "find occurrences in file by line number" @@ -80,14 +80,14 @@ (-> (bb "foo\n Clojure is nice. \nbar\n If you're nice to clojure. " "-i" - "(map-indexed #(-> [%1 %2]) )") - (bb "(keep #(when (re-find #\"(?i)clojure\" (second %)) (first %)) )")))))) + "(map-indexed #(-> [%1 %2]) *input*)") + (bb "(keep #(when (re-find #\"(?i)clojure\" (second %)) (first %)) *input*)")))))) (deftest println-test (is (= "hello\n" (test-utils/bb nil "(println \"hello\")")))) (deftest input-test - (testing "bb doesn't wait for input if isn't used" + (testing "bb doesn't wait for input if *input* isn't used" (is (= "2\n" (with-out-str (main/main "(inc 1)")))))) (deftest System-test @@ -114,12 +114,12 @@ (is (re-find #"doctype html" resp)))) (deftest stream-test - (is (= "2\n3\n4\n" (test-utils/bb "1 2 3" "--stream" "(inc )"))) - (is (= "2\n3\n4\n" (test-utils/bb "{:x 2} {:x 3} {:x 4}" "--stream" "(:x )"))) + (is (= "2\n3\n4\n" (test-utils/bb "1 2 3" "--stream" "(inc *input*)"))) + (is (= "2\n3\n4\n" (test-utils/bb "{:x 2} {:x 3} {:x 4}" "--stream" "(:x *input*)"))) (let [x "foo\n\bar\n"] - (is (= x (test-utils/bb x "--stream" "-io" "")))) + (is (= x (test-utils/bb x "--stream" "-io" "*input*")))) (let [x "f\n\b\n"] - (is (= x (test-utils/bb x "--stream" "-io" "(subs 0 1)"))))) + (is (= x (test-utils/bb x "--stream" "-io" "(subs *input* 0 1)"))))) (deftest load-file-test (let [tmp (java.io.File/createTempFile "script" ".clj")] @@ -145,21 +145,21 @@ (deftest pipe-test (when test-utils/native? (let [out (:out (sh "bash" "-c" "./bb -o '(range)' | - ./bb --stream '(* )' | + ./bb --stream '(* *input* *input*)' | head -n10")) out (str/split-lines out) out (map edn/read-string out)] (is (= (take 10 (map #(* % %) (range))) out)))) (when test-utils/native? (let [out (:out (sh "bash" "-c" "./bb -O '(repeat \"dude\")' | - ./bb --stream '(str \"rino\")' | - ./bb -I '(take 3 )'")) + ./bb --stream '(str *input* \"rino\")' | + ./bb -I '(take 3 *input*)'")) out (edn/read-string out)] (is (= '("duderino" "duderino" "duderino") out))))) (deftest lazy-text-in-test (when test-utils/native? - (let [out (:out (sh "bash" "-c" "yes | ./bb -i '(take 2 )'")) + (let [out (:out (sh "bash" "-c" "yes | ./bb -i '(take 2 *input*)'")) out (edn/read-string out)] (is (= '("y" "y") out))))) @@ -311,6 +311,10 @@ (deftest Thread-test (is (= "hello" (bb nil "(doto (java.lang.Thread. (fn [] (prn \"hello\"))) (.start) (.join)) nil")))) +(deftest dynvar-test + (is (= 1 (bb nil "(binding [*command-line-args* 1] *command-line-args*)"))) + (is (= 1 (bb nil "(binding [*input* 1] *input*)")))) + ;;;; Scratch (comment