for example it’s great for clj/s dev tooling
automatic dependency management in a standalone script#!/usr/bin/env bash
"exec" "plk" \
"-Sdeps" "{:deps {funcool/tubax {:mvn/version \"0.2.0\"}}}" \
"-Ksf" "$0" "$@"
(ns scripts.html2clj
(:require [clojure.string :as string]
[clojure.walk :as walk]
[cljs.pprint :refer [pprint]]
[planck.core :refer [slurp *command-line-args*
*in* line-seq]]
[tubax.core :as tubax]))
...
#!/usr/bin/env bash
"exec" "clj" \
"-Sdeps" "{:deps {zprint {:mvn/version \"0.4.9\"}}}" \
"$0" "$@"
(ns scripts.zprint
(:require [zprint.core :as zp]))
(zp/zprint (slurp *in*) 80 {:parse-string-all? true
:parse {:interpose "\n\n"}
:map {:comma? false}})
(System/exit 0)
- slurp
- in
- command-line-args
etc.
http://planck-repl.org/scripts.html
(defmacro defshellonreg (name cmd &optional replace)
`(defun ,name (beg end)
(interactive "r")
(shell-command-on-region beg end ,cmd
(if ,replace (current-buffer) nil)
,replace)))
(defshellonreg htm2clj-region "html2clj" t)
(defshellonreg zprint-region "zprint" t)
(defun sort-sexp ()
(interactive)
(mark-sexp)
(sort-sexp-region (region-beginning) (region-end))
(zprint-region (region-beginning) (region-end))
(indent-region (region-beginning) (region-end)))
<div>
<h1>hello world</h1>
<br/>
<img src="smile.gif"/>
</div>
(ns clojure.test-clojure.spec
(:require [clojure.spec-alpha2 :as s]
[clojure.spec-alpha2.protocols :as prot]
[clojure.spec-alpha2.gen :as gen]
[clojure.spec-alpha2.test :as stest]
[clojure.test :refer :all]))
(deftest conform-explain
(let [a (s/and #(> % 5) #(< % 10))
o (s/or :s string? :k keyword?)
c (s/cat :a string? :b keyword?)
either (s/alt :a string? :b keyword?)
star (s/* keyword?)
plus (s/+ keyword?)
opt (s/? keyword?)
andre (s/& (s/* keyword?) even-count?)
andre2 (s/& (s/* keyword?) #{[:a]})
m (s/map-of keyword? string?)
mkeys (s/map-of (s/and keyword? (s/conformer name)) any?)
mkeys2 (s/map-of (s/and keyword? (s/conformer name)) any? :conform-keys true)
s (s/coll-of (s/cat :tag keyword? :val any?) :kind list?)
v (s/coll-of keyword? :kind vector?)
coll (s/coll-of keyword?)
lrange (s/int-in 7 42)
drange (s/double-in :infinite? false :NaN? false :min 3.1 :max 3.2)
irange (s/inst-in #inst "1939" #inst "1946")
schema1 (s/schema [::k1 ::k2])
schema2 (s/schema {:a int? :b keyword?})
union (s/union [::k1 ::k2] {:a int? :b keyword?})
select1 (s/select [] [::k1 ::k2])
select2 (s/select [] [::k1 {::sch [::mk1]}])
select* (s/select [::k1 ::k2] [*])
]
(are [spec x conformed ed]
(let [co (result-or-ex (s/conform spec x))
e (result-or-ex (::sa/problems (s/explain-data spec x)))]
(when (not= conformed co) (println "conform fail\n\texpect=" conformed "\n\tactual=" co))
(when (not (every? true? (map submap? ed e)))
(println "explain failures\n\texpect=" ed "\n\tactual failures=" e "\n\tsubmap?=" (map submap? ed e)))
(and (= conformed co) (every? true? (map submap? ed e))))
lrange 7 7 nil
lrange 8 8 nil
lrange 42 ::s/invalid [{:pred '(fn [%] (clojure.spec-alpha2/int-in-range? 7 42 %)), :val 42}]
irange #inst "1938" ::s/invalid [{:pred '(fn [%] (clojure.spec-alpha2/inst-in-range? #inst "1939-01-01T00:00:00.000-00:00" #inst "1946-01-01T00:00:00.000-00:00" %)), :val #inst "1938"}]
irange #inst "1942" #inst "1942" nil
irange #inst "1946" ::s/invalid [{:pred '(fn [%] (clojure.spec-alpha2/inst-in-range? #inst "1939-01-01T00:00:00.000-00:00" #inst "1946-01-01T00:00:00.000-00:00" %)), :val #inst "1946"}]
drange 3.0 ::s/invalid [{:pred '(fn [%] (if 3.1 (clojure.core/<= 3.1 %) true)), :val 3.0}]
drange 3.1 3.1 nil
drange 3.2 3.2 nil
drange Double/POSITIVE_INFINITY ::s/invalid [{:pred '(fn [%] (clojure.core/if-not false (clojure.core/not (Double/isInfinite %)))), :val Double/POSITIVE_INFINITY}]
;; can't use equality-based test for Double/NaN
;; drange Double/NaN ::s/invalid {[] {:pred '(fn [%] (clojure.core/not (Double/isNaN %))), :val Double/NaN}}
(s/spec keyword?) :k :k nil
(s/spec keyword?) nil ::s/invalid [{:pred `keyword? :val nil}]
(s/spec keyword?) "abc" ::s/invalid [{:pred `keyword? :val "abc"}]
a 6 6 nil
a 3 ::s/invalid '[{:pred (fn [%] (clojure.core/> % 5)), :val 3}]
a 20 ::s/invalid '[{:pred (fn [%] (clojure.core/< % 10)), :val 20}]
a nil "java.lang.NullPointerException" "java.lang.NullPointerException"
a :k "java.lang.ClassCastException" "java.lang.ClassCastException"
o "a" [:s "a"] nil
o :a [:k :a] nil
o 'a ::s/invalid '[{:pred clojure.core/string?, :val a, :path [:s]} {:pred clojure.core/keyword?, :val a :path [:k]}]
c nil ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/string?, :val (), :path [:a]}]
c [] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/string?, :val (), :path [:a]}]
c [:a] ::s/invalid '[{:pred clojure.core/string?, :val :a, :path [:a], :in [0]}]
c ["a"] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val (), :path [:b]}]
c ["s" :k] '{:a "s" :b :k} nil
c ["s" :k 5] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec-alpha2/cat :a clojure.core/string? :b clojure.core/keyword?), :val (5)}]
(s/cat) nil {} nil
(s/cat) [5] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec-alpha2/cat), :val (5), :in [0]}]
either nil ::s/invalid '[{:reason "Insufficient input", :pred (clojure.spec-alpha2/alt :a clojure.core/string? :b clojure.core/keyword?), :val () :via []}]
either [] ::s/invalid '[{:reason "Insufficient input", :pred (clojure.spec-alpha2/alt :a clojure.core/string? :b clojure.core/keyword?), :val () :via []}]
either [:k] [:b :k] nil
either ["s"] [:a "s"] nil
either [:b "s"] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec-alpha2/alt :a clojure.core/string? :b clojure.core/keyword?), :val ("s") :via []}]
star nil [] nil
star [] [] nil
star [:k] [:k] nil
star [:k1 :k2] [:k1 :k2] nil
star [:k1 :k2 "x"] ::s/invalid '[{:pred clojure.core/keyword?, :val "x" :via []}]
star ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a" :via []}]
plus nil ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val () :via []}]
plus [] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val () :via []}]
plus [:k] [:k] nil
plus [:k1 :k2] [:k1 :k2] nil
plus [:k1 :k2 "x"] ::s/invalid '[{:pred clojure.core/keyword?, :val "x", :in [2]}]
plus ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a" :via []}]
opt nil nil nil
opt [] nil nil
opt :k ::s/invalid '[{:pred (fn [%] (clojure.core/or (clojure.core/nil? %) (clojure.core/sequential? %))), :val :k}]
opt [:k] :k nil
opt [:k1 :k2] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec-alpha2/? clojure.core/keyword?), :val (:k2)}]
opt [:k1 :k2 "x"] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec-alpha2/? clojure.core/keyword?), :val (:k2 "x")}]
opt ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a"}]
andre nil nil nil
andre [] nil nil
andre :k ::s/invalid '[{:pred (fn [%] (clojure.core/or (clojure.core/nil? %) (clojure.core/sequential? %))), :val :k}]
andre [:k] ::s/invalid '[{:pred clojure.test-clojure.spec/even-count?, :val [:k]}]
andre [:j :k] [:j :k] nil
andre2 nil ::s/invalid [{:pred #{[:a]}, :val []}]
andre2 [] ::s/invalid [{:pred #{[:a]}, :val []}]
andre2 [:a] [:a] nil
m nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
m {} {} nil
m {:a "b"} {:a "b"} nil
mkeys nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
mkeys {} {} nil
mkeys {:a 1 :b 2} {:a 1 :b 2} nil
mkeys2 nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
mkeys2 {} {} nil
mkeys2 {:a 1 :b 2} {"a" 1 "b" 2} nil
s '([:a 1] [:b "2"]) '({:tag :a :val 1} {:tag :b :val "2"}) nil
v [:a :b] [:a :b] nil
v '(:a :b) ::s/invalid '[{:pred clojure.core/vector? :val (:a :b)}]
coll nil ::s/invalid '[{:path [], :pred clojure.core/coll?, :val nil, :via [], :in []}]
coll [] [] nil
coll [:a] [:a] nil
coll [:a :b] [:a :b] nil
coll (map identity [:a :b]) '(:a :b) nil
;;coll [:a "b"] ::s/invalid '[{:pred (coll-checker keyword?), :val [:a b]}]
schema1 {} {} nil
schema1 {::k1 1 ::k2 :a} {::k1 1 ::k2 :a} nil
schema1 "oops" ::s/invalid [{:pred 'clojure.core/map? :val "oops"}]
schema1 {::k1 :a ::k2 1} ::s/invalid [{:pred 'clojure.core/int? :val :a} {:pred 'clojure.core/keyword? :val 1}]
schema2 {} {} nil
schema2 {:a 10 :b :x} {:a 10 :b :x} nil
schema2 {:a :x :b 10} ::s/invalid [{:pred 'clojure.core/int? :val :x} {:pred 'clojure.core/keyword? :val 10}]
union {} {} nil
union {::k1 1 ::k2 :a :a 1 :b :x} {::k1 1 ::k2 :a :a 1 :b :x} nil
union "oops" ::s/invalid [{:pred 'clojure.core/map? :val "oops"}]
union {::k1 :a ::k2 1} ::s/invalid [{:pred 'clojure.core/int? :val :a} {:pred 'clojure.core/keyword? :val 1}]
select1 {::k1 1 ::k2 :a} {::k1 1 ::k2 :a} nil
select1 "oops" ::s/invalid [{:pred 'clojure.core/map? :val "oops"}]
select1 {::k1 1} ::s/invalid [{:pred '(clojure.core/fn [m] (clojure.core/contains? m ::k2)) :val {::k1 1}}]
select1 {::k1 1 ::k2 5} ::s/invalid [{:pred 'clojure.core/keyword? :val 5}]
select2 {::k1 1} {::k1 1} nil
select2 {::k1 1 ::m {::mk1 10}} {::k1 1 ::m {::mk1 10}} nil
;; problems here from both the registered key in the outer map and from missing selection
select2 {::k1 1 ::m {}} ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.core/contains? % ::mk1)) :val {}}
{:pred '(clojure.core/fn [m] (clojure.core/contains? m ::mk1)) :val {}}]
select* {::k1 1 ::k2 :a} {::k1 1 ::k2 :a} nil
select* "oops" ::s/invalid [{:pred 'clojure.core/map? :val "oops"}]
select* {::k1 1} ::s/invalid [{:pred '(clojure.core/fn [m] (clojure.core/contains? m ::k2)) :val {::k1 1}}]
select* {::k1 1 ::k2 5} ::s/invalid [{:pred 'clojure.core/keyword? :val 5}]
)))