Recognize the options of the default command when it's not explicitly activated

This commit is contained in:
Zahary Karadjov 2019-03-26 10:45:19 +02:00
parent 7c0a19416e
commit 510a883594

View File

@ -306,6 +306,9 @@ proc load*(Configuration: type,
printCmdTree rootCmd printCmdTree rootCmd
let confAddr = addr result let confAddr = addr result
var activeCmds = @[addr rootCmd]
template lastCmd: auto = activeCmds[^1]
var rejectNextArgument = lastCmd.argumentsFieldIdx == -1
proc fail(msg: string) = proc fail(msg: string) =
if quitOnFailure: if quitOnFailure:
@ -315,11 +318,12 @@ proc load*(Configuration: type,
else: else:
raise newException(ConfigurationError, msg) raise newException(ConfigurationError, msg)
proc findOption(cmd: ptr CommandDesc, name: TaintedString): ptr OptionDesc = proc findOption(cmds: seq[ptr CommandDesc], name: TaintedString): ptr OptionDesc =
for o in cmd.options.mitems: for i in countdown(cmds.len - 1, 0):
if cmpIgnoreStyle(o.name, string(name)) == 0 or for o in cmds[i].options.mitems:
cmpIgnoreStyle(o.shortform, string(name)) == 0: if cmpIgnoreStyle(o.name, string(name)) == 0 or
return addr(o) cmpIgnoreStyle(o.shortform, string(name)) == 0:
return addr(o)
return nil return nil
@ -350,18 +354,29 @@ proc load*(Configuration: type,
elif o.hasDefault: elif o.hasDefault:
discard fieldSetters[o.fieldIdx][1](conf, TaintedString("")) discard fieldSetters[o.fieldIdx][1](conf, TaintedString(""))
var activeCmds = @[addr rootCmd] template activateCmd(activatedCmd: ptr CommandDesc, key: TaintedString) =
template currentCmd: auto = activeCmds[^1] let cmd = activatedCmd
discard applySetter(cmd.fieldIdx, key)
var rejectNextArgument = currentCmd.argumentsFieldIdx == -1 lastCmd.defaultSubCommand = -1
activeCmds.add cmd
rejectNextArgument = cmd.argumentsFieldIdx == -1
for kind, key, val in getopt(cmdLine): for kind, key, val in getopt(cmdLine):
case kind case kind
of cmdLongOption, cmdShortOption: of cmdLongOption, cmdShortOption:
if string(key) == "help": if string(key) == "help":
showHelp version, currentCmd[] showHelp version, lastCmd[]
var option = findOption(activeCmds, key)
if option == nil:
# We didn't find the option.
# Check if it's from the default command and activate it if necessary:
if lastCmd.defaultSubCommand != -1:
let defaultSubCmd = addr lastCmd.subCommands[lastCmd.defaultSubCommand]
option = findOption(@[defaultSubCmd], key)
if option != nil:
activateCmd(defaultSubCmd, TaintedString(""))
let option = currentCmd.findOption(key)
if option != nil: if option != nil:
if option.rejectNext: if option.rejectNext:
fail "The options '$1' should not be specified more than once" % [string(key)] fail "The options '$1' should not be specified more than once" % [string(key)]
@ -370,19 +385,16 @@ proc load*(Configuration: type,
fail "Unrecognized option '$1'" % [string(key)] fail "Unrecognized option '$1'" % [string(key)]
of cmdArgument: of cmdArgument:
if string(key) == "help" and currentCmd.subCommands.len > 0: if string(key) == "help" and lastCmd.subCommands.len > 0:
showHelp version, currentCmd[] showHelp version, lastCmd[]
let subCmd = currentCmd.findSubcommand(key) let subCmd = lastCmd.findSubcommand(key)
if subCmd != nil: if subCmd != nil:
discard applySetter(subCmd.fieldIdx, key) activateCmd(subCmd, key)
currentCmd.defaultSubCommand = -1
activeCmds.add subCmd
rejectNextArgument = currentCmd.argumentsFieldIdx == -1
else: else:
if rejectNextArgument: if rejectNextArgument:
fail "The command '$1' does not accept additional arguments" % [currentCmd.name] fail "The command '$1' does not accept additional arguments" % [lastCmd.name]
let argumentIdx = currentCmd.argumentsFieldIdx let argumentIdx = lastCmd.argumentsFieldIdx
doAssert argumentIdx != -1 doAssert argumentIdx != -1
rejectNextArgument = applySetter(argumentIdx, key) rejectNextArgument = applySetter(argumentIdx, key)