diff options
Diffstat (limited to 'parse.go')
| -rw-r--r-- | parse.go | 52 |
1 files changed, 29 insertions, 23 deletions
@@ -56,12 +56,13 @@ type spec struct { env string // the name of the environment variable for this option, or empty for none defaultValue reflect.Value // default value for this option defaultString string // default value for this option, in string form to be displayed in help text - placeholder string // name of the data in help + placeholder string // placeholder string in help } // command represents a named subcommand, or the top-level command type command struct { name string + aliases []string help string dest path specs []*spec @@ -75,27 +76,21 @@ var ErrHelp = errors.New("help requested by user") // ErrVersion indicates that the builtin --version was provided var ErrVersion = errors.New("version requested by user") -// for monkey patching in example code +// for monkey patching in example and test code var mustParseExit = os.Exit +var mustParseOut io.Writer = os.Stdout // MustParse processes command line arguments and exits upon failure func MustParse(dest ...interface{}) *Parser { - return mustParse(Config{Exit: mustParseExit}, dest...) + return mustParse(Config{Exit: mustParseExit, Out: mustParseOut}, dest...) } // mustParse is a helper that facilitates testing func mustParse(config Config, dest ...interface{}) *Parser { - if config.Exit == nil { - config.Exit = os.Exit - } - if config.Out == nil { - config.Out = os.Stdout - } - p, err := NewParser(config, dest...) if err != nil { fmt.Fprintln(config.Out, err) - config.Exit(-1) + config.Exit(2) return nil } @@ -153,7 +148,7 @@ type Parser struct { epilogue string // the following field changes during processing of command line arguments - lastCmd *command + subcommand []string } // Versioned is the interface that the destination struct should implement to @@ -341,9 +336,8 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) { spec.help = help } - // Look at the tag - var isSubcommand bool // tracks whether this field is a subcommand - + // process each comma-separated part of the tag + var isSubcommand bool for _, key := range strings.Split(tag, ",") { if key == "" { continue @@ -384,18 +378,24 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) { } case key == "subcommand": // decide on a name for the subcommand - cmdname := value - if cmdname == "" { - cmdname = strings.ToLower(field.Name) + var cmdnames []string + if value == "" { + cmdnames = []string{strings.ToLower(field.Name)} + } else { + cmdnames = strings.Split(value, "|") + } + for i := range cmdnames { + cmdnames[i] = strings.TrimSpace(cmdnames[i]) } // parse the subcommand recursively - subcmd, err := cmdFromStruct(cmdname, subdest, field.Type) + subcmd, err := cmdFromStruct(cmdnames[0], subdest, field.Type) if err != nil { errs = append(errs, err.Error()) return false } + subcmd.aliases = cmdnames[1:] subcmd.parent = &cmd subcmd.help = field.Tag.Get("help") @@ -407,6 +407,7 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) { } } + // placeholder is the string used in the help text like this: "--somearg PLACEHOLDER" placeholder, hasPlaceholder := field.Tag.Lookup("placeholder") if hasPlaceholder { spec.placeholder = placeholder @@ -514,13 +515,13 @@ func (p *Parser) MustParse(args []string) { err := p.Parse(args) switch { case err == ErrHelp: - p.writeHelpForSubcommand(p.config.Out, p.lastCmd) + p.WriteHelpForSubcommand(p.config.Out, p.subcommand...) p.config.Exit(0) case err == ErrVersion: fmt.Fprintln(p.config.Out, p.version) p.config.Exit(0) case err != nil: - p.failWithSubcommand(err.Error(), p.lastCmd) + p.FailSubcommand(err.Error(), p.subcommand...) } } @@ -577,7 +578,7 @@ func (p *Parser) process(args []string) error { // union of specs for the chain of subcommands encountered so far curCmd := p.cmd - p.lastCmd = curCmd + p.subcommand = nil // make a copy of the specs because we will add to this list each time we expand a subcommand specs := make([]*spec, len(curCmd.specs)) @@ -648,7 +649,7 @@ func (p *Parser) process(args []string) error { } curCmd = subcmd - p.lastCmd = curCmd + p.subcommand = append(p.subcommand, arg) continue } @@ -842,6 +843,11 @@ func findSubcommand(cmds []*command, name string) *command { if cmd.name == name { return cmd } + for _, alias := range cmd.aliases { + if alias == name { + return cmd + } + } } return nil } |
