-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathgcli.go
321 lines (264 loc) · 7.62 KB
/
gcli.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
// Package gcli is a simple-to-use command line application and tool library.
//
// Contains: cli app, flags parse, interact, progress, data show tools.
//
// Source code and other details for the project are available at GitHub:
//
// https://github.com/gookit/gcli
//
// Usage please refer examples and see README
package gcli
import (
"flag"
"fmt"
"os"
"strconv"
"strings"
"github.com/gookit/gcli/v3/gflag"
"github.com/gookit/goutil/cflag"
"github.com/gookit/goutil/envutil"
)
const (
// OK success exit code
OK = 0
// ERR error exit code
ERR = 2
// GOON prepare run successful, goon run command
GOON = -1
// CommandSep char
CommandSep = ":"
// HelpCommand name
HelpCommand = "help"
// VerbEnvName for set gcli debug level
VerbEnvName = "GCLI_VERBOSE"
)
// constants for error level (quiet 0 - 5 crazy)
const (
VerbQuiet VerbLevel = iota // don't report anything
VerbError // reporting on error, default level.
VerbWarn
VerbInfo
VerbDebug
VerbCrazy
)
var (
// DefaultVerb the default Verbose level
defaultVerb = VerbError
// Version the gcli version
version = "3.0.0"
// CommitID the gcli last commit ID
commitID = "z20210214"
// global vars
gOpts = newGlobalOpts()
gCtx = NewCtx().InitCtx()
)
// init
func init() {
// set Verbose from ENV var.
if verb := os.Getenv(VerbEnvName); verb != "" {
_ = gOpts.Verbose.Set(verb)
}
}
// GCtx get the global ctx
func GCtx() *Context {
return gCtx
}
// Flags alias of the gflag.Parser
type Flags = gflag.Parser
// FlagMeta alias of the gflag.CliOpt.
// Deprecated: use CliOpt instead
type FlagMeta = gflag.CliOpt
// CliOpt alias of the gflag.CliOpt
type CliOpt = gflag.CliOpt
// FlagsConfig alias of the gflag.Config
type FlagsConfig = gflag.Config
// NewFlags create new gflag.Flags
func NewFlags(nameWithDesc ...string) *gflag.Flags {
return gflag.New(nameWithDesc...)
}
// CliArg alias of the gflag.CliArg
type CliArg = gflag.CliArg
// Argument alias of the gflag.CliArg
type Argument = gflag.CliArg
// CliArgs alias of the gflag.CliArgs
type CliArgs = gflag.CliArgs
// Arguments alias of the gflag.CliArgs
type Arguments = gflag.CliArgs
// NewArgument quick create a new command argument
func NewArgument(name, desc string, requiredAndArrayed ...bool) *Argument {
return gflag.NewArg(name, desc, nil, requiredAndArrayed...)
}
/*************************************************************************
* global options
*************************************************************************/
// GlobalOpts global flag options
type GlobalOpts struct {
Disable bool
NoColor bool
Verbose VerbLevel // message report level
ShowHelp bool
// ShowVersion show version information
ShowVersion bool
// NoProgress dont display progress
NoProgress bool
// NoInteractive close interactive confirm
NoInteractive bool
// TODO Run application an interactive shell environment
inShell bool
// TODO auto format shorts `-a` to POSIX or UNIX style.
// StrictMode use strict mode for parse flags
// If True(default):
// - short opt must be begin "-", long opt must be begin "--"
// - will convert like "-ab" to "-a -b"
// - will check invalid arguments, like to many arguments
strictMode bool
// command auto completion mode.
// eg "./cli --cmd-completion [COMMAND --OPT ARG]"
inCompletion bool
}
// SetVerbose value
func (g *GlobalOpts) SetVerbose(verbose VerbLevel) {
g.Verbose = verbose
}
// SetStrictMode option
func (g *GlobalOpts) SetStrictMode(strictMode bool) {
g.strictMode = strictMode
}
// SetDisable global options
func (g *GlobalOpts) SetDisable() {
g.Disable = true
}
func (g *GlobalOpts) bindingOpts(fs *gflag.Parser) {
fs.BoolOpt(&g.ShowHelp, "help", "h", false, "Display the help information")
fs.AfterParse = func(_ *gflag.Parser) error {
// return ErrHelp on ShowHelp=true
if g.ShowHelp {
return flag.ErrHelp
}
return nil
}
// disabled
if g.Disable {
return
}
// up: allow use int and string.
fs.VarOpt(&g.Verbose, "verbose", "verb", "Set logs reporting level(quiet 0 - 5 crazy)")
fs.BoolOpt(&g.NoColor, "no-color", "nc", g.NoColor, "Disable color when outputting message")
fs.BoolOpt(&g.NoProgress, "no-progress", "np", g.NoProgress, "Disable display progress message")
fs.BoolOpt(&g.ShowVersion, "version", "V", false, "Display app version information")
fs.BoolOpt(&g.NoInteractive, "no-interactive", "ni", g.NoInteractive, "Disable interactive confirmation operation")
// fs.BoolOpt(&g.inShell, "ishell", "", false, "Run in an interactive shell environment(`TODO`)")
}
func newGlobalOpts() *GlobalOpts {
opts := &GlobalOpts{
strictMode: false,
// init error level.
Verbose: defaultVerb,
NoColor: envutil.GetBool("NO_COLOR", false),
}
return opts
}
// GOpts get the global options
func GOpts() *GlobalOpts {
return gOpts
}
// Config global options
func Config(fn func(opts *GlobalOpts)) {
if fn != nil {
fn(gOpts)
}
}
// ResetGOpts instance
func ResetGOpts() {
*gOpts = *newGlobalOpts()
}
// Version of the gcli
func Version() string {
return version
}
// CommitID of the gcli
func CommitID() string { return commitID }
// Verbose returns Verbose level
func Verbose() VerbLevel { return gOpts.Verbose }
// SetVerbose level
func SetVerbose(verbose VerbLevel) { gOpts.SetVerbose(verbose) }
// SetDebugMode level
func SetDebugMode() { SetVerbose(VerbDebug) }
// SetQuietMode level
func SetQuietMode() { SetVerbose(VerbQuiet) }
// ResetVerbose level
func ResetVerbose() { SetVerbose(defaultVerb) }
// StrictMode get is strict mode
func StrictMode() bool { return gOpts.strictMode }
// SetStrictMode for parse flags
func SetStrictMode(strict bool) { gOpts.SetStrictMode(strict) }
// IsGteVerbose get is strict mode
func IsGteVerbose(verb VerbLevel) bool { return gOpts.Verbose >= verb }
// IsDebugMode get is debug mode
func IsDebugMode() bool { return gOpts.Verbose >= VerbDebug }
/*************************************************************************
* options: some special flag vars
* - implemented flag.Value interface
*************************************************************************/
// Ints The int flag list, implemented flag.Value interface
type Ints = cflag.Ints
// Strings The string flag list, implemented flag.Value interface
type Strings = cflag.Strings
// Booleans The bool flag list, implemented flag.Value interface
type Booleans = cflag.Booleans
// EnumString The string flag list, implemented flag.Value interface
type EnumString = cflag.EnumString
// String type, a special string
type String = cflag.String
/*************************************************************************
* Verbose level
*************************************************************************/
// VerbLevel type.
type VerbLevel uint
// Int Verbose level to int.
func (vl *VerbLevel) Int() int {
return int(*vl)
}
// String Verbose level to string.
func (vl *VerbLevel) String() string {
return fmt.Sprintf("%d=%s", *vl, vl.Name())
}
// Upper Verbose level to string.
func (vl *VerbLevel) Upper() string {
return strings.ToUpper(vl.Name())
}
// Name Verbose level to string.
func (vl *VerbLevel) Name() string {
switch *vl {
case VerbQuiet:
return "quiet"
case VerbError:
return "error"
case VerbWarn:
return "warn"
case VerbInfo:
return "info"
case VerbDebug:
return "debug"
case VerbCrazy:
return "crazy"
}
return "unknown"
}
// Set value from option binding.
func (vl *VerbLevel) Set(value string) error {
// int: level value.
if iv, err := strconv.Atoi(value); err == nil {
if iv > int(VerbCrazy) {
*vl = VerbCrazy
} else if iv < 0 { // fallback to default level.
*vl = defaultVerb
} else { // 0 - 5
*vl = VerbLevel(iv)
}
return nil
}
// string: level name.
*vl = name2verbLevel(value)
return nil
}