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