Skip to content
Permalink
Browse files

v0.0.7

  • Loading branch information...
borkdude committed Aug 13, 2019
1 parent aa8a66c commit a0cd0b58d8baccec3d3977304b75446e0c3ab046
Showing with 138 additions and 40 deletions.
  1. +19 −4 README.md
  2. +1 −1 project.clj
  3. +31 −7 reflection.json
  4. +1 −1 resources/BABASHKA_VERSION
  5. +3 −1 script/compile
  6. +1 −1 script/test
  7. +75 −23 src/babashka/main.clj
  8. +6 −1 test/babashka/main_test.clj
  9. +1 −1 test/babashka/test_utils.clj
@@ -17,7 +17,7 @@ $ bb '(vec (dedupe *in*))' <<< '[1 1 1 1 2]'
## Rationale

If you're a bash expert, you probably don't need this. But for those of us who
can use a bit of Clojure in their shell scripts, it may be useful.
scan use a bit of Clojure in their shell scripts, it may be useful.

Properties:

@@ -66,7 +66,7 @@ You may also download a binary from [Github](https://github.com/borkdude/babashk
## Usage

``` shellsession
... | bb [-i] [-o] '<Clojure form>'
bb [ --help ] [ -i ] [ -o ] [ -io ] [ --version ] [ expression ]
```

There is one special variable, `*in*`, which is the input read from stdin. The
@@ -77,8 +77,14 @@ shell-scripting friendly output. To combine `-i` and `-o` you can use `-io`.

The current version can be printed with `bb --version`.

Currently only the macros `if`, `when`, `and`, `or`, `->`, `->>` and `as->` are
supported.
Currently only the following special forms/macros are supported: anonymous
function literals like `#(%1 %2)`, `quote`, `do`,`if`, `when`, `let`, `and`,
`or`, `->`, `->>`, `as->`.

The `clojure.core` functions are accessible without a namespace alias. Those in
`clojure.string` are accessed through the alias `str`, like:
`str/includes?`. Those in `clojure.set` using the alias `set`, like:
`set/difference`.

Examples:

@@ -109,6 +115,15 @@ $ ls | bb -i '(filterv #(re-find #"reflection" %) *in*)'
["reflection.json"]
```

Shell commands can be executed using `csh` which is an alias for
`clojure.java.shell/sh`:

``` shellsession
$ bb '(run! #(csh "touch" (str "/tmp/test/" %)) (range 100))'
$ ls /tmp/test | bb -i '*in*'
["0" "1" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "2" "20" "21" ...]
```

More examples can be found in the [gallery](#gallery).

## Test
@@ -9,7 +9,7 @@
:url "http://opensource.org/licenses/eclipse-1.0.php"}
:source-paths ["src"]
:dependencies [[org.clojure/clojure "1.9.0"]
[borkdude/sci "0.0.2"]]
[borkdude/sci "0.0.4"]]
:profiles {:clojure-1.9.0 {:dependencies [[org.clojure/clojure "1.9.0"]]}
:clojure-1.10.1 {:dependencies [[org.clojure/clojure "1.10.1"]]}
:test {:dependencies [[clj-commons/conch "0.9.2"]]}
@@ -1,9 +1,33 @@
[
{
"name": "java.lang.Class",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true
}
{
"name": "java.lang.Class",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true
},
{
"name":"java.io.BufferedReader",
"allPublicMethods":true
},
{
"name":"java.lang.Process",
"allPublicMethods":true
},
{
"name":"java.lang.ProcessBuilder",
"allPublicConstructors":true
},
{
"name":"java.lang.String",
"allPublicMethods":true
},
{
"name":"java.lang.UNIXProcess",
"allPublicMethods":true
},
{
"name":"java.util.concurrent.LinkedBlockingQueue",
"allPublicMethods":true
}
]
@@ -1 +1 @@
0.0.7-SNAPSHOT
0.0.7
@@ -17,8 +17,10 @@ $GRAALVM_HOME/bin/native-image \
-J-Dclojure.spec.skip-macros=true \
-J-Dclojure.compiler.direct-linking=true \
"-H:IncludeResources=BABASHKA_VERSION" \
"-H:IncludeResources=SCI_VERSION" \
-H:ReflectionConfigurationFiles=reflection.json \
--initialize-at-build-time \
--initialize-at-run-time=java.lang.Math\$RandomNumberGeneratorHolder \
--initialize-at-build-time \
-H:Log=registerResource: \
--verbose \
--no-fallback \
@@ -2,7 +2,7 @@

set -eo pipefail

if [ "$JET_TEST_ENV" = "native" ]; then
if [ "$BABASHKA_TEST_ENV" = "native" ]; then
lein test
else
echo "Testing with Clojure 1.9.0"
@@ -3,11 +3,15 @@
(:require
[clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.java.shell :as cjs]
[clojure.string :as str :refer [starts-with?]]
[sci.core :as sci])
(:gen-class))

(set! *warn-on-reflection* true)
;; To detect problems when generating the image, run:
;; echo '1' | java -agentlib:native-image-agent=config-output-dir=/tmp -jar target/babashka-xxx-standalone.jar '...'
;; with the java provided by GraalVM.

(defn read-edn [s]
(edn/read-string
@@ -33,35 +37,83 @@
(get opts "-io")))
raw-out (boolean (or (get opts "-o")
(get opts "-io")))
println? (boolean (get opts "--println"))]
println? (boolean (get opts "--println"))
help? (boolean (get opts "--help"))]
{:version version
:raw-in raw-in
:raw-out raw-out
:println? println?}))
:println? println?
:help? help?}))

(defn parse-shell-string [s]
(str/split s #"\n"))

(defn print-version []
(println (str "babashka v"(str/trim (slurp (io/resource "BABASHKA_VERSION"))))))

(def usage-string "Usage: [ --help ] [ -i ] [ -o ] [ -io ] [ --version ] [ expression ]")
(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 "
--help: print this help text.
--version: print the current version of babashka.
-i: read shell input into a list of strings instead of reading EDN.
-o: write shell output instead of EDN.
-io: combination of -i and -o.
"))

(defn main
[& args]
(or
(let [{:keys [:version :raw-in :raw-out :println?
:help?]} (parse-opts args)]
(second
(cond version
[(print-version) 0]
help?
[(print-help) 0]
:else
(try
[(let [exprs (drop-while #(str/starts-with? % "-") args)
_ (when (not= (count exprs) 1)
(throw (Exception. ^String usage-string)))
expr (last args)
in (delay (let [in (slurp *in*)]
(if raw-in
(parse-shell-string in)
(read-edn in))))
res (sci/eval-string
expr
{:bindings {(with-meta '*in*
{:sci/deref! true}) in
'run! run!
'csh cjs/sh}})]
(if raw-out
(if (coll? res)
(doseq [l res]
(println l))
(println res))
((if println? println? prn) res))) 0]
(catch Exception e
(binding [*out* *err*]
(println (str/trim
(or (:stderr (ex-data e))
(.getMessage e))) ))
[nil 1])))))
1))

(defn -main
[& args]
(let [{:keys [:version :raw-in :raw-out :println?]} (parse-opts args)]
(cond version
(println (str/trim (slurp (io/resource "BABASHKA_VERSION"))))
:else
(let [expr (last args)
in (slurp *in*)
in (if raw-in
(str/split in #"\n")
(read-edn in))
;; _ (prn in)
res (try (sci/eval-string expr {:bindings {'*in* in}})
(catch Exception e
(binding [*out* *err*]
(println (.getMessage e)))
(System/exit 1)))]
(if raw-out
(if (coll? res)
(doseq [l res]
(println l))
(println res))
((if println? println? prn) res))))))
(System/exit (apply main args)))

;;;; Scratch

@@ -2,6 +2,7 @@
(:require
[clojure.test :as test :refer [deftest is testing]]
[babashka.test-utils :as test-utils]
[babashka.main :as main]
[clojure.edn :as edn]
[clojure.string :as str]))

@@ -50,11 +51,15 @@
"-io"
(str '(shuffle *in*)))
out-lines (set (str/split out #"\n"))]
(= in-lines out-lines)))
(is (= in-lines out-lines))))
(testing "find occurrences in file by line number"
(is (= '(1 3)
(->
(bb "foo\n Clojure is nice. \nbar\n If you're nice to clojure. "
"-i"
"(map-indexed #(-> [%1 %2]) *in*)")
(bb "(keep #(when (re-find #\"(?i)clojure\" (second %)) (first %)) *in*)"))))))

(deftest input-test
(testing "bb doesn't wait for input if *in* isn't used"
(is (= "2\n" (with-out-str (main/main "(inc 1)"))))))
@@ -8,7 +8,7 @@
(defn bb-jvm [input & args]
(with-out-str
(with-in-str input
(apply main/-main args))))
(apply main/main args))))

(defn bb-native [input & args]
(let-programs [bb "./bb"]

0 comments on commit a0cd0b5

Please sign in to comment.
You can’t perform that action at this time.