modify flag inheritance to support individual flags

This commit is contained in:
Daylin Morgan 2024-11-12 14:20:16 -06:00
parent ad57eee373
commit 2a5dce888d
Signed by: daylin
GPG key ID: 950D13E9719334AD
2 changed files with 68 additions and 34 deletions

View file

@ -146,6 +146,12 @@ type
short*: char
long*: string
help*: NimNode
group*: string
Inherit = object
settings: set[CliSetting]
flags: seq[string]
groups: seq[string]
CliCfg = object
stopWords*: seq[string]
@ -160,9 +166,9 @@ type
version*, usage*: NimNode
flags*: seq[CliFlag]
builtinFlags*: seq[BuiltinFlag]
flagGroups: Table[string, seq[CliFlag]]
flagDefs*: seq[CliFlag]
required*: seq[string]
inheritFlags*: seq[string]
inherit*: Inherit
root*: bool
# some debug procs I use to wrap my ahead aroung the magic of *macro*
@ -252,24 +258,35 @@ func parseCliFlags(cfg: var CliCfg, node: NimNode) =
var group: string
expectKind node, nnkStmtList
for n in node:
<<< n
var flag: CliFlag
case n.kind
of nnkCall, nnkCommand:
flag = parseCliFlag(n)
if group == "":
cfg.flags.add flag
else:
if group notin cfg.flagGroups: cfg.flagGroups[group] = @[flag]
else: cfg.flagGroups[group].add flag
flag.group = group
cfg.flagDefs.add flag
of nnkBracket:
group = n[0].strVal
continue
of nnkPrefix:
if n[0].kind != nnkIdent and n[0].strVal != "^":
error "unexpected node in flags: " & $n.kind
expectKind n[1], nnkBracket
cfg.inheritFlags.add n[1][0].strVal
else: bad(n, "flag")
if
n[0].kind != nnkIdent or
n[0].strVal != "^" or
n.len != 2 or
n[1].kind notin [nnkBracket, nnkIdent, nnkStrLit]:
error "unexpected node in flags: " & $n.kind
case n[1].kind
of nnkBracket:
cfg.inherit.groups.add n[1][0].strVal
# cfg.inheritFlags.add n[1][0].strVal
of nnkIdent, nnkStrLit:
cfg.inherit.flags.add n[1].strval
else: bad(n, "flag")
else: bad(n, "flag")
cfg.flags = cfg.flagDefs.filterIt(it.group in ["", "global"])
func parseCliSetting(s: string): CliSetting =
try: parseEnum[CliSetting](s)
@ -332,24 +349,40 @@ func sliceStmts(node: NimNode): seq[
start = i + 1
func addInheritedFlags(child: var CliCfg, parent: CliCfg, self = false) =
let names = child.flags.mapIt(it.name)
var groups: seq[string]
if not self:
groups.add child.inheritFlags
func inheritFrom(child: var CliCfg, parent: CliCfg) =
## inherit settings from parent command
var
pflags: Table[string, CliFlag]
pgroups: Table[string, seq[CliFlag]]
flags: seq[string]
groups: seq[string]
# autoinherit the "global" flags
if "global" in parent.flagGroups:
flags &= child.inherit.flags
groups &= child.inherit.groups
for f in parent.flagDefs:
pflags[f.name] = f
if f.group in pgroups:
pgroups[f.group].add f
else:
pgroups[f.group] = @[f]
if "global" in pgroups:
groups.add "global"
for f in flags:
if f notin pflags:
error "expected parent command to define flag: " & f
else:
child.flags.add pflags[f]
for g in groups:
if g notin parent.flagGroups:
debugEcho parent.flagGroups.keys().toSeq()
error "expected flag group: " & g & " to exist in parent command"
for f in parent.flagGroups[g]:
if f.name in names:
error "global flag " & f.name & " conflicts with command flag"
child.flags.add f
if g notin pgroups:
error "expected parent command to define flag group " & g
else:
child.flags &= pgroups[g]
func parseCliSubcommands(cfg: var CliCfg, node: NimNode) =
expectKind node[1], nnkStmtList
@ -359,7 +392,7 @@ func parseCliSubcommands(cfg: var CliCfg, node: NimNode) =
nnkStmtList.newTree(node[1][s]), cfg.name & " " & name
)
subCfg.subName = name
subCfg.addInheritedFlags(cfg)
subCfg.inheritFrom(cfg)
cfg.subcommands.add subCfg
func parseHiddenFlags(cfg: var CliCfg, node: NimNode) =
@ -454,8 +487,6 @@ func parseCliBody(body: NimNode, name = "", root = false): CliCfg =
sub.pre = result.preSub
sub.post = result.postSub
result.addInheritedFlags(result, self = true)
if result.name == "":
error "missing required option: name"

View file

@ -16,8 +16,10 @@ hwylCli:
yes:
T bool
? "set flag to yes"
[config]
confiG:
[shared]
something:
? "some flag only needed in one subcommand"
config:
T seq[string]
? "path to config file"
* @["config.yml"]
@ -31,7 +33,7 @@ hwylCli:
the first subcommand
this command features both an enum flag and a Count flag
it also inherits the `[[config]` flag group
it also inherits the `[[shared]` flag group
"""
flags:
@ -42,7 +44,7 @@ hwylCli:
T Count
? "a count flag"
- v
^[config]
^[shared]
run:
echo "hello from `example one` command!"
echo args
@ -58,6 +60,7 @@ hwylCli:
and it will automatically be "bb"'ed [bold]this is bold text[/]
"""
flags:
^something
auto:
- a
? "some help"