Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/spf13/cobra/command.go
2875 views
1
// Copyright 2013-2023 The Cobra Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.
16
// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.
17
package cobra
18
19
import (
20
"bytes"
21
"context"
22
"errors"
23
"fmt"
24
"io"
25
"os"
26
"path/filepath"
27
"sort"
28
"strings"
29
30
flag "github.com/spf13/pflag"
31
)
32
33
const (
34
FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
35
CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
36
37
helpFlagName = "help"
38
helpCommandName = "help"
39
)
40
41
// FParseErrWhitelist configures Flag parse errors to be ignored
42
type FParseErrWhitelist flag.ParseErrorsAllowlist
43
44
// Group Structure to manage groups for commands
45
type Group struct {
46
ID string
47
Title string
48
}
49
50
// Command is just that, a command for your application.
51
// E.g. 'go run ...' - 'run' is the command. Cobra requires
52
// you to define the usage and description as part of your command
53
// definition to ensure usability.
54
type Command struct {
55
// Use is the one-line usage message.
56
// Recommended syntax is as follows:
57
// [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required.
58
// ... indicates that you can specify multiple values for the previous argument.
59
// | indicates mutually exclusive information. You can use the argument to the left of the separator or the
60
// argument to the right of the separator. You cannot use both arguments in a single use of the command.
61
// { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are
62
// optional, they are enclosed in brackets ([ ]).
63
// Example: add [-F file | -D dir]... [-f format] profile
64
Use string
65
66
// Aliases is an array of aliases that can be used instead of the first word in Use.
67
Aliases []string
68
69
// SuggestFor is an array of command names for which this command will be suggested -
70
// similar to aliases but only suggests.
71
SuggestFor []string
72
73
// Short is the short description shown in the 'help' output.
74
Short string
75
76
// The group id under which this subcommand is grouped in the 'help' output of its parent.
77
GroupID string
78
79
// Long is the long message shown in the 'help <this-command>' output.
80
Long string
81
82
// Example is examples of how to use the command.
83
Example string
84
85
// ValidArgs is list of all valid non-flag arguments that are accepted in shell completions
86
ValidArgs []Completion
87
// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion.
88
// It is a dynamic version of using ValidArgs.
89
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
90
ValidArgsFunction CompletionFunc
91
92
// Expected arguments
93
Args PositionalArgs
94
95
// ArgAliases is List of aliases for ValidArgs.
96
// These are not suggested to the user in the shell completion,
97
// but accepted if entered manually.
98
ArgAliases []string
99
100
// BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator.
101
// For portability with other shells, it is recommended to instead use ValidArgsFunction
102
BashCompletionFunction string
103
104
// Deprecated defines, if this command is deprecated and should print this string when used.
105
Deprecated string
106
107
// Annotations are key/value pairs that can be used by applications to identify or
108
// group commands or set special options.
109
Annotations map[string]string
110
111
// Version defines the version for this command. If this value is non-empty and the command does not
112
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
113
// will print content of the "Version" variable. A shorthand "v" flag will also be added if the
114
// command does not define one.
115
Version string
116
117
// The *Run functions are executed in the following order:
118
// * PersistentPreRun()
119
// * PreRun()
120
// * Run()
121
// * PostRun()
122
// * PersistentPostRun()
123
// All functions get the same args, the arguments after the command name.
124
// The *PreRun and *PostRun functions will only be executed if the Run function of the current
125
// command has been declared.
126
//
127
// PersistentPreRun: children of this command will inherit and execute.
128
PersistentPreRun func(cmd *Command, args []string)
129
// PersistentPreRunE: PersistentPreRun but returns an error.
130
PersistentPreRunE func(cmd *Command, args []string) error
131
// PreRun: children of this command will not inherit.
132
PreRun func(cmd *Command, args []string)
133
// PreRunE: PreRun but returns an error.
134
PreRunE func(cmd *Command, args []string) error
135
// Run: Typically the actual work function. Most commands will only implement this.
136
Run func(cmd *Command, args []string)
137
// RunE: Run but returns an error.
138
RunE func(cmd *Command, args []string) error
139
// PostRun: run after the Run command.
140
PostRun func(cmd *Command, args []string)
141
// PostRunE: PostRun but returns an error.
142
PostRunE func(cmd *Command, args []string) error
143
// PersistentPostRun: children of this command will inherit and execute after PostRun.
144
PersistentPostRun func(cmd *Command, args []string)
145
// PersistentPostRunE: PersistentPostRun but returns an error.
146
PersistentPostRunE func(cmd *Command, args []string) error
147
148
// groups for subcommands
149
commandgroups []*Group
150
151
// args is actual args parsed from flags.
152
args []string
153
// flagErrorBuf contains all error messages from pflag.
154
flagErrorBuf *bytes.Buffer
155
// flags is full set of flags.
156
flags *flag.FlagSet
157
// pflags contains persistent flags.
158
pflags *flag.FlagSet
159
// lflags contains local flags.
160
// This field does not represent internal state, it's used as a cache to optimise LocalFlags function call
161
lflags *flag.FlagSet
162
// iflags contains inherited flags.
163
// This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call
164
iflags *flag.FlagSet
165
// parentsPflags is all persistent flags of cmd's parents.
166
parentsPflags *flag.FlagSet
167
// globNormFunc is the global normalization function
168
// that we can use on every pflag set and children commands
169
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
170
171
// usageFunc is usage func defined by user.
172
usageFunc func(*Command) error
173
// usageTemplate is usage template defined by user.
174
usageTemplate *tmplFunc
175
// flagErrorFunc is func defined by user and it's called when the parsing of
176
// flags returns an error.
177
flagErrorFunc func(*Command, error) error
178
// helpTemplate is help template defined by user.
179
helpTemplate *tmplFunc
180
// helpFunc is help func defined by user.
181
helpFunc func(*Command, []string)
182
// helpCommand is command with usage 'help'. If it's not defined by user,
183
// cobra uses default help command.
184
helpCommand *Command
185
// helpCommandGroupID is the group id for the helpCommand
186
helpCommandGroupID string
187
188
// completionCommandGroupID is the group id for the completion command
189
completionCommandGroupID string
190
191
// versionTemplate is the version template defined by user.
192
versionTemplate *tmplFunc
193
194
// errPrefix is the error message prefix defined by user.
195
errPrefix string
196
197
// inReader is a reader defined by the user that replaces stdin
198
inReader io.Reader
199
// outWriter is a writer defined by the user that replaces stdout
200
outWriter io.Writer
201
// errWriter is a writer defined by the user that replaces stderr
202
errWriter io.Writer
203
204
// FParseErrWhitelist flag parse errors to be ignored
205
FParseErrWhitelist FParseErrWhitelist
206
207
// CompletionOptions is a set of options to control the handling of shell completion
208
CompletionOptions CompletionOptions
209
210
// commandsAreSorted defines, if command slice are sorted or not.
211
commandsAreSorted bool
212
// commandCalledAs is the name or alias value used to call this command.
213
commandCalledAs struct {
214
name string
215
called bool
216
}
217
218
ctx context.Context
219
220
// commands is the list of commands supported by this program.
221
commands []*Command
222
// parent is a parent command for this command.
223
parent *Command
224
// Max lengths of commands' string lengths for use in padding.
225
commandsMaxUseLen int
226
commandsMaxCommandPathLen int
227
commandsMaxNameLen int
228
229
// TraverseChildren parses flags on all parents before executing child command.
230
TraverseChildren bool
231
232
// Hidden defines, if this command is hidden and should NOT show up in the list of available commands.
233
Hidden bool
234
235
// SilenceErrors is an option to quiet errors down stream.
236
SilenceErrors bool
237
238
// SilenceUsage is an option to silence usage when an error occurs.
239
SilenceUsage bool
240
241
// DisableFlagParsing disables the flag parsing.
242
// If this is true all flags will be passed to the command as arguments.
243
DisableFlagParsing bool
244
245
// DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...")
246
// will be printed by generating docs for this command.
247
DisableAutoGenTag bool
248
249
// DisableFlagsInUseLine will disable the addition of [flags] to the usage
250
// line of a command when printing help or generating docs
251
DisableFlagsInUseLine bool
252
253
// DisableSuggestions disables the suggestions based on Levenshtein distance
254
// that go along with 'unknown command' messages.
255
DisableSuggestions bool
256
257
// SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
258
// Must be > 0.
259
SuggestionsMinimumDistance int
260
}
261
262
// Context returns underlying command context. If command was executed
263
// with ExecuteContext or the context was set with SetContext, the
264
// previously set context will be returned. Otherwise, nil is returned.
265
//
266
// Notice that a call to Execute and ExecuteC will replace a nil context of
267
// a command with a context.Background, so a background context will be
268
// returned by Context after one of these functions has been called.
269
func (c *Command) Context() context.Context {
270
return c.ctx
271
}
272
273
// SetContext sets context for the command. This context will be overwritten by
274
// Command.ExecuteContext or Command.ExecuteContextC.
275
func (c *Command) SetContext(ctx context.Context) {
276
c.ctx = ctx
277
}
278
279
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
280
// particularly useful when testing.
281
func (c *Command) SetArgs(a []string) {
282
c.args = a
283
}
284
285
// SetOutput sets the destination for usage and error messages.
286
// If output is nil, os.Stderr is used.
287
//
288
// Deprecated: Use SetOut and/or SetErr instead
289
func (c *Command) SetOutput(output io.Writer) {
290
c.outWriter = output
291
c.errWriter = output
292
}
293
294
// SetOut sets the destination for usage messages.
295
// If newOut is nil, os.Stdout is used.
296
func (c *Command) SetOut(newOut io.Writer) {
297
c.outWriter = newOut
298
}
299
300
// SetErr sets the destination for error messages.
301
// If newErr is nil, os.Stderr is used.
302
func (c *Command) SetErr(newErr io.Writer) {
303
c.errWriter = newErr
304
}
305
306
// SetIn sets the source for input data
307
// If newIn is nil, os.Stdin is used.
308
func (c *Command) SetIn(newIn io.Reader) {
309
c.inReader = newIn
310
}
311
312
// SetUsageFunc sets usage function. Usage can be defined by application.
313
func (c *Command) SetUsageFunc(f func(*Command) error) {
314
c.usageFunc = f
315
}
316
317
// SetUsageTemplate sets usage template. Can be defined by Application.
318
func (c *Command) SetUsageTemplate(s string) {
319
if s == "" {
320
c.usageTemplate = nil
321
return
322
}
323
c.usageTemplate = tmpl(s)
324
}
325
326
// SetFlagErrorFunc sets a function to generate an error when flag parsing
327
// fails.
328
func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
329
c.flagErrorFunc = f
330
}
331
332
// SetHelpFunc sets help function. Can be defined by Application.
333
func (c *Command) SetHelpFunc(f func(*Command, []string)) {
334
c.helpFunc = f
335
}
336
337
// SetHelpCommand sets help command.
338
func (c *Command) SetHelpCommand(cmd *Command) {
339
c.helpCommand = cmd
340
}
341
342
// SetHelpCommandGroupID sets the group id of the help command.
343
func (c *Command) SetHelpCommandGroupID(groupID string) {
344
if c.helpCommand != nil {
345
c.helpCommand.GroupID = groupID
346
}
347
// helpCommandGroupID is used if no helpCommand is defined by the user
348
c.helpCommandGroupID = groupID
349
}
350
351
// SetCompletionCommandGroupID sets the group id of the completion command.
352
func (c *Command) SetCompletionCommandGroupID(groupID string) {
353
// completionCommandGroupID is used if no completion command is defined by the user
354
c.Root().completionCommandGroupID = groupID
355
}
356
357
// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
358
func (c *Command) SetHelpTemplate(s string) {
359
if s == "" {
360
c.helpTemplate = nil
361
return
362
}
363
c.helpTemplate = tmpl(s)
364
}
365
366
// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
367
func (c *Command) SetVersionTemplate(s string) {
368
if s == "" {
369
c.versionTemplate = nil
370
return
371
}
372
c.versionTemplate = tmpl(s)
373
}
374
375
// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix.
376
func (c *Command) SetErrPrefix(s string) {
377
c.errPrefix = s
378
}
379
380
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
381
// The user should not have a cyclic dependency on commands.
382
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
383
c.Flags().SetNormalizeFunc(n)
384
c.PersistentFlags().SetNormalizeFunc(n)
385
c.globNormFunc = n
386
387
for _, command := range c.commands {
388
command.SetGlobalNormalizationFunc(n)
389
}
390
}
391
392
// OutOrStdout returns output to stdout.
393
func (c *Command) OutOrStdout() io.Writer {
394
return c.getOut(os.Stdout)
395
}
396
397
// OutOrStderr returns output to stderr
398
func (c *Command) OutOrStderr() io.Writer {
399
return c.getOut(os.Stderr)
400
}
401
402
// ErrOrStderr returns output to stderr
403
func (c *Command) ErrOrStderr() io.Writer {
404
return c.getErr(os.Stderr)
405
}
406
407
// InOrStdin returns input to stdin
408
func (c *Command) InOrStdin() io.Reader {
409
return c.getIn(os.Stdin)
410
}
411
412
func (c *Command) getOut(def io.Writer) io.Writer {
413
if c.outWriter != nil {
414
return c.outWriter
415
}
416
if c.HasParent() {
417
return c.parent.getOut(def)
418
}
419
return def
420
}
421
422
func (c *Command) getErr(def io.Writer) io.Writer {
423
if c.errWriter != nil {
424
return c.errWriter
425
}
426
if c.HasParent() {
427
return c.parent.getErr(def)
428
}
429
return def
430
}
431
432
func (c *Command) getIn(def io.Reader) io.Reader {
433
if c.inReader != nil {
434
return c.inReader
435
}
436
if c.HasParent() {
437
return c.parent.getIn(def)
438
}
439
return def
440
}
441
442
// UsageFunc returns either the function set by SetUsageFunc for this command
443
// or a parent, or it returns a default usage function.
444
func (c *Command) UsageFunc() (f func(*Command) error) {
445
if c.usageFunc != nil {
446
return c.usageFunc
447
}
448
if c.HasParent() {
449
return c.Parent().UsageFunc()
450
}
451
return func(c *Command) error {
452
c.mergePersistentFlags()
453
fn := c.getUsageTemplateFunc()
454
err := fn(c.OutOrStderr(), c)
455
if err != nil {
456
c.PrintErrln(err)
457
}
458
return err
459
}
460
}
461
462
// getUsageTemplateFunc returns the usage template function for the command
463
// going up the command tree if necessary.
464
func (c *Command) getUsageTemplateFunc() func(w io.Writer, data interface{}) error {
465
if c.usageTemplate != nil {
466
return c.usageTemplate.fn
467
}
468
469
if c.HasParent() {
470
return c.parent.getUsageTemplateFunc()
471
}
472
return defaultUsageFunc
473
}
474
475
// Usage puts out the usage for the command.
476
// Used when a user provides invalid input.
477
// Can be defined by user by overriding UsageFunc.
478
func (c *Command) Usage() error {
479
return c.UsageFunc()(c)
480
}
481
482
// HelpFunc returns either the function set by SetHelpFunc for this command
483
// or a parent, or it returns a function with default help behavior.
484
func (c *Command) HelpFunc() func(*Command, []string) {
485
if c.helpFunc != nil {
486
return c.helpFunc
487
}
488
if c.HasParent() {
489
return c.Parent().HelpFunc()
490
}
491
return func(c *Command, a []string) {
492
c.mergePersistentFlags()
493
fn := c.getHelpTemplateFunc()
494
// The help should be sent to stdout
495
// See https://github.com/spf13/cobra/issues/1002
496
err := fn(c.OutOrStdout(), c)
497
if err != nil {
498
c.PrintErrln(err)
499
}
500
}
501
}
502
503
// getHelpTemplateFunc returns the help template function for the command
504
// going up the command tree if necessary.
505
func (c *Command) getHelpTemplateFunc() func(w io.Writer, data interface{}) error {
506
if c.helpTemplate != nil {
507
return c.helpTemplate.fn
508
}
509
510
if c.HasParent() {
511
return c.parent.getHelpTemplateFunc()
512
}
513
514
return defaultHelpFunc
515
}
516
517
// Help puts out the help for the command.
518
// Used when a user calls help [command].
519
// Can be defined by user by overriding HelpFunc.
520
func (c *Command) Help() error {
521
c.HelpFunc()(c, []string{})
522
return nil
523
}
524
525
// UsageString returns usage string.
526
func (c *Command) UsageString() string {
527
// Storing normal writers
528
tmpOutput := c.outWriter
529
tmpErr := c.errWriter
530
531
bb := new(bytes.Buffer)
532
c.outWriter = bb
533
c.errWriter = bb
534
535
CheckErr(c.Usage())
536
537
// Setting things back to normal
538
c.outWriter = tmpOutput
539
c.errWriter = tmpErr
540
541
return bb.String()
542
}
543
544
// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this
545
// command or a parent, or it returns a function which returns the original
546
// error.
547
func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
548
if c.flagErrorFunc != nil {
549
return c.flagErrorFunc
550
}
551
552
if c.HasParent() {
553
return c.parent.FlagErrorFunc()
554
}
555
return func(c *Command, err error) error {
556
return err
557
}
558
}
559
560
var minUsagePadding = 25
561
562
// UsagePadding return padding for the usage.
563
func (c *Command) UsagePadding() int {
564
if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
565
return minUsagePadding
566
}
567
return c.parent.commandsMaxUseLen
568
}
569
570
var minCommandPathPadding = 11
571
572
// CommandPathPadding return padding for the command path.
573
func (c *Command) CommandPathPadding() int {
574
if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
575
return minCommandPathPadding
576
}
577
return c.parent.commandsMaxCommandPathLen
578
}
579
580
var minNamePadding = 11
581
582
// NamePadding returns padding for the name.
583
func (c *Command) NamePadding() int {
584
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
585
return minNamePadding
586
}
587
return c.parent.commandsMaxNameLen
588
}
589
590
// UsageTemplate returns usage template for the command.
591
// This function is kept for backwards-compatibility reasons.
592
func (c *Command) UsageTemplate() string {
593
if c.usageTemplate != nil {
594
return c.usageTemplate.tmpl
595
}
596
597
if c.HasParent() {
598
return c.parent.UsageTemplate()
599
}
600
return defaultUsageTemplate
601
}
602
603
// HelpTemplate return help template for the command.
604
// This function is kept for backwards-compatibility reasons.
605
func (c *Command) HelpTemplate() string {
606
if c.helpTemplate != nil {
607
return c.helpTemplate.tmpl
608
}
609
610
if c.HasParent() {
611
return c.parent.HelpTemplate()
612
}
613
return defaultHelpTemplate
614
}
615
616
// VersionTemplate return version template for the command.
617
// This function is kept for backwards-compatibility reasons.
618
func (c *Command) VersionTemplate() string {
619
if c.versionTemplate != nil {
620
return c.versionTemplate.tmpl
621
}
622
623
if c.HasParent() {
624
return c.parent.VersionTemplate()
625
}
626
return defaultVersionTemplate
627
}
628
629
// getVersionTemplateFunc returns the version template function for the command
630
// going up the command tree if necessary.
631
func (c *Command) getVersionTemplateFunc() func(w io.Writer, data interface{}) error {
632
if c.versionTemplate != nil {
633
return c.versionTemplate.fn
634
}
635
636
if c.HasParent() {
637
return c.parent.getVersionTemplateFunc()
638
}
639
return defaultVersionFunc
640
}
641
642
// ErrPrefix return error message prefix for the command
643
func (c *Command) ErrPrefix() string {
644
if c.errPrefix != "" {
645
return c.errPrefix
646
}
647
648
if c.HasParent() {
649
return c.parent.ErrPrefix()
650
}
651
return "Error:"
652
}
653
654
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
655
flag := fs.Lookup(name)
656
if flag == nil {
657
return false
658
}
659
return flag.NoOptDefVal != ""
660
}
661
662
func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
663
if len(name) == 0 {
664
return false
665
}
666
667
flag := fs.ShorthandLookup(name[:1])
668
if flag == nil {
669
return false
670
}
671
return flag.NoOptDefVal != ""
672
}
673
674
func stripFlags(args []string, c *Command) []string {
675
if len(args) == 0 {
676
return args
677
}
678
c.mergePersistentFlags()
679
680
commands := []string{}
681
flags := c.Flags()
682
683
Loop:
684
for len(args) > 0 {
685
s := args[0]
686
args = args[1:]
687
switch {
688
case s == "--":
689
// "--" terminates the flags
690
break Loop
691
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
692
// If '--flag arg' then
693
// delete arg from args.
694
fallthrough // (do the same as below)
695
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
696
// If '-f arg' then
697
// delete 'arg' from args or break the loop if len(args) <= 1.
698
if len(args) <= 1 {
699
break Loop
700
} else {
701
args = args[1:]
702
continue
703
}
704
case s != "" && !strings.HasPrefix(s, "-"):
705
commands = append(commands, s)
706
}
707
}
708
709
return commands
710
}
711
712
// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
713
// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
714
// Special care needs to be taken not to remove a flag value.
715
func (c *Command) argsMinusFirstX(args []string, x string) []string {
716
if len(args) == 0 {
717
return args
718
}
719
c.mergePersistentFlags()
720
flags := c.Flags()
721
722
Loop:
723
for pos := 0; pos < len(args); pos++ {
724
s := args[pos]
725
switch {
726
case s == "--":
727
// -- means we have reached the end of the parseable args. Break out of the loop now.
728
break Loop
729
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
730
fallthrough
731
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
732
// This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip
733
// over the next arg, because that is the value of this flag.
734
pos++
735
continue
736
case !strings.HasPrefix(s, "-"):
737
// This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so,
738
// return the args, excluding the one at this position.
739
if s == x {
740
ret := make([]string, 0, len(args)-1)
741
ret = append(ret, args[:pos]...)
742
ret = append(ret, args[pos+1:]...)
743
return ret
744
}
745
}
746
}
747
return args
748
}
749
750
func isFlagArg(arg string) bool {
751
return ((len(arg) >= 3 && arg[0:2] == "--") ||
752
(len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
753
}
754
755
// Find the target command given the args and command tree
756
// Meant to be run on the highest node. Only searches down.
757
func (c *Command) Find(args []string) (*Command, []string, error) {
758
var innerfind func(*Command, []string) (*Command, []string)
759
760
innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
761
argsWOflags := stripFlags(innerArgs, c)
762
if len(argsWOflags) == 0 {
763
return c, innerArgs
764
}
765
nextSubCmd := argsWOflags[0]
766
767
cmd := c.findNext(nextSubCmd)
768
if cmd != nil {
769
return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd))
770
}
771
return c, innerArgs
772
}
773
774
commandFound, a := innerfind(c, args)
775
if commandFound.Args == nil {
776
return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
777
}
778
return commandFound, a, nil
779
}
780
781
func (c *Command) findSuggestions(arg string) string {
782
if c.DisableSuggestions {
783
return ""
784
}
785
if c.SuggestionsMinimumDistance <= 0 {
786
c.SuggestionsMinimumDistance = 2
787
}
788
var sb strings.Builder
789
if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 {
790
sb.WriteString("\n\nDid you mean this?\n")
791
for _, s := range suggestions {
792
_, _ = fmt.Fprintf(&sb, "\t%v\n", s)
793
}
794
}
795
return sb.String()
796
}
797
798
func (c *Command) findNext(next string) *Command {
799
matches := make([]*Command, 0)
800
for _, cmd := range c.commands {
801
if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) {
802
cmd.commandCalledAs.name = next
803
return cmd
804
}
805
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
806
matches = append(matches, cmd)
807
}
808
}
809
810
if len(matches) == 1 {
811
// Temporarily disable gosec G602, which produces a false positive.
812
// See https://github.com/securego/gosec/issues/1005.
813
return matches[0] // #nosec G602
814
}
815
816
return nil
817
}
818
819
// Traverse the command tree to find the command, and parse args for
820
// each parent.
821
func (c *Command) Traverse(args []string) (*Command, []string, error) {
822
flags := []string{}
823
inFlag := false
824
825
for i, arg := range args {
826
switch {
827
// A long flag with a space separated value
828
case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="):
829
// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
830
inFlag = !hasNoOptDefVal(arg[2:], c.Flags())
831
flags = append(flags, arg)
832
continue
833
// A short flag with a space separated value
834
case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()):
835
inFlag = true
836
flags = append(flags, arg)
837
continue
838
// The value for a flag
839
case inFlag:
840
inFlag = false
841
flags = append(flags, arg)
842
continue
843
// A flag without a value, or with an `=` separated value
844
case isFlagArg(arg):
845
flags = append(flags, arg)
846
continue
847
}
848
849
cmd := c.findNext(arg)
850
if cmd == nil {
851
return c, args, nil
852
}
853
854
if err := c.ParseFlags(flags); err != nil {
855
return nil, args, err
856
}
857
return cmd.Traverse(args[i+1:])
858
}
859
return c, args, nil
860
}
861
862
// SuggestionsFor provides suggestions for the typedName.
863
func (c *Command) SuggestionsFor(typedName string) []string {
864
suggestions := []string{}
865
for _, cmd := range c.commands {
866
if cmd.IsAvailableCommand() {
867
levenshteinDistance := ld(typedName, cmd.Name(), true)
868
suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance
869
suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))
870
if suggestByLevenshtein || suggestByPrefix {
871
suggestions = append(suggestions, cmd.Name())
872
}
873
for _, explicitSuggestion := range cmd.SuggestFor {
874
if strings.EqualFold(typedName, explicitSuggestion) {
875
suggestions = append(suggestions, cmd.Name())
876
}
877
}
878
}
879
}
880
return suggestions
881
}
882
883
// VisitParents visits all parents of the command and invokes fn on each parent.
884
func (c *Command) VisitParents(fn func(*Command)) {
885
if c.HasParent() {
886
fn(c.Parent())
887
c.Parent().VisitParents(fn)
888
}
889
}
890
891
// Root finds root command.
892
func (c *Command) Root() *Command {
893
if c.HasParent() {
894
return c.Parent().Root()
895
}
896
return c
897
}
898
899
// ArgsLenAtDash will return the length of c.Flags().Args at the moment
900
// when a -- was found during args parsing.
901
func (c *Command) ArgsLenAtDash() int {
902
return c.Flags().ArgsLenAtDash()
903
}
904
905
func (c *Command) execute(a []string) (err error) {
906
if c == nil {
907
return fmt.Errorf("called Execute() on a nil Command")
908
}
909
910
if len(c.Deprecated) > 0 {
911
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
912
}
913
914
// initialize help and version flag at the last point possible to allow for user
915
// overriding
916
c.InitDefaultHelpFlag()
917
c.InitDefaultVersionFlag()
918
919
err = c.ParseFlags(a)
920
if err != nil {
921
return c.FlagErrorFunc()(c, err)
922
}
923
924
// If help is called, regardless of other flags, return we want help.
925
// Also say we need help if the command isn't runnable.
926
helpVal, err := c.Flags().GetBool(helpFlagName)
927
if err != nil {
928
// should be impossible to get here as we always declare a help
929
// flag in InitDefaultHelpFlag()
930
c.Println("\"help\" flag declared as non-bool. Please correct your code")
931
return err
932
}
933
934
if helpVal {
935
return flag.ErrHelp
936
}
937
938
// for back-compat, only add version flag behavior if version is defined
939
if c.Version != "" {
940
versionVal, err := c.Flags().GetBool("version")
941
if err != nil {
942
c.Println("\"version\" flag declared as non-bool. Please correct your code")
943
return err
944
}
945
if versionVal {
946
fn := c.getVersionTemplateFunc()
947
err := fn(c.OutOrStdout(), c)
948
if err != nil {
949
c.Println(err)
950
}
951
return err
952
}
953
}
954
955
if !c.Runnable() {
956
return flag.ErrHelp
957
}
958
959
c.preRun()
960
961
defer c.postRun()
962
963
argWoFlags := c.Flags().Args()
964
if c.DisableFlagParsing {
965
argWoFlags = a
966
}
967
968
if err := c.ValidateArgs(argWoFlags); err != nil {
969
return err
970
}
971
972
parents := make([]*Command, 0, 5)
973
for p := c; p != nil; p = p.Parent() {
974
if EnableTraverseRunHooks {
975
// When EnableTraverseRunHooks is set:
976
// - Execute all persistent pre-runs from the root parent till this command.
977
// - Execute all persistent post-runs from this command till the root parent.
978
parents = append([]*Command{p}, parents...)
979
} else {
980
// Otherwise, execute only the first found persistent hook.
981
parents = append(parents, p)
982
}
983
}
984
for _, p := range parents {
985
if p.PersistentPreRunE != nil {
986
if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
987
return err
988
}
989
if !EnableTraverseRunHooks {
990
break
991
}
992
} else if p.PersistentPreRun != nil {
993
p.PersistentPreRun(c, argWoFlags)
994
if !EnableTraverseRunHooks {
995
break
996
}
997
}
998
}
999
if c.PreRunE != nil {
1000
if err := c.PreRunE(c, argWoFlags); err != nil {
1001
return err
1002
}
1003
} else if c.PreRun != nil {
1004
c.PreRun(c, argWoFlags)
1005
}
1006
1007
if err := c.ValidateRequiredFlags(); err != nil {
1008
return err
1009
}
1010
if err := c.ValidateFlagGroups(); err != nil {
1011
return err
1012
}
1013
1014
if c.RunE != nil {
1015
if err := c.RunE(c, argWoFlags); err != nil {
1016
return err
1017
}
1018
} else {
1019
c.Run(c, argWoFlags)
1020
}
1021
if c.PostRunE != nil {
1022
if err := c.PostRunE(c, argWoFlags); err != nil {
1023
return err
1024
}
1025
} else if c.PostRun != nil {
1026
c.PostRun(c, argWoFlags)
1027
}
1028
for p := c; p != nil; p = p.Parent() {
1029
if p.PersistentPostRunE != nil {
1030
if err := p.PersistentPostRunE(c, argWoFlags); err != nil {
1031
return err
1032
}
1033
if !EnableTraverseRunHooks {
1034
break
1035
}
1036
} else if p.PersistentPostRun != nil {
1037
p.PersistentPostRun(c, argWoFlags)
1038
if !EnableTraverseRunHooks {
1039
break
1040
}
1041
}
1042
}
1043
1044
return nil
1045
}
1046
1047
func (c *Command) preRun() {
1048
for _, x := range initializers {
1049
x()
1050
}
1051
}
1052
1053
func (c *Command) postRun() {
1054
for _, x := range finalizers {
1055
x()
1056
}
1057
}
1058
1059
// ExecuteContext is the same as Execute(), but sets the ctx on the command.
1060
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs
1061
// functions.
1062
func (c *Command) ExecuteContext(ctx context.Context) error {
1063
c.ctx = ctx
1064
return c.Execute()
1065
}
1066
1067
// Execute uses the args (os.Args[1:] by default)
1068
// and run through the command tree finding appropriate matches
1069
// for commands and then corresponding flags.
1070
func (c *Command) Execute() error {
1071
_, err := c.ExecuteC()
1072
return err
1073
}
1074
1075
// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command.
1076
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs
1077
// functions.
1078
func (c *Command) ExecuteContextC(ctx context.Context) (*Command, error) {
1079
c.ctx = ctx
1080
return c.ExecuteC()
1081
}
1082
1083
// ExecuteC executes the command.
1084
func (c *Command) ExecuteC() (cmd *Command, err error) {
1085
if c.ctx == nil {
1086
c.ctx = context.Background()
1087
}
1088
1089
// Regardless of what command execute is called on, run on Root only
1090
if c.HasParent() {
1091
return c.Root().ExecuteC()
1092
}
1093
1094
// windows hook
1095
if preExecHookFn != nil {
1096
preExecHookFn(c)
1097
}
1098
1099
// initialize help at the last point to allow for user overriding
1100
c.InitDefaultHelpCmd()
1101
1102
args := c.args
1103
1104
// Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
1105
if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
1106
args = os.Args[1:]
1107
}
1108
1109
// initialize the __complete command to be used for shell completion
1110
c.initCompleteCmd(args)
1111
1112
// initialize the default completion command
1113
c.InitDefaultCompletionCmd(args...)
1114
1115
// Now that all commands have been created, let's make sure all groups
1116
// are properly created also
1117
c.checkCommandGroups()
1118
1119
var flags []string
1120
if c.TraverseChildren {
1121
cmd, flags, err = c.Traverse(args)
1122
} else {
1123
cmd, flags, err = c.Find(args)
1124
}
1125
if err != nil {
1126
// If found parse to a subcommand and then failed, talk about the subcommand
1127
if cmd != nil {
1128
c = cmd
1129
}
1130
if !c.SilenceErrors {
1131
c.PrintErrln(c.ErrPrefix(), err.Error())
1132
c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
1133
}
1134
return c, err
1135
}
1136
1137
cmd.commandCalledAs.called = true
1138
if cmd.commandCalledAs.name == "" {
1139
cmd.commandCalledAs.name = cmd.Name()
1140
}
1141
1142
// We have to pass global context to children command
1143
// if context is present on the parent command.
1144
if cmd.ctx == nil {
1145
cmd.ctx = c.ctx
1146
}
1147
1148
err = cmd.execute(flags)
1149
if err != nil {
1150
// Always show help if requested, even if SilenceErrors is in
1151
// effect
1152
if errors.Is(err, flag.ErrHelp) {
1153
cmd.HelpFunc()(cmd, args)
1154
return cmd, nil
1155
}
1156
1157
// If root command has SilenceErrors flagged,
1158
// all subcommands should respect it
1159
if !cmd.SilenceErrors && !c.SilenceErrors {
1160
c.PrintErrln(cmd.ErrPrefix(), err.Error())
1161
}
1162
1163
// If root command has SilenceUsage flagged,
1164
// all subcommands should respect it
1165
if !cmd.SilenceUsage && !c.SilenceUsage {
1166
c.Println(cmd.UsageString())
1167
}
1168
}
1169
return cmd, err
1170
}
1171
1172
func (c *Command) ValidateArgs(args []string) error {
1173
if c.Args == nil {
1174
return ArbitraryArgs(c, args)
1175
}
1176
return c.Args(c, args)
1177
}
1178
1179
// ValidateRequiredFlags validates all required flags are present and returns an error otherwise
1180
func (c *Command) ValidateRequiredFlags() error {
1181
if c.DisableFlagParsing {
1182
return nil
1183
}
1184
1185
flags := c.Flags()
1186
missingFlagNames := []string{}
1187
flags.VisitAll(func(pflag *flag.Flag) {
1188
requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
1189
if !found {
1190
return
1191
}
1192
if (requiredAnnotation[0] == "true") && !pflag.Changed {
1193
missingFlagNames = append(missingFlagNames, pflag.Name)
1194
}
1195
})
1196
1197
if len(missingFlagNames) > 0 {
1198
return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
1199
}
1200
return nil
1201
}
1202
1203
// checkCommandGroups checks if a command has been added to a group that does not exists.
1204
// If so, we panic because it indicates a coding error that should be corrected.
1205
func (c *Command) checkCommandGroups() {
1206
for _, sub := range c.commands {
1207
// if Group is not defined let the developer know right away
1208
if sub.GroupID != "" && !c.ContainsGroup(sub.GroupID) {
1209
panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", sub.GroupID, sub.CommandPath()))
1210
}
1211
1212
sub.checkCommandGroups()
1213
}
1214
}
1215
1216
// InitDefaultHelpFlag adds default help flag to c.
1217
// It is called automatically by executing the c or by calling help and usage.
1218
// If c already has help flag, it will do nothing.
1219
func (c *Command) InitDefaultHelpFlag() {
1220
c.mergePersistentFlags()
1221
if c.Flags().Lookup(helpFlagName) == nil {
1222
usage := "help for "
1223
name := c.DisplayName()
1224
if name == "" {
1225
usage += "this command"
1226
} else {
1227
usage += name
1228
}
1229
c.Flags().BoolP(helpFlagName, "h", false, usage)
1230
_ = c.Flags().SetAnnotation(helpFlagName, FlagSetByCobraAnnotation, []string{"true"})
1231
}
1232
}
1233
1234
// InitDefaultVersionFlag adds default version flag to c.
1235
// It is called automatically by executing the c.
1236
// If c already has a version flag, it will do nothing.
1237
// If c.Version is empty, it will do nothing.
1238
func (c *Command) InitDefaultVersionFlag() {
1239
if c.Version == "" {
1240
return
1241
}
1242
1243
c.mergePersistentFlags()
1244
if c.Flags().Lookup("version") == nil {
1245
usage := "version for "
1246
if c.Name() == "" {
1247
usage += "this command"
1248
} else {
1249
usage += c.DisplayName()
1250
}
1251
if c.Flags().ShorthandLookup("v") == nil {
1252
c.Flags().BoolP("version", "v", false, usage)
1253
} else {
1254
c.Flags().Bool("version", false, usage)
1255
}
1256
_ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"})
1257
}
1258
}
1259
1260
// InitDefaultHelpCmd adds default help command to c.
1261
// It is called automatically by executing the c or by calling help and usage.
1262
// If c already has help command or c has no subcommands, it will do nothing.
1263
func (c *Command) InitDefaultHelpCmd() {
1264
if !c.HasSubCommands() {
1265
return
1266
}
1267
1268
if c.helpCommand == nil {
1269
c.helpCommand = &Command{
1270
Use: "help [command]",
1271
Short: "Help about any command",
1272
Long: `Help provides help for any command in the application.
1273
Simply type ` + c.DisplayName() + ` help [path to command] for full details.`,
1274
ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) {
1275
var completions []Completion
1276
cmd, _, e := c.Root().Find(args)
1277
if e != nil {
1278
return nil, ShellCompDirectiveNoFileComp
1279
}
1280
if cmd == nil {
1281
// Root help command.
1282
cmd = c.Root()
1283
}
1284
for _, subCmd := range cmd.Commands() {
1285
if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand {
1286
if strings.HasPrefix(subCmd.Name(), toComplete) {
1287
completions = append(completions, CompletionWithDesc(subCmd.Name(), subCmd.Short))
1288
}
1289
}
1290
}
1291
return completions, ShellCompDirectiveNoFileComp
1292
},
1293
Run: func(c *Command, args []string) {
1294
cmd, _, e := c.Root().Find(args)
1295
if cmd == nil || e != nil {
1296
c.Printf("Unknown help topic %#q\n", args)
1297
CheckErr(c.Root().Usage())
1298
} else {
1299
// FLow the context down to be used in help text
1300
if cmd.ctx == nil {
1301
cmd.ctx = c.ctx
1302
}
1303
1304
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
1305
cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown
1306
CheckErr(cmd.Help())
1307
}
1308
},
1309
GroupID: c.helpCommandGroupID,
1310
}
1311
}
1312
c.RemoveCommand(c.helpCommand)
1313
c.AddCommand(c.helpCommand)
1314
}
1315
1316
// ResetCommands delete parent, subcommand and help command from c.
1317
func (c *Command) ResetCommands() {
1318
c.parent = nil
1319
c.commands = nil
1320
c.helpCommand = nil
1321
c.parentsPflags = nil
1322
}
1323
1324
// Sorts commands by their names.
1325
type commandSorterByName []*Command
1326
1327
func (c commandSorterByName) Len() int { return len(c) }
1328
func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
1329
func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }
1330
1331
// Commands returns a sorted slice of child commands.
1332
func (c *Command) Commands() []*Command {
1333
// do not sort commands if it already sorted or sorting was disabled
1334
if EnableCommandSorting && !c.commandsAreSorted {
1335
sort.Sort(commandSorterByName(c.commands))
1336
c.commandsAreSorted = true
1337
}
1338
return c.commands
1339
}
1340
1341
// AddCommand adds one or more commands to this parent command.
1342
func (c *Command) AddCommand(cmds ...*Command) {
1343
for i, x := range cmds {
1344
if cmds[i] == c {
1345
panic("Command can't be a child of itself")
1346
}
1347
cmds[i].parent = c
1348
// update max lengths
1349
usageLen := len(x.Use)
1350
if usageLen > c.commandsMaxUseLen {
1351
c.commandsMaxUseLen = usageLen
1352
}
1353
commandPathLen := len(x.CommandPath())
1354
if commandPathLen > c.commandsMaxCommandPathLen {
1355
c.commandsMaxCommandPathLen = commandPathLen
1356
}
1357
nameLen := len(x.Name())
1358
if nameLen > c.commandsMaxNameLen {
1359
c.commandsMaxNameLen = nameLen
1360
}
1361
// If global normalization function exists, update all children
1362
if c.globNormFunc != nil {
1363
x.SetGlobalNormalizationFunc(c.globNormFunc)
1364
}
1365
c.commands = append(c.commands, x)
1366
c.commandsAreSorted = false
1367
}
1368
}
1369
1370
// Groups returns a slice of child command groups.
1371
func (c *Command) Groups() []*Group {
1372
return c.commandgroups
1373
}
1374
1375
// AllChildCommandsHaveGroup returns if all subcommands are assigned to a group
1376
func (c *Command) AllChildCommandsHaveGroup() bool {
1377
for _, sub := range c.commands {
1378
if (sub.IsAvailableCommand() || sub == c.helpCommand) && sub.GroupID == "" {
1379
return false
1380
}
1381
}
1382
return true
1383
}
1384
1385
// ContainsGroup return if groupID exists in the list of command groups.
1386
func (c *Command) ContainsGroup(groupID string) bool {
1387
for _, x := range c.commandgroups {
1388
if x.ID == groupID {
1389
return true
1390
}
1391
}
1392
return false
1393
}
1394
1395
// AddGroup adds one or more command groups to this parent command.
1396
func (c *Command) AddGroup(groups ...*Group) {
1397
c.commandgroups = append(c.commandgroups, groups...)
1398
}
1399
1400
// RemoveCommand removes one or more commands from a parent command.
1401
func (c *Command) RemoveCommand(cmds ...*Command) {
1402
commands := []*Command{}
1403
main:
1404
for _, command := range c.commands {
1405
for _, cmd := range cmds {
1406
if command == cmd {
1407
command.parent = nil
1408
continue main
1409
}
1410
}
1411
commands = append(commands, command)
1412
}
1413
c.commands = commands
1414
// recompute all lengths
1415
c.commandsMaxUseLen = 0
1416
c.commandsMaxCommandPathLen = 0
1417
c.commandsMaxNameLen = 0
1418
for _, command := range c.commands {
1419
usageLen := len(command.Use)
1420
if usageLen > c.commandsMaxUseLen {
1421
c.commandsMaxUseLen = usageLen
1422
}
1423
commandPathLen := len(command.CommandPath())
1424
if commandPathLen > c.commandsMaxCommandPathLen {
1425
c.commandsMaxCommandPathLen = commandPathLen
1426
}
1427
nameLen := len(command.Name())
1428
if nameLen > c.commandsMaxNameLen {
1429
c.commandsMaxNameLen = nameLen
1430
}
1431
}
1432
}
1433
1434
// Print is a convenience method to Print to the defined output, fallback to Stderr if not set.
1435
func (c *Command) Print(i ...interface{}) {
1436
fmt.Fprint(c.OutOrStderr(), i...)
1437
}
1438
1439
// Println is a convenience method to Println to the defined output, fallback to Stderr if not set.
1440
func (c *Command) Println(i ...interface{}) {
1441
c.Print(fmt.Sprintln(i...))
1442
}
1443
1444
// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set.
1445
func (c *Command) Printf(format string, i ...interface{}) {
1446
c.Print(fmt.Sprintf(format, i...))
1447
}
1448
1449
// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set.
1450
func (c *Command) PrintErr(i ...interface{}) {
1451
fmt.Fprint(c.ErrOrStderr(), i...)
1452
}
1453
1454
// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
1455
func (c *Command) PrintErrln(i ...interface{}) {
1456
c.PrintErr(fmt.Sprintln(i...))
1457
}
1458
1459
// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
1460
func (c *Command) PrintErrf(format string, i ...interface{}) {
1461
c.PrintErr(fmt.Sprintf(format, i...))
1462
}
1463
1464
// CommandPath returns the full path to this command.
1465
func (c *Command) CommandPath() string {
1466
if c.HasParent() {
1467
return c.Parent().CommandPath() + " " + c.Name()
1468
}
1469
return c.DisplayName()
1470
}
1471
1472
// DisplayName returns the name to display in help text. Returns command Name()
1473
// If CommandDisplayNameAnnoation is not set
1474
func (c *Command) DisplayName() string {
1475
if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok {
1476
return displayName
1477
}
1478
return c.Name()
1479
}
1480
1481
// UseLine puts out the full usage for a given command (including parents).
1482
func (c *Command) UseLine() string {
1483
var useline string
1484
use := strings.Replace(c.Use, c.Name(), c.DisplayName(), 1)
1485
if c.HasParent() {
1486
useline = c.parent.CommandPath() + " " + use
1487
} else {
1488
useline = use
1489
}
1490
if c.DisableFlagsInUseLine {
1491
return useline
1492
}
1493
if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
1494
useline += " [flags]"
1495
}
1496
return useline
1497
}
1498
1499
// DebugFlags used to determine which flags have been assigned to which commands
1500
// and which persist.
1501
func (c *Command) DebugFlags() {
1502
c.Println("DebugFlags called on", c.Name())
1503
var debugflags func(*Command)
1504
1505
debugflags = func(x *Command) {
1506
if x.HasFlags() || x.HasPersistentFlags() {
1507
c.Println(x.Name())
1508
}
1509
if x.HasFlags() {
1510
x.flags.VisitAll(func(f *flag.Flag) {
1511
if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil {
1512
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
1513
} else {
1514
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
1515
}
1516
})
1517
}
1518
if x.HasPersistentFlags() {
1519
x.pflags.VisitAll(func(f *flag.Flag) {
1520
if x.HasFlags() {
1521
if x.flags.Lookup(f.Name) == nil {
1522
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1523
}
1524
} else {
1525
c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1526
}
1527
})
1528
}
1529
c.Println(x.flagErrorBuf)
1530
if x.HasSubCommands() {
1531
for _, y := range x.commands {
1532
debugflags(y)
1533
}
1534
}
1535
}
1536
1537
debugflags(c)
1538
}
1539
1540
// Name returns the command's name: the first word in the use line.
1541
func (c *Command) Name() string {
1542
name := c.Use
1543
i := strings.Index(name, " ")
1544
if i >= 0 {
1545
name = name[:i]
1546
}
1547
return name
1548
}
1549
1550
// HasAlias determines if a given string is an alias of the command.
1551
func (c *Command) HasAlias(s string) bool {
1552
for _, a := range c.Aliases {
1553
if commandNameMatches(a, s) {
1554
return true
1555
}
1556
}
1557
return false
1558
}
1559
1560
// CalledAs returns the command name or alias that was used to invoke
1561
// this command or an empty string if the command has not been called.
1562
func (c *Command) CalledAs() string {
1563
if c.commandCalledAs.called {
1564
return c.commandCalledAs.name
1565
}
1566
return ""
1567
}
1568
1569
// hasNameOrAliasPrefix returns true if the Name or any of aliases start
1570
// with prefix
1571
func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
1572
if strings.HasPrefix(c.Name(), prefix) {
1573
c.commandCalledAs.name = c.Name()
1574
return true
1575
}
1576
for _, alias := range c.Aliases {
1577
if strings.HasPrefix(alias, prefix) {
1578
c.commandCalledAs.name = alias
1579
return true
1580
}
1581
}
1582
return false
1583
}
1584
1585
// NameAndAliases returns a list of the command name and all aliases
1586
func (c *Command) NameAndAliases() string {
1587
return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
1588
}
1589
1590
// HasExample determines if the command has example.
1591
func (c *Command) HasExample() bool {
1592
return len(c.Example) > 0
1593
}
1594
1595
// Runnable determines if the command is itself runnable.
1596
func (c *Command) Runnable() bool {
1597
return c.Run != nil || c.RunE != nil
1598
}
1599
1600
// HasSubCommands determines if the command has children commands.
1601
func (c *Command) HasSubCommands() bool {
1602
return len(c.commands) > 0
1603
}
1604
1605
// IsAvailableCommand determines if a command is available as a non-help command
1606
// (this includes all non deprecated/hidden commands).
1607
func (c *Command) IsAvailableCommand() bool {
1608
if len(c.Deprecated) != 0 || c.Hidden {
1609
return false
1610
}
1611
1612
if c.HasParent() && c.Parent().helpCommand == c {
1613
return false
1614
}
1615
1616
if c.Runnable() || c.HasAvailableSubCommands() {
1617
return true
1618
}
1619
1620
return false
1621
}
1622
1623
// IsAdditionalHelpTopicCommand determines if a command is an additional
1624
// help topic command; additional help topic command is determined by the
1625
// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that
1626
// are runnable/hidden/deprecated.
1627
// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.
1628
func (c *Command) IsAdditionalHelpTopicCommand() bool {
1629
// if a command is runnable, deprecated, or hidden it is not a 'help' command
1630
if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
1631
return false
1632
}
1633
1634
// if any non-help sub commands are found, the command is not a 'help' command
1635
for _, sub := range c.commands {
1636
if !sub.IsAdditionalHelpTopicCommand() {
1637
return false
1638
}
1639
}
1640
1641
// the command either has no sub commands, or no non-help sub commands
1642
return true
1643
}
1644
1645
// HasHelpSubCommands determines if a command has any available 'help' sub commands
1646
// that need to be shown in the usage/help default template under 'additional help
1647
// topics'.
1648
func (c *Command) HasHelpSubCommands() bool {
1649
// return true on the first found available 'help' sub command
1650
for _, sub := range c.commands {
1651
if sub.IsAdditionalHelpTopicCommand() {
1652
return true
1653
}
1654
}
1655
1656
// the command either has no sub commands, or no available 'help' sub commands
1657
return false
1658
}
1659
1660
// HasAvailableSubCommands determines if a command has available sub commands that
1661
// need to be shown in the usage/help default template under 'available commands'.
1662
func (c *Command) HasAvailableSubCommands() bool {
1663
// return true on the first found available (non deprecated/help/hidden)
1664
// sub command
1665
for _, sub := range c.commands {
1666
if sub.IsAvailableCommand() {
1667
return true
1668
}
1669
}
1670
1671
// the command either has no sub commands, or no available (non deprecated/help/hidden)
1672
// sub commands
1673
return false
1674
}
1675
1676
// HasParent determines if the command is a child command.
1677
func (c *Command) HasParent() bool {
1678
return c.parent != nil
1679
}
1680
1681
// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
1682
func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
1683
return c.globNormFunc
1684
}
1685
1686
// Flags returns the complete FlagSet that applies
1687
// to this command (local and persistent declared here and by all parents).
1688
func (c *Command) Flags() *flag.FlagSet {
1689
if c.flags == nil {
1690
c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1691
if c.flagErrorBuf == nil {
1692
c.flagErrorBuf = new(bytes.Buffer)
1693
}
1694
c.flags.SetOutput(c.flagErrorBuf)
1695
}
1696
1697
return c.flags
1698
}
1699
1700
// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.
1701
// This function does not modify the flags of the current command, it's purpose is to return the current state.
1702
func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
1703
persistentFlags := c.PersistentFlags()
1704
1705
out := flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1706
c.LocalFlags().VisitAll(func(f *flag.Flag) {
1707
if persistentFlags.Lookup(f.Name) == nil {
1708
out.AddFlag(f)
1709
}
1710
})
1711
return out
1712
}
1713
1714
// LocalFlags returns the local FlagSet specifically set in the current command.
1715
// This function does not modify the flags of the current command, it's purpose is to return the current state.
1716
func (c *Command) LocalFlags() *flag.FlagSet {
1717
c.mergePersistentFlags()
1718
1719
if c.lflags == nil {
1720
c.lflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1721
if c.flagErrorBuf == nil {
1722
c.flagErrorBuf = new(bytes.Buffer)
1723
}
1724
c.lflags.SetOutput(c.flagErrorBuf)
1725
}
1726
c.lflags.SortFlags = c.Flags().SortFlags
1727
if c.globNormFunc != nil {
1728
c.lflags.SetNormalizeFunc(c.globNormFunc)
1729
}
1730
1731
addToLocal := func(f *flag.Flag) {
1732
// Add the flag if it is not a parent PFlag, or it shadows a parent PFlag
1733
if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) {
1734
c.lflags.AddFlag(f)
1735
}
1736
}
1737
c.Flags().VisitAll(addToLocal)
1738
c.PersistentFlags().VisitAll(addToLocal)
1739
return c.lflags
1740
}
1741
1742
// InheritedFlags returns all flags which were inherited from parent commands.
1743
// This function does not modify the flags of the current command, it's purpose is to return the current state.
1744
func (c *Command) InheritedFlags() *flag.FlagSet {
1745
c.mergePersistentFlags()
1746
1747
if c.iflags == nil {
1748
c.iflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1749
if c.flagErrorBuf == nil {
1750
c.flagErrorBuf = new(bytes.Buffer)
1751
}
1752
c.iflags.SetOutput(c.flagErrorBuf)
1753
}
1754
1755
local := c.LocalFlags()
1756
if c.globNormFunc != nil {
1757
c.iflags.SetNormalizeFunc(c.globNormFunc)
1758
}
1759
1760
c.parentsPflags.VisitAll(func(f *flag.Flag) {
1761
if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
1762
c.iflags.AddFlag(f)
1763
}
1764
})
1765
return c.iflags
1766
}
1767
1768
// NonInheritedFlags returns all flags which were not inherited from parent commands.
1769
// This function does not modify the flags of the current command, it's purpose is to return the current state.
1770
func (c *Command) NonInheritedFlags() *flag.FlagSet {
1771
return c.LocalFlags()
1772
}
1773
1774
// PersistentFlags returns the persistent FlagSet specifically set in the current command.
1775
func (c *Command) PersistentFlags() *flag.FlagSet {
1776
if c.pflags == nil {
1777
c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1778
if c.flagErrorBuf == nil {
1779
c.flagErrorBuf = new(bytes.Buffer)
1780
}
1781
c.pflags.SetOutput(c.flagErrorBuf)
1782
}
1783
return c.pflags
1784
}
1785
1786
// ResetFlags deletes all flags from command.
1787
func (c *Command) ResetFlags() {
1788
c.flagErrorBuf = new(bytes.Buffer)
1789
c.flagErrorBuf.Reset()
1790
c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1791
c.flags.SetOutput(c.flagErrorBuf)
1792
c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1793
c.pflags.SetOutput(c.flagErrorBuf)
1794
1795
c.lflags = nil
1796
c.iflags = nil
1797
c.parentsPflags = nil
1798
}
1799
1800
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
1801
func (c *Command) HasFlags() bool {
1802
return c.Flags().HasFlags()
1803
}
1804
1805
// HasPersistentFlags checks if the command contains persistent flags.
1806
func (c *Command) HasPersistentFlags() bool {
1807
return c.PersistentFlags().HasFlags()
1808
}
1809
1810
// HasLocalFlags checks if the command has flags specifically declared locally.
1811
func (c *Command) HasLocalFlags() bool {
1812
return c.LocalFlags().HasFlags()
1813
}
1814
1815
// HasInheritedFlags checks if the command has flags inherited from its parent command.
1816
func (c *Command) HasInheritedFlags() bool {
1817
return c.InheritedFlags().HasFlags()
1818
}
1819
1820
// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire
1821
// structure) which are not hidden or deprecated.
1822
func (c *Command) HasAvailableFlags() bool {
1823
return c.Flags().HasAvailableFlags()
1824
}
1825
1826
// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
1827
func (c *Command) HasAvailablePersistentFlags() bool {
1828
return c.PersistentFlags().HasAvailableFlags()
1829
}
1830
1831
// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden
1832
// or deprecated.
1833
func (c *Command) HasAvailableLocalFlags() bool {
1834
return c.LocalFlags().HasAvailableFlags()
1835
}
1836
1837
// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are
1838
// not hidden or deprecated.
1839
func (c *Command) HasAvailableInheritedFlags() bool {
1840
return c.InheritedFlags().HasAvailableFlags()
1841
}
1842
1843
// Flag climbs up the command tree looking for matching flag.
1844
func (c *Command) Flag(name string) (flag *flag.Flag) {
1845
flag = c.Flags().Lookup(name)
1846
1847
if flag == nil {
1848
flag = c.persistentFlag(name)
1849
}
1850
1851
return
1852
}
1853
1854
// Recursively find matching persistent flag.
1855
func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
1856
if c.HasPersistentFlags() {
1857
flag = c.PersistentFlags().Lookup(name)
1858
}
1859
1860
if flag == nil {
1861
c.updateParentsPflags()
1862
flag = c.parentsPflags.Lookup(name)
1863
}
1864
return
1865
}
1866
1867
// ParseFlags parses persistent flag tree and local flags.
1868
func (c *Command) ParseFlags(args []string) error {
1869
if c.DisableFlagParsing {
1870
return nil
1871
}
1872
1873
if c.flagErrorBuf == nil {
1874
c.flagErrorBuf = new(bytes.Buffer)
1875
}
1876
beforeErrorBufLen := c.flagErrorBuf.Len()
1877
c.mergePersistentFlags()
1878
1879
// do it here after merging all flags and just before parse
1880
c.Flags().ParseErrorsAllowlist = flag.ParseErrorsAllowlist(c.FParseErrWhitelist)
1881
1882
err := c.Flags().Parse(args)
1883
// Print warnings if they occurred (e.g. deprecated flag messages).
1884
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
1885
c.Print(c.flagErrorBuf.String())
1886
}
1887
1888
return err
1889
}
1890
1891
// Parent returns a commands parent command.
1892
func (c *Command) Parent() *Command {
1893
return c.parent
1894
}
1895
1896
// mergePersistentFlags merges c.PersistentFlags() to c.Flags()
1897
// and adds missing persistent flags of all parents.
1898
func (c *Command) mergePersistentFlags() {
1899
c.updateParentsPflags()
1900
c.Flags().AddFlagSet(c.PersistentFlags())
1901
c.Flags().AddFlagSet(c.parentsPflags)
1902
}
1903
1904
// updateParentsPflags updates c.parentsPflags by adding
1905
// new persistent flags of all parents.
1906
// If c.parentsPflags == nil, it makes new.
1907
func (c *Command) updateParentsPflags() {
1908
if c.parentsPflags == nil {
1909
c.parentsPflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
1910
c.parentsPflags.SetOutput(c.flagErrorBuf)
1911
c.parentsPflags.SortFlags = false
1912
}
1913
1914
if c.globNormFunc != nil {
1915
c.parentsPflags.SetNormalizeFunc(c.globNormFunc)
1916
}
1917
1918
c.Root().PersistentFlags().AddFlagSet(flag.CommandLine)
1919
1920
c.VisitParents(func(parent *Command) {
1921
c.parentsPflags.AddFlagSet(parent.PersistentFlags())
1922
})
1923
}
1924
1925
// commandNameMatches checks if two command names are equal
1926
// taking into account case sensitivity according to
1927
// EnableCaseInsensitive global configuration.
1928
func commandNameMatches(s string, t string) bool {
1929
if EnableCaseInsensitive {
1930
return strings.EqualFold(s, t)
1931
}
1932
1933
return s == t
1934
}
1935
1936
// tmplFunc holds a template and a function that will execute said template.
1937
type tmplFunc struct {
1938
tmpl string
1939
fn func(io.Writer, interface{}) error
1940
}
1941
1942
var defaultUsageTemplate = `Usage:{{if .Runnable}}
1943
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
1944
{{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
1945
1946
Aliases:
1947
{{.NameAndAliases}}{{end}}{{if .HasExample}}
1948
1949
Examples:
1950
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}
1951
1952
Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
1953
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
1954
1955
{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
1956
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
1957
1958
Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
1959
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
1960
1961
Flags:
1962
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
1963
1964
Global Flags:
1965
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
1966
1967
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
1968
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
1969
1970
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
1971
`
1972
1973
// defaultUsageFunc is equivalent to executing defaultUsageTemplate. The two should be changed in sync.
1974
func defaultUsageFunc(w io.Writer, in interface{}) error {
1975
c := in.(*Command)
1976
fmt.Fprint(w, "Usage:")
1977
if c.Runnable() {
1978
fmt.Fprintf(w, "\n %s", c.UseLine())
1979
}
1980
if c.HasAvailableSubCommands() {
1981
fmt.Fprintf(w, "\n %s [command]", c.CommandPath())
1982
}
1983
if len(c.Aliases) > 0 {
1984
fmt.Fprintf(w, "\n\nAliases:\n")
1985
fmt.Fprintf(w, " %s", c.NameAndAliases())
1986
}
1987
if c.HasExample() {
1988
fmt.Fprintf(w, "\n\nExamples:\n")
1989
fmt.Fprintf(w, "%s", c.Example)
1990
}
1991
if c.HasAvailableSubCommands() {
1992
cmds := c.Commands()
1993
if len(c.Groups()) == 0 {
1994
fmt.Fprintf(w, "\n\nAvailable Commands:")
1995
for _, subcmd := range cmds {
1996
if subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName {
1997
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
1998
}
1999
}
2000
} else {
2001
for _, group := range c.Groups() {
2002
fmt.Fprintf(w, "\n\n%s", group.Title)
2003
for _, subcmd := range cmds {
2004
if subcmd.GroupID == group.ID && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) {
2005
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
2006
}
2007
}
2008
}
2009
if !c.AllChildCommandsHaveGroup() {
2010
fmt.Fprintf(w, "\n\nAdditional Commands:")
2011
for _, subcmd := range cmds {
2012
if subcmd.GroupID == "" && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) {
2013
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
2014
}
2015
}
2016
}
2017
}
2018
}
2019
if c.HasAvailableLocalFlags() {
2020
fmt.Fprintf(w, "\n\nFlags:\n")
2021
fmt.Fprint(w, trimRightSpace(c.LocalFlags().FlagUsages()))
2022
}
2023
if c.HasAvailableInheritedFlags() {
2024
fmt.Fprintf(w, "\n\nGlobal Flags:\n")
2025
fmt.Fprint(w, trimRightSpace(c.InheritedFlags().FlagUsages()))
2026
}
2027
if c.HasHelpSubCommands() {
2028
fmt.Fprintf(w, "\n\nAdditional help topics:")
2029
for _, subcmd := range c.Commands() {
2030
if subcmd.IsAdditionalHelpTopicCommand() {
2031
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.CommandPath(), subcmd.CommandPathPadding()), subcmd.Short)
2032
}
2033
}
2034
}
2035
if c.HasAvailableSubCommands() {
2036
fmt.Fprintf(w, "\n\nUse \"%s [command] --help\" for more information about a command.", c.CommandPath())
2037
}
2038
fmt.Fprintln(w)
2039
return nil
2040
}
2041
2042
var defaultHelpTemplate = `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
2043
2044
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
2045
2046
// defaultHelpFunc is equivalent to executing defaultHelpTemplate. The two should be changed in sync.
2047
func defaultHelpFunc(w io.Writer, in interface{}) error {
2048
c := in.(*Command)
2049
usage := c.Long
2050
if usage == "" {
2051
usage = c.Short
2052
}
2053
usage = trimRightSpace(usage)
2054
if usage != "" {
2055
fmt.Fprintln(w, usage)
2056
fmt.Fprintln(w)
2057
}
2058
if c.Runnable() || c.HasSubCommands() {
2059
fmt.Fprint(w, c.UsageString())
2060
}
2061
return nil
2062
}
2063
2064
var defaultVersionTemplate = `{{with .DisplayName}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
2065
`
2066
2067
// defaultVersionFunc is equivalent to executing defaultVersionTemplate. The two should be changed in sync.
2068
func defaultVersionFunc(w io.Writer, in interface{}) error {
2069
c := in.(*Command)
2070
_, err := fmt.Fprintf(w, "%s version %s\n", c.DisplayName(), c.Version)
2071
return err
2072
}
2073
2074