Commit c577e6e67d222e20662f2fe90d06fe1d013a27a0
1 parent
809a975c
Added failures collection and help/version helpers.
Showing
1 changed file
with
68 additions
and
18 deletions
lapp.nim
@@ -253,6 +253,9 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | @@ -253,6 +253,9 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | ||
253 | parseSpec(usage) | 253 | parseSpec(usage) |
254 | addQuitProc(closeFiles) | 254 | addQuitProc(closeFiles) |
255 | 255 | ||
256 | + # Collect failures | ||
257 | + var failures = newSeq[string]() | ||
258 | + | ||
256 | # parse the flags and arguments | 259 | # parse the flags and arguments |
257 | while i <= n: | 260 | while i <= n: |
258 | arg = next() | 261 | arg = next() |
@@ -275,7 +278,8 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | @@ -275,7 +278,8 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | ||
275 | for c in arg.tail: | 278 | for c in arg.tail: |
276 | let f = get_alias(c) | 279 | let f = get_alias(c) |
277 | let i = get_spec(f) | 280 | let i = get_spec(f) |
278 | - if i.needsValue: fail("needs value! " & f) | 281 | + if i.needsValue: |
282 | + failures.add("option " & f & " needs a value") | ||
279 | flagvalues.add(@[f,"true"]) | 283 | flagvalues.add(@[f,"true"]) |
280 | i.used = true | 284 | i.used = true |
281 | else: # argument (stored as \001, \002, etc | 285 | else: # argument (stored as \001, \002, etc |
@@ -286,14 +290,28 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | @@ -286,14 +290,28 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = | ||
286 | if not info.multiple: k += 1 | 290 | if not info.multiple: k += 1 |
287 | flagvalues.add(@[flag,value]) | 291 | flagvalues.add(@[flag,value]) |
288 | info.used = true | 292 | info.used = true |
289 | - | 293 | + |
294 | + # Some options disables checking | ||
295 | + var enableChecks = true | ||
296 | + for flag,info in parm_spec: | ||
297 | + if info.used: | ||
298 | + if flag == "help" or flag == "version": | ||
299 | + enableChecks = false | ||
300 | + | ||
301 | + | ||
290 | # any flags not mentioned? | 302 | # any flags not mentioned? |
291 | for flag,info in parm_spec: | 303 | for flag,info in parm_spec: |
292 | if not info.used: | 304 | if not info.used: |
293 | if info.defVal == "": # no default! | 305 | if info.defVal == "": # no default! |
294 | - fail("required option or argument missing: " & flag) | ||
295 | - flagvalues.add(@[flag,info.defVal]) | ||
296 | - | 306 | + failures.add("required option or argument missing: " & flag) |
307 | + else: | ||
308 | + flagvalues.add(@[flag,info.defVal]) | ||
309 | + | ||
310 | + if enableChecks: | ||
311 | + # any failures up until now - then we fail | ||
312 | + if failures.len > 0: | ||
313 | + fail(failures.join(", ")) | ||
314 | + | ||
297 | # cool, we have the info, can convert known flags | 315 | # cool, we have the info, can convert known flags |
298 | for item in flagvalues: | 316 | for item in flagvalues: |
299 | var pval: PValue; | 317 | var pval: PValue; |
@@ -362,23 +380,55 @@ proc parse*(usage: string): Table[string,PValue] = | @@ -362,23 +380,55 @@ proc parse*(usage: string): Table[string,PValue] = | ||
362 | args[i] = paramStr(i) | 380 | args[i] = paramStr(i) |
363 | return parseArguments(usage,args) | 381 | return parseArguments(usage,args) |
364 | 382 | ||
383 | +# Helper proc for verbosity level. | ||
384 | +proc verbosityLevel(args: Table[string,PValue]): int = | ||
385 | + if args.hasKey("verbose"): | ||
386 | + let verbosity = args["verbose"].asSeq | ||
387 | + result = verbosity.len | ||
388 | + if not verbosity[0].asBool: | ||
389 | + result = 0 | ||
390 | + else: | ||
391 | + result = 0 | ||
392 | + | ||
393 | +# Helper to check if we should show version | ||
394 | +proc showVersion(args: Table[string,PValue]): bool = | ||
395 | + args["version"].asBool | ||
396 | + | ||
397 | +# Helper to check if we should show help | ||
398 | +proc showHelp(args: Table[string,PValue]): bool = | ||
399 | + args["help"].asBool | ||
400 | + | ||
401 | + | ||
402 | +# Typical usage | ||
365 | when isMainModule: | 403 | when isMainModule: |
366 | - var args = parse""" | ||
367 | - head [flags] file [out] | ||
368 | - -n: (default 10) number of lines | ||
369 | - -v,--verbose: (bool...) verbosity level | ||
370 | - -a,--alpha useless parm | ||
371 | - <file>: (default stdin...) | ||
372 | - <out>: (default stdout) | 404 | + let help = """ |
405 | + head [flags] files... [out] | ||
406 | + -h,--help Show this help | ||
407 | + --version Show version | ||
408 | + -n: (default 10) Number of lines to show | ||
409 | + -v,--verbose: (bool...) Verbosity level, ignored | ||
410 | + -o,--out: (default stdout) Optional outfile, defaults to stdout | ||
411 | + <files>: (default stdin...) Files to take head of | ||
373 | """ | 412 | """ |
413 | + # On parsing failure this will show usage automatically | ||
414 | + var args = parse(help) | ||
374 | 415 | ||
375 | - echo args["n"].asInt | ||
376 | - echo args["alpha"].asBool | 416 | + # These two are special, they short out |
417 | + if args.showHelp: quit(help) | ||
418 | + if args.showVersion: quit("Version: 1.99") | ||
377 | 419 | ||
378 | - for v in args["verbose"].asSeq: | ||
379 | - echo "got ",v.asBool | 420 | + # Ok, so what did we get... |
421 | + let n = args["n"].asInt | ||
422 | + | ||
423 | + # This one is a helper | ||
424 | + let v = verbosityLevel(args) | ||
425 | + | ||
426 | + echo "Lines to show: " & $n | ||
427 | + echo "Verbosity level: " & $verbosityLevel(args) | ||
380 | 428 | ||
381 | let myfiles = args["files"].asSeq | 429 | let myfiles = args["files"].asSeq |
430 | + var outFile = args["out"].asFile | ||
431 | + | ||
382 | for f in myfiles: | 432 | for f in myfiles: |
383 | - echo f.asFile.readLine() | ||
384 | - | 433 | + for i in 1..n: |
434 | + writeln(outFile, string(f.asFile.readLine())) |