Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/spf13/pflag/flag.go
2875 views
1
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
5
/*
6
Package pflag is a drop-in replacement for Go's flag package, implementing
7
POSIX/GNU-style --flags.
8
9
pflag is compatible with the GNU extensions to the POSIX recommendations
10
for command-line options. See
11
http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
12
13
Usage:
14
15
pflag is a drop-in replacement of Go's native flag package. If you import
16
pflag under the name "flag" then all code should continue to function
17
with no changes.
18
19
import flag "github.com/spf13/pflag"
20
21
There is one exception to this: if you directly instantiate the Flag struct
22
there is one more field "Shorthand" that you will need to set.
23
Most code never instantiates this struct directly, and instead uses
24
functions such as String(), BoolVar(), and Var(), and is therefore
25
unaffected.
26
27
Define flags using flag.String(), Bool(), Int(), etc.
28
29
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
30
31
var ip = flag.Int("flagname", 1234, "help message for flagname")
32
33
If you like, you can bind the flag to a variable using the Var() functions.
34
35
var flagvar int
36
func init() {
37
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
38
}
39
40
Or you can create custom flags that satisfy the Value interface (with
41
pointer receivers) and couple them to flag parsing by
42
43
flag.Var(&flagVal, "name", "help message for flagname")
44
45
For such flags, the default value is just the initial value of the variable.
46
47
After all flags are defined, call
48
49
flag.Parse()
50
51
to parse the command line into the defined flags.
52
53
Flags may then be used directly. If you're using the flags themselves,
54
they are all pointers; if you bind to variables, they're values.
55
56
fmt.Println("ip has value ", *ip)
57
fmt.Println("flagvar has value ", flagvar)
58
59
After parsing, the arguments after the flag are available as the
60
slice flag.Args() or individually as flag.Arg(i).
61
The arguments are indexed from 0 through flag.NArg()-1.
62
63
The pflag package also defines some new functions that are not in flag,
64
that give one-letter shorthands for flags. You can use these by appending
65
'P' to the name of any function that defines a flag.
66
67
var ip = flag.IntP("flagname", "f", 1234, "help message")
68
var flagvar bool
69
func init() {
70
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
71
}
72
flag.VarP(&flagval, "varname", "v", "help message")
73
74
Shorthand letters can be used with single dashes on the command line.
75
Boolean shorthand flags can be combined with other shorthand flags.
76
77
Command line flag syntax:
78
79
--flag // boolean flags only
80
--flag=x
81
82
Unlike the flag package, a single dash before an option means something
83
different than a double dash. Single dashes signify a series of shorthand
84
letters for flags. All but the last shorthand letter must be boolean flags.
85
86
// boolean flags
87
-f
88
-abc
89
// non-boolean flags
90
-n 1234
91
-Ifile
92
// mixed
93
-abcs "hello"
94
-abcn1234
95
96
Flag parsing stops after the terminator "--". Unlike the flag package,
97
flags can be interspersed with arguments anywhere on the command line
98
before this terminator.
99
100
Integer flags accept 1234, 0664, 0x1234 and may be negative.
101
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
102
TRUE, FALSE, True, False.
103
Duration flags accept any input valid for time.ParseDuration.
104
105
The default set of command-line flags is controlled by
106
top-level functions. The FlagSet type allows one to define
107
independent sets of flags, such as to implement subcommands
108
in a command-line interface. The methods of FlagSet are
109
analogous to the top-level functions for the command-line
110
flag set.
111
*/
112
package pflag
113
114
import (
115
"bytes"
116
"errors"
117
goflag "flag"
118
"fmt"
119
"io"
120
"os"
121
"sort"
122
"strings"
123
)
124
125
// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
126
var ErrHelp = errors.New("pflag: help requested")
127
128
// ErrorHandling defines how to handle flag parsing errors.
129
type ErrorHandling int
130
131
const (
132
// ContinueOnError will return an err from Parse() if an error is found
133
ContinueOnError ErrorHandling = iota
134
// ExitOnError will call os.Exit(2) if an error is found when parsing
135
ExitOnError
136
// PanicOnError will panic() if an error is found when parsing flags
137
PanicOnError
138
)
139
140
// ParseErrorsAllowlist defines the parsing errors that can be ignored
141
type ParseErrorsAllowlist struct {
142
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
143
UnknownFlags bool
144
}
145
146
// ParseErrorsWhitelist defines the parsing errors that can be ignored.
147
//
148
// Deprecated: use [ParseErrorsAllowlist] instead. This type will be removed in a future release.
149
type ParseErrorsWhitelist = ParseErrorsAllowlist
150
151
// NormalizedName is a flag name that has been normalized according to rules
152
// for the FlagSet (e.g. making '-' and '_' equivalent).
153
type NormalizedName string
154
155
// A FlagSet represents a set of defined flags.
156
type FlagSet struct {
157
// Usage is the function called when an error occurs while parsing flags.
158
// The field is a function (not a method) that may be changed to point to
159
// a custom error handler.
160
Usage func()
161
162
// SortFlags is used to indicate, if user wants to have sorted flags in
163
// help/usage messages.
164
SortFlags bool
165
166
// ParseErrorsAllowlist is used to configure an allowlist of errors
167
ParseErrorsAllowlist ParseErrorsAllowlist
168
169
// ParseErrorsAllowlist is used to configure an allowlist of errors.
170
//
171
// Deprecated: use [FlagSet.ParseErrorsAllowlist] instead. This field will be removed in a future release.
172
ParseErrorsWhitelist ParseErrorsAllowlist
173
174
name string
175
parsed bool
176
actual map[NormalizedName]*Flag
177
orderedActual []*Flag
178
sortedActual []*Flag
179
formal map[NormalizedName]*Flag
180
orderedFormal []*Flag
181
sortedFormal []*Flag
182
shorthands map[byte]*Flag
183
args []string // arguments after flags
184
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
185
errorHandling ErrorHandling
186
output io.Writer // nil means stderr; use Output() accessor
187
interspersed bool // allow interspersed option/non-option args
188
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
189
190
addedGoFlagSets []*goflag.FlagSet
191
}
192
193
// A Flag represents the state of a flag.
194
type Flag struct {
195
Name string // name as it appears on command line
196
Shorthand string // one-letter abbreviated flag
197
Usage string // help message
198
Value Value // value as set
199
DefValue string // default value (as text); for usage message
200
Changed bool // If the user set the value (or if left to default)
201
NoOptDefVal string // default value (as text); if the flag is on the command line without any options
202
Deprecated string // If this flag is deprecated, this string is the new or now thing to use
203
Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
204
ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
205
Annotations map[string][]string // used by cobra.Command bash autocomple code
206
}
207
208
// Value is the interface to the dynamic value stored in a flag.
209
// (The default value is represented as a string.)
210
type Value interface {
211
String() string
212
Set(string) error
213
Type() string
214
}
215
216
// SliceValue is a secondary interface to all flags which hold a list
217
// of values. This allows full control over the value of list flags,
218
// and avoids complicated marshalling and unmarshalling to csv.
219
type SliceValue interface {
220
// Append adds the specified value to the end of the flag value list.
221
Append(string) error
222
// Replace will fully overwrite any data currently in the flag value list.
223
Replace([]string) error
224
// GetSlice returns the flag value list as an array of strings.
225
GetSlice() []string
226
}
227
228
// sortFlags returns the flags as a slice in lexicographical sorted order.
229
func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
230
list := make(sort.StringSlice, len(flags))
231
i := 0
232
for k := range flags {
233
list[i] = string(k)
234
i++
235
}
236
list.Sort()
237
result := make([]*Flag, len(list))
238
for i, name := range list {
239
result[i] = flags[NormalizedName(name)]
240
}
241
return result
242
}
243
244
// SetNormalizeFunc allows you to add a function which can translate flag names.
245
// Flags added to the FlagSet will be translated and then when anything tries to
246
// look up the flag that will also be translated. So it would be possible to create
247
// a flag named "getURL" and have it translated to "geturl". A user could then pass
248
// "--getUrl" which may also be translated to "geturl" and everything will work.
249
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
250
f.normalizeNameFunc = n
251
f.sortedFormal = f.sortedFormal[:0]
252
for fname, flag := range f.formal {
253
nname := f.normalizeFlagName(flag.Name)
254
if fname == nname {
255
continue
256
}
257
flag.Name = string(nname)
258
delete(f.formal, fname)
259
f.formal[nname] = flag
260
if _, set := f.actual[fname]; set {
261
delete(f.actual, fname)
262
f.actual[nname] = flag
263
}
264
}
265
}
266
267
// GetNormalizeFunc returns the previously set NormalizeFunc of a function which
268
// does no translation, if not set previously.
269
func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName {
270
if f.normalizeNameFunc != nil {
271
return f.normalizeNameFunc
272
}
273
return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) }
274
}
275
276
func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
277
n := f.GetNormalizeFunc()
278
return n(f, name)
279
}
280
281
// Output returns the destination for usage and error messages. os.Stderr is returned if
282
// output was not set or was set to nil.
283
func (f *FlagSet) Output() io.Writer {
284
if f.output == nil {
285
return os.Stderr
286
}
287
return f.output
288
}
289
290
// Name returns the name of the flag set.
291
func (f *FlagSet) Name() string {
292
return f.name
293
}
294
295
// SetOutput sets the destination for usage and error messages.
296
// If output is nil, os.Stderr is used.
297
func (f *FlagSet) SetOutput(output io.Writer) {
298
f.output = output
299
}
300
301
// VisitAll visits the flags in lexicographical order or
302
// in primordial order if f.SortFlags is false, calling fn for each.
303
// It visits all flags, even those not set.
304
func (f *FlagSet) VisitAll(fn func(*Flag)) {
305
if len(f.formal) == 0 {
306
return
307
}
308
309
var flags []*Flag
310
if f.SortFlags {
311
if len(f.formal) != len(f.sortedFormal) {
312
f.sortedFormal = sortFlags(f.formal)
313
}
314
flags = f.sortedFormal
315
} else {
316
flags = f.orderedFormal
317
}
318
319
for _, flag := range flags {
320
fn(flag)
321
}
322
}
323
324
// HasFlags returns a bool to indicate if the FlagSet has any flags defined.
325
func (f *FlagSet) HasFlags() bool {
326
return len(f.formal) > 0
327
}
328
329
// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
330
// that are not hidden.
331
func (f *FlagSet) HasAvailableFlags() bool {
332
for _, flag := range f.formal {
333
if !flag.Hidden {
334
return true
335
}
336
}
337
return false
338
}
339
340
// VisitAll visits the command-line flags in lexicographical order or
341
// in primordial order if f.SortFlags is false, calling fn for each.
342
// It visits all flags, even those not set.
343
func VisitAll(fn func(*Flag)) {
344
CommandLine.VisitAll(fn)
345
}
346
347
// Visit visits the flags in lexicographical order or
348
// in primordial order if f.SortFlags is false, calling fn for each.
349
// It visits only those flags that have been set.
350
func (f *FlagSet) Visit(fn func(*Flag)) {
351
if len(f.actual) == 0 {
352
return
353
}
354
355
var flags []*Flag
356
if f.SortFlags {
357
if len(f.actual) != len(f.sortedActual) {
358
f.sortedActual = sortFlags(f.actual)
359
}
360
flags = f.sortedActual
361
} else {
362
flags = f.orderedActual
363
}
364
365
for _, flag := range flags {
366
fn(flag)
367
}
368
}
369
370
// Visit visits the command-line flags in lexicographical order or
371
// in primordial order if f.SortFlags is false, calling fn for each.
372
// It visits only those flags that have been set.
373
func Visit(fn func(*Flag)) {
374
CommandLine.Visit(fn)
375
}
376
377
// Lookup returns the Flag structure of the named flag, returning nil if none exists.
378
func (f *FlagSet) Lookup(name string) *Flag {
379
return f.lookup(f.normalizeFlagName(name))
380
}
381
382
// ShorthandLookup returns the Flag structure of the short handed flag,
383
// returning nil if none exists.
384
// It panics, if len(name) > 1.
385
func (f *FlagSet) ShorthandLookup(name string) *Flag {
386
if name == "" {
387
return nil
388
}
389
if len(name) > 1 {
390
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
391
fmt.Fprintf(f.Output(), msg)
392
panic(msg)
393
}
394
c := name[0]
395
return f.shorthands[c]
396
}
397
398
// lookup returns the Flag structure of the named flag, returning nil if none exists.
399
func (f *FlagSet) lookup(name NormalizedName) *Flag {
400
return f.formal[name]
401
}
402
403
// func to return a given type for a given flag name
404
func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
405
flag := f.Lookup(name)
406
if flag == nil {
407
err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
408
return nil, err
409
}
410
411
if flag.Value.Type() != ftype {
412
err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type())
413
return nil, err
414
}
415
416
sval := flag.Value.String()
417
result, err := convFunc(sval)
418
if err != nil {
419
return nil, err
420
}
421
return result, nil
422
}
423
424
// ArgsLenAtDash will return the length of f.Args at the moment when a -- was
425
// found during arg parsing. This allows your program to know which args were
426
// before the -- and which came after.
427
func (f *FlagSet) ArgsLenAtDash() int {
428
return f.argsLenAtDash
429
}
430
431
// MarkDeprecated indicated that a flag is deprecated in your program. It will
432
// continue to function but will not show up in help or usage messages. Using
433
// this flag will also print the given usageMessage.
434
func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
435
flag := f.Lookup(name)
436
if flag == nil {
437
return &NotExistError{name: name, messageType: flagNotExistMessage}
438
}
439
if usageMessage == "" {
440
return fmt.Errorf("deprecated message for flag %q must be set", name)
441
}
442
flag.Deprecated = usageMessage
443
flag.Hidden = true
444
return nil
445
}
446
447
// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your
448
// program. It will continue to function but will not show up in help or usage
449
// messages. Using this flag will also print the given usageMessage.
450
func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
451
flag := f.Lookup(name)
452
if flag == nil {
453
return &NotExistError{name: name, messageType: flagNotExistMessage}
454
}
455
if usageMessage == "" {
456
return fmt.Errorf("deprecated message for flag %q must be set", name)
457
}
458
flag.ShorthandDeprecated = usageMessage
459
return nil
460
}
461
462
// MarkHidden sets a flag to 'hidden' in your program. It will continue to
463
// function but will not show up in help or usage messages.
464
func (f *FlagSet) MarkHidden(name string) error {
465
flag := f.Lookup(name)
466
if flag == nil {
467
return &NotExistError{name: name, messageType: flagNotExistMessage}
468
}
469
flag.Hidden = true
470
return nil
471
}
472
473
// Lookup returns the Flag structure of the named command-line flag,
474
// returning nil if none exists.
475
func Lookup(name string) *Flag {
476
return CommandLine.Lookup(name)
477
}
478
479
// ShorthandLookup returns the Flag structure of the short handed flag,
480
// returning nil if none exists.
481
func ShorthandLookup(name string) *Flag {
482
return CommandLine.ShorthandLookup(name)
483
}
484
485
// Set sets the value of the named flag.
486
func (f *FlagSet) Set(name, value string) error {
487
normalName := f.normalizeFlagName(name)
488
flag, ok := f.formal[normalName]
489
if !ok {
490
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
491
}
492
493
err := flag.Value.Set(value)
494
if err != nil {
495
return &InvalidValueError{
496
flag: flag,
497
value: value,
498
cause: err,
499
}
500
}
501
502
if !flag.Changed {
503
if f.actual == nil {
504
f.actual = make(map[NormalizedName]*Flag)
505
}
506
f.actual[normalName] = flag
507
f.orderedActual = append(f.orderedActual, flag)
508
509
flag.Changed = true
510
}
511
512
if flag.Deprecated != "" {
513
fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
514
}
515
return nil
516
}
517
518
// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet.
519
// This is sometimes used by spf13/cobra programs which want to generate additional
520
// bash completion information.
521
func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
522
normalName := f.normalizeFlagName(name)
523
flag, ok := f.formal[normalName]
524
if !ok {
525
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
526
}
527
if flag.Annotations == nil {
528
flag.Annotations = map[string][]string{}
529
}
530
flag.Annotations[key] = values
531
return nil
532
}
533
534
// Changed returns true if the flag was explicitly set during Parse() and false
535
// otherwise
536
func (f *FlagSet) Changed(name string) bool {
537
flag := f.Lookup(name)
538
// If a flag doesn't exist, it wasn't changed....
539
if flag == nil {
540
return false
541
}
542
return flag.Changed
543
}
544
545
// Set sets the value of the named command-line flag.
546
func Set(name, value string) error {
547
return CommandLine.Set(name, value)
548
}
549
550
// PrintDefaults prints, to standard error unless configured
551
// otherwise, the default values of all defined flags in the set.
552
func (f *FlagSet) PrintDefaults() {
553
usages := f.FlagUsages()
554
fmt.Fprint(f.Output(), usages)
555
}
556
557
// defaultIsZeroValue returns true if the default value for this flag represents
558
// a zero value.
559
func (f *Flag) defaultIsZeroValue() bool {
560
switch f.Value.(type) {
561
case boolFlag:
562
return f.DefValue == "false" || f.DefValue == ""
563
case *durationValue:
564
// Beginning in Go 1.7, duration zero values are "0s"
565
return f.DefValue == "0" || f.DefValue == "0s"
566
case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value:
567
return f.DefValue == "0"
568
case *stringValue:
569
return f.DefValue == ""
570
case *ipValue, *ipMaskValue, *ipNetValue:
571
return f.DefValue == "<nil>"
572
case *intSliceValue, *stringSliceValue, *stringArrayValue:
573
return f.DefValue == "[]"
574
default:
575
switch f.DefValue {
576
case "false":
577
return true
578
case "<nil>":
579
return true
580
case "":
581
return true
582
case "0":
583
return true
584
}
585
return false
586
}
587
}
588
589
// UnquoteUsage extracts a back-quoted name from the usage
590
// string for a flag and returns it and the un-quoted usage.
591
// Given "a `name` to show" it returns ("name", "a name to show").
592
// If there are no back quotes, the name is an educated guess of the
593
// type of the flag's value, or the empty string if the flag is boolean.
594
func UnquoteUsage(flag *Flag) (name string, usage string) {
595
// Look for a back-quoted name, but avoid the strings package.
596
usage = flag.Usage
597
for i := 0; i < len(usage); i++ {
598
if usage[i] == '`' {
599
for j := i + 1; j < len(usage); j++ {
600
if usage[j] == '`' {
601
name = usage[i+1 : j]
602
usage = usage[:i] + name + usage[j+1:]
603
return name, usage
604
}
605
}
606
break // Only one back quote; use type name.
607
}
608
}
609
610
name = flag.Value.Type()
611
switch name {
612
case "bool", "boolfunc":
613
name = ""
614
case "func":
615
name = "value"
616
case "float64":
617
name = "float"
618
case "int64":
619
name = "int"
620
case "uint64":
621
name = "uint"
622
case "stringSlice":
623
name = "strings"
624
case "intSlice":
625
name = "ints"
626
case "uintSlice":
627
name = "uints"
628
case "boolSlice":
629
name = "bools"
630
}
631
632
return
633
}
634
635
// Splits the string `s` on whitespace into an initial substring up to
636
// `i` runes in length and the remainder. Will go `slop` over `i` if
637
// that encompasses the entire string (which allows the caller to
638
// avoid short orphan words on the final line).
639
func wrapN(i, slop int, s string) (string, string) {
640
if i+slop > len(s) {
641
return s, ""
642
}
643
644
w := strings.LastIndexAny(s[:i], " \t\n")
645
if w <= 0 {
646
return s, ""
647
}
648
nlPos := strings.LastIndex(s[:i], "\n")
649
if nlPos > 0 && nlPos < w {
650
return s[:nlPos], s[nlPos+1:]
651
}
652
return s[:w], s[w+1:]
653
}
654
655
// Wraps the string `s` to a maximum width `w` with leading indent
656
// `i`. The first line is not indented (this is assumed to be done by
657
// caller). Pass `w` == 0 to do no wrapping
658
func wrap(i, w int, s string) string {
659
if w == 0 {
660
return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
661
}
662
663
// space between indent i and end of line width w into which
664
// we should wrap the text.
665
wrap := w - i
666
667
var r, l string
668
669
// Not enough space for sensible wrapping. Wrap as a block on
670
// the next line instead.
671
if wrap < 24 {
672
i = 16
673
wrap = w - i
674
r += "\n" + strings.Repeat(" ", i)
675
}
676
// If still not enough space then don't even try to wrap.
677
if wrap < 24 {
678
return strings.Replace(s, "\n", r, -1)
679
}
680
681
// Try to avoid short orphan words on the final line, by
682
// allowing wrapN to go a bit over if that would fit in the
683
// remainder of the line.
684
slop := 5
685
wrap = wrap - slop
686
687
// Handle first line, which is indented by the caller (or the
688
// special case above)
689
l, s = wrapN(wrap, slop, s)
690
r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
691
692
// Now wrap the rest
693
for s != "" {
694
var t string
695
696
t, s = wrapN(wrap, slop, s)
697
r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
698
}
699
700
return r
701
702
}
703
704
// FlagUsagesWrapped returns a string containing the usage information
705
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
706
// wrapping)
707
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
708
buf := new(bytes.Buffer)
709
710
lines := make([]string, 0, len(f.formal))
711
712
maxlen := 0
713
f.VisitAll(func(flag *Flag) {
714
if flag.Hidden {
715
return
716
}
717
718
line := ""
719
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
720
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
721
} else {
722
line = fmt.Sprintf(" --%s", flag.Name)
723
}
724
725
varname, usage := UnquoteUsage(flag)
726
if varname != "" {
727
line += " " + varname
728
}
729
if flag.NoOptDefVal != "" {
730
switch flag.Value.Type() {
731
case "string":
732
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
733
case "bool", "boolfunc":
734
if flag.NoOptDefVal != "true" {
735
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
736
}
737
case "count":
738
if flag.NoOptDefVal != "+1" {
739
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
740
}
741
default:
742
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
743
}
744
}
745
746
// This special character will be replaced with spacing once the
747
// correct alignment is calculated
748
line += "\x00"
749
if len(line) > maxlen {
750
maxlen = len(line)
751
}
752
753
line += usage
754
if !flag.defaultIsZeroValue() {
755
if flag.Value.Type() == "string" {
756
line += fmt.Sprintf(" (default %q)", flag.DefValue)
757
} else {
758
line += fmt.Sprintf(" (default %s)", flag.DefValue)
759
}
760
}
761
if len(flag.Deprecated) != 0 {
762
line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
763
}
764
765
lines = append(lines, line)
766
})
767
768
for _, line := range lines {
769
sidx := strings.Index(line, "\x00")
770
spacing := strings.Repeat(" ", maxlen-sidx)
771
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
772
fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
773
}
774
775
return buf.String()
776
}
777
778
// FlagUsages returns a string containing the usage information for all flags in
779
// the FlagSet
780
func (f *FlagSet) FlagUsages() string {
781
return f.FlagUsagesWrapped(0)
782
}
783
784
// PrintDefaults prints to standard error the default values of all defined command-line flags.
785
func PrintDefaults() {
786
CommandLine.PrintDefaults()
787
}
788
789
// defaultUsage is the default function to print a usage message.
790
func defaultUsage(f *FlagSet) {
791
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
792
f.PrintDefaults()
793
}
794
795
// NOTE: Usage is not just defaultUsage(CommandLine)
796
// because it serves (via godoc flag Usage) as the example
797
// for how to write your own usage function.
798
799
// Usage prints to standard error a usage message documenting all defined command-line flags.
800
// The function is a variable that may be changed to point to a custom function.
801
// By default it prints a simple header and calls PrintDefaults; for details about the
802
// format of the output and how to control it, see the documentation for PrintDefaults.
803
var Usage = func() {
804
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
805
PrintDefaults()
806
}
807
808
// NFlag returns the number of flags that have been set.
809
func (f *FlagSet) NFlag() int { return len(f.actual) }
810
811
// NFlag returns the number of command-line flags that have been set.
812
func NFlag() int { return len(CommandLine.actual) }
813
814
// Arg returns the i'th argument. Arg(0) is the first remaining argument
815
// after flags have been processed.
816
func (f *FlagSet) Arg(i int) string {
817
if i < 0 || i >= len(f.args) {
818
return ""
819
}
820
return f.args[i]
821
}
822
823
// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
824
// after flags have been processed.
825
func Arg(i int) string {
826
return CommandLine.Arg(i)
827
}
828
829
// NArg is the number of arguments remaining after flags have been processed.
830
func (f *FlagSet) NArg() int { return len(f.args) }
831
832
// NArg is the number of arguments remaining after flags have been processed.
833
func NArg() int { return len(CommandLine.args) }
834
835
// Args returns the non-flag arguments.
836
func (f *FlagSet) Args() []string { return f.args }
837
838
// Args returns the non-flag command-line arguments.
839
func Args() []string { return CommandLine.args }
840
841
// Var defines a flag with the specified name and usage string. The type and
842
// value of the flag are represented by the first argument, of type Value, which
843
// typically holds a user-defined implementation of Value. For instance, the
844
// caller could create a flag that turns a comma-separated string into a slice
845
// of strings by giving the slice the methods of Value; in particular, Set would
846
// decompose the comma-separated string into the slice.
847
func (f *FlagSet) Var(value Value, name string, usage string) {
848
f.VarP(value, name, "", usage)
849
}
850
851
// VarPF is like VarP, but returns the flag created
852
func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
853
// Remember the default value as a string; it won't change.
854
flag := &Flag{
855
Name: name,
856
Shorthand: shorthand,
857
Usage: usage,
858
Value: value,
859
DefValue: value.String(),
860
}
861
f.AddFlag(flag)
862
return flag
863
}
864
865
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
866
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
867
f.VarPF(value, name, shorthand, usage)
868
}
869
870
// AddFlag will add the flag to the FlagSet
871
func (f *FlagSet) AddFlag(flag *Flag) {
872
normalizedFlagName := f.normalizeFlagName(flag.Name)
873
874
_, alreadyThere := f.formal[normalizedFlagName]
875
if alreadyThere {
876
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
877
fmt.Fprintln(f.Output(), msg)
878
panic(msg) // Happens only if flags are declared with identical names
879
}
880
if f.formal == nil {
881
f.formal = make(map[NormalizedName]*Flag)
882
}
883
884
flag.Name = string(normalizedFlagName)
885
f.formal[normalizedFlagName] = flag
886
f.orderedFormal = append(f.orderedFormal, flag)
887
888
if flag.Shorthand == "" {
889
return
890
}
891
if len(flag.Shorthand) > 1 {
892
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
893
fmt.Fprintf(f.Output(), msg)
894
panic(msg)
895
}
896
if f.shorthands == nil {
897
f.shorthands = make(map[byte]*Flag)
898
}
899
c := flag.Shorthand[0]
900
used, alreadyThere := f.shorthands[c]
901
if alreadyThere {
902
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
903
fmt.Fprintf(f.Output(), msg)
904
panic(msg)
905
}
906
f.shorthands[c] = flag
907
}
908
909
// AddFlagSet adds one FlagSet to another. If a flag is already present in f
910
// the flag from newSet will be ignored.
911
func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
912
if newSet == nil {
913
return
914
}
915
newSet.VisitAll(func(flag *Flag) {
916
if f.Lookup(flag.Name) == nil {
917
f.AddFlag(flag)
918
}
919
})
920
}
921
922
// Var defines a flag with the specified name and usage string. The type and
923
// value of the flag are represented by the first argument, of type Value, which
924
// typically holds a user-defined implementation of Value. For instance, the
925
// caller could create a flag that turns a comma-separated string into a slice
926
// of strings by giving the slice the methods of Value; in particular, Set would
927
// decompose the comma-separated string into the slice.
928
func Var(value Value, name string, usage string) {
929
CommandLine.VarP(value, name, "", usage)
930
}
931
932
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
933
func VarP(value Value, name, shorthand, usage string) {
934
CommandLine.VarP(value, name, shorthand, usage)
935
}
936
937
// fail prints an error message and usage message to standard error and
938
// returns the error.
939
func (f *FlagSet) fail(err error) error {
940
if f.errorHandling != ContinueOnError {
941
f.usage()
942
}
943
return err
944
}
945
946
// usage calls the Usage method for the flag set, or the usage function if
947
// the flag set is CommandLine.
948
func (f *FlagSet) usage() {
949
if f == CommandLine {
950
Usage()
951
} else if f.Usage == nil {
952
defaultUsage(f)
953
} else {
954
f.Usage()
955
}
956
}
957
958
// --unknown (args will be empty)
959
// --unknown --next-flag ... (args will be --next-flag ...)
960
// --unknown arg ... (args will be arg ...)
961
func stripUnknownFlagValue(args []string) []string {
962
if len(args) == 0 {
963
//--unknown
964
return args
965
}
966
967
first := args[0]
968
if len(first) > 0 && first[0] == '-' {
969
//--unknown --next-flag ...
970
return args
971
}
972
973
//--unknown arg ... (args will be arg ...)
974
if len(args) > 1 {
975
return args[1:]
976
}
977
return nil
978
}
979
980
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
981
a = args
982
name := s[2:]
983
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
984
err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
985
return
986
}
987
988
split := strings.SplitN(name, "=", 2)
989
name = split[0]
990
flag, exists := f.formal[f.normalizeFlagName(name)]
991
992
if !exists {
993
switch {
994
case name == "help":
995
f.usage()
996
return a, ErrHelp
997
case f.ParseErrorsWhitelist.UnknownFlags:
998
fallthrough
999
case f.ParseErrorsAllowlist.UnknownFlags:
1000
// --unknown=unknownval arg ...
1001
// we do not want to lose arg in this case
1002
if len(split) >= 2 {
1003
return a, nil
1004
}
1005
1006
return stripUnknownFlagValue(a), nil
1007
default:
1008
err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
1009
return
1010
}
1011
}
1012
1013
var value string
1014
if len(split) == 2 {
1015
// '--flag=arg'
1016
value = split[1]
1017
} else if flag.NoOptDefVal != "" {
1018
// '--flag' (arg was optional)
1019
value = flag.NoOptDefVal
1020
} else if len(a) > 0 {
1021
// '--flag arg'
1022
value = a[0]
1023
a = a[1:]
1024
} else {
1025
// '--flag' (arg was required)
1026
err = f.fail(&ValueRequiredError{
1027
flag: flag,
1028
specifiedName: name,
1029
})
1030
return
1031
}
1032
1033
err = fn(flag, value)
1034
if err != nil {
1035
f.fail(err)
1036
}
1037
return
1038
}
1039
1040
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
1041
outArgs = args
1042
1043
if isGotestShorthandFlag(shorthands) {
1044
return
1045
}
1046
1047
outShorts = shorthands[1:]
1048
c := shorthands[0]
1049
1050
flag, exists := f.shorthands[c]
1051
if !exists {
1052
switch {
1053
case c == 'h':
1054
f.usage()
1055
err = ErrHelp
1056
return
1057
case f.ParseErrorsWhitelist.UnknownFlags:
1058
fallthrough
1059
case f.ParseErrorsAllowlist.UnknownFlags:
1060
// '-f=arg arg ...'
1061
// we do not want to lose arg in this case
1062
if len(shorthands) > 2 && shorthands[1] == '=' {
1063
outShorts = ""
1064
return
1065
}
1066
1067
outArgs = stripUnknownFlagValue(outArgs)
1068
return
1069
default:
1070
err = f.fail(&NotExistError{
1071
name: string(c),
1072
specifiedShorthands: shorthands,
1073
messageType: flagUnknownShorthandFlagMessage,
1074
})
1075
return
1076
}
1077
}
1078
1079
var value string
1080
if len(shorthands) > 2 && shorthands[1] == '=' {
1081
// '-f=arg'
1082
value = shorthands[2:]
1083
outShorts = ""
1084
} else if flag.NoOptDefVal != "" {
1085
// '-f' (arg was optional)
1086
value = flag.NoOptDefVal
1087
} else if len(shorthands) > 1 {
1088
// '-farg'
1089
value = shorthands[1:]
1090
outShorts = ""
1091
} else if len(args) > 0 {
1092
// '-f arg'
1093
value = args[0]
1094
outArgs = args[1:]
1095
} else {
1096
// '-f' (arg was required)
1097
err = f.fail(&ValueRequiredError{
1098
flag: flag,
1099
specifiedName: string(c),
1100
specifiedShorthands: shorthands,
1101
})
1102
return
1103
}
1104
1105
if flag.ShorthandDeprecated != "" {
1106
fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
1107
}
1108
1109
err = fn(flag, value)
1110
if err != nil {
1111
f.fail(err)
1112
}
1113
return
1114
}
1115
1116
func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
1117
a = args
1118
shorthands := s[1:]
1119
1120
// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
1121
for len(shorthands) > 0 {
1122
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
1123
if err != nil {
1124
return
1125
}
1126
}
1127
1128
return
1129
}
1130
1131
func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
1132
for len(args) > 0 {
1133
s := args[0]
1134
args = args[1:]
1135
if len(s) == 0 || s[0] != '-' || len(s) == 1 {
1136
if !f.interspersed {
1137
f.args = append(f.args, s)
1138
f.args = append(f.args, args...)
1139
return nil
1140
}
1141
f.args = append(f.args, s)
1142
continue
1143
}
1144
1145
if s[1] == '-' {
1146
if len(s) == 2 { // "--" terminates the flags
1147
f.argsLenAtDash = len(f.args)
1148
f.args = append(f.args, args...)
1149
break
1150
}
1151
args, err = f.parseLongArg(s, args, fn)
1152
} else {
1153
args, err = f.parseShortArg(s, args, fn)
1154
}
1155
if err != nil {
1156
return
1157
}
1158
}
1159
return
1160
}
1161
1162
// Parse parses flag definitions from the argument list, which should not
1163
// include the command name. Must be called after all flags in the FlagSet
1164
// are defined and before flags are accessed by the program.
1165
// The return value will be ErrHelp if -help was set but not defined.
1166
func (f *FlagSet) Parse(arguments []string) error {
1167
if f.addedGoFlagSets != nil {
1168
for _, goFlagSet := range f.addedGoFlagSets {
1169
goFlagSet.Parse(nil)
1170
}
1171
}
1172
f.parsed = true
1173
1174
f.args = make([]string, 0, len(arguments))
1175
1176
if len(arguments) == 0 {
1177
return nil
1178
}
1179
1180
set := func(flag *Flag, value string) error {
1181
return f.Set(flag.Name, value)
1182
}
1183
1184
err := f.parseArgs(arguments, set)
1185
if err != nil {
1186
switch f.errorHandling {
1187
case ContinueOnError:
1188
return err
1189
case ExitOnError:
1190
if err == ErrHelp {
1191
os.Exit(0)
1192
}
1193
fmt.Fprintln(f.Output(), err)
1194
os.Exit(2)
1195
case PanicOnError:
1196
panic(err)
1197
}
1198
}
1199
return nil
1200
}
1201
1202
type parseFunc func(flag *Flag, value string) error
1203
1204
// ParseAll parses flag definitions from the argument list, which should not
1205
// include the command name. The arguments for fn are flag and value. Must be
1206
// called after all flags in the FlagSet are defined and before flags are
1207
// accessed by the program. The return value will be ErrHelp if -help was set
1208
// but not defined.
1209
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
1210
f.parsed = true
1211
f.args = make([]string, 0, len(arguments))
1212
1213
err := f.parseArgs(arguments, fn)
1214
if err != nil {
1215
switch f.errorHandling {
1216
case ContinueOnError:
1217
return err
1218
case ExitOnError:
1219
if err == ErrHelp {
1220
os.Exit(0)
1221
}
1222
fmt.Fprintln(f.Output(), err)
1223
os.Exit(2)
1224
case PanicOnError:
1225
panic(err)
1226
}
1227
}
1228
return nil
1229
}
1230
1231
// Parsed reports whether f.Parse has been called.
1232
func (f *FlagSet) Parsed() bool {
1233
return f.parsed
1234
}
1235
1236
// Parse parses the command-line flags from os.Args[1:]. Must be called
1237
// after all flags are defined and before flags are accessed by the program.
1238
func Parse() {
1239
// Ignore errors; CommandLine is set for ExitOnError.
1240
CommandLine.Parse(os.Args[1:])
1241
}
1242
1243
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
1244
// The arguments for fn are flag and value. Must be called after all flags are
1245
// defined and before flags are accessed by the program.
1246
func ParseAll(fn func(flag *Flag, value string) error) {
1247
// Ignore errors; CommandLine is set for ExitOnError.
1248
CommandLine.ParseAll(os.Args[1:], fn)
1249
}
1250
1251
// SetInterspersed sets whether to support interspersed option/non-option arguments.
1252
func SetInterspersed(interspersed bool) {
1253
CommandLine.SetInterspersed(interspersed)
1254
}
1255
1256
// Parsed returns true if the command-line flags have been parsed.
1257
func Parsed() bool {
1258
return CommandLine.Parsed()
1259
}
1260
1261
// CommandLine is the default set of command-line flags, parsed from os.Args.
1262
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
1263
1264
// NewFlagSet returns a new, empty flag set with the specified name,
1265
// error handling property and SortFlags set to true.
1266
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
1267
f := &FlagSet{
1268
name: name,
1269
errorHandling: errorHandling,
1270
argsLenAtDash: -1,
1271
interspersed: true,
1272
SortFlags: true,
1273
}
1274
return f
1275
}
1276
1277
// SetInterspersed sets whether to support interspersed option/non-option arguments.
1278
func (f *FlagSet) SetInterspersed(interspersed bool) {
1279
f.interspersed = interspersed
1280
}
1281
1282
// Init sets the name and error handling property for a flag set.
1283
// By default, the zero FlagSet uses an empty name and the
1284
// ContinueOnError error handling policy.
1285
func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
1286
f.name = name
1287
f.errorHandling = errorHandling
1288
f.argsLenAtDash = -1
1289
}
1290
1291