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