mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
116 lines
4.1 KiB
Go
116 lines
4.1 KiB
Go
// 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...)
|
|
}
|