-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand.go
157 lines (148 loc) · 3.42 KB
/
command.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package command
import (
"context"
"github.com/gookit/color"
"os"
"regexp"
"strings"
)
type Cmd struct {
usage string
options []Option
commands []Command
execMap map[string]interface{}
runCommand Command
commandOtherOpts []string
runOptions []Option
searchGroup string
isHelp bool
}
func New() *Cmd {
return new(Cmd)
}
// 设置用法说明
func (c *Cmd) SetUsage(usage string) {
c.usage = usage
}
// 设置参数
func (c *Cmd) SetOptions(opts ...Option) {
c.options = append(c.options, opts...)
}
// 设置命令
func (c *Cmd) SetCommands(opts ...Command) {
c.commands = append(c.commands, opts...)
}
// 执行输出
func (c *Cmd) Run(opts ...string) {
// 增加系统参数
c.SetOptions(&versionOption{}, &daemonOption{}, &helpOption{})
c.valid(opts...)
if len(opts) > 1 && c.searchGroup == "" && c.Exec(opts...) {
return
}
s := help(c)
s += commandMsg(c.searchGroup, c.commands)
color.Print(s)
}
func (c *Cmd) valid(opts ...string) {
if c.execMap == nil {
c.execMap = map[string]interface{}{}
}
optReg := regexp.MustCompile(`^-{1,2}[a-zA-Z]+[a-zA-Z0-9_-]*$`)
for _, opt := range c.options {
explain := opt.Explain()
for _, cmd := range explain.Commands {
if !optReg.MatchString(cmd) {
errorMsg("Option format is \"^-{1,2}[a-zA-Z]+[a-zA-Z0-9_-]*$\"")
}
if c.execMap[cmd] != nil {
errorMsg("Option \"" + cmd + "\" repeated")
}
c.execMap[cmd] = opt
}
}
cmdReg := regexp.MustCompile(`^[a-zA-Z]+:*[a-zA-Z]+[a-zA-Z0-9_-]*$`)
for _, opt := range c.commands {
explain := opt.Explain()
cmd := ""
if explain.Group != "" {
cmd += explain.Group + ":"
}
cmd += explain.Command
if !cmdReg.MatchString(cmd) {
errorMsg("Command format is \"^[a-zA-Z]+[a-zA-Z0-9_-]*$\"")
}
if c.execMap[cmd] != nil {
errorMsg("Command \"" + cmd + "\" repeated")
}
c.execMap[cmd] = opt
}
for _, opt := range opts[1:] {
if opt[0:1] == "-" {
if cmd, ok := c.execMap[opt].(Option); ok {
c.runOptions = append(c.runOptions, cmd)
} else {
errorMsg("The \"" + opt + "\" option does not exist.")
}
} else {
if c.runCommand == nil {
tmpList := strings.Split(opt, "/")
if len(tmpList) == 1 {
opt = tmpList[0]
} else if len(tmpList) == 2 {
opt = tmpList[0]
if tmpList[1] == "help" {
c.isHelp = true
}
} else {
errorSuggest(opt, c.commands)
}
if cmd, ok := c.execMap[opt].(Command); ok {
c.runCommand = cmd
} else {
for _, command := range c.commands {
if command.Explain().Group == opt {
c.searchGroup = opt
return
}
}
errorSuggest(opt, c.commands)
}
} else {
c.commandOtherOpts = append(c.commandOtherOpts, opt)
}
}
}
}
func (c *Cmd) Exec(opts ...string) bool {
if c.runCommand == nil && len(c.runOptions) == 0 {
return true
}
// 参数
for _, opt := range c.runOptions {
opt.Handle(context.Background(), opts...)
os.Exit(0)
}
// 帮助
if c.isHelp {
explain := c.runCommand.Explain()
cmd := ""
if explain.Group != "" {
cmd += explain.Group + ":"
}
cmd += explain.Command
if explain.Help == nil {
errorMsg("No help document for command \"" + cmd + "\"")
}
s := help(c)
s += "<fg=yellow>Command \"" + cmd + "\" Help:</>"
color.Println(s)
explain.Help()
os.Exit(0)
}
// 命令
if c.runCommand != nil {
c.runCommand.Handle(context.Background(), c.commandOtherOpts...)
}
return true
}