Commit c577e6e67d222e20662f2fe90d06fe1d013a27a0

Authored by Göran Krampe
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()))