2021-11-21 13:09:45 +08:00
|
|
|
// 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"
|
|
|
|
"fmt"
|
2021-11-21 22:38:47 +08:00
|
|
|
"os"
|
2021-11-21 13:09:45 +08:00
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
|
|
)
|
|
|
|
|
2021-11-21 13:11:28 +08:00
|
|
|
// Run calls custom function that bound to this command.
|
2021-11-21 13:09:45 +08:00
|
|
|
func (c *Command) Run(ctx context.Context) error {
|
2021-11-23 20:26:55 +08:00
|
|
|
_, err := c.RunWithValue(ctx)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// RunWithValue calls custom function that bound to this command with value output.
|
|
|
|
func (c *Command) RunWithValue(ctx context.Context) (value interface{}, err error) {
|
2021-11-21 13:09:45 +08:00
|
|
|
// Parse command arguments and options using default algorithm.
|
|
|
|
parser, err := Parse(nil)
|
|
|
|
if err != nil {
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, err
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
args := parser.GetArgAll()
|
|
|
|
if len(args) == 1 {
|
2021-11-24 16:17:50 +08:00
|
|
|
// If no arguments passed but binary name, it then prints help.
|
2021-11-21 13:09:45 +08:00
|
|
|
if c.HelpFunc != nil {
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, c.HelpFunc(ctx, parser)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, c.defaultHelpFunc(ctx, parser)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Exclude the root binary name.
|
|
|
|
args = args[1:]
|
|
|
|
|
|
|
|
// Find the matched command and run it.
|
|
|
|
if subCommand := c.searchCommand(args); subCommand != nil {
|
|
|
|
return subCommand.doRun(ctx, parser)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print error and help command if no command found.
|
2021-11-21 22:38:47 +08:00
|
|
|
fmt.Printf(
|
|
|
|
"ERROR: command \"%s\" not found for arguments \"%s\"\n",
|
|
|
|
gstr.Join(args, " "),
|
|
|
|
gstr.Join(os.Args, " "),
|
|
|
|
)
|
2021-11-21 13:09:45 +08:00
|
|
|
c.Print()
|
|
|
|
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, nil
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
|
2021-11-23 20:26:55 +08:00
|
|
|
func (c *Command) doRun(ctx context.Context, parser *Parser) (value interface{}, err error) {
|
2021-11-21 13:09:45 +08:00
|
|
|
// Check built-in help command.
|
|
|
|
if parser.ContainsOpt(helpOptionName) || parser.ContainsOpt(helpOptionNameShort) {
|
|
|
|
if c.HelpFunc != nil {
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, c.HelpFunc(ctx, parser)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, c.defaultHelpFunc(ctx, parser)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
// Reparse the arguments for current command configuration.
|
|
|
|
parser, err = c.reParse(ctx, parser)
|
|
|
|
if err != nil {
|
2021-11-23 20:26:55 +08:00
|
|
|
return nil, err
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
// Registered command function calling.
|
2021-11-23 20:26:55 +08:00
|
|
|
if c.Func != nil {
|
|
|
|
return nil, c.Func(ctx, parser)
|
|
|
|
}
|
|
|
|
if c.FuncWithValue != nil {
|
|
|
|
return c.FuncWithValue(ctx, parser)
|
|
|
|
}
|
2021-11-24 16:17:50 +08:00
|
|
|
// If no function defined in current command, it then prints help.
|
|
|
|
if c.HelpFunc != nil {
|
|
|
|
return nil, c.HelpFunc(ctx, parser)
|
|
|
|
}
|
|
|
|
return nil, c.defaultHelpFunc(ctx, parser)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
|
2021-11-21 22:38:47 +08:00
|
|
|
// reParse re-parses the arguments using option configuration of current command.
|
2021-11-21 13:09:45 +08:00
|
|
|
func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error) {
|
|
|
|
var (
|
|
|
|
optionKey string
|
|
|
|
supportedOptions = make(map[string]bool)
|
|
|
|
)
|
|
|
|
for _, option := range c.Options {
|
|
|
|
if option.Short != "" {
|
2021-11-23 20:26:55 +08:00
|
|
|
optionKey = fmt.Sprintf(`%s,%s`, option.Name, option.Short)
|
2021-11-21 13:09:45 +08:00
|
|
|
} else {
|
|
|
|
optionKey = option.Name
|
|
|
|
}
|
2021-11-22 11:23:46 +08:00
|
|
|
supportedOptions[optionKey] = !option.Orphan
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
2021-11-25 14:56:15 +08:00
|
|
|
return Parse(supportedOptions, c.Strict)
|
2021-11-21 13:09:45 +08:00
|
|
|
}
|
|
|
|
|
2021-11-21 22:38:47 +08:00
|
|
|
// searchCommand recursively searches the command according given arguments.
|
2021-11-21 13:09:45 +08:00
|
|
|
func (c *Command) searchCommand(args []string) *Command {
|
|
|
|
if len(args) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
for _, cmd := range c.commands {
|
|
|
|
if cmd.Name == args[0] {
|
|
|
|
leftArgs := args[1:]
|
|
|
|
if len(leftArgs) == 0 {
|
|
|
|
return &cmd
|
|
|
|
}
|
|
|
|
return cmd.searchCommand(leftArgs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|