123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with this file,
- // You can obtain one at https://github.com/gogf/gf.
- //
- package gcmd
- import (
- "context"
- "github.com/gogf/gf/v2/container/gset"
- "github.com/gogf/gf/v2/errors/gerror"
- "github.com/gogf/gf/v2/text/gstr"
- )
- // Command holds the info about an argument that can handle custom logic.
- type Command struct {
- Name string // Command name(case-sensitive).
- Usage string // A brief line description about its usage, eg: gf build main.go [OPTION]
- Brief string // A brief info that describes what this command will do.
- Description string // A detailed description.
- Arguments []Argument // Argument array, configuring how this command act.
- Func Function // Custom function.
- FuncWithValue FuncWithValue // Custom function with output parameters that can interact with command caller.
- HelpFunc Function // Custom help function
- Examples string // Usage examples.
- Additional string // Additional info about this command, which will be appended to the end of help info.
- Strict bool // Strict parsing options, which means it returns error if invalid option given.
- CaseSensitive bool // CaseSensitive parsing options, which means it parses input options in case-sensitive way.
- Config string // Config node name, which also retrieves the values from config component along with command line.
- parent *Command // Parent command for internal usage.
- commands []*Command // Sub commands of this command.
- }
- // Function is a custom command callback function that is bound to a certain argument.
- type Function func(ctx context.Context, parser *Parser) (err error)
- // FuncWithValue is similar like Func but with output parameters that can interact with command caller.
- type FuncWithValue func(ctx context.Context, parser *Parser) (out interface{}, err error)
- // Argument is the command value that are used by certain command.
- type Argument struct {
- Name string // Option name.
- Short string // Option short.
- Brief string // Brief info about this Option, which is used in help info.
- IsArg bool // IsArg marks this argument taking value from command line argument instead of option.
- Orphan bool // Whether this Option having or having no value bound to it.
- }
- var (
- // defaultHelpOption is the default help option that will be automatically added to each command.
- defaultHelpOption = Argument{
- Name: `help`,
- Short: `h`,
- Brief: `more information about this command`,
- Orphan: true,
- }
- )
- // CommandFromCtx retrieves and returns Command from context.
- func CommandFromCtx(ctx context.Context) *Command {
- if v := ctx.Value(CtxKeyCommand); v != nil {
- if p, ok := v.(*Command); ok {
- return p
- }
- }
- return nil
- }
- // AddCommand adds one or more sub-commands to current command.
- func (c *Command) AddCommand(commands ...*Command) error {
- for _, cmd := range commands {
- if err := c.doAddCommand(cmd); err != nil {
- return err
- }
- }
- return nil
- }
- // doAddCommand adds one sub-command to current command.
- func (c *Command) doAddCommand(command *Command) error {
- command.Name = gstr.Trim(command.Name)
- if command.Name == "" {
- return gerror.New("command name should not be empty")
- }
- // Repeated check.
- var (
- commandNameSet = gset.NewStrSet()
- )
- for _, cmd := range c.commands {
- commandNameSet.Add(cmd.Name)
- }
- if commandNameSet.Contains(command.Name) {
- return gerror.Newf(`command "%s" is already added to command "%s"`, command.Name, c.Name)
- }
- // Add the given command to its sub-commands array.
- command.parent = c
- c.commands = append(c.commands, command)
- return nil
- }
- // AddObject adds one or more sub-commands to current command using struct object.
- func (c *Command) AddObject(objects ...interface{}) error {
- var (
- commands []*Command
- )
- for _, object := range objects {
- rootCommand, err := NewFromObject(object)
- if err != nil {
- return err
- }
- commands = append(commands, rootCommand)
- }
- return c.AddCommand(commands...)
- }
|