github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf.
     6  //
     7  
     8  package gcmd
     9  
    10  import (
    11  	"context"
    12  
    13  	"github.com/wangyougui/gf/v2/container/gset"
    14  	"github.com/wangyougui/gf/v2/errors/gerror"
    15  	"github.com/wangyougui/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  }