Commit 7be5e09db10b63f84cbf307a4b4de0f14b2c9181
1 parent
19ec8d35
Fixed float parsing, exported PValue, added example.nim.
Showing
4 changed files
with
82 additions
and
15 deletions
README.md
0 → 100644
1 | +Lapp is a command line parser that uses the regular help text for the synopsis as the specification | ||
2 | +for the options and arguments, it was originally written by Steve Donovan in Lua: | ||
3 | + | ||
4 | +http://lua-users.org/wiki/LappFramework | ||
5 | + | ||
6 | +...and ported to Nim by Steve. Then I made it work with current Nim. | ||
7 | + | ||
8 | +See example.nim for how to use it. |
example.nim
0 → 100644
1 | +import lapp, tables | ||
2 | + | ||
3 | +# This is a trivial example trying to cover all features of lapp. | ||
4 | + | ||
5 | +let help = """ | ||
6 | + example [options] command filenames | ||
7 | + | ||
8 | + -r Just an optional single character flag. Show the args using repr. | ||
9 | + -a,--alpha Or with additional long variant, no whitespace there. | ||
10 | + -n: A colon can be added, but has no meaning, instead () specifies further. | ||
11 | + -N (default 10) And it can take a value, and have a default value. | ||
12 | + -f (default 0.04) And be a float | ||
13 | + -s (default banana) Or a string | ||
14 | + -x (int) And it can be typed with int, string, float, stdin, stdout - without a | ||
15 | + default value. This implies that the option is mandatory! | ||
16 | + -X (int...) And allow multiples. | ||
17 | + -v,--verbose: (bool...) Verbosity level, "..." means can be multiple. | ||
18 | + -o,--out (default stdout) A file to direct to. | ||
19 | + <command> Arguments are string by default. | ||
20 | + <file>: (default stdin...) One or more files or stdin by default | ||
21 | + | ||
22 | + | ||
23 | + The first line in this help text is arbitrary, or rather | ||
24 | + its only the lines (trimmed) beginning with '-' or '<' that constitute | ||
25 | + the speciciation, so this text is also ignored. | ||
26 | + | ||
27 | + Things we know are not working: | ||
28 | + ranges. The lexer in lapp does it, but there is no more support. | ||
29 | + """ | ||
30 | + | ||
31 | +# We call `parse` in lapp with our help text as argument. | ||
32 | +# This will both parse the help text above and then, parse the | ||
33 | +# arguments passed to this program. A table is returned | ||
34 | +# with all command line elements in it, keyed by their name | ||
35 | +# and with a PValue as value. | ||
36 | +var args = parse(help) | ||
37 | + | ||
38 | +# Let's examine what we got using repr | ||
39 | +for k,v in args: | ||
40 | + echo "Parameter: " & k & " PValue: " & repr(v) | ||
41 | + | ||
42 | +# Or print out a bit cleaner | ||
43 | +echo "Parameters and their values:" | ||
44 | +echo "r == " & $args["r"].asBool | ||
45 | +echo "alpha == " & $args["alpha"].asBool # Long name is used as key, if its specified | ||
46 | +echo "n == " & $args["n"].asBool | ||
47 | +echo "N == " & $args["N"].asInt | ||
48 | +echo "f == " & $args["f"].asFloat | ||
49 | +echo "s == " & $args["s"].asString | ||
50 | +echo "x == " & $args["x"].asInt | ||
51 | +echo "X == " & $args["X"].asSeq.map(proc(x:PValue):int = x.asInt) | ||
52 | +echo "verbose == " & $args["verbose"].asSeq.len | ||
53 | +echo "out == " & $args["out"].filename | ||
54 | +echo "command == " & $args["command"].asString | ||
55 | +echo "file == " & $args["file"].asSeq.map(proc(x:PValue):string = x.filename) | ||
56 | + | ||
57 | + |
lapp.nim
@@ -50,10 +50,10 @@ proc get(L: PLexer; t: var TLexType): string = | @@ -50,10 +50,10 @@ proc get(L: PLexer; t: var TLexType): string = | ||
50 | next(L) | 50 | next(L) |
51 | if thisChar(L) == '.': | 51 | if thisChar(L) == '.': |
52 | t = tfloat | 52 | t = tfloat |
53 | - result.add(c) | 53 | + result.add(thisChar(L)) |
54 | next(L) | 54 | next(L) |
55 | while thisChar(L) in Digits: | 55 | while thisChar(L) in Digits: |
56 | - result.add(c) | 56 | + result.add(thisChar(L)) |
57 | next(L) | 57 | next(L) |
58 | of '.': # ".", "..", "..." | 58 | of '.': # ".", "..", "..." |
59 | if thisChar(L) == '.': | 59 | if thisChar(L) == '.': |
@@ -89,17 +89,17 @@ type | @@ -89,17 +89,17 @@ type | ||
89 | vFile, | 89 | vFile, |
90 | vSeq | 90 | vSeq |
91 | 91 | ||
92 | - PValue = ref TValue | ||
93 | - TValue = object | ||
94 | - case kind: TValueKind | ||
95 | - of vInt: asInt *: int | ||
96 | - of vFloat: asFloat *: float | ||
97 | - of vString: asString *: string | ||
98 | - of vBool: asBool *: bool | 92 | + PValue* = ref TValue |
93 | + TValue* = object | ||
94 | + case kind*: TValueKind | ||
95 | + of vInt: asInt*: int | ||
96 | + of vFloat: asFloat*: float | ||
97 | + of vString: asString*: string | ||
98 | + of vBool: asBool*: bool | ||
99 | of vFile: | 99 | of vFile: |
100 | - asFile *: File | ||
101 | - fileName *: string | ||
102 | - of vSeq: asSeq *: seq[PValue] | 100 | + asFile*: File |
101 | + fileName*: string | ||
102 | + of vSeq: asSeq*: seq[PValue] | ||
103 | 103 | ||
104 | proc boolValue(c: bool): PValue = PValue(kind: vBool, asBool: c) | 104 | proc boolValue(c: bool): PValue = PValue(kind: vBool, asBool: c) |
105 | 105 | ||
@@ -205,6 +205,7 @@ proc parseSpec(u: string) = | @@ -205,6 +205,7 @@ proc parseSpec(u: string) = | ||
205 | defValue = "false" | 205 | defValue = "false" |
206 | 206 | ||
207 | if name != nil: | 207 | if name != nil: |
208 | + # echo("Param: " & name & " type: " & $ftype & " needsvalue: " & $(ftype != "bool") & " default: " & $defValue & " multiple: " & $multiple) | ||
208 | let spec = PSpec(defVal:defValue, ptype: ftype, needsValue: ftype != "bool",multiple:multiple) | 209 | let spec = PSpec(defVal:defValue, ptype: ftype, needsValue: ftype != "bool",multiple:multiple) |
209 | aliases[alias] = name | 210 | aliases[alias] = name |
210 | parm_spec[name] = spec | 211 | parm_spec[name] = spec |
@@ -314,7 +315,7 @@ proc parseArguments(usage: string, args: seq[string]): Table[string,PValue] = | @@ -314,7 +315,7 @@ proc parseArguments(usage: string, args: seq[string]): Table[string,PValue] = | ||
314 | try: | 315 | try: |
315 | v = value.parseFloat | 316 | v = value.parseFloat |
316 | except: | 317 | except: |
317 | - fail("bad integer") | 318 | + fail("bad float") |
318 | pval = floatValue(v) | 319 | pval = floatValue(v) |
319 | of "bool": | 320 | of "bool": |
320 | pval = boolValue(value.parseBool) | 321 | pval = boolValue(value.parseBool) |
@@ -359,12 +360,12 @@ proc parse*(usage: string): Table[string,PValue] = | @@ -359,12 +360,12 @@ proc parse*(usage: string): Table[string,PValue] = | ||
359 | 360 | ||
360 | when isMainModule: | 361 | when isMainModule: |
361 | var args = parse""" | 362 | var args = parse""" |
362 | - head [flags] filename | 363 | + head [flags] [file1, file2 ...] [outfile] |
363 | -n: (default 10) number of lines | 364 | -n: (default 10) number of lines |
364 | -v,--verbose: (bool...) verbosity level | 365 | -v,--verbose: (bool...) verbosity level |
365 | -a,--alpha useless parm | 366 | -a,--alpha useless parm |
366 | <file>: (default stdin...) | 367 | <file>: (default stdin...) |
367 | - |<out>: (default stdout) | 368 | + <out>: (default stdout) |
368 | """ | 369 | """ |
369 | 370 | ||
370 | echo args["n"].asInt | 371 | echo args["n"].asInt |