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 | 253 | parseSpec(usage) |
254 | 254 | addQuitProc(closeFiles) |
255 | 255 | |
256 | + # Collect failures | |
257 | + var failures = newSeq[string]() | |
258 | + | |
256 | 259 | # parse the flags and arguments |
257 | 260 | while i <= n: |
258 | 261 | arg = next() |
... | ... | @@ -275,7 +278,8 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = |
275 | 278 | for c in arg.tail: |
276 | 279 | let f = get_alias(c) |
277 | 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 | 283 | flagvalues.add(@[f,"true"]) |
280 | 284 | i.used = true |
281 | 285 | else: # argument (stored as \001, \002, etc |
... | ... | @@ -286,14 +290,28 @@ proc parseArguments*(usage: string, args: seq[string]): Table[string,PValue] = |
286 | 290 | if not info.multiple: k += 1 |
287 | 291 | flagvalues.add(@[flag,value]) |
288 | 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 | 302 | # any flags not mentioned? |
291 | 303 | for flag,info in parm_spec: |
292 | 304 | if not info.used: |
293 | 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 | 315 | # cool, we have the info, can convert known flags |
298 | 316 | for item in flagvalues: |
299 | 317 | var pval: PValue; |
... | ... | @@ -362,23 +380,55 @@ proc parse*(usage: string): Table[string,PValue] = |
362 | 380 | args[i] = paramStr(i) |
363 | 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 | 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 | 429 | let myfiles = args["files"].asSeq |
430 | + var outFile = args["out"].asFile | |
431 | + | |
382 | 432 | for f in myfiles: |
383 | - echo f.asFile.readLine() | |
384 | - | |
433 | + for i in 1..n: | |
434 | + writeln(outFile, string(f.asFile.readLine())) | ... | ... |