1// Copyright © 2013 Steve Francia <spf@spf13.com>.
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// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.
15// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.
16package cobra
17
18import (
19 "bytes"
20 "fmt"
21 "io"
22 "os"
23 "path/filepath"
24 "sort"
25 "strings"
26
27 flag "github.com/spf13/pflag"
28)
29
30// FParseErrWhitelist configures Flag parse errors to be ignored
31type FParseErrWhitelist flag.ParseErrorsWhitelist
32
33// Command is just that, a command for your application.
34// E.g. 'go run ...' - 'run' is the command. Cobra requires
35// you to define the usage and description as part of your command
36// definition to ensure usability.
37type Command struct {
38 // Use is the one-line usage message.
39 Use string
40
41 // Aliases is an array of aliases that can be used instead of the first word in Use.
42 Aliases []string
43
44 // SuggestFor is an array of command names for which this command will be suggested -
45 // similar to aliases but only suggests.
46 SuggestFor []string
47
48 // Short is the short description shown in the 'help' output.
49 Short string
50
51 // Long is the long message shown in the 'help <this-command>' output.
52 Long string
53
54 // Example is examples of how to use the command.
55 Example string
56
57 // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
58 ValidArgs []string
59
60 // Expected arguments
61 Args PositionalArgs
62
63 // ArgAliases is List of aliases for ValidArgs.
64 // These are not suggested to the user in the bash completion,
65 // but accepted if entered manually.
66 ArgAliases []string
67
68 // BashCompletionFunction is custom functions used by the bash autocompletion generator.
69 BashCompletionFunction string
70
71 // Deprecated defines, if this command is deprecated and should print this string when used.
72 Deprecated string
73
74 // Hidden defines, if this command is hidden and should NOT show up in the list of available commands.
75 Hidden bool
76
77 // Annotations are key/value pairs that can be used by applications to identify or
78 // group commands.
79 Annotations map[string]string
80
81 // Version defines the version for this command. If this value is non-empty and the command does not
82 // define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
83 // will print content of the "Version" variable.
84 Version string
85
86 // The *Run functions are executed in the following order:
87 // * PersistentPreRun()
88 // * PreRun()
89 // * Run()
90 // * PostRun()
91 // * PersistentPostRun()
92 // All functions get the same args, the arguments after the command name.
93 //
94 // PersistentPreRun: children of this command will inherit and execute.
95 PersistentPreRun func(cmd *Command, args []string)
96 // PersistentPreRunE: PersistentPreRun but returns an error.
97 PersistentPreRunE func(cmd *Command, args []string) error
98 // PreRun: children of this command will not inherit.
99 PreRun func(cmd *Command, args []string)
100 // PreRunE: PreRun but returns an error.
101 PreRunE func(cmd *Command, args []string) error
102 // Run: Typically the actual work function. Most commands will only implement this.
103 Run func(cmd *Command, args []string)
104 // RunE: Run but returns an error.
105 RunE func(cmd *Command, args []string) error
106 // PostRun: run after the Run command.
107 PostRun func(cmd *Command, args []string)
108 // PostRunE: PostRun but returns an error.
109 PostRunE func(cmd *Command, args []string) error
110 // PersistentPostRun: children of this command will inherit and execute after PostRun.
111 PersistentPostRun func(cmd *Command, args []string)
112 // PersistentPostRunE: PersistentPostRun but returns an error.
113 PersistentPostRunE func(cmd *Command, args []string) error
114
115 // SilenceErrors is an option to quiet errors down stream.
116 SilenceErrors bool
117
118 // SilenceUsage is an option to silence usage when an error occurs.
119 SilenceUsage bool
120
121 // DisableFlagParsing disables the flag parsing.
122 // If this is true all flags will be passed to the command as arguments.
123 DisableFlagParsing bool
124
125 // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...")
126 // will be printed by generating docs for this command.
127 DisableAutoGenTag bool
128
129 // DisableFlagsInUseLine will disable the addition of [flags] to the usage
130 // line of a command when printing help or generating docs
131 DisableFlagsInUseLine bool
132
133 // DisableSuggestions disables the suggestions based on Levenshtein distance
134 // that go along with 'unknown command' messages.
135 DisableSuggestions bool
136 // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
137 // Must be > 0.
138 SuggestionsMinimumDistance int
139
140 // TraverseChildren parses flags on all parents before executing child command.
141 TraverseChildren bool
142
143 //FParseErrWhitelist flag parse errors to be ignored
144 FParseErrWhitelist FParseErrWhitelist
145
146 // commands is the list of commands supported by this program.
147 commands []*Command
148 // parent is a parent command for this command.
149 parent *Command
150 // Max lengths of commands' string lengths for use in padding.
151 commandsMaxUseLen int
152 commandsMaxCommandPathLen int
153 commandsMaxNameLen int
154 // commandsAreSorted defines, if command slice are sorted or not.
155 commandsAreSorted bool
156 // commandCalledAs is the name or alias value used to call this command.
157 commandCalledAs struct {
158 name string
159 called bool
160 }
161
162 // args is actual args parsed from flags.
163 args []string
164 // flagErrorBuf contains all error messages from pflag.
165 flagErrorBuf *bytes.Buffer
166 // flags is full set of flags.
167 flags *flag.FlagSet
168 // pflags contains persistent flags.
169 pflags *flag.FlagSet
170 // lflags contains local flags.
171 lflags *flag.FlagSet
172 // iflags contains inherited flags.
173 iflags *flag.FlagSet
174 // parentsPflags is all persistent flags of cmd's parents.
175 parentsPflags *flag.FlagSet
176 // globNormFunc is the global normalization function
177 // that we can use on every pflag set and children commands
178 globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
179
180 // usageFunc is usage func defined by user.
181 usageFunc func(*Command) error
182 // usageTemplate is usage template defined by user.
183 usageTemplate string
184 // flagErrorFunc is func defined by user and it's called when the parsing of
185 // flags returns an error.
186 flagErrorFunc func(*Command, error) error
187 // helpTemplate is help template defined by user.
188 helpTemplate string
189 // helpFunc is help func defined by user.
190 helpFunc func(*Command, []string)
191 // helpCommand is command with usage 'help'. If it's not defined by user,
192 // cobra uses default help command.
193 helpCommand *Command
194 // versionTemplate is the version template defined by user.
195 versionTemplate 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
205// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
206// particularly useful when testing.
207func (c *Command) SetArgs(a []string) {
208 c.args = a
209}
210
211// SetOutput sets the destination for usage and error messages.
212// If output is nil, os.Stderr is used.
213// Deprecated: Use SetOut and/or SetErr instead
214func (c *Command) SetOutput(output io.Writer) {
215 c.outWriter = output
216 c.errWriter = output
217}
218
219// SetOut sets the destination for usage messages.
220// If newOut is nil, os.Stdout is used.
221func (c *Command) SetOut(newOut io.Writer) {
222 c.outWriter = newOut
223}
224
225// SetErr sets the destination for error messages.
226// If newErr is nil, os.Stderr is used.
227func (c *Command) SetErr(newErr io.Writer) {
228 c.errWriter = newErr
229}
230
231// SetOut sets the source for input data
232// If newIn is nil, os.Stdin is used.
233func (c *Command) SetIn(newIn io.Reader) {
234 c.inReader = newIn
235}
236
237// SetUsageFunc sets usage function. Usage can be defined by application.
238func (c *Command) SetUsageFunc(f func(*Command) error) {
239 c.usageFunc = f
240}
241
242// SetUsageTemplate sets usage template. Can be defined by Application.
243func (c *Command) SetUsageTemplate(s string) {
244 c.usageTemplate = s
245}
246
247// SetFlagErrorFunc sets a function to generate an error when flag parsing
248// fails.
249func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
250 c.flagErrorFunc = f
251}
252
253// SetHelpFunc sets help function. Can be defined by Application.
254func (c *Command) SetHelpFunc(f func(*Command, []string)) {
255 c.helpFunc = f
256}
257
258// SetHelpCommand sets help command.
259func (c *Command) SetHelpCommand(cmd *Command) {
260 c.helpCommand = cmd
261}
262
263// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
264func (c *Command) SetHelpTemplate(s string) {
265 c.helpTemplate = s
266}
267
268// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
269func (c *Command) SetVersionTemplate(s string) {
270 c.versionTemplate = s
271}
272
273// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
274// The user should not have a cyclic dependency on commands.
275func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
276 c.Flags().SetNormalizeFunc(n)
277 c.PersistentFlags().SetNormalizeFunc(n)
278 c.globNormFunc = n
279
280 for _, command := range c.commands {
281 command.SetGlobalNormalizationFunc(n)
282 }
283}
284
285// OutOrStdout returns output to stdout.
286func (c *Command) OutOrStdout() io.Writer {
287 return c.getOut(os.Stdout)
288}
289
290// OutOrStderr returns output to stderr
291func (c *Command) OutOrStderr() io.Writer {
292 return c.getOut(os.Stderr)
293}
294
295// ErrOrStderr returns output to stderr
296func (c *Command) ErrOrStderr() io.Writer {
297 return c.getErr(os.Stderr)
298}
299
300// ErrOrStderr returns output to stderr
301func (c *Command) InOrStdin() io.Reader {
302 return c.getIn(os.Stdin)
303}
304
305func (c *Command) getOut(def io.Writer) io.Writer {
306 if c.outWriter != nil {
307 return c.outWriter
308 }
309 if c.HasParent() {
310 return c.parent.getOut(def)
311 }
312 return def
313}
314
315func (c *Command) getErr(def io.Writer) io.Writer {
316 if c.errWriter != nil {
317 return c.errWriter
318 }
319 if c.HasParent() {
320 return c.parent.getErr(def)
321 }
322 return def
323}
324
325func (c *Command) getIn(def io.Reader) io.Reader {
326 if c.inReader != nil {
327 return c.inReader
328 }
329 if c.HasParent() {
330 return c.parent.getIn(def)
331 }
332 return def
333}
334
335// UsageFunc returns either the function set by SetUsageFunc for this command
336// or a parent, or it returns a default usage function.
337func (c *Command) UsageFunc() (f func(*Command) error) {
338 if c.usageFunc != nil {
339 return c.usageFunc
340 }
341 if c.HasParent() {
342 return c.Parent().UsageFunc()
343 }
344 return func(c *Command) error {
345 c.mergePersistentFlags()
346 err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
347 if err != nil {
348 c.Println(err)
349 }
350 return err
351 }
352}
353
354// Usage puts out the usage for the command.
355// Used when a user provides invalid input.
356// Can be defined by user by overriding UsageFunc.
357func (c *Command) Usage() error {
358 return c.UsageFunc()(c)
359}
360
361// HelpFunc returns either the function set by SetHelpFunc for this command
362// or a parent, or it returns a function with default help behavior.
363func (c *Command) HelpFunc() func(*Command, []string) {
364 if c.helpFunc != nil {
365 return c.helpFunc
366 }
367 if c.HasParent() {
368 return c.Parent().HelpFunc()
369 }
370 return func(c *Command, a []string) {
371 c.mergePersistentFlags()
372 err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
373 if err != nil {
374 c.Println(err)
375 }
376 }
377}
378
379// Help puts out the help for the command.
380// Used when a user calls help [command].
381// Can be defined by user by overriding HelpFunc.
382func (c *Command) Help() error {
383 c.HelpFunc()(c, []string{})
384 return nil
385}
386
387// UsageString returns usage string.
388func (c *Command) UsageString() string {
389 // Storing normal writers
390 tmpOutput := c.outWriter
391 tmpErr := c.errWriter
392
393 bb := new(bytes.Buffer)
394 c.outWriter = bb
395 c.errWriter = bb
396
397 c.Usage()
398
399 // Setting things back to normal
400 c.outWriter = tmpOutput
401 c.errWriter = tmpErr
402
403 return bb.String()
404}
405
406// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this
407// command or a parent, or it returns a function which returns the original
408// error.
409func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
410 if c.flagErrorFunc != nil {
411 return c.flagErrorFunc
412 }
413
414 if c.HasParent() {
415 return c.parent.FlagErrorFunc()
416 }
417 return func(c *Command, err error) error {
418 return err
419 }
420}
421
422var minUsagePadding = 25
423
424// UsagePadding return padding for the usage.
425func (c *Command) UsagePadding() int {
426 if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
427 return minUsagePadding
428 }
429 return c.parent.commandsMaxUseLen
430}
431
432var minCommandPathPadding = 11
433
434// CommandPathPadding return padding for the command path.
435func (c *Command) CommandPathPadding() int {
436 if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
437 return minCommandPathPadding
438 }
439 return c.parent.commandsMaxCommandPathLen
440}
441
442var minNamePadding = 11
443
444// NamePadding returns padding for the name.
445func (c *Command) NamePadding() int {
446 if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
447 return minNamePadding
448 }
449 return c.parent.commandsMaxNameLen
450}
451
452// UsageTemplate returns usage template for the command.
453func (c *Command) UsageTemplate() string {
454 if c.usageTemplate != "" {
455 return c.usageTemplate
456 }
457
458 if c.HasParent() {
459 return c.parent.UsageTemplate()
460 }
461 return `Usage:{{if .Runnable}}
462 {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
463 {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
464
465Aliases:
466 {{.NameAndAliases}}{{end}}{{if .HasExample}}
467
468Examples:
469{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
470
471Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
472 {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
473
474Flags:
475{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
476
477Global Flags:
478{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
479
480Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
481 {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
482
483Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
484`
485}
486
487// HelpTemplate return help template for the command.
488func (c *Command) HelpTemplate() string {
489 if c.helpTemplate != "" {
490 return c.helpTemplate
491 }
492
493 if c.HasParent() {
494 return c.parent.HelpTemplate()
495 }
496 return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
497
498{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
499}
500
501// VersionTemplate return version template for the command.
502func (c *Command) VersionTemplate() string {
503 if c.versionTemplate != "" {
504 return c.versionTemplate
505 }
506
507 if c.HasParent() {
508 return c.parent.VersionTemplate()
509 }
510 return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
511`
512}
513
514func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
515 flag := fs.Lookup(name)
516 if flag == nil {
517 return false
518 }
519 return flag.NoOptDefVal != ""
520}
521
522func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
523 if len(name) == 0 {
524 return false
525 }
526
527 flag := fs.ShorthandLookup(name[:1])
528 if flag == nil {
529 return false
530 }
531 return flag.NoOptDefVal != ""
532}
533
534func stripFlags(args []string, c *Command) []string {
535 if len(args) == 0 {
536 return args
537 }
538 c.mergePersistentFlags()
539
540 commands := []string{}
541 flags := c.Flags()
542
543Loop:
544 for len(args) > 0 {
545 s := args[0]
546 args = args[1:]
547 switch {
548 case s == "--":
549 // "--" terminates the flags
550 break Loop
551 case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
552 // If '--flag arg' then
553 // delete arg from args.
554 fallthrough // (do the same as below)
555 case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
556 // If '-f arg' then
557 // delete 'arg' from args or break the loop if len(args) <= 1.
558 if len(args) <= 1 {
559 break Loop
560 } else {
561 args = args[1:]
562 continue
563 }
564 case s != "" && !strings.HasPrefix(s, "-"):
565 commands = append(commands, s)
566 }
567 }
568
569 return commands
570}
571
572// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
573// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
574func argsMinusFirstX(args []string, x string) []string {
575 for i, y := range args {
576 if x == y {
577 ret := []string{}
578 ret = append(ret, args[:i]...)
579 ret = append(ret, args[i+1:]...)
580 return ret
581 }
582 }
583 return args
584}
585
586func isFlagArg(arg string) bool {
587 return ((len(arg) >= 3 && arg[1] == '-') ||
588 (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
589}
590
591// Find the target command given the args and command tree
592// Meant to be run on the highest node. Only searches down.
593func (c *Command) Find(args []string) (*Command, []string, error) {
594 var innerfind func(*Command, []string) (*Command, []string)
595
596 innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
597 argsWOflags := stripFlags(innerArgs, c)
598 if len(argsWOflags) == 0 {
599 return c, innerArgs
600 }
601 nextSubCmd := argsWOflags[0]
602
603 cmd := c.findNext(nextSubCmd)
604 if cmd != nil {
605 return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
606 }
607 return c, innerArgs
608 }
609
610 commandFound, a := innerfind(c, args)
611 if commandFound.Args == nil {
612 return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
613 }
614 return commandFound, a, nil
615}
616
617func (c *Command) findSuggestions(arg string) string {
618 if c.DisableSuggestions {
619 return ""
620 }
621 if c.SuggestionsMinimumDistance <= 0 {
622 c.SuggestionsMinimumDistance = 2
623 }
624 suggestionsString := ""
625 if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 {
626 suggestionsString += "\n\nDid you mean this?\n"
627 for _, s := range suggestions {
628 suggestionsString += fmt.Sprintf("\t%v\n", s)
629 }
630 }
631 return suggestionsString
632}
633
634func (c *Command) findNext(next string) *Command {
635 matches := make([]*Command, 0)
636 for _, cmd := range c.commands {
637 if cmd.Name() == next || cmd.HasAlias(next) {
638 cmd.commandCalledAs.name = next
639 return cmd
640 }
641 if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
642 matches = append(matches, cmd)
643 }
644 }
645
646 if len(matches) == 1 {
647 return matches[0]
648 }
649
650 return nil
651}
652
653// Traverse the command tree to find the command, and parse args for
654// each parent.
655func (c *Command) Traverse(args []string) (*Command, []string, error) {
656 flags := []string{}
657 inFlag := false
658
659 for i, arg := range args {
660 switch {
661 // A long flag with a space separated value
662 case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="):
663 // TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
664 inFlag = !hasNoOptDefVal(arg[2:], c.Flags())
665 flags = append(flags, arg)
666 continue
667 // A short flag with a space separated value
668 case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()):
669 inFlag = true
670 flags = append(flags, arg)
671 continue
672 // The value for a flag
673 case inFlag:
674 inFlag = false
675 flags = append(flags, arg)
676 continue
677 // A flag without a value, or with an `=` separated value
678 case isFlagArg(arg):
679 flags = append(flags, arg)
680 continue
681 }
682
683 cmd := c.findNext(arg)
684 if cmd == nil {
685 return c, args, nil
686 }
687
688 if err := c.ParseFlags(flags); err != nil {
689 return nil, args, err
690 }
691 return cmd.Traverse(args[i+1:])
692 }
693 return c, args, nil
694}
695
696// SuggestionsFor provides suggestions for the typedName.
697func (c *Command) SuggestionsFor(typedName string) []string {
698 suggestions := []string{}
699 for _, cmd := range c.commands {
700 if cmd.IsAvailableCommand() {
701 levenshteinDistance := ld(typedName, cmd.Name(), true)
702 suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance
703 suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))
704 if suggestByLevenshtein || suggestByPrefix {
705 suggestions = append(suggestions, cmd.Name())
706 }
707 for _, explicitSuggestion := range cmd.SuggestFor {
708 if strings.EqualFold(typedName, explicitSuggestion) {
709 suggestions = append(suggestions, cmd.Name())
710 }
711 }
712 }
713 }
714 return suggestions
715}
716
717// VisitParents visits all parents of the command and invokes fn on each parent.
718func (c *Command) VisitParents(fn func(*Command)) {
719 if c.HasParent() {
720 fn(c.Parent())
721 c.Parent().VisitParents(fn)
722 }
723}
724
725// Root finds root command.
726func (c *Command) Root() *Command {
727 if c.HasParent() {
728 return c.Parent().Root()
729 }
730 return c
731}
732
733// ArgsLenAtDash will return the length of c.Flags().Args at the moment
734// when a -- was found during args parsing.
735func (c *Command) ArgsLenAtDash() int {
736 return c.Flags().ArgsLenAtDash()
737}
738
739func (c *Command) execute(a []string) (err error) {
740 if c == nil {
741 return fmt.Errorf("Called Execute() on a nil Command")
742 }
743
744 if len(c.Deprecated) > 0 {
745 c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
746 }
747
748 // initialize help and version flag at the last point possible to allow for user
749 // overriding
750 c.InitDefaultHelpFlag()
751 c.InitDefaultVersionFlag()
752
753 err = c.ParseFlags(a)
754 if err != nil {
755 return c.FlagErrorFunc()(c, err)
756 }
757
758 // If help is called, regardless of other flags, return we want help.
759 // Also say we need help if the command isn't runnable.
760 helpVal, err := c.Flags().GetBool("help")
761 if err != nil {
762 // should be impossible to get here as we always declare a help
763 // flag in InitDefaultHelpFlag()
764 c.Println("\"help\" flag declared as non-bool. Please correct your code")
765 return err
766 }
767
768 if helpVal {
769 return flag.ErrHelp
770 }
771
772 // for back-compat, only add version flag behavior if version is defined
773 if c.Version != "" {
774 versionVal, err := c.Flags().GetBool("version")
775 if err != nil {
776 c.Println("\"version\" flag declared as non-bool. Please correct your code")
777 return err
778 }
779 if versionVal {
780 err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
781 if err != nil {
782 c.Println(err)
783 }
784 return err
785 }
786 }
787
788 if !c.Runnable() {
789 return flag.ErrHelp
790 }
791
792 c.preRun()
793
794 argWoFlags := c.Flags().Args()
795 if c.DisableFlagParsing {
796 argWoFlags = a
797 }
798
799 if err := c.ValidateArgs(argWoFlags); err != nil {
800 return err
801 }
802
803 for p := c; p != nil; p = p.Parent() {
804 if p.PersistentPreRunE != nil {
805 if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
806 return err
807 }
808 break
809 } else if p.PersistentPreRun != nil {
810 p.PersistentPreRun(c, argWoFlags)
811 break
812 }
813 }
814 if c.PreRunE != nil {
815 if err := c.PreRunE(c, argWoFlags); err != nil {
816 return err
817 }
818 } else if c.PreRun != nil {
819 c.PreRun(c, argWoFlags)
820 }
821
822 if err := c.validateRequiredFlags(); err != nil {
823 return err
824 }
825 if c.RunE != nil {
826 if err := c.RunE(c, argWoFlags); err != nil {
827 return err
828 }
829 } else {
830 c.Run(c, argWoFlags)
831 }
832 if c.PostRunE != nil {
833 if err := c.PostRunE(c, argWoFlags); err != nil {
834 return err
835 }
836 } else if c.PostRun != nil {
837 c.PostRun(c, argWoFlags)
838 }
839 for p := c; p != nil; p = p.Parent() {
840 if p.PersistentPostRunE != nil {
841 if err := p.PersistentPostRunE(c, argWoFlags); err != nil {
842 return err
843 }
844 break
845 } else if p.PersistentPostRun != nil {
846 p.PersistentPostRun(c, argWoFlags)
847 break
848 }
849 }
850
851 return nil
852}
853
854func (c *Command) preRun() {
855 for _, x := range initializers {
856 x()
857 }
858}
859
860// Execute uses the args (os.Args[1:] by default)
861// and run through the command tree finding appropriate matches
862// for commands and then corresponding flags.
863func (c *Command) Execute() error {
864 _, err := c.ExecuteC()
865 return err
866}
867
868// ExecuteC executes the command.
869func (c *Command) ExecuteC() (cmd *Command, err error) {
870 // Regardless of what command execute is called on, run on Root only
871 if c.HasParent() {
872 return c.Root().ExecuteC()
873 }
874
875 // windows hook
876 if preExecHookFn != nil {
877 preExecHookFn(c)
878 }
879
880 // initialize help as the last point possible to allow for user
881 // overriding
882 c.InitDefaultHelpCmd()
883
884 args := c.args
885
886 // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
887 if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
888 args = os.Args[1:]
889 }
890
891 var flags []string
892 if c.TraverseChildren {
893 cmd, flags, err = c.Traverse(args)
894 } else {
895 cmd, flags, err = c.Find(args)
896 }
897 if err != nil {
898 // If found parse to a subcommand and then failed, talk about the subcommand
899 if cmd != nil {
900 c = cmd
901 }
902 if !c.SilenceErrors {
903 c.Println("Error:", err.Error())
904 c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
905 }
906 return c, err
907 }
908
909 cmd.commandCalledAs.called = true
910 if cmd.commandCalledAs.name == "" {
911 cmd.commandCalledAs.name = cmd.Name()
912 }
913
914 err = cmd.execute(flags)
915 if err != nil {
916 // Always show help if requested, even if SilenceErrors is in
917 // effect
918 if err == flag.ErrHelp {
919 cmd.HelpFunc()(cmd, args)
920 return cmd, nil
921 }
922
923 // If root command has SilentErrors flagged,
924 // all subcommands should respect it
925 if !cmd.SilenceErrors && !c.SilenceErrors {
926 c.Println("Error:", err.Error())
927 }
928
929 // If root command has SilentUsage flagged,
930 // all subcommands should respect it
931 if !cmd.SilenceUsage && !c.SilenceUsage {
932 c.Println(cmd.UsageString())
933 }
934 }
935 return cmd, err
936}
937
938func (c *Command) ValidateArgs(args []string) error {
939 if c.Args == nil {
940 return nil
941 }
942 return c.Args(c, args)
943}
944
945func (c *Command) validateRequiredFlags() error {
946 flags := c.Flags()
947 missingFlagNames := []string{}
948 flags.VisitAll(func(pflag *flag.Flag) {
949 requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
950 if !found {
951 return
952 }
953 if (requiredAnnotation[0] == "true") && !pflag.Changed {
954 missingFlagNames = append(missingFlagNames, pflag.Name)
955 }
956 })
957
958 if len(missingFlagNames) > 0 {
959 return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
960 }
961 return nil
962}
963
964// InitDefaultHelpFlag adds default help flag to c.
965// It is called automatically by executing the c or by calling help and usage.
966// If c already has help flag, it will do nothing.
967func (c *Command) InitDefaultHelpFlag() {
968 c.mergePersistentFlags()
969 if c.Flags().Lookup("help") == nil {
970 usage := "help for "
971 if c.Name() == "" {
972 usage += "this command"
973 } else {
974 usage += c.Name()
975 }
976 c.Flags().BoolP("help", "h", false, usage)
977 }
978}
979
980// InitDefaultVersionFlag adds default version flag to c.
981// It is called automatically by executing the c.
982// If c already has a version flag, it will do nothing.
983// If c.Version is empty, it will do nothing.
984func (c *Command) InitDefaultVersionFlag() {
985 if c.Version == "" {
986 return
987 }
988
989 c.mergePersistentFlags()
990 if c.Flags().Lookup("version") == nil {
991 usage := "version for "
992 if c.Name() == "" {
993 usage += "this command"
994 } else {
995 usage += c.Name()
996 }
997 c.Flags().Bool("version", false, usage)
998 }
999}
1000
1001// InitDefaultHelpCmd adds default help command to c.
1002// It is called automatically by executing the c or by calling help and usage.
1003// If c already has help command or c has no subcommands, it will do nothing.
1004func (c *Command) InitDefaultHelpCmd() {
1005 if !c.HasSubCommands() {
1006 return
1007 }
1008
1009 if c.helpCommand == nil {
1010 c.helpCommand = &Command{
1011 Use: "help [command]",
1012 Short: "Help about any command",
1013 Long: `Help provides help for any command in the application.
1014Simply type ` + c.Name() + ` help [path to command] for full details.`,
1015
1016 Run: func(c *Command, args []string) {
1017 cmd, _, e := c.Root().Find(args)
1018 if cmd == nil || e != nil {
1019 c.Printf("Unknown help topic %#q\n", args)
1020 c.Root().Usage()
1021 } else {
1022 cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
1023 cmd.Help()
1024 }
1025 },
1026 }
1027 }
1028 c.RemoveCommand(c.helpCommand)
1029 c.AddCommand(c.helpCommand)
1030}
1031
1032// ResetCommands delete parent, subcommand and help command from c.
1033func (c *Command) ResetCommands() {
1034 c.parent = nil
1035 c.commands = nil
1036 c.helpCommand = nil
1037 c.parentsPflags = nil
1038}
1039
1040// Sorts commands by their names.
1041type commandSorterByName []*Command
1042
1043func (c commandSorterByName) Len() int { return len(c) }
1044func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
1045func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }
1046
1047// Commands returns a sorted slice of child commands.
1048func (c *Command) Commands() []*Command {
1049 // do not sort commands if it already sorted or sorting was disabled
1050 if EnableCommandSorting && !c.commandsAreSorted {
1051 sort.Sort(commandSorterByName(c.commands))
1052 c.commandsAreSorted = true
1053 }
1054 return c.commands
1055}
1056
1057// AddCommand adds one or more commands to this parent command.
1058func (c *Command) AddCommand(cmds ...*Command) {
1059 for i, x := range cmds {
1060 if cmds[i] == c {
1061 panic("Command can't be a child of itself")
1062 }
1063 cmds[i].parent = c
1064 // update max lengths
1065 usageLen := len(x.Use)
1066 if usageLen > c.commandsMaxUseLen {
1067 c.commandsMaxUseLen = usageLen
1068 }
1069 commandPathLen := len(x.CommandPath())
1070 if commandPathLen > c.commandsMaxCommandPathLen {
1071 c.commandsMaxCommandPathLen = commandPathLen
1072 }
1073 nameLen := len(x.Name())
1074 if nameLen > c.commandsMaxNameLen {
1075 c.commandsMaxNameLen = nameLen
1076 }
1077 // If global normalization function exists, update all children
1078 if c.globNormFunc != nil {
1079 x.SetGlobalNormalizationFunc(c.globNormFunc)
1080 }
1081 c.commands = append(c.commands, x)
1082 c.commandsAreSorted = false
1083 }
1084}
1085
1086// RemoveCommand removes one or more commands from a parent command.
1087func (c *Command) RemoveCommand(cmds ...*Command) {
1088 commands := []*Command{}
1089main:
1090 for _, command := range c.commands {
1091 for _, cmd := range cmds {
1092 if command == cmd {
1093 command.parent = nil
1094 continue main
1095 }
1096 }
1097 commands = append(commands, command)
1098 }
1099 c.commands = commands
1100 // recompute all lengths
1101 c.commandsMaxUseLen = 0
1102 c.commandsMaxCommandPathLen = 0
1103 c.commandsMaxNameLen = 0
1104 for _, command := range c.commands {
1105 usageLen := len(command.Use)
1106 if usageLen > c.commandsMaxUseLen {
1107 c.commandsMaxUseLen = usageLen
1108 }
1109 commandPathLen := len(command.CommandPath())
1110 if commandPathLen > c.commandsMaxCommandPathLen {
1111 c.commandsMaxCommandPathLen = commandPathLen
1112 }
1113 nameLen := len(command.Name())
1114 if nameLen > c.commandsMaxNameLen {
1115 c.commandsMaxNameLen = nameLen
1116 }
1117 }
1118}
1119
1120// Print is a convenience method to Print to the defined output, fallback to Stderr if not set.
1121func (c *Command) Print(i ...interface{}) {
1122 fmt.Fprint(c.OutOrStderr(), i...)
1123}
1124
1125// Println is a convenience method to Println to the defined output, fallback to Stderr if not set.
1126func (c *Command) Println(i ...interface{}) {
1127 c.Print(fmt.Sprintln(i...))
1128}
1129
1130// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set.
1131func (c *Command) Printf(format string, i ...interface{}) {
1132 c.Print(fmt.Sprintf(format, i...))
1133}
1134
1135// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set.
1136func (c *Command) PrintErr(i ...interface{}) {
1137 fmt.Fprint(c.ErrOrStderr(), i...)
1138}
1139
1140// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
1141func (c *Command) PrintErrln(i ...interface{}) {
1142 c.Print(fmt.Sprintln(i...))
1143}
1144
1145// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
1146func (c *Command) PrintErrf(format string, i ...interface{}) {
1147 c.Print(fmt.Sprintf(format, i...))
1148}
1149
1150// CommandPath returns the full path to this command.
1151func (c *Command) CommandPath() string {
1152 if c.HasParent() {
1153 return c.Parent().CommandPath() + " " + c.Name()
1154 }
1155 return c.Name()
1156}
1157
1158// UseLine puts out the full usage for a given command (including parents).
1159func (c *Command) UseLine() string {
1160 var useline string
1161 if c.HasParent() {
1162 useline = c.parent.CommandPath() + " " + c.Use
1163 } else {
1164 useline = c.Use
1165 }
1166 if c.DisableFlagsInUseLine {
1167 return useline
1168 }
1169 if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
1170 useline += " [flags]"
1171 }
1172 return useline
1173}
1174
1175// DebugFlags used to determine which flags have been assigned to which commands
1176// and which persist.
1177func (c *Command) DebugFlags() {
1178 c.Println("DebugFlags called on", c.Name())
1179 var debugflags func(*Command)
1180
1181 debugflags = func(x *Command) {
1182 if x.HasFlags() || x.HasPersistentFlags() {
1183 c.Println(x.Name())
1184 }
1185 if x.HasFlags() {
1186 x.flags.VisitAll(func(f *flag.Flag) {
1187 if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil {
1188 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
1189 } else {
1190 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
1191 }
1192 })
1193 }
1194 if x.HasPersistentFlags() {
1195 x.pflags.VisitAll(func(f *flag.Flag) {
1196 if x.HasFlags() {
1197 if x.flags.Lookup(f.Name) == nil {
1198 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1199 }
1200 } else {
1201 c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
1202 }
1203 })
1204 }
1205 c.Println(x.flagErrorBuf)
1206 if x.HasSubCommands() {
1207 for _, y := range x.commands {
1208 debugflags(y)
1209 }
1210 }
1211 }
1212
1213 debugflags(c)
1214}
1215
1216// Name returns the command's name: the first word in the use line.
1217func (c *Command) Name() string {
1218 name := c.Use
1219 i := strings.Index(name, " ")
1220 if i >= 0 {
1221 name = name[:i]
1222 }
1223 return name
1224}
1225
1226// HasAlias determines if a given string is an alias of the command.
1227func (c *Command) HasAlias(s string) bool {
1228 for _, a := range c.Aliases {
1229 if a == s {
1230 return true
1231 }
1232 }
1233 return false
1234}
1235
1236// CalledAs returns the command name or alias that was used to invoke
1237// this command or an empty string if the command has not been called.
1238func (c *Command) CalledAs() string {
1239 if c.commandCalledAs.called {
1240 return c.commandCalledAs.name
1241 }
1242 return ""
1243}
1244
1245// hasNameOrAliasPrefix returns true if the Name or any of aliases start
1246// with prefix
1247func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
1248 if strings.HasPrefix(c.Name(), prefix) {
1249 c.commandCalledAs.name = c.Name()
1250 return true
1251 }
1252 for _, alias := range c.Aliases {
1253 if strings.HasPrefix(alias, prefix) {
1254 c.commandCalledAs.name = alias
1255 return true
1256 }
1257 }
1258 return false
1259}
1260
1261// NameAndAliases returns a list of the command name and all aliases
1262func (c *Command) NameAndAliases() string {
1263 return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
1264}
1265
1266// HasExample determines if the command has example.
1267func (c *Command) HasExample() bool {
1268 return len(c.Example) > 0
1269}
1270
1271// Runnable determines if the command is itself runnable.
1272func (c *Command) Runnable() bool {
1273 return c.Run != nil || c.RunE != nil
1274}
1275
1276// HasSubCommands determines if the command has children commands.
1277func (c *Command) HasSubCommands() bool {
1278 return len(c.commands) > 0
1279}
1280
1281// IsAvailableCommand determines if a command is available as a non-help command
1282// (this includes all non deprecated/hidden commands).
1283func (c *Command) IsAvailableCommand() bool {
1284 if len(c.Deprecated) != 0 || c.Hidden {
1285 return false
1286 }
1287
1288 if c.HasParent() && c.Parent().helpCommand == c {
1289 return false
1290 }
1291
1292 if c.Runnable() || c.HasAvailableSubCommands() {
1293 return true
1294 }
1295
1296 return false
1297}
1298
1299// IsAdditionalHelpTopicCommand determines if a command is an additional
1300// help topic command; additional help topic command is determined by the
1301// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that
1302// are runnable/hidden/deprecated.
1303// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.
1304func (c *Command) IsAdditionalHelpTopicCommand() bool {
1305 // if a command is runnable, deprecated, or hidden it is not a 'help' command
1306 if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
1307 return false
1308 }
1309
1310 // if any non-help sub commands are found, the command is not a 'help' command
1311 for _, sub := range c.commands {
1312 if !sub.IsAdditionalHelpTopicCommand() {
1313 return false
1314 }
1315 }
1316
1317 // the command either has no sub commands, or no non-help sub commands
1318 return true
1319}
1320
1321// HasHelpSubCommands determines if a command has any available 'help' sub commands
1322// that need to be shown in the usage/help default template under 'additional help
1323// topics'.
1324func (c *Command) HasHelpSubCommands() bool {
1325 // return true on the first found available 'help' sub command
1326 for _, sub := range c.commands {
1327 if sub.IsAdditionalHelpTopicCommand() {
1328 return true
1329 }
1330 }
1331
1332 // the command either has no sub commands, or no available 'help' sub commands
1333 return false
1334}
1335
1336// HasAvailableSubCommands determines if a command has available sub commands that
1337// need to be shown in the usage/help default template under 'available commands'.
1338func (c *Command) HasAvailableSubCommands() bool {
1339 // return true on the first found available (non deprecated/help/hidden)
1340 // sub command
1341 for _, sub := range c.commands {
1342 if sub.IsAvailableCommand() {
1343 return true
1344 }
1345 }
1346
1347 // the command either has no sub commands, or no available (non deprecated/help/hidden)
1348 // sub commands
1349 return false
1350}
1351
1352// HasParent determines if the command is a child command.
1353func (c *Command) HasParent() bool {
1354 return c.parent != nil
1355}
1356
1357// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
1358func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
1359 return c.globNormFunc
1360}
1361
1362// Flags returns the complete FlagSet that applies
1363// to this command (local and persistent declared here and by all parents).
1364func (c *Command) Flags() *flag.FlagSet {
1365 if c.flags == nil {
1366 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1367 if c.flagErrorBuf == nil {
1368 c.flagErrorBuf = new(bytes.Buffer)
1369 }
1370 c.flags.SetOutput(c.flagErrorBuf)
1371 }
1372
1373 return c.flags
1374}
1375
1376// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.
1377func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
1378 persistentFlags := c.PersistentFlags()
1379
1380 out := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1381 c.LocalFlags().VisitAll(func(f *flag.Flag) {
1382 if persistentFlags.Lookup(f.Name) == nil {
1383 out.AddFlag(f)
1384 }
1385 })
1386 return out
1387}
1388
1389// LocalFlags returns the local FlagSet specifically set in the current command.
1390func (c *Command) LocalFlags() *flag.FlagSet {
1391 c.mergePersistentFlags()
1392
1393 if c.lflags == nil {
1394 c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1395 if c.flagErrorBuf == nil {
1396 c.flagErrorBuf = new(bytes.Buffer)
1397 }
1398 c.lflags.SetOutput(c.flagErrorBuf)
1399 }
1400 c.lflags.SortFlags = c.Flags().SortFlags
1401 if c.globNormFunc != nil {
1402 c.lflags.SetNormalizeFunc(c.globNormFunc)
1403 }
1404
1405 addToLocal := func(f *flag.Flag) {
1406 if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil {
1407 c.lflags.AddFlag(f)
1408 }
1409 }
1410 c.Flags().VisitAll(addToLocal)
1411 c.PersistentFlags().VisitAll(addToLocal)
1412 return c.lflags
1413}
1414
1415// InheritedFlags returns all flags which were inherited from parent commands.
1416func (c *Command) InheritedFlags() *flag.FlagSet {
1417 c.mergePersistentFlags()
1418
1419 if c.iflags == nil {
1420 c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1421 if c.flagErrorBuf == nil {
1422 c.flagErrorBuf = new(bytes.Buffer)
1423 }
1424 c.iflags.SetOutput(c.flagErrorBuf)
1425 }
1426
1427 local := c.LocalFlags()
1428 if c.globNormFunc != nil {
1429 c.iflags.SetNormalizeFunc(c.globNormFunc)
1430 }
1431
1432 c.parentsPflags.VisitAll(func(f *flag.Flag) {
1433 if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
1434 c.iflags.AddFlag(f)
1435 }
1436 })
1437 return c.iflags
1438}
1439
1440// NonInheritedFlags returns all flags which were not inherited from parent commands.
1441func (c *Command) NonInheritedFlags() *flag.FlagSet {
1442 return c.LocalFlags()
1443}
1444
1445// PersistentFlags returns the persistent FlagSet specifically set in the current command.
1446func (c *Command) PersistentFlags() *flag.FlagSet {
1447 if c.pflags == nil {
1448 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1449 if c.flagErrorBuf == nil {
1450 c.flagErrorBuf = new(bytes.Buffer)
1451 }
1452 c.pflags.SetOutput(c.flagErrorBuf)
1453 }
1454 return c.pflags
1455}
1456
1457// ResetFlags deletes all flags from command.
1458func (c *Command) ResetFlags() {
1459 c.flagErrorBuf = new(bytes.Buffer)
1460 c.flagErrorBuf.Reset()
1461 c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1462 c.flags.SetOutput(c.flagErrorBuf)
1463 c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1464 c.pflags.SetOutput(c.flagErrorBuf)
1465
1466 c.lflags = nil
1467 c.iflags = nil
1468 c.parentsPflags = nil
1469}
1470
1471// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
1472func (c *Command) HasFlags() bool {
1473 return c.Flags().HasFlags()
1474}
1475
1476// HasPersistentFlags checks if the command contains persistent flags.
1477func (c *Command) HasPersistentFlags() bool {
1478 return c.PersistentFlags().HasFlags()
1479}
1480
1481// HasLocalFlags checks if the command has flags specifically declared locally.
1482func (c *Command) HasLocalFlags() bool {
1483 return c.LocalFlags().HasFlags()
1484}
1485
1486// HasInheritedFlags checks if the command has flags inherited from its parent command.
1487func (c *Command) HasInheritedFlags() bool {
1488 return c.InheritedFlags().HasFlags()
1489}
1490
1491// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire
1492// structure) which are not hidden or deprecated.
1493func (c *Command) HasAvailableFlags() bool {
1494 return c.Flags().HasAvailableFlags()
1495}
1496
1497// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
1498func (c *Command) HasAvailablePersistentFlags() bool {
1499 return c.PersistentFlags().HasAvailableFlags()
1500}
1501
1502// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden
1503// or deprecated.
1504func (c *Command) HasAvailableLocalFlags() bool {
1505 return c.LocalFlags().HasAvailableFlags()
1506}
1507
1508// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are
1509// not hidden or deprecated.
1510func (c *Command) HasAvailableInheritedFlags() bool {
1511 return c.InheritedFlags().HasAvailableFlags()
1512}
1513
1514// Flag climbs up the command tree looking for matching flag.
1515func (c *Command) Flag(name string) (flag *flag.Flag) {
1516 flag = c.Flags().Lookup(name)
1517
1518 if flag == nil {
1519 flag = c.persistentFlag(name)
1520 }
1521
1522 return
1523}
1524
1525// Recursively find matching persistent flag.
1526func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
1527 if c.HasPersistentFlags() {
1528 flag = c.PersistentFlags().Lookup(name)
1529 }
1530
1531 if flag == nil {
1532 c.updateParentsPflags()
1533 flag = c.parentsPflags.Lookup(name)
1534 }
1535 return
1536}
1537
1538// ParseFlags parses persistent flag tree and local flags.
1539func (c *Command) ParseFlags(args []string) error {
1540 if c.DisableFlagParsing {
1541 return nil
1542 }
1543
1544 if c.flagErrorBuf == nil {
1545 c.flagErrorBuf = new(bytes.Buffer)
1546 }
1547 beforeErrorBufLen := c.flagErrorBuf.Len()
1548 c.mergePersistentFlags()
1549
1550 //do it here after merging all flags and just before parse
1551 c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
1552
1553 err := c.Flags().Parse(args)
1554 // Print warnings if they occurred (e.g. deprecated flag messages).
1555 if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
1556 c.Print(c.flagErrorBuf.String())
1557 }
1558
1559 return err
1560}
1561
1562// Parent returns a commands parent command.
1563func (c *Command) Parent() *Command {
1564 return c.parent
1565}
1566
1567// mergePersistentFlags merges c.PersistentFlags() to c.Flags()
1568// and adds missing persistent flags of all parents.
1569func (c *Command) mergePersistentFlags() {
1570 c.updateParentsPflags()
1571 c.Flags().AddFlagSet(c.PersistentFlags())
1572 c.Flags().AddFlagSet(c.parentsPflags)
1573}
1574
1575// updateParentsPflags updates c.parentsPflags by adding
1576// new persistent flags of all parents.
1577// If c.parentsPflags == nil, it makes new.
1578func (c *Command) updateParentsPflags() {
1579 if c.parentsPflags == nil {
1580 c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
1581 c.parentsPflags.SetOutput(c.flagErrorBuf)
1582 c.parentsPflags.SortFlags = false
1583 }
1584
1585 if c.globNormFunc != nil {
1586 c.parentsPflags.SetNormalizeFunc(c.globNormFunc)
1587 }
1588
1589 c.Root().PersistentFlags().AddFlagSet(flag.CommandLine)
1590
1591 c.VisitParents(func(parent *Command) {
1592 c.parentsPflags.AddFlagSet(parent.PersistentFlags())
1593 })
1594}