support functions and raw input
This commit is contained in:
parent
b46d163eb6
commit
be91fdabde
4 changed files with 67 additions and 17 deletions
23
README.md
23
README.md
|
|
@ -37,13 +37,23 @@ You may also download a binary from [Github](https://github.com/borkdude/babashk
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The first argument to `bb` is the form to be executed. There is one special
|
The first argument to `bb` is the form to be executed. There is one special
|
||||||
variable, `*in*`.
|
variable, `*in*` which is EDN that is piped from stdin.
|
||||||
|
|
||||||
If the first argument is `--version`, then `bb` will print the version and exit.
|
If the first argument is `--version`, then `bb` will print the version and exit.
|
||||||
|
If the first argument is `--raw`, then `bb` will interpret stdin as string input.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
``` shellsession
|
``` shellsession
|
||||||
|
$ ls | bb --raw '*in*'
|
||||||
|
["LICENSE" "README.md" "bb" "doc" "pom.xml" "project.clj" "reflection.json" "resources" "script" "src" "target" "test"]
|
||||||
|
|
||||||
|
$ ls | bb --raw '*in*' | bb '(count *in*)'
|
||||||
|
11
|
||||||
|
|
||||||
|
$ ls | bb --raw '*in*' | bb '(count *in*)'
|
||||||
|
11
|
||||||
|
|
||||||
$ echo 1 | bb '(inc *in*)'
|
$ echo 1 | bb '(inc *in*)'
|
||||||
2
|
2
|
||||||
|
|
||||||
|
|
@ -60,6 +70,17 @@ $ echo '"babashka"' | bb '(re-find (re-pattern "b.b.*") *in*)'
|
||||||
"babashka"
|
"babashka"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Functions are written using the reader tag `#bb/fn`. Currently up to three
|
||||||
|
arguments are supported.
|
||||||
|
|
||||||
|
``` shellsession
|
||||||
|
$ echo '' | bb '(#bb/fn (+ %1 %2) 1 2)'
|
||||||
|
3
|
||||||
|
|
||||||
|
$ ls | bb --raw '*in*' | bb '(filterv #bb/fn (re-find (re-pattern "reflection") %) *in*)'
|
||||||
|
["reflection.json"]
|
||||||
|
```
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|
||||||
Test the JVM version:
|
Test the JVM version:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
(ns babashka.interpreter
|
(ns babashka.interpreter
|
||||||
{:no-doc true}
|
{:no-doc true}
|
||||||
(:refer-clojure :exclude [comparator]))
|
(:refer-clojure :exclude [comparator])
|
||||||
|
(:require [clojure.walk :refer [postwalk]]))
|
||||||
|
|
||||||
(defn safe-nth [x n]
|
(defn safe-nth [x n]
|
||||||
(try (nth x n)
|
(try (nth x n)
|
||||||
|
|
@ -8,7 +9,7 @@
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
(def syms '(= < <= >= + +' - * /
|
(def syms '(= < <= >= + +' - * /
|
||||||
aget alength assoc assoc-in
|
aget alength apply assoc assoc-in
|
||||||
bit-set bit-shift-left bit-shift-right bit-xor boolean boolean? booleans boolean-array butlast
|
bit-set bit-shift-left bit-shift-right bit-xor boolean boolean? booleans boolean-array butlast
|
||||||
char char? conj cons contains? count
|
char char? conj cons contains? count
|
||||||
dec dec' decimal? dedupe dissoc distinct disj drop
|
dec dec' decimal? dedupe dissoc distinct disj drop
|
||||||
|
|
@ -17,15 +18,15 @@
|
||||||
first float? floats fnil
|
first float? floats fnil
|
||||||
identity inc int-array iterate
|
identity inc int-array iterate
|
||||||
juxt
|
juxt
|
||||||
filter find
|
filter filterv find
|
||||||
last line-seq
|
last line-seq
|
||||||
keep keep-indexed keys
|
keep keep-indexed keys
|
||||||
map map-indexed mapcat merge merge-with munge
|
map map-indexed mapcat merge merge-with munge
|
||||||
newline not= num
|
name newline not= num
|
||||||
neg? nth nthrest
|
neg? nth nthrest
|
||||||
peek pos?
|
peek pos?
|
||||||
re-seq re-find re-pattern rest reverse
|
re-seq re-find re-pattern rest reverse
|
||||||
safe-nth set? sequential? some?
|
safe-nth set? sequential? some? str
|
||||||
take take-last take-nth tree-seq type
|
take take-last take-nth tree-seq type
|
||||||
unchecked-inc-int unchecked-long unchecked-negate unchecked-remainder-int
|
unchecked-inc-int unchecked-long unchecked-negate unchecked-remainder-int
|
||||||
unchecked-subtract-int unsigned-bit-shift-right unchecked-float
|
unchecked-subtract-int unsigned-bit-shift-right unchecked-float
|
||||||
|
|
@ -37,7 +38,7 @@
|
||||||
#_(def all-syms
|
#_(def all-syms
|
||||||
'#{when-first while if-not when-let inc' cat StackTraceElement->vec flush take-while vary-meta <= alter -' if-some conj! repeatedly zipmap reset-vals! alter-var-root biginteger remove * re-pattern min pop! chunk-append prn-str with-precision format reversible? shutdown-agents conj bound? transduce lazy-seq *print-length* *file* compare-and-set! *use-context-classloader* await1 let ref-set pop-thread-bindings interleave printf map? -> defstruct *err* assert-same-protocol get doto identity into areduce long double volatile? definline nfirst meta find-protocol-impl bit-and-not *default-data-reader-fn* var? method-sig unchecked-add-int unquote-splicing hash-ordered-coll future reset-meta! Vec cycle fn seque empty? short definterface add-tap filterv hash quot ns-aliases read unchecked-double key longs not= string? uri? aset-double unchecked-multiply-int chunk-rest pcalls *allow-unresolved-vars* remove-all-methods ns-resolve as-> aset-boolean trampoline double? when-not *1 vec *print-meta* when int map-entry? ns-refers rand second vector-of hash-combine > replace int? associative? unchecked-int set-error-handler! inst-ms* keyword? force bound-fn* namespace-munge group-by prn extend unchecked-multiply some->> default-data-readers ->VecSeq even? unchecked-dec Inst tagged-literal? double-array in-ns create-ns re-matcher defn ref bigint extends? promise aset-char rseq ex-cause construct-proxy agent-errors *compile-files* ex-message *math-context* float pr-str concat aset-short set-agent-send-off-executor! ns symbol to-array-2d mod amap pop use VecNode unquote declare dissoc! reductions aset-byte indexed? ref-history-count - assoc! hash-set reduce-kv or cast reset! name ffirst sorted-set counted? byte-array IVecImpl tagged-literal println extend-type macroexpand-1 assoc-in char-name-string bit-test defmethod requiring-resolve EMPTY-NODE time memoize alter-meta! future? zero? simple-keyword? require unchecked-dec-int persistent! nnext add-watch not-every? class? rem agent-error some future-cancelled? memfn neg-int? struct-map drop *data-readers* nth sorted? nil? extend-protocol split-at *e load-reader random-sample cond-> dotimes select-keys bit-and bounded-count update list* reify update-in prefer-method aset-int *clojure-version* ensure-reduced *' instance? with-open mix-collection-hash re-find run! val defonce unchecked-add loaded-libs ->Vec bytes? not with-meta unreduced the-ns record? type identical? unchecked-divide-int ns-name max-key *unchecked-math* defn- *out* file-seq agent ns-map set-validator! ident? defprotocol swap! vals unchecked-subtract tap> *warn-on-reflection* sorted-set-by sync qualified-ident? assert *compile-path* true? release-pending-sends print empty remove-method *in* print-ctor letfn volatile! / read-line reader-conditional? bit-or clear-agent-errors vector proxy-super >= drop-last not-empty distinct partition loop add-classpath bit-flip long-array descendants merge accessor integer? mapv partition-all partition-by numerator object-array with-out-str condp derive load-string special-symbol? ancestors subseq error-handler gensym cond ratio? delay? intern print-simple flatten doubles halt-when with-in-str remove-watch ex-info ifn? some-> nat-int? proxy-name ns-interns all-ns find-protocol-method subvec for binding partial chunked-seq? find-keyword replicate min-key reduced char-escape-string re-matches array-map unchecked-byte with-local-vars ns-imports send-off defmacro every-pred keys rationalize load-file distinct? pos-int? extenders unchecked-short methods odd? ->ArrayChunk float-array *3 alias frequencies read-string proxy rsubseq inc get-method with-redefs uuid? bit-clear filter locking list + split-with aset ->VecNode keyword *ns* destructure *assert* defmulti chars str next hash-map if-let underive ref-max-history Throwable->map false? *print-readably* ints class some-fn case *flush-on-newline* to-array bigdec list? simple-ident? bit-not io! xml-seq VecSeq byte max == *agent* lazy-cat comment parents count supers *fn-loader* ArrayChunk sorted-map-by apply interpose deref assoc rational? transient clojure-version chunk-cons comparator sorted-map send drop-while proxy-call-with-super realized? char-array resolve compare complement *compiler-options* *print-dup* defrecord with-redefs-fn sequence constantly get-proxy-class make-array shorts completing update-proxy unchecked-negate-int hash-unordered-coll repeat unchecked-inc nthnext and create-struct get-validator number? await-for chunk-next print-str not-any? into-array qualified-symbol? init-proxy chunk-buffer seqable? symbol? when-some unchecked-char ->> future-cancel var-get commute coll? get-in fnext denominator bytes gen-and-load-class refer-clojure})
|
'#{when-first while if-not when-let inc' cat StackTraceElement->vec flush take-while vary-meta <= alter -' if-some conj! repeatedly zipmap reset-vals! alter-var-root biginteger remove * re-pattern min pop! chunk-append prn-str with-precision format reversible? shutdown-agents conj bound? transduce lazy-seq *print-length* *file* compare-and-set! *use-context-classloader* await1 let ref-set pop-thread-bindings interleave printf map? -> defstruct *err* assert-same-protocol get doto identity into areduce long double volatile? definline nfirst meta find-protocol-impl bit-and-not *default-data-reader-fn* var? method-sig unchecked-add-int unquote-splicing hash-ordered-coll future reset-meta! Vec cycle fn seque empty? short definterface add-tap filterv hash quot ns-aliases read unchecked-double key longs not= string? uri? aset-double unchecked-multiply-int chunk-rest pcalls *allow-unresolved-vars* remove-all-methods ns-resolve as-> aset-boolean trampoline double? when-not *1 vec *print-meta* when int map-entry? ns-refers rand second vector-of hash-combine > replace int? associative? unchecked-int set-error-handler! inst-ms* keyword? force bound-fn* namespace-munge group-by prn extend unchecked-multiply some->> default-data-readers ->VecSeq even? unchecked-dec Inst tagged-literal? double-array in-ns create-ns re-matcher defn ref bigint extends? promise aset-char rseq ex-cause construct-proxy agent-errors *compile-files* ex-message *math-context* float pr-str concat aset-short set-agent-send-off-executor! ns symbol to-array-2d mod amap pop use VecNode unquote declare dissoc! reductions aset-byte indexed? ref-history-count - assoc! hash-set reduce-kv or cast reset! name ffirst sorted-set counted? byte-array IVecImpl tagged-literal println extend-type macroexpand-1 assoc-in char-name-string bit-test defmethod requiring-resolve EMPTY-NODE time memoize alter-meta! future? zero? simple-keyword? require unchecked-dec-int persistent! nnext add-watch not-every? class? rem agent-error some future-cancelled? memfn neg-int? struct-map drop *data-readers* nth sorted? nil? extend-protocol split-at *e load-reader random-sample cond-> dotimes select-keys bit-and bounded-count update list* reify update-in prefer-method aset-int *clojure-version* ensure-reduced *' instance? with-open mix-collection-hash re-find run! val defonce unchecked-add loaded-libs ->Vec bytes? not with-meta unreduced the-ns record? type identical? unchecked-divide-int ns-name max-key *unchecked-math* defn- *out* file-seq agent ns-map set-validator! ident? defprotocol swap! vals unchecked-subtract tap> *warn-on-reflection* sorted-set-by sync qualified-ident? assert *compile-path* true? release-pending-sends print empty remove-method *in* print-ctor letfn volatile! / read-line reader-conditional? bit-or clear-agent-errors vector proxy-super >= drop-last not-empty distinct partition loop add-classpath bit-flip long-array descendants merge accessor integer? mapv partition-all partition-by numerator object-array with-out-str condp derive load-string special-symbol? ancestors subseq error-handler gensym cond ratio? delay? intern print-simple flatten doubles halt-when with-in-str remove-watch ex-info ifn? some-> nat-int? proxy-name ns-interns all-ns find-protocol-method subvec for binding partial chunked-seq? find-keyword replicate min-key reduced char-escape-string re-matches array-map unchecked-byte with-local-vars ns-imports send-off defmacro every-pred keys rationalize load-file distinct? pos-int? extenders unchecked-short methods odd? ->ArrayChunk float-array *3 alias frequencies read-string proxy rsubseq inc get-method with-redefs uuid? bit-clear filter locking list + split-with aset ->VecNode keyword *ns* destructure *assert* defmulti chars str next hash-map if-let underive ref-max-history Throwable->map false? *print-readably* ints class some-fn case *flush-on-newline* to-array bigdec list? simple-ident? bit-not io! xml-seq VecSeq byte max == *agent* lazy-cat comment parents count supers *fn-loader* ArrayChunk sorted-map-by apply interpose deref assoc rational? transient clojure-version chunk-cons comparator sorted-map send drop-while proxy-call-with-super realized? char-array resolve compare complement *compiler-options* *print-dup* defrecord with-redefs-fn sequence constantly get-proxy-class make-array shorts completing update-proxy unchecked-negate-int hash-unordered-coll repeat unchecked-inc nthnext and create-struct get-validator number? await-for chunk-next print-str not-any? into-array qualified-symbol? init-proxy chunk-buffer seqable? symbol? when-some unchecked-char ->> future-cancel var-get commute coll? get-in fnext denominator bytes gen-and-load-class refer-clojure})
|
||||||
|
|
||||||
(declare var-lookup)
|
(declare var-lookup apply-fn)
|
||||||
|
|
||||||
(defmacro define-lookup []
|
(defmacro define-lookup []
|
||||||
`(defn ~'var-lookup [sym#]
|
`(defn ~'var-lookup [sym#]
|
||||||
|
|
@ -53,17 +54,33 @@
|
||||||
[expr in]
|
[expr in]
|
||||||
(cond
|
(cond
|
||||||
(= '*in* expr) in
|
(= '*in* expr) in
|
||||||
|
(symbol? expr) (var-lookup expr)
|
||||||
(list? expr)
|
(list? expr)
|
||||||
(if-let [f (first expr)]
|
(if-let [f (first expr)]
|
||||||
(if-let [v (or (var-lookup f))]
|
(if-let [v (var-lookup f)]
|
||||||
(apply v (map #(interpret % in) (rest expr)))
|
(apply-fn v in (rest expr))
|
||||||
(if (or (symbol? f) (keyword? f))
|
(if (ifn? f)
|
||||||
(get in f)
|
(apply-fn f in (rest expr))
|
||||||
nil))
|
nil))
|
||||||
expr)
|
expr)
|
||||||
:else
|
:else
|
||||||
expr))
|
expr))
|
||||||
|
|
||||||
|
(defn read-fn [form]
|
||||||
|
^:bb/fn
|
||||||
|
(fn [& [x y z]]
|
||||||
|
(postwalk (fn [elt]
|
||||||
|
(case elt
|
||||||
|
% x
|
||||||
|
%1 x
|
||||||
|
%2 y
|
||||||
|
%3 z
|
||||||
|
(interpret elt x))) form)))
|
||||||
|
|
||||||
|
(defn apply-fn [f in args]
|
||||||
|
(let [args (map #(interpret % in) args)]
|
||||||
|
(apply f args)))
|
||||||
|
|
||||||
;;;; Scratch
|
;;;; Scratch
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
(defn read-edn [s]
|
||||||
|
(edn/read-string
|
||||||
|
{:readers *data-readers*}
|
||||||
|
s))
|
||||||
|
|
||||||
(defn- parse-opts [options]
|
(defn- parse-opts [options]
|
||||||
(let [opts (loop [options options
|
(let [opts (loop [options options
|
||||||
opts-map {}
|
opts-map {}
|
||||||
|
|
@ -22,19 +27,25 @@
|
||||||
(update opts-map current-opt conj opt)
|
(update opts-map current-opt conj opt)
|
||||||
current-opt))
|
current-opt))
|
||||||
opts-map))
|
opts-map))
|
||||||
version (boolean (get opts "--version"))]
|
version (boolean (get opts "--version"))
|
||||||
{:version version}))
|
raw (boolean (get opts "--raw"))]
|
||||||
|
{:version version
|
||||||
|
:raw raw}))
|
||||||
|
|
||||||
(defn -main
|
(defn -main
|
||||||
[& args]
|
[& args]
|
||||||
(let [{:keys [:version]} (parse-opts args)]
|
(let [{:keys [:version :raw]} (parse-opts args)]
|
||||||
(cond version
|
(cond version
|
||||||
(println (str/trim (slurp (io/resource "BABASHKA_VERSION"))))
|
(println (str/trim (slurp (io/resource "BABASHKA_VERSION"))))
|
||||||
:else
|
:else
|
||||||
(let [expr (edn/read-string (first args))
|
(let [expr (if raw (second args) (first args))
|
||||||
|
expr (read-edn expr)
|
||||||
in (slurp *in*)
|
in (slurp *in*)
|
||||||
edn (edn/read-string in)]
|
in (if raw
|
||||||
(prn (i/interpret expr edn))))))
|
(str/split in #"\s")
|
||||||
|
(read-edn (format "[%s]" in)))
|
||||||
|
in (if (= 1 (count in)) (first in) in)]
|
||||||
|
(prn (i/interpret expr in))))))
|
||||||
|
|
||||||
;;;; Scratch
|
;;;; Scratch
|
||||||
|
|
||||||
|
|
|
||||||
1
src/data_readers.clj
Normal file
1
src/data_readers.clj
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{bb/fn babashka.interpreter/read-fn}
|
||||||
Loading…
Reference in a new issue