summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/integrii/flaggy/subCommand.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/integrii/flaggy/subCommand.go')
-rw-r--r--vendor/github.com/integrii/flaggy/subCommand.go109
1 files changed, 86 insertions, 23 deletions
diff --git a/vendor/github.com/integrii/flaggy/subCommand.go b/vendor/github.com/integrii/flaggy/subCommand.go
index c0c13073d..7f99e3e8a 100644
--- a/vendor/github.com/integrii/flaggy/subCommand.go
+++ b/vendor/github.com/integrii/flaggy/subCommand.go
@@ -23,15 +23,20 @@ type Subcommand struct {
Subcommands []*Subcommand
Flags []*Flag
PositionalFlags []*PositionalValue
- AdditionalHelpPrepend string // additional prepended message when Help is displayed
- AdditionalHelpAppend string // additional appended message when Help is displayed
- Used bool // indicates this subcommand was found and parsed
- Hidden bool // indicates this subcommand should be hidden from help
+ ParsedValues []parsedValue // a list of values and positionals parsed
+ AdditionalHelpPrepend string // additional prepended message when Help is displayed
+ AdditionalHelpAppend string // additional appended message when Help is displayed
+ Used bool // indicates this subcommand was found and parsed
+ Hidden bool // indicates this subcommand should be hidden from help
}
// NewSubcommand creates a new subcommand that can have flags or PositionalFlags
// added to it. The position starts with 1, not 0
func NewSubcommand(name string) *Subcommand {
+ if len(name) == 0 {
+ fmt.Fprintln(os.Stderr, "Error creating subcommand (NewSubcommand()). No subcommand name was specified.")
+ exitOrPanic(2)
+ }
newSC := &Subcommand{
Name: name,
}
@@ -39,10 +44,11 @@ func NewSubcommand(name string) *Subcommand {
}
// parseAllFlagsFromArgs parses the non-positional flags such as -f or -v=value
-// out of the supplied args and returns the positional items in order.
+// out of the supplied args and returns the resulting positional items in order,
+// all the flag names found (without values), a bool to indicate if help was
+// requested, and any errors found during parsing
func (sc *Subcommand) parseAllFlagsFromArgs(p *Parser, args []string) ([]string, bool, error) {
- var err error
var positionalOnlyArguments []string
var helpRequested bool // indicates the user has supplied -h and we
// should render help if we are the last subcommand
@@ -58,7 +64,7 @@ func (sc *Subcommand) parseAllFlagsFromArgs(p *Parser, args []string) ([]string,
// find all the normal flags (not positional) and parse them out
for i, a := range args {
- debugPrint("parsing arg", 1, a)
+ debugPrint("parsing arg:", a)
// evaluate if there is a following arg to avoid panics
var nextArgExists bool
@@ -121,62 +127,107 @@ func (sc *Subcommand) parseAllFlagsFromArgs(p *Parser, args []string) ([]string,
// this positional argument into a slice of their own, so that
// we can determine if its a subcommand or positional value later
positionalOnlyArguments = append(positionalOnlyArguments, a)
- case argIsFlagWithSpace:
+ // track this as a parsed value with the subcommand
+ sc.addParsedPositionalValue(a)
+ case argIsFlagWithSpace: // a flag with a space. ex) -k v or --key value
a = parseFlagToName(a)
+
// debugPrint("Arg", i, "is flag with space:", a)
// parse next arg as value to this flag and apply to subcommand flags
// if the flag is a bool flag, then we check for a following positional
// and skip it if necessary
if flagIsBool(sc, p, a) {
debugPrint(sc.Name, "bool flag", a, "next var is:", nextArg)
- _, err = setValueForParsers(a, "true", p, sc)
+ // set the value in this subcommand and its root parser
+ valueSet, err := setValueForParsers(a, "true", p, sc)
// if an error occurs, just return it and quit parsing
if err != nil {
return []string{}, false, err
}
- // by default, we just assign the next argument to the value and continue
+
+ // log all values parsed by this subcommand. We leave the value blank
+ // because the bool value had no explicit true or false supplied
+ if valueSet {
+ sc.addParsedFlag(a, "")
+ }
+
+ // we've found and set a standalone bool flag, so we move on to the next
+ // argument in the list of arguments
continue
}
skipNext = true
- debugPrint(sc.Name, "NOT bool flag", a)
+ // debugPrint(sc.Name, "NOT bool flag", a)
// if the next arg was not found, then show a Help message
if !nextArgExists {
p.ShowHelpWithMessage("Expected a following arg for flag " + a + ", but it did not exist.")
exitOrPanic(2)
}
- _, err = setValueForParsers(a, nextArg, p, sc)
+ valueSet, err := setValueForParsers(a, nextArg, p, sc)
if err != nil {
return []string{}, false, err
}
- case argIsFlagWithValue:
+
+ // log all parsed values in the subcommand
+ if valueSet {
+ sc.addParsedFlag(a, nextArg)
+ }
+ case argIsFlagWithValue: // a flag with an equals sign. ex) -k=v or --key=value
// debugPrint("Arg", i, "is flag with value:", a)
a = parseFlagToName(a)
+
// parse flag into key and value and apply to subcommand flags
key, val := parseArgWithValue(a)
- _, err = setValueForParsers(key, val, p, sc)
+
+ // set the value in this subcommand and its root parser
+ valueSet, err := setValueForParsers(key, val, p, sc)
if err != nil {
return []string{}, false, err
}
- // if this flag type was found and not set, and the parser is set to show
- // Help when an unknown flag is found, then show Help and exit.
- }
+ // log all values parsed by the subcommand
+ if valueSet {
+ sc.addParsedFlag(a, val)
+ }
+ }
}
return positionalOnlyArguments, helpRequested, nil
}
-// Parse causes the argument parser to parse based on the supplied []string.
-// depth specifies the non-flag subcommand positional depth
+// findAllParsedValues finds all values parsed by all subcommands and this
+// subcommand and its child subcommands
+func (sc *Subcommand) findAllParsedValues() []parsedValue {
+ parsedValues := sc.ParsedValues
+ for _, sc := range sc.Subcommands {
+ // skip unused subcommands
+ if !sc.Used {
+ continue
+ }
+ parsedValues = append(parsedValues, sc.findAllParsedValues()...)
+ }
+ return parsedValues
+}
+
+// parse causes the argument parser to parse based on the supplied []string.
+// depth specifies the non-flag subcommand positional depth. A slice of flags
+// and subcommands parsed is returned so that the parser can ultimately decide
+// if there were any unexpected values supplied by the user
func (sc *Subcommand) parse(p *Parser, args []string, depth int) error {
debugPrint("- Parsing subcommand", sc.Name, "with depth of", depth, "and args", args)
// if a command is parsed, its used
sc.Used = true
+ debugPrint("used subcommand", sc.Name, sc.ShortName)
+ if len(sc.Name) > 0 {
+ sc.addParsedPositionalValue(sc.Name)
+ }
+ if len(sc.ShortName) > 0 {
+ sc.addParsedPositionalValue(sc.ShortName)
+ }
// as subcommands are used, they become the context of the parser. This helps
// us understand how to display help based on which subcommand is being used
@@ -191,9 +242,10 @@ func (sc *Subcommand) parse(p *Parser, args []string, depth int) error {
sc.ensureNoConflictWithBuiltinVersion()
}
- // Parse the normal flags out of the argument list and retain the positionals.
- // Apply the flags to the parent parser and the current subcommand context.
- // ./command -f -z subcommand someVar -b becomes ./command subcommand somevar
+ // Parse the normal flags out of the argument list and return the positionals
+ // (subcommands and positional values), along with the flags used.
+ // Then the flag values are applied to the parent parser and the current
+ // subcommand being parsed.
positionalOnlyArguments, helpRequested, err := sc.parseAllFlagsFromArgs(p, args)
if err != nil {
return err
@@ -292,7 +344,7 @@ func (sc *Subcommand) parse(p *Parser, args []string, depth int) error {
}
// find any positionals that were not used on subcommands that were
- // found and throw help (unknown argument)
+ // found and throw help (unknown argument) in the global parse or subcommand
for _, pv := range p.PositionalFlags {
if pv.Required && !pv.Found {
p.ShowHelpWithMessage("Required global positional variable " + pv.Name + " not found at position " + strconv.Itoa(pv.Position))
@@ -309,6 +361,17 @@ func (sc *Subcommand) parse(p *Parser, args []string, depth int) error {
return nil
}
+// addParsedFlag makes it easy to append flag values parsed by the subcommand
+func (sc *Subcommand) addParsedFlag(key string, value string) {
+ sc.ParsedValues = append(sc.ParsedValues, newParsedValue(key, value, false))
+}
+
+// addParsedPositionalValue makes it easy to append positionals parsed by the
+// subcommand
+func (sc *Subcommand) addParsedPositionalValue(value string) {
+ sc.ParsedValues = append(sc.ParsedValues, newParsedValue("", value, true))
+}
+
// FlagExists lets you know if the flag name exists as either a short or long
// name in the (sub)command
func (sc *Subcommand) FlagExists(name string) bool {