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