11 Commits
0.0.1 ... 0.0.6

Author SHA1 Message Date
5b3b72e127 vbump 2020-01-31 22:30:42 +01:00
99ce77695c make = work as well 2020-01-31 22:26:37 +01:00
e55dc7556d version bump 2020-01-31 17:31:06 +01:00
14d25abc35 bugfix for printing none 2020-01-31 17:28:31 +01:00
10ba753ee3 cli: better to-map 2020-01-31 10:43:42 +01:00
0b185aa3b9 cli: add morphers 2020-01-30 16:43:58 +01:00
b5eb3a917b cli: fix memerror in usage 2020-01-30 16:01:11 +01:00
cb5c9f0bfe docs: fix typos 2020-01-29 21:13:13 +01:00
7bd0817c27 update docs 2020-01-29 21:09:48 +01:00
493d0016d5 vbump 2020-01-29 21:08:47 +01:00
aaf413ac04 cli: fix printing of types and do not override previous errors 2020-01-29 21:07:31 +01:00
4 changed files with 100 additions and 49 deletions

View File

@@ -3,7 +3,7 @@
A simple CLI library for Carp. A simple CLI library for Carp.
```clojure ```clojure
(load "https://veitheller.de/git/carpentry/cli@master") (load "https://veitheller.de/git/carpentry/cli@0.0.6")
(defn main [] (defn main []
(let [p (=> (CLI.new @"My super cool tool!") (let [p (=> (CLI.new @"My super cool tool!")
@@ -18,7 +18,7 @@ A simple CLI library for Carp.
## Installation ## Installation
```clojure ```clojure
(load "https://veitheller.de/git/carpentry/cli@master") (load "https://veitheller.de/git/carpentry/cli@0.0.6")
``` ```
## Usage ## Usage
@@ -43,8 +43,8 @@ manually.
Once youre done building your flag structure, you can run `CLI.parse`. It Once youre done building your flag structure, you can run `CLI.parse`. It
will not abort the program on error, instead it will tell you what went wrong will not abort the program on error, instead it will tell you what went wrong
in a `Result.Error`. If it succeeds, the `Result.Success` contains a `Map` from in a `Result.Error`. If it succeeds, the `Result.Success` contains a `Map` from
the long flag name to the value (the values are `Maybe`s, since they might be the long flag name to the value. The values are not in the map if they are
optional arguments. unset.
<hr/> <hr/>

View File

@@ -6,7 +6,7 @@
(doc CLI "is a simple CLI library for Carp. (doc CLI "is a simple CLI library for Carp.
```clojure ```clojure
(load \"https://veitheller.de/git/carpentry/cli@0.0.1\") (load \"https://veitheller.de/git/carpentry/cli@0.0.6\")
(defn main [] (defn main []
(let [p (=> (CLI.new @\"My super cool tool!\") (let [p (=> (CLI.new @\"My super cool tool!\")
@@ -21,7 +21,7 @@
## Installation ## Installation
```clojure ```clojure
(load \"https://veitheller.de/git/carpentry/cli@0.0.1\") (load \"https://veitheller.de/git/carpentry/cli@0.0.6\")
``` ```
## Usage ## Usage
@@ -46,8 +46,8 @@ manually.
Once youre done building your flag structure, you can run `CLI.parse`. It Once youre done building your flag structure, you can run `CLI.parse`. It
will not abort the program on error, instead it will tell you what went wrong will not abort the program on error, instead it will tell you what went wrong
in a `Result.Error`. If it succeeds, the `Result.Success` contains a `Map` from in a `Result.Error`. If it succeeds, the `Result.Success` contains a `Map` from
the long flag name to the value (the values are `Maybe`s, since they might be the long flag name to the value. The values are not in the map if they are
optional arguments.") unset.")
(defmodule CLI (defmodule CLI
(hidden Type) (hidden Type)
(private Type) (private Type)
@@ -55,11 +55,16 @@ optional arguments.")
(Integer [Long]) (Integer [Long])
(Floating [Double]) (Floating [Double])
(Str [String]) (Str [String])
(None [])
) )
(defmodule Type (defmodule Type
(defn = [a b] (defn = [a b]
(match @a (match @a
(None)
(match @b
(None) true
_ false)
(Integer i) (Integer i)
(match @b (match @b
(Integer j) (= i j) (Integer j) (= i j)
@@ -78,6 +83,40 @@ optional arguments.")
(Integer i) (Long.format s i) (Integer i) (Long.format s i)
(Floating f) (Double.format s f) (Floating f) (Double.format s f)
(Str s2) (String.format s &s2))) (Str s2) (String.format s &s2)))
(defn str [t]
(match @t
(Integer i) (str i)
(Floating f) (str f)
(Str s) (str s)
(None) @"none"))
(defn to-int [x]
(match x
(Integer l) (Long.to-int l)
_ 0))
(defn to-long [x]
(match x
(Integer l) l
_ 0l))
(defn to-str [x]
(match x
(Str s) s
_ @""))
(defn to-float [x]
(match x
(Floating d) (Double.to-float d)
_ 0.0f))
(defn to-double [x]
(match x
(Floating d) d
_ 0.0))
(defn zero [] (None))
) )
(hidden Tag) (hidden Tag)
@@ -97,7 +136,7 @@ optional arguments.")
) )
(doc Option "is the option type. To construct an `Option`, please use (doc Option "is the option type. To construct an `Option`, please use
[`int`](#int), [`float`](#float), or [`str](#str).") [`int`](#int), [`float`](#float), or [`str`](#str).")
(deftype Option [ (deftype Option [
type- Tag type- Tag
long String long String
@@ -109,7 +148,7 @@ optional arguments.")
]) ])
(doc Parser "is the parser type. To construct a `Parser`, please use (doc Parser "is the parser type. To construct a `Parser`, please use
[`new](#new).") [`new`](#new).")
(deftype Parser [ (deftype Parser [
description String description String
options (Array Option) options (Array Option)
@@ -197,7 +236,10 @@ optional arguments.")
(defn to-map [m] (defn to-map [m]
(Array.reduce (Array.reduce
&(fn [a v] (Map.put a (Pair.a (Pair.a v)) (Pair.b (Pair.b v)))) &(fn [a v]
(match @(Pair.b (Pair.b v))
(Maybe.Just e) (Map.put a (Pair.a (Pair.a v)) &e)
(Maybe.Nothing) a))
{} {}
(values m))) (values m)))
) )
@@ -265,7 +307,7 @@ optional arguments.")
(Option.long arg) (Option.short arg) (Option.description arg))) (Option.long arg) (Option.short arg) (Option.description arg)))
(when @(Option.required? arg) (IO.print " REQUIRED")) (when @(Option.required? arg) (IO.print " REQUIRED"))
(when (Maybe.just? (Option.default arg)) (when (Maybe.just? (Option.default arg))
(IO.print &(fmt " (default: %s)" &(Maybe.unsafe-from @(Option.default arg))))) (IO.print &(fmt " (default: %s)" &(str &(Maybe.unsafe-from @(Option.default arg))))))
(match @(Option.options arg) (match @(Option.options arg)
(Maybe.Just o) (Maybe.Just o)
(IO.print &(fmt " (options: %s)" &(join ", " &(Array.copy-map &str &o)))) (IO.print &(fmt " (options: %s)" &(join ", " &(Array.copy-map &str &o))))
@@ -289,17 +331,22 @@ mesage is empty, `--help` was requested. If you dont want to provide a
(for [i 1 (System.get-args-len)] (for [i 1 (System.get-args-len)]
(let [x (System.get-arg i)] (let [x (System.get-arg i)]
(if (or (String.starts-with? x "--") (String.starts-with? x "-")) (if (or (String.starts-with? x "--") (String.starts-with? x "-"))
(let [flag (Pattern.substitute #"^\-\-?" x "" 1)] (let [flag (Pattern.substitute #"^\-\-?" x "" 1)
splt (String.split-by &flag &[\=])
k (if (> (Array.length &splt) 1) (Array.unsafe-nth &splt 0) &flag)
v (cond (> (Array.length &splt) 1) (Array.nth &splt 1)
(< i (System.get-args-len))
(do (set! i (Int.inc i)) (Maybe.Just @(System.get-arg i)))
(Maybe.Nothing))]
(cond (cond
(CmdMap.contains? &values &flag) (CmdMap.contains? &values k)
(do (match v
(set! i (Int.inc i)) (Maybe.Just val) (CmdMap.put! &values k &val)
(if (< i (System.get-args-len)) (Maybe.Nothing)
(CmdMap.put! &values &flag (System.get-arg i))
(do (do
(set! res (Result.Error (fmt "No value for: %s" &flag))) (set! res (Result.Error (fmt "No value for: %s" &flag)))
(break)))) (break)))
(or (= &flag "help") (= &flag "h")) (or (= k "help") (= k "h"))
(do (do
(set! res (Result.Error @"")) (set! res (Result.Error @""))
(break)) (break))
@@ -309,6 +356,7 @@ mesage is empty, `--help` was requested. If you dont want to provide a
(do (do
(set! res (Result.Error (fmt "Unexpected argument: %s" x))) (set! res (Result.Error (fmt "Unexpected argument: %s" x)))
(break))))) (break)))))
(when (Result.success? &res)
(foreach [o options] (foreach [o options]
(cond (cond
(and @(Option.required? o) (and @(Option.required? o)
@@ -328,7 +376,7 @@ mesage is empty, `--help` was requested. If you dont want to provide a
&(CmdMap.get &values (Option.long o)) &(CmdMap.get &values (Option.long o))
&(join ", " &(Array.copy-map &str &opts))))) &(join ", " &(Array.copy-map &str &opts)))))
(break)))) (break))))
())) ())))
(match res (match res
(Result.Success _) (Result.Success (CmdMap.to-map &values)) (Result.Success _) (Result.Success (CmdMap.to-map &values))
(Result.Error x) (Result.Error x)))) (Result.Error x) (Result.Error x))))

View File

@@ -30,7 +30,7 @@
</h1> </h1>
<div class="module-description"> <div class="module-description">
<p>is a simple CLI library for Carp.</p> <p>is a simple CLI library for Carp.</p>
<pre><code class="language-clojure">(load &quot;https://veitheller.de/git/carpentry/cli@0.0.1&quot;) <pre><code class="language-clojure">(load &quot;https://veitheller.de/git/carpentry/cli@0.0.6&quot;)
(defn main [] (defn main []
(let [p (=&gt; (CLI.new @&quot;My super cool tool!&quot;) (let [p (=&gt; (CLI.new @&quot;My super cool tool!&quot;)
@@ -42,7 +42,7 @@
(Result.Error msg) (do (IO.errorln &amp;msg) (CLI.usage &amp;p))))) (Result.Error msg) (do (IO.errorln &amp;msg) (CLI.usage &amp;p)))))
</code></pre> </code></pre>
<h2>Installation</h2> <h2>Installation</h2>
<pre><code class="language-clojure">(load &quot;https://veitheller.de/git/carpentry/cli@0.0.1&quot;) <pre><code class="language-clojure">(load &quot;https://veitheller.de/git/carpentry/cli@0.0.6&quot;)
</code></pre> </code></pre>
<h2>Usage</h2> <h2>Usage</h2>
<p><code>CLI</code> should be built using combinators, as in the example above. It has, as of <p><code>CLI</code> should be built using combinators, as in the example above. It has, as of
@@ -61,8 +61,8 @@ manually.</p>
<p>Once youre done building your flag structure, you can run <code>CLI.parse</code>. It <p>Once youre done building your flag structure, you can run <code>CLI.parse</code>. It
will not abort the program on error, instead it will tell you what went wrong will not abort the program on error, instead it will tell you what went wrong
in a <code>Result.Error</code>. If it succeeds, the <code>Result.Success</code> contains a <code>Map</code> from in a <code>Result.Error</code>. If it succeeds, the <code>Result.Success</code> contains a <code>Map</code> from
the long flag name to the value (the values are <code>Maybe</code>s, since they might be the long flag name to the value. The values are not in the map if they are
optional arguments.</p> unset.</p>
</div> </div>
<div class="binder"> <div class="binder">
@@ -82,7 +82,7 @@ optional arguments.</p>
</span> </span>
<p class="doc"> <p class="doc">
<p>is the option type. To construct an <code>Option</code>, please use <p>is the option type. To construct an <code>Option</code>, please use
<a href="#int"><code>int</code></a>, <a href="#float"><code>float</code></a>, or <a href="#str">`str</a>.</p> <a href="#int"><code>int</code></a>, <a href="#float"><code>float</code></a>, or <a href="#str"><code>str</code></a>.</p>
</p> </p>
</div> </div>
@@ -103,7 +103,7 @@ optional arguments.</p>
</span> </span>
<p class="doc"> <p class="doc">
<p>is the parser type. To construct a <code>Parser</code>, please use <p>is the parser type. To construct a <code>Parser</code>, please use
<a href="#new">`new</a>.</p> <a href="#new"><code>new</code></a>.</p>
</p> </p>
</div> </div>
@@ -197,7 +197,7 @@ optional arguments.</p>
defn defn
</div> </div>
<p class="sig"> <p class="sig">
(λ [(Ref Parser)] (Result (Map String (Maybe Type)) String)) (λ [(Ref Parser)] (Result (Map String Type) String))
</p> </p>
<pre class="args"> <pre class="args">
(parse p) (parse p)

View File

@@ -3,8 +3,11 @@
(defn main [] (defn main []
(let [p (=> (CLI.new @"My super cool tool!") (let [p (=> (CLI.new @"My super cool tool!")
(CLI.add &(CLI.int "flag" "f" "my flag" true)) (CLI.add &(CLI.int "flag" "f" "my flag" true))
(CLI.add &(CLI.str "thing" "t" "my thing" false @"hi" &[@"a" @"b" @"hi"])))] (CLI.add &(CLI.str "thing" "t" "my thing" false @"hi" &[@"a" @"b" @"hi"]))
(CLI.add &(CLI.str "other" "o" "my thing" false)))]
(match (CLI.parse &p) (match (CLI.parse &p)
(Result.Success flags) (Result.Success flags)
(println* &(str &(Map.get &flags "flag")) " " &(str &(Map.get &flags "thing"))) (println*
&(str &(Map.get &flags "flag")) " " &(str &(Map.get &flags "thing"))
" " &(str &(Map.get &flags "other")))
(Result.Error msg) (do (IO.errorln &msg) (CLI.usage &p))))) (Result.Error msg) (do (IO.errorln &msg) (CLI.usage &p)))))