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