Skip to content

Commit 9083013

Browse files
committed
add new interact method: select
1 parent fae3367 commit 9083013

21 files changed

+473
-74
lines changed

LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 inhere
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

_examples/cliapp.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,27 @@ import (
1313
func main() {
1414
runtime.GOMAXPROCS(runtime.NumCPU())
1515

16-
app := cliapp.NewApp()
16+
app := cliapp.NewApp(func(a *cliapp.Application) {
17+
a.Hooks[cliapp.EvtInit] = func(a *cliapp.Application, data interface{}) {
18+
// do something...
19+
// fmt.Println("init app")
20+
}
21+
})
1722
app.Version = "1.0.6"
1823
app.Description = "this is my cli application"
1924

2025
// app.SetVerbose(cliapp.VerbDebug)
2126
// app.DefaultCommand("example")
22-
app.Hooks[cliapp.EvtInit] = func(app *cliapp.Application, data interface{}) {
23-
// do something...
24-
}
2527

2628
app.Add(cmd.ExampleCommand())
2729
app.Add(cmd.EnvInfoCommand())
2830
app.Add(cmd.GitCommand())
2931
app.Add(cmd.ColorCommand())
32+
app.Add(cmd.ShowDemoCommand(), cmd.InteractDemoCommand())
33+
3034
app.Add(filewatcher.FileWatcher(nil))
3135
app.Add(reverseproxy.ReverseProxyCommand())
36+
3237
app.Add(&cliapp.Command{
3338
Name: "test",
3439
Aliases: []string{"ts"},

_examples/cmd/example.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,18 @@ func ExampleCommand() *cliapp.Command {
6464
func exampleExecute(c *cliapp.Command, args []string) int {
6565
fmt.Print("hello, in example command\n")
6666

67-
color.Magentaln("All options:")
67+
magentaln := color.Magenta.Println
68+
69+
magentaln("All options:")
6870
fmt.Printf("%+v\n", exampleOpts)
69-
color.Magentaln("Raw args:")
71+
magentaln("Raw args:")
7072
fmt.Printf("%v\n", args)
7173

72-
color.Magentaln("Get arg by name:")
74+
magentaln("Get arg by name:")
7375
arr := c.Arg("arrArg")
7476
fmt.Printf("named array arg '%s', value: %v\n", arr.Name, arr.Value)
7577

76-
color.Magentaln("All named args:")
78+
magentaln("All named args:")
7779
for _, arg := range c.Args() {
7880
fmt.Printf("named arg '%s': %+v\n", arg.Name, *arg)
7981
}

_examples/cmd/interact_demo.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package cmd
2+
3+
import (
4+
"github.com/gookit/cliapp"
5+
"github.com/gookit/cliapp/interact"
6+
"github.com/gookit/color"
7+
)
8+
9+
// InteractDemoCommand create
10+
func InteractDemoCommand() *cliapp.Command {
11+
c := &cliapp.Command{
12+
Name: "interact",
13+
Func: interactDemo,
14+
// Aliases: []string{"im"}
15+
Description: "the command will show some interactive methods",
16+
Examples: `{$fullCmd} confirm
17+
{$fullCmd} select
18+
`,
19+
Help: `Supported interactive methods:
20+
answerIsYes check user answer is Yes
21+
confirm confirm message
22+
select select one from multi options
23+
`,
24+
}
25+
26+
c.AddArg("name", "want running interact method name", true)
27+
return c
28+
}
29+
30+
var funcMap = map[string]func(c *cliapp.Command){
31+
"select": demoSelect,
32+
"confirm": demoConfirm,
33+
"answerIsYes": demoAnswerIsYes,
34+
}
35+
36+
func interactDemo(c *cliapp.Command, _ []string) int {
37+
name := c.Arg("name").String()
38+
if handler, ok := funcMap[name]; ok {
39+
handler(c)
40+
} else {
41+
return c.Errorf("want run unknown demo method: %s", name)
42+
}
43+
44+
return 0
45+
}
46+
47+
func demoSelect(_ *cliapp.Command) {
48+
// s := interact.NewSelect("Your city", []string{"chengdu", "beijing", "shanghai"})
49+
// s.DefOpt = "2"
50+
// val := s.Run()
51+
// color.Comment.Println("your select is: ", val.String())
52+
53+
ans := interact.QuickSelect(
54+
"Your city name(use array)?",
55+
[]string{"chengdu", "beijing", "shanghai"},
56+
"",
57+
)
58+
color.Comment.Println("your select is: ", ans)
59+
60+
ans = interact.QuickSelect(
61+
"Your city name(use map)?",
62+
map[string]string{"a":"chengdu", "b":"beijing", "c":"shanghai"},
63+
"a",
64+
)
65+
color.Comment.Println("your select is: ", ans)
66+
}
67+
68+
func demoConfirm(_ *cliapp.Command) {
69+
70+
}
71+
72+
func demoAnswerIsYes(_ *cliapp.Command) {
73+
74+
}

_examples/cmd/show_demo.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cmd
2+
3+
import "github.com/gookit/cliapp"
4+
5+
// ShowDemoCommand create
6+
func ShowDemoCommand() *cliapp.Command {
7+
c := &cliapp.Command{
8+
Name: "show",
9+
Func: runShow,
10+
//
11+
Description: "the command will show some data format methods",
12+
}
13+
14+
return c
15+
}
16+
17+
func runShow(c *cliapp.Command, _ []string) int {
18+
19+
return 0
20+
}

_examples/servermanager/commands.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"os/exec"
77
"github.com/gookit/color"
88
"fmt"
9-
"os"
109
)
1110

1211
type Config struct {
@@ -76,7 +75,7 @@ func stopServer() int {
7675
command := exec.Command("kill", string(bs))
7776
command.Start()
7877

79-
color.Successln("server stopped")
78+
color.Success.Println("server stopped")
8079
return 0
8180
}
8281

app.go

+21-24
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ const (
3434
EvtError = "error"
3535
)
3636

37-
// OK success code
38-
const OK = 0
39-
40-
// ERR error code
41-
const ERR = 2
37+
const (
38+
// OK success exit code
39+
OK = 0
40+
// ERR error exit code
41+
ERR = 2
42+
)
4243

4344
// Logo app logo, ASCII logo
4445
type Logo struct {
@@ -118,36 +119,33 @@ func Verbose() uint {
118119
}
119120

120121
// NewApp create new app.
121-
// The settings (name, version, description)
122122
// eg:
123-
// cliapp.NewApp("cli app", "1.0.1", "The is is my cil application")
124-
func NewApp(settings ...string) *Application {
123+
// cliapp.NewApp()
124+
// cliapp.NewApp(func(a *Application) {
125+
// // do something before init ....
126+
// a.Hooks[cliapp.EvtInit] = func () {}
127+
// })
128+
func NewApp(fn ...func(a *Application)) *Application {
125129
app = &Application{
126-
Name: "My CLI Application",
127-
Logo: Logo{Style: "info"},
130+
Name: "My CLI Application",
131+
Logo: Logo{Style: "info"},
132+
Hooks: make(map[string]appHookFunc, 0),
128133
// set a default version
129134
Version: "1.0.0",
130135
}
131136

132-
for k, v := range settings {
133-
switch k {
134-
case 0:
135-
app.Name = v
136-
case 1:
137-
app.Version = v
138-
case 2:
139-
app.Description = v
140-
}
137+
if len(fn) > 0 {
138+
fn[0](app)
141139
}
142140

143141
// init
144-
app.initialize()
142+
app.Initialize()
145143

146144
return app
147145
}
148146

149147
// initialize application
150-
func (app *Application) initialize() {
148+
func (app *Application) Initialize() {
151149
app.pid = os.Getpid()
152150
app.names = make(map[string]int)
153151

@@ -158,7 +156,6 @@ func (app *Application) initialize() {
158156
"binName": binName,
159157
}
160158

161-
app.Hooks = make(map[string]appHookFunc, 0)
162159
app.callHook(EvtInit, nil)
163160
}
164161

@@ -232,8 +229,8 @@ func (app *Application) callHook(event string, data interface{}) {
232229
}
233230
}
234231

235-
// AddHook handler for a hook event
236-
func (app *Application) AddHook(name string, handler func(*Application, interface{})) {
232+
// On add hook handler for a hook event
233+
func (app *Application) On(name string, handler func(a *Application, data interface{})) {
237234
app.Hooks[name] = handler
238235
}
239236

app_help.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Use "<cyan>{$binName} {command} -h</>" for more information about a command
2929
func (app *Application) showVersionInfo() {
3030
fmt.Printf(
3131
"%s\n\nVersion: %s\n",
32-
utils.UpperFirst(app.Description),
32+
utils.UcFirst(app.Description),
3333
color.ApplyTag("cyan", app.Version),
3434
)
3535
Exit(OK)
@@ -38,17 +38,17 @@ func (app *Application) showVersionInfo() {
3838
// display app commands help
3939
func (app *Application) showCommandsHelp() {
4040
commandsHelp = color.ReplaceTag(commandsHelp)
41+
// render help text template
4142
str := utils.RenderTemplate(commandsHelp, map[string]interface{}{
4243
"Cs": commands,
4344
// app version
4445
"Version": app.Version,
4546
// always upper first char
46-
"Description": utils.UpperFirst(app.Description),
47+
"Description": utils.UcFirst(app.Description),
4748
}, false)
4849

49-
// parse help vars
50-
str = replaceVars(str, app.vars)
51-
fmt.Print(color.RenderStr(str))
50+
// parse help vars and render color tags
51+
fmt.Print(color.RenderStr(replaceVars(str, app.vars)))
5252
Exit(OK)
5353
}
5454

builtin/filewatcher/file_watcher.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func FileWatcher(handler func(event fsnotify.Event)) *cliapp.Command {
5454
// test run:
5555
// go run ./_examples/cliapp.go watch -e .git -e .idea -d ./_examples
5656
func watch(c *cliapp.Command, _ []string) int {
57-
color.Infoln("Work directory: ", c.WorkDir())
57+
color.Info.Println("Work directory: ", c.WorkDir())
5858

5959
if opts.Dir == "" && len(opts.Files) == 0 {
6060
return c.Errorf("watched directory or files cannot be empty")

builtin/gen_auto_complete.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func GenAutoCompleteScript() *cliapp.Command {
6666
return &c
6767
}
6868

69-
func doGen(_ *cliapp.Command, _ []string) int {
69+
func doGen(c *cliapp.Command, _ []string) int {
7070
if len(genOpts.binName) == 0 {
7171
genOpts.binName = cliapp.BinName()
7272
}
@@ -103,22 +103,21 @@ func doGen(_ *cliapp.Command, _ []string) int {
103103

104104
str := utils.RenderTemplate(shellTpls[genOpts.shell], &data)
105105

106-
color.Infoln("Now, will write content to file ", genOpts.output)
107-
color.Normal("Continue?")
106+
color.Info.Println("Now, will write content to file ", genOpts.output)
107+
color.Normal.Print("Continue?")
108108

109109
if !interact.AnswerIsYes(true) {
110-
color.Info("\nBye :)\n")
110+
color.Info.Print("\nBye :)\n")
111111
return 0
112112
}
113113

114114
// 以读写方式打开文件,如果不存在,则创建
115115
err := ioutil.WriteFile(genOpts.output, []byte(str), 0664)
116116
if err != nil {
117-
color.Errorln("Write file error: ", err.Error())
118-
return -2
117+
return c.Errorf("Write file error: %s", err.Error())
119118
}
120119

121-
color.Sucln("\nOK, auto-complete file generate successful")
120+
color.Success.Println("\nOK, auto-complete file generate successful")
122121
return 0
123122
}
124123

builtin/tcpproxy/tcp_proxy.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
// ref links:
99
// https://www.jianshu.com/p/53e219fbf3c5
10+
// https://github.com/yangxikun/gsproxy
1011
type TCPProxy struct {
1112
lock sync.Mutex
1213
}

cmd.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (c *Command) Runnable() bool {
103103
// Init command
104104
func (c *Command) Init() *Command {
105105
if len(c.Description) > 0 {
106-
c.Description = utils.UpperFirst(c.Description)
106+
c.Description = utils.UcFirst(c.Description)
107107

108108
// contains help var "{$cmd}". replace on here is for 'app help'
109109
if strings.Contains(c.Description, "{$cmd}") {
@@ -112,7 +112,8 @@ func (c *Command) Init() *Command {
112112
}
113113

114114
// set help vars
115-
c.Vars = c.app.vars
115+
// c.Vars = c.app.vars // Error: var is map, map is ref addr
116+
c.AddVars(c.app.vars)
116117
c.AddVars(map[string]string{
117118
"cmd": c.Name,
118119
// full command
@@ -218,6 +219,11 @@ func (c *Command) Copy() *Command {
218219
return &nc
219220
}
220221

222+
// On add hook handler for a hook event
223+
func (c *Command) On(name string, handler func(c *Command, data interface{})) {
224+
c.Hooks[name] = handler
225+
}
226+
221227
/*************************************************************
222228
* alone running
223229
*************************************************************/

0 commit comments

Comments
 (0)