mirror of
https://github.com/daylinmorgan/hwylterm.git
synced 2024-11-16 06:28:32 -06:00
add support for enums and count flags
This commit is contained in:
parent
8b37c0dad9
commit
77cfae4d26
2 changed files with 44 additions and 10 deletions
|
@ -121,6 +121,9 @@ proc `$`*(cli: HwylCliHelp): string =
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Count* = object
|
||||||
|
val*: int
|
||||||
|
|
||||||
CliSetting = enum
|
CliSetting = enum
|
||||||
NoHelpFlag, NoArgsShowHelp
|
NoHelpFlag, NoArgsShowHelp
|
||||||
BuiltinFlag = object
|
BuiltinFlag = object
|
||||||
|
@ -453,6 +456,7 @@ func parseCliBody(body: NimNode, name = ""): CliCfg =
|
||||||
if result.name == "":
|
if result.name == "":
|
||||||
error "missing required option: name"
|
error "missing required option: name"
|
||||||
|
|
||||||
|
# TODO: validate "required" flags exist here
|
||||||
result.addBuiltinFlags()
|
result.addBuiltinFlags()
|
||||||
|
|
||||||
func flagToTuple(f: CliFlag | BuiltinFlag): NimNode =
|
func flagToTuple(f: CliFlag | BuiltinFlag): NimNode =
|
||||||
|
@ -523,6 +527,22 @@ proc parse*(p: OptParser, key: string, val: string, target: var int) =
|
||||||
"failed to parse value for [b]" & key & "[/] as integer: [b]" & val
|
"failed to parse value for [b]" & key & "[/] as integer: [b]" & val
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro enumNames(a: typed): untyped =
|
||||||
|
## unexported macro copied from std/enumutils
|
||||||
|
result = newNimNode(nnkBracket)
|
||||||
|
for ai in a.getType[1][1..^1]:
|
||||||
|
assert ai.kind == nnkSym
|
||||||
|
result.add newLit ai.strVal
|
||||||
|
|
||||||
|
proc parse*[E: enum](p: OptParser, key: string, val: string, target: var E) =
|
||||||
|
try:
|
||||||
|
target = parseEnum[E](val)
|
||||||
|
except:
|
||||||
|
let choices = enumNames(E).join(",")
|
||||||
|
hwylCliError(
|
||||||
|
"failed to parse value for [b]" & key & "[/] as enum: [b]" & val & "[/], expected one of: " & choices
|
||||||
|
)
|
||||||
|
|
||||||
proc parse*(p: OptParser, key: string, val: string, target: var float) =
|
proc parse*(p: OptParser, key: string, val: string, target: var float) =
|
||||||
try:
|
try:
|
||||||
target = parseFloat(val)
|
target = parseFloat(val)
|
||||||
|
@ -531,11 +551,14 @@ proc parse*(p: OptParser, key: string, val: string, target: var float) =
|
||||||
"failed to parse value for [b]" & key & "[/] as float: [b]" & val
|
"failed to parse value for [b]" & key & "[/] as float: [b]" & val
|
||||||
)
|
)
|
||||||
|
|
||||||
proc parse[T](p: OptParser, key: string, val: string, target: var seq[T]) =
|
proc parse*[T](p: OptParser, key: string, val: string, target: var seq[T]) =
|
||||||
var parsed: T
|
var parsed: T
|
||||||
parse(p, key, val, parsed)
|
parse(p, key, val, parsed)
|
||||||
target.add parsed
|
target.add parsed
|
||||||
|
|
||||||
|
proc parse*(p: OptParser, key: string, val: string, target: var Count) =
|
||||||
|
inc target.val
|
||||||
|
|
||||||
func shortLongCaseStmt(cfg: CliCfg, printHelpName: NimNode, version: NimNode): NimNode =
|
func shortLongCaseStmt(cfg: CliCfg, printHelpName: NimNode, version: NimNode): NimNode =
|
||||||
var caseStmt = nnkCaseStmt.newTree(ident("key"))
|
var caseStmt = nnkCaseStmt.newTree(ident("key"))
|
||||||
caseStmt.add nnkOfBranch.newTree(newLit(""), quote do: hwylCliError("empty flag not supported currently"))
|
caseStmt.add nnkOfBranch.newTree(newLit(""), quote do: hwylCliError("empty flag not supported currently"))
|
||||||
|
@ -567,15 +590,18 @@ func shortLongCaseStmt(cfg: CliCfg, printHelpName: NimNode, version: NimNode): N
|
||||||
func isBool(f: CliFlag): bool =
|
func isBool(f: CliFlag): bool =
|
||||||
f.typeNode == ident"bool"
|
f.typeNode == ident"bool"
|
||||||
|
|
||||||
|
func isCount(f: CliFlag): bool =
|
||||||
|
f.typeNode == ident"Count"
|
||||||
|
|
||||||
func getNoVals(cfg: CliCfg): tuple[long: NimNode, short: NimNode] =
|
func getNoVals(cfg: CliCfg): tuple[long: NimNode, short: NimNode] =
|
||||||
let boolFlags = cfg.flags.filterIt(it.isBool)
|
let flagFlags = cfg.flags.filterIt(it.isBool or it.isCount)
|
||||||
let long =
|
let long =
|
||||||
nnkBracket.newTree(
|
nnkBracket.newTree(
|
||||||
(boolFlags.mapIt(it.long) & cfg.builtinFlags.mapIt(it.long)).filterIt(it != "").mapIt(newLit(it))
|
(flagFlags.mapIt(it.long) & cfg.builtinFlags.mapIt(it.long)).filterIt(it != "").mapIt(newLit(it))
|
||||||
)
|
)
|
||||||
let short =
|
let short =
|
||||||
nnkCurly.newTree(
|
nnkCurly.newTree(
|
||||||
(boolFlags.mapIt(it.short) & cfg.builtinFlags.mapIt(it.short)).filterIt(it != '\x00').mapIt(newLit(it))
|
(flagFlags.mapIt(it.short) & cfg.builtinFlags.mapIt(it.short)).filterIt(it != '\x00').mapIt(newLit(it))
|
||||||
)
|
)
|
||||||
result = (nnkPrefix.newTree(ident"@",long), short)
|
result = (nnkPrefix.newTree(ident"@",long), short)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import std/strformat
|
import std/strformat
|
||||||
import hwylterm/hwylcli
|
import hwylterm/hwylcli
|
||||||
|
|
||||||
|
type
|
||||||
|
Color = enum
|
||||||
|
red, blue, green
|
||||||
|
|
||||||
hwylCli:
|
hwylCli:
|
||||||
name "example"
|
name "example"
|
||||||
V "0.1.0"
|
V "0.1.0"
|
||||||
|
@ -20,14 +24,18 @@ hwylCli:
|
||||||
subcommands:
|
subcommands:
|
||||||
--- one
|
--- one
|
||||||
... "the first subcommand"
|
... "the first subcommand"
|
||||||
required flag
|
|
||||||
flags:
|
flags:
|
||||||
`long-flag` "some help"
|
color:
|
||||||
flag:
|
T Color
|
||||||
? "some other help"
|
? "a color (red, green, blue)"
|
||||||
|
verbose:
|
||||||
|
T Count
|
||||||
|
? "a count flag"
|
||||||
|
- v
|
||||||
run:
|
run:
|
||||||
echo "hello from `example one` command!"
|
echo "hello from `example one` command!"
|
||||||
echo "long-flag and flag are: " & `long-flag` & "," & `flag` & " by default strings"
|
echo fmt"{color=}"
|
||||||
|
echo fmt"{verbose=}"
|
||||||
|
|
||||||
--- two
|
--- two
|
||||||
... """
|
... """
|
||||||
|
|
Loading…
Reference in a new issue