github.com/gogf/gf/v2@v2.7.4/os/gcmd/gcmd_command.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 // 7 8 package gcmd 9 10 import ( 11 "context" 12 13 "github.com/gogf/gf/v2/container/gset" 14 "github.com/gogf/gf/v2/errors/gerror" 15 "github.com/gogf/gf/v2/text/gstr" 16 ) 17 18 // Command holds the info about an argument that can handle custom logic. 19 type Command struct { 20 Name string // Command name(case-sensitive). 21 Usage string // A brief line description about its usage, eg: gf build main.go [OPTION] 22 Brief string // A brief info that describes what this command will do. 23 Description string // A detailed description. 24 Arguments []Argument // Argument array, configuring how this command act. 25 Func Function // Custom function. 26 FuncWithValue FuncWithValue // Custom function with output parameters that can interact with command caller. 27 HelpFunc Function // Custom help function 28 Examples string // Usage examples. 29 Additional string // Additional info about this command, which will be appended to the end of help info. 30 Strict bool // Strict parsing options, which means it returns error if invalid option given. 31 CaseSensitive bool // CaseSensitive parsing options, which means it parses input options in case-sensitive way. 32 Config string // Config node name, which also retrieves the values from config component along with command line. 33 parent *Command // Parent command for internal usage. 34 commands []*Command // Sub commands of this command. 35 } 36 37 // Function is a custom command callback function that is bound to a certain argument. 38 type Function func(ctx context.Context, parser *Parser) (err error) 39 40 // FuncWithValue is similar like Func but with output parameters that can interact with command caller. 41 type FuncWithValue func(ctx context.Context, parser *Parser) (out interface{}, err error) 42 43 // Argument is the command value that are used by certain command. 44 type Argument struct { 45 Name string // Option name. 46 Short string // Option short. 47 Brief string // Brief info about this Option, which is used in help info. 48 IsArg bool // IsArg marks this argument taking value from command line argument instead of option. 49 Orphan bool // Whether this Option having or having no value bound to it. 50 } 51 52 var ( 53 // defaultHelpOption is the default help option that will be automatically added to each command. 54 defaultHelpOption = Argument{ 55 Name: `help`, 56 Short: `h`, 57 Brief: `more information about this command`, 58 Orphan: true, 59 } 60 ) 61 62 // CommandFromCtx retrieves and returns Command from context. 63 func CommandFromCtx(ctx context.Context) *Command { 64 if v := ctx.Value(CtxKeyCommand); v != nil { 65 if p, ok := v.(*Command); ok { 66 return p 67 } 68 } 69 return nil 70 } 71 72 // AddCommand adds one or more sub-commands to current command. 73 func (c *Command) AddCommand(commands ...*Command) error { 74 for _, cmd := range commands { 75 if err := c.doAddCommand(cmd); err != nil { 76 return err 77 } 78 } 79 return nil 80 } 81 82 // doAddCommand adds one sub-command to current command. 83 func (c *Command) doAddCommand(command *Command) error { 84 command.Name = gstr.Trim(command.Name) 85 if command.Name == "" { 86 return gerror.New("command name should not be empty") 87 } 88 // Repeated check. 89 var ( 90 commandNameSet = gset.NewStrSet() 91 ) 92 for _, cmd := range c.commands { 93 commandNameSet.Add(cmd.Name) 94 } 95 if commandNameSet.Contains(command.Name) { 96 return gerror.Newf(`command "%s" is already added to command "%s"`, command.Name, c.Name) 97 } 98 // Add the given command to its sub-commands array. 99 command.parent = c 100 c.commands = append(c.commands, command) 101 return nil 102 } 103 104 // AddObject adds one or more sub-commands to current command using struct object. 105 func (c *Command) AddObject(objects ...interface{}) error { 106 var commands []*Command 107 for _, object := range objects { 108 rootCommand, err := NewFromObject(object) 109 if err != nil { 110 return err 111 } 112 commands = append(commands, rootCommand) 113 } 114 return c.AddCommand(commands...) 115 }