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