change how flags are propagated

This commit is contained in:
Daylin Morgan 2024-11-13 11:29:09 -06:00
parent 2b2bf15fb9
commit cbeefd675c
Signed by: daylin
GPG key ID: 950D13E9719334AD
2 changed files with 59 additions and 23 deletions

View file

@ -154,6 +154,7 @@ type
long*: string long*: string
help*: NimNode help*: NimNode
group*: string group*: string
inherited*: bool
Inherit = object Inherit = object
settings: set[CliSetting] settings: set[CliSetting]
@ -188,9 +189,25 @@ template `<<<`(s: string) {.used.} =
# some debug procs I use to wrap my ahead aroung the magic of *macro* # some debug procs I use to wrap my ahead aroung the magic of *macro*
template `<<<`(n: NimNode) {.used.} = template `<<<`(n: NimNode) {.used.} =
## for debugging macros ## for debugging macros
<<< astToStr n
<<< treeRepr n <<< treeRepr n
func `<<<`(f: CliFlag) {.used.}=
var s: string
let fields = [
("name", f.name),
("long", f.long),
("short", $f.short),
("typeNode", f.typeNode.lispRepr),
("group", f.group)
]
s.add "CliFlag(\n"
for (k,v) in fields:
s.add "$1 = $2\n" % [k,v]
s.add ")"
<<< s
func bad(n: NimNode, argument: string = "") = func bad(n: NimNode, argument: string = "") =
var msg = "unexpected node kind: " & $n.kind var msg = "unexpected node kind: " & $n.kind
if argument != "": if argument != "":
@ -384,15 +401,19 @@ func inheritFrom(child: var CliCfg, parent: CliCfg) =
for f in flags: for f in flags:
if f notin pflags: if f notin pflags:
error "expected parent command to define flag: " & f error "expected parent command to have flag: " & f
else: else:
child.flags.add pflags[f] child.flags.add pflags[f]
# so subcommands can continue the inheritance
child.flagDefs.add pflags[f]
for g in groups: for g in groups:
if g notin pgroups: if g notin pgroups:
error "expected parent command to define flag group " & g error "expected parent command to have flag group " & g
else: else:
child.flags &= pgroups[g] child.flags.add pgroups[g]
# so subcommands can continue the inheritance
child.flagDefs.add pgroups[g]
func parseCliSubcommands(cfg: var CliCfg, node: NimNode) = func parseCliSubcommands(cfg: var CliCfg, node: NimNode) =
expectKind node[1], nnkStmtList expectKind node[1], nnkStmtList
@ -401,7 +422,6 @@ func parseCliSubcommands(cfg: var CliCfg, node: NimNode) =
nnkStmtList.newTree(node[1][s]), cfg.name & " " & name nnkStmtList.newTree(node[1][s]), cfg.name & " " & name
) )
subCfg.subName = name subCfg.subName = name
subCfg.inheritFrom(cfg)
cfg.stopWords.add name cfg.stopWords.add name
cfg.stopWords.add subCfg.alias.toSeq() cfg.stopWords.add subCfg.alias.toSeq()
cfg.subcommands.add subCfg cfg.subcommands.add subCfg
@ -466,6 +486,13 @@ func pasrseCliAlias(cfg: var CliCfg, node: NimNode) =
cfg.alias.incl s cfg.alias.incl s
else: bad(n, "alias") else: bad(n, "alias")
func propagate(c: var CliCfg) =
for child in c.subcommands.mitems:
child.pre = c.preSub
child.post = c.postSub
child.inheritFrom(c)
propagate(child)
func parseCliBody(body: NimNode, name = "", root = false): CliCfg = func parseCliBody(body: NimNode, name = "", root = false): CliCfg =
result.name = name result.name = name
@ -510,16 +537,19 @@ func parseCliBody(body: NimNode, name = "", root = false): CliCfg =
result.postSub = call[1] result.postSub = call[1]
else: else:
error "unknown hwylCli setting: " & name error "unknown hwylCli setting: " & name
#
for sub in result.subcommands.mitems: # for sub in result.subcommands.mitems:
sub.pre = result.preSub # # sub.inheritFrom(result)
sub.post = result.postSub # sub.pre = result.preSub
# sub.post = result.postSub
if result.name == "": if result.name == "":
error "missing required option: name" error "missing required option: name"
# TODO: validate "required" flags exist here # TODO: validate "required" flags exist here
result.addBuiltinFlags() result.addBuiltinFlags()
if root:
propagate(result)
func flagToTuple(f: CliFlag | BuiltinFlag): NimNode = func flagToTuple(f: CliFlag | BuiltinFlag): NimNode =
let let
@ -695,11 +725,15 @@ func getNoVals(cfg: CliCfg): tuple[long: NimNode, short: NimNode] =
result = (nnkPrefix.newTree(ident"@",long), short) result = (nnkPrefix.newTree(ident"@",long), short)
func setFlagVars(cfg: CliCfg): NimNode = func setFlagVars(cfg: CliCfg): NimNode =
result = nnkVarSection.newTree().add( ## generate all variables not covered in global module
cfg.flags.mapIt( result = nnkVarSection.newTree()
nnkIdentDefs.newTree(it.ident, it.typeNode, newEmptyNode()) let flags =
) if cfg.root: cfg.flags
) else: cfg.flags.filterIt(it.group != "global")
result.add flags.mapIt(
nnkIdentDefs.newTree(it.ident, it.typeNode, newEmptyNode())
)
func literalFlags(f: CliFlag): NimNode = func literalFlags(f: CliFlag): NimNode =
var flags: seq[string] var flags: seq[string]

View file

@ -13,6 +13,9 @@ hwylCli:
... "a description of hwylterm" ... "a description of hwylterm"
flags: flags:
[global] [global]
color:
T Color
? "a color (red, green, blue)"
yes: yes:
T bool T bool
? "set flag to yes" ? "set flag to yes"
@ -25,10 +28,12 @@ hwylCli:
* @["config.yml"] * @["config.yml"]
preSub: preSub:
echo "this is run after subcommand parsing but before its run block" echo "this is run after subcommand parsing but before its run block"
echo fmt"{yes=}, {color=}"
run: run:
echo "this is always run prior to subcommand parsing" echo "this is always run prior to subcommand parsing"
echo fmt"{yes=}, {color=}"
subcommands: subcommands:
[onelonger] [one]
... """ ... """
the first subcommand the first subcommand
@ -36,11 +41,8 @@ hwylCli:
it also inherits the `[[shared]` flag group it also inherits the `[[shared]` flag group
""" """
alias o,"one", `one-l` alias o
flags: flags:
color:
T Color
? "a color (red, green, blue)"
verbose: verbose:
T Count T Count
? "a count flag" ? "a count flag"
@ -50,7 +52,7 @@ hwylCli:
[subsub] [subsub]
... "another level down subcommand" ... "another level down subcommand"
flags: flags:
^color ^config
run: run:
echo fmt"{color=}" echo fmt"{color=}"
@ -61,7 +63,7 @@ hwylCli:
echo fmt"{verbose=}" echo fmt"{verbose=}"
echo fmt"{config=}" echo fmt"{config=}"
["two-longer"] [two]
... """ ... """
some second subcommand some second subcommand