Commit 1b2c46b87b58271f61bc813e17af41cb670fa6f7
1 parent
c577e6e6
Added groups support using divider and exported some procs.
Showing
1 changed file
with
28 additions
and
12 deletions
lapp.nim
@@ -17,6 +17,8 @@ type | @@ -17,6 +17,8 @@ type | ||
17 | trange | 17 | trange |
18 | telipsis | 18 | telipsis |
19 | tchar | 19 | tchar |
20 | + toption | ||
21 | + tdivider | ||
20 | 22 | ||
21 | proc thisChar(L: PLexer):char = L.str[L.idx] | 23 | proc thisChar(L: PLexer):char = L.str[L.idx] |
22 | proc next(L: PLexer) = L.idx += 1 | 24 | proc next(L: PLexer) = L.idx += 1 |
@@ -35,9 +37,15 @@ proc get(L: PLexer; t: var TLexType): string = | @@ -35,9 +37,15 @@ proc get(L: PLexer; t: var TLexType): string = | ||
35 | t = tchar | 37 | t = tchar |
36 | case c | 38 | case c |
37 | of '-': # '-", "--" | 39 | of '-': # '-", "--" |
40 | + t = toption | ||
38 | if thisChar(L) == '-': | 41 | if thisChar(L) == '-': |
39 | result.add('-') | 42 | result.add('-') |
40 | next(L) | 43 | next(L) |
44 | + if thisChar(L) == '-': # "---..." | ||
45 | + t = tdivider | ||
46 | + result.add('-') | ||
47 | + while thisChar(L) == '-': | ||
48 | + next(L) | ||
41 | of Letters: # word | 49 | of Letters: # word |
42 | t = tword | 50 | t = tword |
43 | while thisChar(L) in Letters: | 51 | while thisChar(L) in Letters: |
@@ -112,14 +120,13 @@ proc intValue(v: int): PValue = PValue(kind: vInt, asInt: v) | @@ -112,14 +120,13 @@ proc intValue(v: int): PValue = PValue(kind: vInt, asInt: v) | ||
112 | proc floatValue(v: float): PValue = PValue(kind: vFloat, asFloat: v) | 120 | proc floatValue(v: float): PValue = PValue(kind: vFloat, asFloat: v) |
113 | 121 | ||
114 | proc seqValue(v: seq[PValue]): PValue = PValue(kind: vSeq, asSeq: v) | 122 | proc seqValue(v: seq[PValue]): PValue = PValue(kind: vSeq, asSeq: v) |
115 | - | ||
116 | -const MAX_FILES = 30 | ||
117 | 123 | ||
118 | type | 124 | type |
119 | PSpec = ref TSpec | 125 | PSpec = ref TSpec |
120 | TSpec = object | 126 | TSpec = object |
121 | defVal: string | 127 | defVal: string |
122 | ptype: string | 128 | ptype: string |
129 | + group: int | ||
123 | needsValue, multiple, used: bool | 130 | needsValue, multiple, used: bool |
124 | var | 131 | var |
125 | progname, usage: string | 132 | progname, usage: string |
@@ -134,6 +141,7 @@ proc parseSpec(u: string) = | @@ -134,6 +141,7 @@ proc parseSpec(u: string) = | ||
134 | var | 141 | var |
135 | L: PLexer | 142 | L: PLexer |
136 | tok: string | 143 | tok: string |
144 | + groupCounter: int | ||
137 | k = 1 | 145 | k = 1 |
138 | 146 | ||
139 | let lines = u.splitLines | 147 | let lines = u.splitLines |
@@ -173,7 +181,8 @@ proc parseSpec(u: string) = | @@ -173,7 +181,8 @@ proc parseSpec(u: string) = | ||
173 | k += 1 | 181 | k += 1 |
174 | tok = L.get | 182 | tok = L.get |
175 | if tok != ">": fail("argument must be enclosed in <...>") | 183 | if tok != ">": fail("argument must be enclosed in <...>") |
176 | - | 184 | + elif tok == "---": # divider |
185 | + inc(groupCounter) | ||
177 | if getnext: tok = L.get | 186 | if getnext: tok = L.get |
178 | if tok == ":": # allowed to have colon after flags | 187 | if tok == ":": # allowed to have colon after flags |
179 | tok = L.get | 188 | tok = L.get |
@@ -205,8 +214,8 @@ proc parseSpec(u: string) = | @@ -205,8 +214,8 @@ proc parseSpec(u: string) = | ||
205 | defValue = "false" | 214 | defValue = "false" |
206 | 215 | ||
207 | if name != nil: | 216 | if name != nil: |
208 | - # echo("Param: " & name & " type: " & $ftype & " needsvalue: " & $(ftype != "bool") & " default: " & $defValue & " multiple: " & $multiple) | ||
209 | - let spec = PSpec(defVal:defValue, ptype: ftype, needsValue: ftype != "bool",multiple:multiple) | 217 | + #echo("Param: " & name & " type: " & $ftype & " group: " & $groupCounter & " needsvalue: " & $(ftype != "bool") & " default: " & $defValue & " multiple: " & $multiple) |
218 | + let spec = PSpec(defVal:defValue, ptype: ftype, group: groupCounter, needsValue: ftype != "bool",multiple:multiple) | ||
210 | aliases[alias] = name | 219 | aliases[alias] = name |
211 | parm_spec[name] = spec | 220 | parm_spec[name] = spec |
212 | 221 | ||
@@ -297,12 +306,19 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | @@ -297,12 +306,19 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | ||
297 | if info.used: | 306 | if info.used: |
298 | if flag == "help" or flag == "version": | 307 | if flag == "help" or flag == "version": |
299 | enableChecks = false | 308 | enableChecks = false |
300 | - | ||
301 | - | 309 | + |
310 | + # Check maximum group used | ||
311 | + var maxGroup = 0 | ||
312 | + for item in flagvalues: | ||
313 | + info = get_spec(item[0]) | ||
314 | + if maxGroup < info.group: | ||
315 | + maxGroup = info.group | ||
316 | + | ||
302 | # any flags not mentioned? | 317 | # any flags not mentioned? |
303 | for flag,info in parm_spec: | 318 | for flag,info in parm_spec: |
304 | if not info.used: | 319 | if not info.used: |
305 | - if info.defVal == "": # no default! | 320 | + # Is there no default and we have used options in this group? |
321 | + if info.defVal == "" and info.group <= maxGroup: | ||
306 | failures.add("required option or argument missing: " & flag) | 322 | failures.add("required option or argument missing: " & flag) |
307 | else: | 323 | else: |
308 | flagvalues.add(@[flag,info.defVal]) | 324 | flagvalues.add(@[flag,info.defVal]) |
@@ -310,7 +326,7 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | @@ -310,7 +326,7 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | ||
310 | if enableChecks: | 326 | if enableChecks: |
311 | # any failures up until now - then we fail | 327 | # any failures up until now - then we fail |
312 | if failures.len > 0: | 328 | if failures.len > 0: |
313 | - fail(failures.join(", ")) | 329 | + fail(failures.join("\n") & "\n") |
314 | 330 | ||
315 | # cool, we have the info, can convert known flags | 331 | # cool, we have the info, can convert known flags |
316 | for item in flagvalues: | 332 | for item in flagvalues: |
@@ -381,7 +397,7 @@ proc parse*(usage: string): Table[string,PValue] = | @@ -381,7 +397,7 @@ proc parse*(usage: string): Table[string,PValue] = | ||
381 | return parseArguments(usage,args) | 397 | return parseArguments(usage,args) |
382 | 398 | ||
383 | # Helper proc for verbosity level. | 399 | # Helper proc for verbosity level. |
384 | -proc verbosityLevel(args: Table[string,PValue]): int = | 400 | +proc verbosityLevel*(args: Table[string,PValue]): int = |
385 | if args.hasKey("verbose"): | 401 | if args.hasKey("verbose"): |
386 | let verbosity = args["verbose"].asSeq | 402 | let verbosity = args["verbose"].asSeq |
387 | result = verbosity.len | 403 | result = verbosity.len |
@@ -391,11 +407,11 @@ proc verbosityLevel(args: Table[string,PValue]): int = | @@ -391,11 +407,11 @@ proc verbosityLevel(args: Table[string,PValue]): int = | ||
391 | result = 0 | 407 | result = 0 |
392 | 408 | ||
393 | # Helper to check if we should show version | 409 | # Helper to check if we should show version |
394 | -proc showVersion(args: Table[string,PValue]): bool = | 410 | +proc showVersion*(args: Table[string,PValue]): bool = |
395 | args["version"].asBool | 411 | args["version"].asBool |
396 | 412 | ||
397 | # Helper to check if we should show help | 413 | # Helper to check if we should show help |
398 | -proc showHelp(args: Table[string,PValue]): bool = | 414 | +proc showHelp*(args: Table[string,PValue]): bool = |
399 | args["help"].asBool | 415 | args["help"].asBool |
400 | 416 | ||
401 | 417 |