Compare commits
No commits in common. "74e7586c36630dcdb39de7ee5c44e977f0b36803" and "9f26d1cf299205ce5a9f993eb9fd77658912c028" have entirely different histories.
74e7586c36
...
9f26d1cf29
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
// 使用 IntelliSense 了解相关属性。
|
|
||||||
// 悬停以查看现有属性的描述。
|
|
||||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Launch Package",
|
|
||||||
"type": "go",
|
|
||||||
"request": "launch",
|
|
||||||
"mode": "auto",
|
|
||||||
"program": "${fileDirname}",
|
|
||||||
"args":[
|
|
||||||
"-a",
|
|
||||||
"ssd"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
44
README.md
44
README.md
|
|
@ -1,47 +1,3 @@
|
||||||
# command
|
# command
|
||||||
|
|
||||||
utils for command line app
|
utils for command line app
|
||||||
|
|
||||||
Provide two style for command line args parse:
|
|
||||||
|
|
||||||
- use struct field tag
|
|
||||||
- use command
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
use struct field tag
|
|
||||||
|
|
||||||
```go
|
|
||||||
type targs struct {
|
|
||||||
Test string `flag_default:"test" flag_usage:"this is test"`
|
|
||||||
TestBool bool `flag_short:"b"`
|
|
||||||
TestInt int
|
|
||||||
}
|
|
||||||
sargs := &targs{}
|
|
||||||
v, _ := NewFVSet(sargs)
|
|
||||||
v.Usage()
|
|
||||||
err := Parse([]string{"--test", "test", "--test-bool", "--test-int", "1"}, v)
|
|
||||||
```
|
|
||||||
|
|
||||||
use command style
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.pyer.club/kingecg/command"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var cmd = command.NewCommand("test", "test command")
|
|
||||||
cmd.AddArg("arg1", "a", "arg1 description", "default value")
|
|
||||||
cmd.AddArg("arg2", "b", "arg2 description", "default value")
|
|
||||||
cmd.AddSubCommand("sub1", "sub1 description")
|
|
||||||
cmd.Parse(os.Args[1:])
|
|
||||||
fmt.Println(cmd.GetGlobalOptions())
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
154
command.go
154
command.go
|
|
@ -2,12 +2,9 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option struct {
|
type Option struct {
|
||||||
|
|
@ -18,48 +15,17 @@ type Option struct {
|
||||||
OType string
|
OType string
|
||||||
DefaultValue interface{}
|
DefaultValue interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var UsageTemplate, _ = template.New("Usage").Parse(`Usage:
|
|
||||||
{{if .ParentCommand }} {{.ParentCommand.Name}} {{end}} {{.Name}} [OPTIONS] [ARGS]
|
|
||||||
{{ if .Description }}
|
|
||||||
Description:
|
|
||||||
{{.Description}}
|
|
||||||
{{ end }}
|
|
||||||
{{ if .Args }}
|
|
||||||
Options:
|
|
||||||
{{range .Args}}
|
|
||||||
-{{.ShortName}}|--{{.LongName}} {{.OType}} {{.Description}} default:{{.DefaultValue}}
|
|
||||||
{{end}}
|
|
||||||
{{ end }}
|
|
||||||
{{ if .SubCommands }}
|
|
||||||
Sub Commands:
|
|
||||||
{{range .SubCommands}}
|
|
||||||
{{.Name}} {{.Description}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
`)
|
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Args []*Option
|
Args []*Option
|
||||||
SubCommands []*Command
|
SubCommands []*Command
|
||||||
ParentCommand *Command
|
parentCommand *Command
|
||||||
subcommand string
|
subcommand string
|
||||||
globalOptions map[string]interface{}
|
globalOptions map[string]interface{}
|
||||||
subcommandOptions map[string]interface{}
|
subcommandOptions map[string]interface{}
|
||||||
remainArgs []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) GetGlobalOptions() map[string]interface{} {
|
|
||||||
return c.globalOptions
|
|
||||||
}
|
|
||||||
func (c *Command) GetSubCommandOptions() map[string]interface{} {
|
|
||||||
return c.subcommandOptions
|
|
||||||
}
|
|
||||||
func (c *Command) GetSubCommand() string {
|
|
||||||
return c.subcommand
|
|
||||||
}
|
|
||||||
func (c *Command) AddArg(name string, shortName string, description string, defaultValue interface{}) {
|
func (c *Command) AddArg(name string, shortName string, description string, defaultValue interface{}) {
|
||||||
oType := reflect.TypeOf(defaultValue).String()
|
oType := reflect.TypeOf(defaultValue).String()
|
||||||
c.Args = append(c.Args, &Option{
|
c.Args = append(c.Args, &Option{
|
||||||
|
|
@ -73,19 +39,19 @@ func (c *Command) AddArg(name string, shortName string, description string, defa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) AddSubCommand(name string, description string) *Command {
|
func (c *Command) AddSubCommand(name string, description string) *Command {
|
||||||
if c.ParentCommand != nil {
|
if c.parentCommand != nil {
|
||||||
panic("Sub commands can only be added to top level commands")
|
panic("Sub commands can only be added to top level commands")
|
||||||
}
|
}
|
||||||
command := &Command{
|
command := &Command{
|
||||||
Name: name,
|
Name: name,
|
||||||
Description: description,
|
Description: description,
|
||||||
ParentCommand: c,
|
parentCommand: c,
|
||||||
}
|
}
|
||||||
c.SubCommands = append(c.SubCommands, command)
|
c.SubCommands = append(c.SubCommands, command)
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
func (c *Command) Usage() {
|
func (c *Command) Usage() {
|
||||||
UsageTemplate.Execute(os.Stdout, c)
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
func (c *Command) GetOption(name string) *Option {
|
func (c *Command) GetOption(name string) *Option {
|
||||||
if len(name) > 1 {
|
if len(name) > 1 {
|
||||||
|
|
@ -102,91 +68,17 @@ func (c *Command) GetOption(name string) *Option {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (c *Command) parseError(errMsg string) {
|
|
||||||
fmt.Println(errMsg)
|
func (c *Command) parse(args []string) {
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
func (c *Command) showHelpWithOption(args []string) {
|
|
||||||
if len(args) > 0 && (args[0] == "-h" || args[0] == "--help") {
|
|
||||||
c.Usage()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (c *Command) showSubCommandHelp(args []string) {
|
|
||||||
if len(args) == 2 && args[0] == "help" {
|
|
||||||
cmd := c.findSubcommand(args[1])
|
|
||||||
if cmd == nil {
|
|
||||||
c.parseError("Unknown subcommand " + args[1])
|
|
||||||
}
|
|
||||||
cmd.Usage()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (c *Command) Parse(args []string) ([]string, error) {
|
|
||||||
c.showHelpWithOption(args)
|
|
||||||
c.showSubCommandHelp(args)
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
if len(c.Args) != 0 || len(c.SubCommands) != 0 || c.ParentCommand == nil {
|
if len(c.Args) != 0 || len(c.SubCommands) != 0 || c.parentCommand == nil {
|
||||||
c.Usage()
|
c.Usage()
|
||||||
}
|
}
|
||||||
if c.ParentCommand != nil {
|
if c.parentCommand != nil {
|
||||||
c.ParentCommand.subcommand = c.Name
|
c.parentCommand.subcommand = c.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vargs := args
|
|
||||||
for {
|
|
||||||
if len(vargs) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var parsed bool
|
|
||||||
var err error
|
|
||||||
vargs, parsed, err = c.longOption(vargs)
|
|
||||||
if err != nil {
|
|
||||||
c.parseError(err.Error())
|
|
||||||
}
|
|
||||||
if parsed {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vargs, parsed, err = c.shortOption(vargs)
|
|
||||||
if err != nil {
|
|
||||||
c.parseError(err.Error())
|
|
||||||
}
|
|
||||||
if parsed {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(c.SubCommands) > 0 {
|
|
||||||
cmd := c.findSubcommand(args[0])
|
|
||||||
if cmd != nil {
|
|
||||||
c.subcommand = cmd.Name
|
|
||||||
vargs = vargs[1:]
|
|
||||||
vargs, err = cmd.Parse(vargs)
|
|
||||||
if err != nil {
|
|
||||||
c.parseError(err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.parseError("Unknown subcommand " + args[0])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if c.ParentCommand != nil {
|
|
||||||
c.ParentCommand.remainArgs = append(c.ParentCommand.remainArgs, vargs[0])
|
|
||||||
|
|
||||||
} else {
|
|
||||||
c.remainArgs = append(c.remainArgs, vargs[0])
|
|
||||||
}
|
|
||||||
vargs = vargs[1:]
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vargs, nil
|
|
||||||
}
|
|
||||||
func (c *Command) findSubcommand(cmd string) *Command {
|
|
||||||
for _, subCmd := range c.SubCommands {
|
|
||||||
if subCmd.Name == cmd {
|
|
||||||
return subCmd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) longOption(args []string) ([]string, bool, error) {
|
func (c *Command) longOption(args []string) ([]string, bool, error) {
|
||||||
|
|
@ -206,8 +98,8 @@ func (c *Command) longOption(args []string) ([]string, bool, error) {
|
||||||
return args, false, err
|
return args, false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.ParentCommand != nil {
|
if c.parentCommand != nil {
|
||||||
return c.ParentCommand.longOption(args)
|
return c.parentCommand.longOption(args)
|
||||||
}
|
}
|
||||||
return args, false, errors.New("Unknown option " + args[0])
|
return args, false, errors.New("Unknown option " + args[0])
|
||||||
}
|
}
|
||||||
|
|
@ -237,10 +129,10 @@ func (c *Command) shortOption(args []string) ([]string, bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if c.ParentCommand != nil {
|
if c.parentCommand != nil {
|
||||||
opt = c.ParentCommand.GetOption(string(s))
|
opt = c.parentCommand.GetOption(string(s))
|
||||||
if opt != nil {
|
if opt != nil {
|
||||||
rargs, _, err := c.ParentCommand.getOptValue(args[i:], opt, i != last)
|
rargs, _, err := c.parentCommand.getOptValue(args[i:], opt, i != last)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return rargs, true, nil
|
return rargs, true, nil
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -258,8 +150,8 @@ func (c *Command) shortOption(args []string) ([]string, bool, error) {
|
||||||
func (c *Command) getOptValue(args []string, opt *Option, isFixBool bool) ([]string, interface{}, error) {
|
func (c *Command) getOptValue(args []string, opt *Option, isFixBool bool) ([]string, interface{}, error) {
|
||||||
|
|
||||||
paramMap := c.globalOptions
|
paramMap := c.globalOptions
|
||||||
if c.ParentCommand != nil {
|
if c.parentCommand != nil {
|
||||||
paramMap = c.ParentCommand.subcommandOptions
|
paramMap = c.parentCommand.subcommandOptions
|
||||||
}
|
}
|
||||||
if isFixBool {
|
if isFixBool {
|
||||||
if opt.OType != "bool" {
|
if opt.OType != "bool" {
|
||||||
|
|
@ -304,18 +196,8 @@ func (c *Command) getOptValue(args []string, opt *Option, isFixBool bool) ([]str
|
||||||
return args[2:], true, nil
|
return args[2:], true, nil
|
||||||
}
|
}
|
||||||
case "default":
|
case "default":
|
||||||
return args, nil, errors.New("unsupported type")
|
return args, nil, errors.New("Unsupported type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return args, nil, errors.New("unsupported type")
|
return args, nil, errors.New("Unsupported type")
|
||||||
}
|
|
||||||
|
|
||||||
func NewCommand(name string, desc string) *Command {
|
|
||||||
return &Command{
|
|
||||||
Name: name,
|
|
||||||
Description: desc,
|
|
||||||
globalOptions: map[string]interface{}{},
|
|
||||||
subcommandOptions: map[string]interface{}{},
|
|
||||||
remainArgs: []string{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.pyer.club/kingecg/command"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var cmd = command.NewCommand("test", "test command")
|
|
||||||
cmd.AddArg("arg1", "a", "arg1 description", "default value")
|
|
||||||
cmd.AddArg("arg2", "b", "arg2 description", "default value")
|
|
||||||
cmd.AddSubCommand("sub1", "sub1 description")
|
|
||||||
cmd.Parse(os.Args[1:])
|
|
||||||
fmt.Println(cmd.GetGlobalOptions())
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue