3535 isOptional* : bool
3636 # # When an argument is optional, it means that the user
3737 # # doesn't have to provide it when executing the command
38+ choices* : seq [string ]
39+ # # For `any` arguments, the list of allowed values
3840
3941 CommandType * = enum
4042 # # The type of the command, used for parsing and validation at runtime
@@ -217,7 +219,8 @@ proc toCommand*(cmd: PluginCommand): Command =
217219 kind: a.kind,
218220 dataType: a.datatype,
219221 name: a.name,
220- isOptional: a.isOptional
222+ isOptional: a.isOptional,
223+ choices: a.choices
221224 )
222225
223226proc preparePrintCommand (cmd: Command ,
@@ -240,14 +243,23 @@ proc preparePrintCommand(cmd: Command,
240243 parts.add ColoredSegment (text: " ?" , fg: fgBlack, bright: true )
241244 parts.add ColoredSegment (text: arg.name, fg: fgDefault)
242245 if showTypes:
243- parts.add ColoredSegment (text: " :" & $ arg.dataType, fg: fgCyan)
246+ var typeStr = " :" & $ arg.dataType
247+ if arg.dataType == ktAny and arg.choices.len > 0 :
248+ typeStr.add " [" & arg.choices.join (" ," ) & " ]"
249+ parts.add ColoredSegment (text: typeStr, fg: fgCyan)
244250 parts.add ColoredSegment (text: " >" , fg: fgBlack, bright: true )
245251 of cmdLongOption:
246252 if showFlags:
247- flags.add arg.name & " :" & $ arg.dataType
253+ var flagStr = arg.name & " :" & $ arg.dataType
254+ if arg.dataType == ktAny and arg.choices.len > 0 :
255+ flagStr.add " [" & arg.choices.join (" ," ) & " ]"
256+ flags.add flagStr
248257 of cmdShortOption:
249258 if showFlags:
250- flags.add arg.name & " :" & $ arg.dataType
259+ var flagStr = arg.name & " :" & $ arg.dataType
260+ if arg.dataType == ktAny and arg.choices.len > 0 :
261+ flagStr.add " [" & arg.choices.join (" ," ) & " ]"
262+ flags.add flagStr
251263 else : discard
252264 if cmd.arguments.len > 0 :
253265 if not showFlags:
@@ -309,16 +321,17 @@ proc printUsage(app: Kapsis,
309321 var isHighlighted = false
310322 if x[1 ].len > 0 :
311323 let plainLen = segmentLen (x[0 ])
312- var pad = longestCmd - plainLen + 18
324+ var pad = longestCmd - plainLen + 8
313325 let hasFlagIcon = block :
314326 var found = false
315327 for s in x[0 ]:
316328 if s.text.contains (" ⚑" ): found = true ; break
317329 found
318330 if showTypes:
319- pad -= 2
331+ pad += 4
320332 elif hasFlagIcon:
321333 pad += 2
334+ if pad < 1 : pad = 1
322335 let wrapped = wrapWords (x[1 ], 60 )
323336 let lines = wrapped.splitLines
324337 let descCol = visualLen (x[0 ]) + pad
@@ -406,6 +419,7 @@ proc parseCommand(cmdName: NimNode, cmdArgs: seq[NimNode] = @[],
406419 # parse arguments and subcommands
407420 var isOptional: bool
408421 var argTypeNode, argNameNode: NimNode
422+ var argChoices: seq [string ]
409423 var kind: CmdLineKind
410424 case n.kind
411425 of nnkDotExpr:
@@ -415,6 +429,13 @@ proc parseCommand(cmdName: NimNode, cmdArgs: seq[NimNode] = @[],
415429 of nnkCommand, nnkCall:
416430 argTypeNode = n[0 ]
417431 argNameNode = n[1 ]
432+ if argTypeNode.eqIdent " any" :
433+ # `any(name = ["a", "b"])` — arg name + allowed choices
434+ if argNameNode.kind != nnkExprEqExpr:
435+ error (" `any` arguments require a list of choices: any(name = [\" a\" , \" b\" ])" , n)
436+ for v in argNameNode[1 ]:
437+ argChoices.add v.strVal
438+ argNameNode = argNameNode[0 ]
418439 if argNameNode.kind == nnkStrLit and argNameNode.strVal.startsWith (" --" ):
419440 # we handle long options like `--verbose` by
420441 kind = cmdLongOption
@@ -438,6 +459,13 @@ proc parseCommand(cmdName: NimNode, cmdArgs: seq[NimNode] = @[],
438459 elif n[1 ].kind == nnkCall:
439460 argTypeNode = n[1 ][0 ]
440461 argNameNode = n[1 ][1 ]
462+ if argTypeNode.eqIdent " any" :
463+ # `?any(name = ["a", "b"])`
464+ if argNameNode.kind != nnkExprEqExpr:
465+ error (" `any` arguments require a list of choices: any(name = [\" a\" , \" b\" ])" , n)
466+ for v in argNameNode[1 ]:
467+ argChoices.add v.strVal
468+ argNameNode = argNameNode[0 ]
441469 if argNameNode.strVal.startsWith (" --" ):
442470 kind = cmdLongOption
443471 elif argNameNode.strVal.startsWith (" -" ):
@@ -462,6 +490,7 @@ proc parseCommand(cmdName: NimNode, cmdArgs: seq[NimNode] = @[],
462490 nnkExprColonExpr.newTree (ident " dataType" ,newLit (argType)),
463491 nnkExprColonExpr.newTree (ident " name" , newLit (argNameNode.strVal)),
464492 nnkExprColonExpr.newTree (ident " isOptional" , newLit (isOptional)),
493+ nnkExprColonExpr.newTree (ident " choices" , newLit (argChoices)),
465494 )
466495 )
467496
0 commit comments