// Copyright 2013-2023 The Cobra Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.
// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.
package cobraimport (flag)const (FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"CommandDisplayNameAnnotation = "cobra_annotation_command_display_name")// FParseErrWhitelist configures Flag parse errors to be ignoredtypeFParseErrWhitelistflag.ParseErrorsWhitelist// Group Structure to manage groups for commandstypeGroupstruct { ID string Title string}// Command is just that, a command for your application.// E.g. 'go run ...' - 'run' is the command. Cobra requires// you to define the usage and description as part of your command// definition to ensure usability.typeCommandstruct {// Use is the one-line usage message. // Recommended syntax is as follows: // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. // ... indicates that you can specify multiple values for the previous argument. // | indicates mutually exclusive information. You can use the argument to the left of the separator or the // argument to the right of the separator. You cannot use both arguments in a single use of the command. // { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are // optional, they are enclosed in brackets ([ ]). // Example: add [-F file | -D dir]... [-f format] profile Use string// Aliases is an array of aliases that can be used instead of the first word in Use. Aliases []string// SuggestFor is an array of command names for which this command will be suggested - // similar to aliases but only suggests. SuggestFor []string// Short is the short description shown in the 'help' output. Short string// The group id under which this subcommand is grouped in the 'help' output of its parent. GroupID string// Long is the long message shown in the 'help <this-command>' output. Long string// Example is examples of how to use the command. Example string// ValidArgs is list of all valid non-flag arguments that are accepted in shell completions ValidArgs []string// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. // It is a dynamic version of using ValidArgs. // Only one of ValidArgs and ValidArgsFunction can be used for a command. ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)// Expected arguments Args PositionalArgs// ArgAliases is List of aliases for ValidArgs. // These are not suggested to the user in the shell completion, // but accepted if entered manually. ArgAliases []string// BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. // For portability with other shells, it is recommended to instead use ValidArgsFunction BashCompletionFunction string// Deprecated defines, if this command is deprecated and should print this string when used. Deprecated string// Annotations are key/value pairs that can be used by applications to identify or // group commands or set special options. Annotations map[string]string// Version defines the version for this command. If this value is non-empty and the command does not // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, // will print content of the "Version" variable. A shorthand "v" flag will also be added if the // command does not define one. Version string// The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() // * Run() // * PostRun() // * PersistentPostRun() // All functions get the same args, the arguments after the command name. // The *PreRun and *PostRun functions will only be executed if the Run function of the current // command has been declared. // // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string)// PersistentPreRunE: PersistentPreRun but returns an error. PersistentPreRunE func(cmd *Command, args []string) error// PreRun: children of this command will not inherit. PreRun func(cmd *Command, args []string)// PreRunE: PreRun but returns an error. PreRunE func(cmd *Command, args []string) error// Run: Typically the actual work function. Most commands will only implement this. Run func(cmd *Command, args []string)// RunE: Run but returns an error. RunE func(cmd *Command, args []string) error// PostRun: run after the Run command. PostRun func(cmd *Command, args []string)// PostRunE: PostRun but returns an error. PostRunE func(cmd *Command, args []string) error// PersistentPostRun: children of this command will inherit and execute after PostRun. PersistentPostRun func(cmd *Command, args []string)// PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error// groups for subcommands commandgroups []*Group// args is actual args parsed from flags. args []string// flagErrorBuf contains all error messages from pflag. flagErrorBuf *bytes.Buffer// flags is full set of flags. flags *flag.FlagSet// pflags contains persistent flags. pflags *flag.FlagSet// lflags contains local flags. // This field does not represent internal state, it's used as a cache to optimise LocalFlags function call lflags *flag.FlagSet// iflags contains inherited flags. // This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call iflags *flag.FlagSet// parentsPflags is all persistent flags of cmd's parents. parentsPflags *flag.FlagSet// globNormFunc is the global normalization function // that we can use on every pflag set and children commands globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName// usageFunc is usage func defined by user. usageFunc func(*Command) error// usageTemplate is usage template defined by user. usageTemplate string// flagErrorFunc is func defined by user and it's called when the parsing of // flags returns an error. flagErrorFunc func(*Command, error) error// helpTemplate is help template defined by user. helpTemplate string// helpFunc is help func defined by user. helpFunc func(*Command, []string)// helpCommand is command with usage 'help'. If it's not defined by user, // cobra uses default help command. helpCommand *Command// helpCommandGroupID is the group id for the helpCommand helpCommandGroupID string// completionCommandGroupID is the group id for the completion command completionCommandGroupID string// versionTemplate is the version template defined by user. versionTemplate string// errPrefix is the error message prefix defined by user. errPrefix string// inReader is a reader defined by the user that replaces stdin inReader io.Reader// outWriter is a writer defined by the user that replaces stdout outWriter io.Writer// errWriter is a writer defined by the user that replaces stderr errWriter io.Writer// FParseErrWhitelist flag parse errors to be ignored FParseErrWhitelist FParseErrWhitelist// CompletionOptions is a set of options to control the handling of shell completion CompletionOptions CompletionOptions// commandsAreSorted defines, if command slice are sorted or not. commandsAreSorted bool// commandCalledAs is the name or alias value used to call this command. commandCalledAs struct { name string called bool } ctx context.Context// commands is the list of commands supported by this program. commands []*Command// parent is a parent command for this command. parent *Command// Max lengths of commands' string lengths for use in padding. commandsMaxUseLen int commandsMaxCommandPathLen int commandsMaxNameLen int// TraverseChildren parses flags on all parents before executing child command. TraverseChildren bool// Hidden defines, if this command is hidden and should NOT show up in the list of available commands. Hidden bool// SilenceErrors is an option to quiet errors down stream. SilenceErrors bool// SilenceUsage is an option to silence usage when an error occurs. SilenceUsage bool// DisableFlagParsing disables the flag parsing. // If this is true all flags will be passed to the command as arguments. DisableFlagParsing bool// DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") // will be printed by generating docs for this command. DisableAutoGenTag bool// DisableFlagsInUseLine will disable the addition of [flags] to the usage // line of a command when printing help or generating docs DisableFlagsInUseLine bool// DisableSuggestions disables the suggestions based on Levenshtein distance // that go along with 'unknown command' messages. DisableSuggestions bool// SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. // Must be > 0. SuggestionsMinimumDistance int}// Context returns underlying command context. If command was executed// with ExecuteContext or the context was set with SetContext, the// previously set context will be returned. Otherwise, nil is returned.//// Notice that a call to Execute and ExecuteC will replace a nil context of// a command with a context.Background, so a background context will be// returned by Context after one of these functions has been called.func ( *Command) () context.Context {return .ctx}// SetContext sets context for the command. This context will be overwritten by// Command.ExecuteContext or Command.ExecuteContextC.func ( *Command) ( context.Context) { .ctx = }// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden// particularly useful when testing.func ( *Command) ( []string) { .args = }// SetOutput sets the destination for usage and error messages.// If output is nil, os.Stderr is used.// Deprecated: Use SetOut and/or SetErr insteadfunc ( *Command) ( io.Writer) { .outWriter = .errWriter = }// SetOut sets the destination for usage messages.// If newOut is nil, os.Stdout is used.func ( *Command) ( io.Writer) { .outWriter = }// SetErr sets the destination for error messages.// If newErr is nil, os.Stderr is used.func ( *Command) ( io.Writer) { .errWriter = }// SetIn sets the source for input data// If newIn is nil, os.Stdin is used.func ( *Command) ( io.Reader) { .inReader = }// SetUsageFunc sets usage function. Usage can be defined by application.func ( *Command) ( func(*Command) error) { .usageFunc = }// SetUsageTemplate sets usage template. Can be defined by Application.func ( *Command) ( string) { .usageTemplate = }// SetFlagErrorFunc sets a function to generate an error when flag parsing// fails.func ( *Command) ( func(*Command, error) error) { .flagErrorFunc = }// SetHelpFunc sets help function. Can be defined by Application.func ( *Command) ( func(*Command, []string)) { .helpFunc = }// SetHelpCommand sets help command.func ( *Command) ( *Command) { .helpCommand = }// SetHelpCommandGroupID sets the group id of the help command.func ( *Command) ( string) {if .helpCommand != nil { .helpCommand.GroupID = }// helpCommandGroupID is used if no helpCommand is defined by the user .helpCommandGroupID = }// SetCompletionCommandGroupID sets the group id of the completion command.func ( *Command) ( string) {// completionCommandGroupID is used if no completion command is defined by the user .Root().completionCommandGroupID = }// SetHelpTemplate sets help template to be used. Application can use it to set custom template.func ( *Command) ( string) { .helpTemplate = }// SetVersionTemplate sets version template to be used. Application can use it to set custom template.func ( *Command) ( string) { .versionTemplate = }// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix.func ( *Command) ( string) { .errPrefix = }// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.// The user should not have a cyclic dependency on commands.func ( *Command) ( func( *flag.FlagSet, string) flag.NormalizedName) { .Flags().SetNormalizeFunc() .PersistentFlags().SetNormalizeFunc() .globNormFunc = for , := range .commands { .() }}// OutOrStdout returns output to stdout.func ( *Command) () io.Writer {return .getOut(os.Stdout)}// OutOrStderr returns output to stderrfunc ( *Command) () io.Writer {return .getOut(os.Stderr)}// ErrOrStderr returns output to stderrfunc ( *Command) () io.Writer {return .getErr(os.Stderr)}// InOrStdin returns input to stdinfunc ( *Command) () io.Reader {return .getIn(os.Stdin)}func ( *Command) ( io.Writer) io.Writer {if .outWriter != nil {return .outWriter }if .HasParent() {return .parent.() }return}func ( *Command) ( io.Writer) io.Writer {if .errWriter != nil {return .errWriter }if .HasParent() {return .parent.() }return}func ( *Command) ( io.Reader) io.Reader {if .inReader != nil {return .inReader }if .HasParent() {return .parent.() }return}// UsageFunc returns either the function set by SetUsageFunc for this command// or a parent, or it returns a default usage function.func ( *Command) () ( func(*Command) error) {if .usageFunc != nil {return .usageFunc }if .HasParent() {return .Parent().() }returnfunc( *Command) error { .mergePersistentFlags() := tmpl(.OutOrStderr(), .UsageTemplate(), )if != nil { .PrintErrln() }return }}// Usage puts out the usage for the command.// Used when a user provides invalid input.// Can be defined by user by overriding UsageFunc.func ( *Command) () error {return .UsageFunc()()}// HelpFunc returns either the function set by SetHelpFunc for this command// or a parent, or it returns a function with default help behavior.func ( *Command) () func(*Command, []string) {if .helpFunc != nil {return .helpFunc }if .HasParent() {return .Parent().() }returnfunc( *Command, []string) { .mergePersistentFlags()// The help should be sent to stdout // See https://github.com/spf13/cobra/issues/1002 := tmpl(.OutOrStdout(), .HelpTemplate(), )if != nil { .PrintErrln() } }}// Help puts out the help for the command.// Used when a user calls help [command].// Can be defined by user by overriding HelpFunc.func ( *Command) () error { .HelpFunc()(, []string{})returnnil}// UsageString returns usage string.func ( *Command) () string {// Storing normal writers := .outWriter := .errWriter := new(bytes.Buffer) .outWriter = .errWriter = CheckErr(.Usage())// Setting things back to normal .outWriter = .errWriter = return .String()}// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this// command or a parent, or it returns a function which returns the original// error.func ( *Command) () ( func(*Command, error) error) {if .flagErrorFunc != nil {return .flagErrorFunc }if .HasParent() {return .parent.() }returnfunc( *Command, error) error {return }}var minUsagePadding = 25// UsagePadding return padding for the usage.func ( *Command) () int {if .parent == nil || minUsagePadding > .parent.commandsMaxUseLen {returnminUsagePadding }return .parent.commandsMaxUseLen}var minCommandPathPadding = 11// CommandPathPadding return padding for the command path.func ( *Command) () int {if .parent == nil || minCommandPathPadding > .parent.commandsMaxCommandPathLen {returnminCommandPathPadding }return .parent.commandsMaxCommandPathLen}var minNamePadding = 11// NamePadding returns padding for the name.func ( *Command) () int {if .parent == nil || minNamePadding > .parent.commandsMaxNameLen {returnminNamePadding }return .parent.commandsMaxNameLen}// UsageTemplate returns usage template for the command.func ( *Command) () string {if .usageTemplate != "" {return .usageTemplate }if .HasParent() {return .parent.() }return`Usage:{{if .Runnable}} {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}Aliases: {{.NameAndAliases}}{{end}}{{if .HasExample}}Examples:{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}Flags:{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}Global Flags:{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}`}// HelpTemplate return help template for the command.func ( *Command) () string {if .helpTemplate != "" {return .helpTemplate }if .HasParent() {return .parent.() }return`{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`}// VersionTemplate return version template for the command.func ( *Command) () string {if .versionTemplate != "" {return .versionTemplate }if .HasParent() {return .parent.() }return`{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}`}// ErrPrefix return error message prefix for the commandfunc ( *Command) () string {if .errPrefix != "" {return .errPrefix }if .HasParent() {return .parent.() }return"Error:"}func hasNoOptDefVal( string, *flag.FlagSet) bool { := .Lookup()if == nil {returnfalse }return .NoOptDefVal != ""}func shortHasNoOptDefVal( string, *flag.FlagSet) bool {iflen() == 0 {returnfalse } := .ShorthandLookup([:1])if == nil {returnfalse }return .NoOptDefVal != ""}func stripFlags( []string, *Command) []string {iflen() == 0 {return } .mergePersistentFlags() := []string{} := .Flags():forlen() > 0 { := [0] = [1:]switch {case == "--":// "--" terminates the flagsbreakcasestrings.HasPrefix(, "--") && !strings.Contains(, "=") && !hasNoOptDefVal([2:], ):// If '--flag arg' then // delete arg from args.fallthrough// (do the same as below)casestrings.HasPrefix(, "-") && !strings.Contains(, "=") && len() == 2 && !shortHasNoOptDefVal([1:], ):// If '-f arg' then // delete 'arg' from args or break the loop if len(args) <= 1.iflen() <= 1 {break } else { = [1:]continue }case != "" && !strings.HasPrefix(, "-"): = append(, ) } }return}// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).// Special care needs to be taken not to remove a flag value.func ( *Command) ( []string, string) []string {iflen() == 0 {return } .mergePersistentFlags() := .Flags():for := 0; < len(); ++ { := []switch {case == "--":// -- means we have reached the end of the parseable args. Break out of the loop now.breakcasestrings.HasPrefix(, "--") && !strings.Contains(, "=") && !hasNoOptDefVal([2:], ):fallthroughcasestrings.HasPrefix(, "-") && !strings.Contains(, "=") && len() == 2 && !shortHasNoOptDefVal([1:], ):// This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip // over the next arg, because that is the value of this flag. ++continuecase !strings.HasPrefix(, "-"):// This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, // return the args, excluding the one at this position.if == { := make([]string, 0, len()-1) = append(, [:]...) = append(, [+1:]...)return } } }return}func isFlagArg( string) bool {return ((len() >= 3 && [0:2] == "--") || (len() >= 2 && [0] == '-' && [1] != '-'))}// Find the target command given the args and command tree// Meant to be run on the highest node. Only searches down.func ( *Command) ( []string) (*Command, []string, error) {varfunc(*Command, []string) (*Command, []string) = func( *Command, []string) (*Command, []string) { := stripFlags(, )iflen() == 0 {return , } := [0] := .findNext()if != nil {return (, .argsMinusFirstX(, )) }return , } , := (, )if .Args == nil {return , , legacyArgs(, stripFlags(, )) }return , , nil}func ( *Command) ( string) string {if .DisableSuggestions {return"" }if .SuggestionsMinimumDistance <= 0 { .SuggestionsMinimumDistance = 2 }varstrings.Builderif := .SuggestionsFor(); len() > 0 { .WriteString("\n\nDid you mean this?\n")for , := range { _, _ = fmt.Fprintf(&, "\t%v\n", ) } }return .String()}func ( *Command) ( string) *Command { := make([]*Command, 0)for , := range .commands {ifcommandNameMatches(.Name(), ) || .HasAlias() { .commandCalledAs.name = return }ifEnablePrefixMatching && .hasNameOrAliasPrefix() { = append(, ) } }iflen() == 1 {// Temporarily disable gosec G602, which produces a false positive. // See https://github.com/securego/gosec/issues/1005.return [0] // #nosec G602 }returnnil}// Traverse the command tree to find the command, and parse args for// each parent.func ( *Command) ( []string) (*Command, []string, error) { := []string{} := falsefor , := range {switch {// A long flag with a space separated valuecasestrings.HasPrefix(, "--") && !strings.Contains(, "="):// TODO: this isn't quite right, we should really check ahead for 'true' or 'false' = !hasNoOptDefVal([2:], .Flags()) = append(, )continue// A short flag with a space separated valuecasestrings.HasPrefix(, "-") && !strings.Contains(, "=") && len() == 2 && !shortHasNoOptDefVal([1:], .Flags()): = true = append(, )continue// The value for a flagcase : = false = append(, )continue// A flag without a value, or with an `=` separated valuecaseisFlagArg(): = append(, )continue } := .findNext()if == nil {return , , nil }if := .ParseFlags(); != nil {returnnil, , }return .([+1:]) }return , , nil}// SuggestionsFor provides suggestions for the typedName.func ( *Command) ( string) []string { := []string{}for , := range .commands {if .IsAvailableCommand() { := ld(, .Name(), true) := <= .SuggestionsMinimumDistance := strings.HasPrefix(strings.ToLower(.Name()), strings.ToLower())if || { = append(, .Name()) }for , := range .SuggestFor {ifstrings.EqualFold(, ) { = append(, .Name()) } } } }return}// VisitParents visits all parents of the command and invokes fn on each parent.func ( *Command) ( func(*Command)) {if .HasParent() { (.Parent()) .Parent().() }}// Root finds root command.func ( *Command) () *Command {if .HasParent() {return .Parent().() }return}// ArgsLenAtDash will return the length of c.Flags().Args at the moment// when a -- was found during args parsing.func ( *Command) () int {return .Flags().ArgsLenAtDash()}func ( *Command) ( []string) ( error) {if == nil {returnfmt.Errorf("called Execute() on a nil Command") }iflen(.Deprecated) > 0 { .Printf("Command %q is deprecated, %s\n", .Name(), .Deprecated) }// initialize help and version flag at the last point possible to allow for user // overriding .InitDefaultHelpFlag() .InitDefaultVersionFlag() = .ParseFlags()if != nil {return .FlagErrorFunc()(, ) }// If help is called, regardless of other flags, return we want help. // Also say we need help if the command isn't runnable. , := .Flags().GetBool("help")if != nil {// should be impossible to get here as we always declare a help // flag in InitDefaultHelpFlag() .Println("\"help\" flag declared as non-bool. Please correct your code")return }if {returnflag.ErrHelp }// for back-compat, only add version flag behavior if version is definedif .Version != "" { , := .Flags().GetBool("version")if != nil { .Println("\"version\" flag declared as non-bool. Please correct your code")return }if { := tmpl(.OutOrStdout(), .VersionTemplate(), )if != nil { .Println() }return } }if !.Runnable() {returnflag.ErrHelp } .preRun()defer .postRun() := .Flags().Args()if .DisableFlagParsing { = }if := .ValidateArgs(); != nil {return } := make([]*Command, 0, 5)for := ; != nil; = .Parent() {ifEnableTraverseRunHooks {// When EnableTraverseRunHooks is set: // - Execute all persistent pre-runs from the root parent till this command. // - Execute all persistent post-runs from this command till the root parent. = append([]*Command{}, ...) } else {// Otherwise, execute only the first found persistent hook. = append(, ) } }for , := range {if .PersistentPreRunE != nil {if := .PersistentPreRunE(, ); != nil {return }if !EnableTraverseRunHooks {break } } elseif .PersistentPreRun != nil { .PersistentPreRun(, )if !EnableTraverseRunHooks {break } } }if .PreRunE != nil {if := .PreRunE(, ); != nil {return } } elseif .PreRun != nil { .PreRun(, ) }if := .ValidateRequiredFlags(); != nil {return }if := .ValidateFlagGroups(); != nil {return }if .RunE != nil {if := .RunE(, ); != nil {return } } else { .Run(, ) }if .PostRunE != nil {if := .PostRunE(, ); != nil {return } } elseif .PostRun != nil { .PostRun(, ) }for := ; != nil; = .Parent() {if .PersistentPostRunE != nil {if := .PersistentPostRunE(, ); != nil {return }if !EnableTraverseRunHooks {break } } elseif .PersistentPostRun != nil { .PersistentPostRun(, )if !EnableTraverseRunHooks {break } } }returnnil}func ( *Command) () {for , := rangeinitializers { () }}func ( *Command) () {for , := rangefinalizers { () }}// ExecuteContext is the same as Execute(), but sets the ctx on the command.// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs// functions.func ( *Command) ( context.Context) error { .ctx = return .Execute()}// Execute uses the args (os.Args[1:] by default)// and run through the command tree finding appropriate matches// for commands and then corresponding flags.func ( *Command) () error { , := .ExecuteC()return}// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command.// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs// functions.func ( *Command) ( context.Context) (*Command, error) { .ctx = return .ExecuteC()}// ExecuteC executes the command.func ( *Command) () ( *Command, error) {if .ctx == nil { .ctx = context.Background() }// Regardless of what command execute is called on, run on Root onlyif .HasParent() {return .Root().() }// windows hookifpreExecHookFn != nil {preExecHookFn() }// initialize help at the last point to allow for user overriding .InitDefaultHelpCmd()// initialize completion at the last point to allow for user overriding .InitDefaultCompletionCmd()// Now that all commands have been created, let's make sure all groups // are properly created also .checkCommandGroups() := .args// Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155if .args == nil && filepath.Base(os.Args[0]) != "cobra.test" { = os.Args[1:] }// initialize the hidden command to be used for shell completion .initCompleteCmd()var []stringif .TraverseChildren { , , = .Traverse() } else { , , = .Find() }if != nil {// If found parse to a subcommand and then failed, talk about the subcommandif != nil { = }if !.SilenceErrors { .PrintErrln(.ErrPrefix(), .Error()) .PrintErrf("Run '%v --help' for usage.\n", .CommandPath()) }return , } .commandCalledAs.called = trueif .commandCalledAs.name == "" { .commandCalledAs.name = .Name() }// We have to pass global context to children command // if context is present on the parent command.if .ctx == nil { .ctx = .ctx } = .execute()if != nil {// Always show help if requested, even if SilenceErrors is in // effectiferrors.Is(, flag.ErrHelp) { .HelpFunc()(, )return , nil }// If root command has SilenceErrors flagged, // all subcommands should respect itif !.SilenceErrors && !.SilenceErrors { .PrintErrln(.ErrPrefix(), .Error()) }// If root command has SilenceUsage flagged, // all subcommands should respect itif !.SilenceUsage && !.SilenceUsage { .Println(.UsageString()) } }return , }func ( *Command) ( []string) error {if .Args == nil {returnArbitraryArgs(, ) }return .Args(, )}// ValidateRequiredFlags validates all required flags are present and returns an error otherwisefunc ( *Command) () error {if .DisableFlagParsing {returnnil } := .Flags() := []string{} .VisitAll(func( *flag.Flag) { , := .Annotations[BashCompOneRequiredFlag]if ! {return }if ([0] == "true") && !.Changed { = append(, .Name) } })iflen() > 0 {returnfmt.Errorf(`required flag(s) "%s" not set`, strings.Join(, `", "`)) }returnnil}// checkCommandGroups checks if a command has been added to a group that does not exists.// If so, we panic because it indicates a coding error that should be corrected.func ( *Command) () {for , := range .commands {// if Group is not defined let the developer know right awayif .GroupID != "" && !.ContainsGroup(.GroupID) {panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", .GroupID, .CommandPath())) } .() }}// InitDefaultHelpFlag adds default help flag to c.// It is called automatically by executing the c or by calling help and usage.// If c already has help flag, it will do nothing.func ( *Command) () { .mergePersistentFlags()if .Flags().Lookup("help") == nil { := "help for " := .displayName()if == "" { += "this command" } else { += } .Flags().BoolP("help", "h", false, ) _ = .Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) }}// InitDefaultVersionFlag adds default version flag to c.// It is called automatically by executing the c.// If c already has a version flag, it will do nothing.// If c.Version is empty, it will do nothing.func ( *Command) () {if .Version == "" {return } .mergePersistentFlags()if .Flags().Lookup("version") == nil { := "version for "if .Name() == "" { += "this command" } else { += .Name() }if .Flags().ShorthandLookup("v") == nil { .Flags().BoolP("version", "v", false, ) } else { .Flags().Bool("version", false, ) } _ = .Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"}) }}// InitDefaultHelpCmd adds default help command to c.// It is called automatically by executing the c or by calling help and usage.// If c already has help command or c has no subcommands, it will do nothing.func ( *Command) () {if !.HasSubCommands() {return }if .helpCommand == nil { .helpCommand = &Command{Use: "help [command]",Short: "Help about any command",Long: `Help provides help for any command in the application.Simply type ` + .displayName() + ` help [path to command] for full details.`,ValidArgsFunction: func( *Command, []string, string) ([]string, ShellCompDirective) {var []string , , := .Root().Find()if != nil {returnnil, ShellCompDirectiveNoFileComp }if == nil {// Root help command. = .Root() }for , := range .Commands() {if .IsAvailableCommand() || == .helpCommand {ifstrings.HasPrefix(.Name(), ) { = append(, fmt.Sprintf("%s\t%s", .Name(), .Short)) } } }return , ShellCompDirectiveNoFileComp },Run: func( *Command, []string) { , , := .Root().Find()if == nil || != nil { .Printf("Unknown help topic %#q\n", )CheckErr(.Root().Usage()) } else { .InitDefaultHelpFlag() // make possible 'help' flag to be shown .InitDefaultVersionFlag() // make possible 'version' flag to be shownCheckErr(.Help()) } },GroupID: .helpCommandGroupID, } } .RemoveCommand(.helpCommand) .AddCommand(.helpCommand)}// ResetCommands delete parent, subcommand and help command from c.func ( *Command) () { .parent = nil .commands = nil .helpCommand = nil .parentsPflags = nil}// Sorts commands by their names.type commandSorterByName []*Commandfunc ( commandSorterByName) () int { returnlen() }func ( commandSorterByName) (, int) { [], [] = [], [] }func ( commandSorterByName) (, int) bool { return [].Name() < [].Name() }// Commands returns a sorted slice of child commands.func ( *Command) () []*Command {// do not sort commands if it already sorted or sorting was disabledifEnableCommandSorting && !.commandsAreSorted {sort.Sort(commandSorterByName(.commands)) .commandsAreSorted = true }return .commands}// AddCommand adds one or more commands to this parent command.func ( *Command) ( ...*Command) {for , := range {if [] == {panic("Command can't be a child of itself") } [].parent = // update max lengths := len(.Use)if > .commandsMaxUseLen { .commandsMaxUseLen = } := len(.CommandPath())if > .commandsMaxCommandPathLen { .commandsMaxCommandPathLen = } := len(.Name())if > .commandsMaxNameLen { .commandsMaxNameLen = }// If global normalization function exists, update all childrenif .globNormFunc != nil { .SetGlobalNormalizationFunc(.globNormFunc) } .commands = append(.commands, ) .commandsAreSorted = false }}// Groups returns a slice of child command groups.func ( *Command) () []*Group {return .commandgroups}// AllChildCommandsHaveGroup returns if all subcommands are assigned to a groupfunc ( *Command) () bool {for , := range .commands {if (.IsAvailableCommand() || == .helpCommand) && .GroupID == "" {returnfalse } }returntrue}// ContainsGroup return if groupID exists in the list of command groups.func ( *Command) ( string) bool {for , := range .commandgroups {if .ID == {returntrue } }returnfalse}// AddGroup adds one or more command groups to this parent command.func ( *Command) ( ...*Group) { .commandgroups = append(.commandgroups, ...)}// RemoveCommand removes one or more commands from a parent command.func ( *Command) ( ...*Command) { := []*Command{}:for , := range .commands {for , := range {if == { .parent = nilcontinue } } = append(, ) } .commands = // recompute all lengths .commandsMaxUseLen = 0 .commandsMaxCommandPathLen = 0 .commandsMaxNameLen = 0for , := range .commands { := len(.Use)if > .commandsMaxUseLen { .commandsMaxUseLen = } := len(.CommandPath())if > .commandsMaxCommandPathLen { .commandsMaxCommandPathLen = } := len(.Name())if > .commandsMaxNameLen { .commandsMaxNameLen = } }}// Print is a convenience method to Print to the defined output, fallback to Stderr if not set.func ( *Command) ( ...interface{}) {fmt.Fprint(.OutOrStderr(), ...)}// Println is a convenience method to Println to the defined output, fallback to Stderr if not set.func ( *Command) ( ...interface{}) { .Print(fmt.Sprintln(...))}// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set.func ( *Command) ( string, ...interface{}) { .Print(fmt.Sprintf(, ...))}// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set.func ( *Command) ( ...interface{}) {fmt.Fprint(.ErrOrStderr(), ...)}// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.func ( *Command) ( ...interface{}) { .PrintErr(fmt.Sprintln(...))}// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.func ( *Command) ( string, ...interface{}) { .PrintErr(fmt.Sprintf(, ...))}// CommandPath returns the full path to this command.func ( *Command) () string {if .HasParent() {return .Parent().() + " " + .Name() }return .displayName()}func ( *Command) () string {if , := .Annotations[CommandDisplayNameAnnotation]; {return }return .Name()}// UseLine puts out the full usage for a given command (including parents).func ( *Command) () string {varstring := strings.Replace(.Use, .Name(), .displayName(), 1)if .HasParent() { = .parent.CommandPath() + " " + } else { = }if .DisableFlagsInUseLine {return }if .HasAvailableFlags() && !strings.Contains(, "[flags]") { += " [flags]" }return}// DebugFlags used to determine which flags have been assigned to which commands// and which persist.func ( *Command) () { .Println("DebugFlags called on", .Name())varfunc(*Command) = func( *Command) {if .HasFlags() || .HasPersistentFlags() { .Println(.Name()) }if .HasFlags() { .flags.VisitAll(func( *flag.Flag) {if .HasPersistentFlags() && .persistentFlag(.Name) != nil { .Println(" -"+.Shorthand+",", "--"+.Name, "["+.DefValue+"]", "", .Value, " [LP]") } else { .Println(" -"+.Shorthand+",", "--"+.Name, "["+.DefValue+"]", "", .Value, " [L]") } }) }if .HasPersistentFlags() { .pflags.VisitAll(func( *flag.Flag) {if .HasFlags() {if .flags.Lookup(.Name) == nil { .Println(" -"+.Shorthand+",", "--"+.Name, "["+.DefValue+"]", "", .Value, " [P]") } } else { .Println(" -"+.Shorthand+",", "--"+.Name, "["+.DefValue+"]", "", .Value, " [P]") } }) } .Println(.flagErrorBuf)if .HasSubCommands() {for , := range .commands { () } } } ()}// Name returns the command's name: the first word in the use line.func ( *Command) () string { := .Use := strings.Index(, " ")if >= 0 { = [:] }return}// HasAlias determines if a given string is an alias of the command.func ( *Command) ( string) bool {for , := range .Aliases {ifcommandNameMatches(, ) {returntrue } }returnfalse}// CalledAs returns the command name or alias that was used to invoke// this command or an empty string if the command has not been called.func ( *Command) () string {if .commandCalledAs.called {return .commandCalledAs.name }return""}// hasNameOrAliasPrefix returns true if the Name or any of aliases start// with prefixfunc ( *Command) ( string) bool {ifstrings.HasPrefix(.Name(), ) { .commandCalledAs.name = .Name()returntrue }for , := range .Aliases {ifstrings.HasPrefix(, ) { .commandCalledAs.name = returntrue } }returnfalse}// NameAndAliases returns a list of the command name and all aliasesfunc ( *Command) () string {returnstrings.Join(append([]string{.Name()}, .Aliases...), ", ")}// HasExample determines if the command has example.func ( *Command) () bool {returnlen(.Example) > 0}// Runnable determines if the command is itself runnable.func ( *Command) () bool {return .Run != nil || .RunE != nil}// HasSubCommands determines if the command has children commands.func ( *Command) () bool {returnlen(.commands) > 0}// IsAvailableCommand determines if a command is available as a non-help command// (this includes all non deprecated/hidden commands).func ( *Command) () bool {iflen(.Deprecated) != 0 || .Hidden {returnfalse }if .HasParent() && .Parent().helpCommand == {returnfalse }if .Runnable() || .HasAvailableSubCommands() {returntrue }returnfalse}// IsAdditionalHelpTopicCommand determines if a command is an additional// help topic command; additional help topic command is determined by the// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that// are runnable/hidden/deprecated.// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.func ( *Command) () bool {// if a command is runnable, deprecated, or hidden it is not a 'help' commandif .Runnable() || len(.Deprecated) != 0 || .Hidden {returnfalse }// if any non-help sub commands are found, the command is not a 'help' commandfor , := range .commands {if !.() {returnfalse } }// the command either has no sub commands, or no non-help sub commandsreturntrue}// HasHelpSubCommands determines if a command has any available 'help' sub commands// that need to be shown in the usage/help default template under 'additional help// topics'.func ( *Command) () bool {// return true on the first found available 'help' sub commandfor , := range .commands {if .IsAdditionalHelpTopicCommand() {returntrue } }// the command either has no sub commands, or no available 'help' sub commandsreturnfalse}// HasAvailableSubCommands determines if a command has available sub commands that// need to be shown in the usage/help default template under 'available commands'.func ( *Command) () bool {// return true on the first found available (non deprecated/help/hidden) // sub commandfor , := range .commands {if .IsAvailableCommand() {returntrue } }// the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commandsreturnfalse}// HasParent determines if the command is a child command.func ( *Command) () bool {return .parent != nil}// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.func ( *Command) () func( *flag.FlagSet, string) flag.NormalizedName {return .globNormFunc}// Flags returns the complete FlagSet that applies// to this command (local and persistent declared here and by all parents).func ( *Command) () *flag.FlagSet {if .flags == nil { .flags = flag.NewFlagSet(.displayName(), flag.ContinueOnError)if .flagErrorBuf == nil { .flagErrorBuf = new(bytes.Buffer) } .flags.SetOutput(.flagErrorBuf) }return .flags}// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.// This function does not modify the flags of the current command, it's purpose is to return the current state.func ( *Command) () *flag.FlagSet { := .PersistentFlags() := flag.NewFlagSet(.displayName(), flag.ContinueOnError) .LocalFlags().VisitAll(func( *flag.Flag) {if .Lookup(.Name) == nil { .AddFlag() } })return}// LocalFlags returns the local FlagSet specifically set in the current command.// This function does not modify the flags of the current command, it's purpose is to return the current state.func ( *Command) () *flag.FlagSet { .mergePersistentFlags()if .lflags == nil { .lflags = flag.NewFlagSet(.displayName(), flag.ContinueOnError)if .flagErrorBuf == nil { .flagErrorBuf = new(bytes.Buffer) } .lflags.SetOutput(.flagErrorBuf) } .lflags.SortFlags = .Flags().SortFlagsif .globNormFunc != nil { .lflags.SetNormalizeFunc(.globNormFunc) } := func( *flag.Flag) {// Add the flag if it is not a parent PFlag, or it shadows a parent PFlagif .lflags.Lookup(.Name) == nil && != .parentsPflags.Lookup(.Name) { .lflags.AddFlag() } } .Flags().VisitAll() .PersistentFlags().VisitAll()return .lflags}// InheritedFlags returns all flags which were inherited from parent commands.// This function does not modify the flags of the current command, it's purpose is to return the current state.func ( *Command) () *flag.FlagSet { .mergePersistentFlags()if .iflags == nil { .iflags = flag.NewFlagSet(.displayName(), flag.ContinueOnError)if .flagErrorBuf == nil { .flagErrorBuf = new(bytes.Buffer) } .iflags.SetOutput(.flagErrorBuf) } := .LocalFlags()if .globNormFunc != nil { .iflags.SetNormalizeFunc(.globNormFunc) } .parentsPflags.VisitAll(func( *flag.Flag) {if .iflags.Lookup(.Name) == nil && .Lookup(.Name) == nil { .iflags.AddFlag() } })return .iflags}// NonInheritedFlags returns all flags which were not inherited from parent commands.// This function does not modify the flags of the current command, it's purpose is to return the current state.func ( *Command) () *flag.FlagSet {return .LocalFlags()}// PersistentFlags returns the persistent FlagSet specifically set in the current command.func ( *Command) () *flag.FlagSet {if .pflags == nil { .pflags = flag.NewFlagSet(.displayName(), flag.ContinueOnError)if .flagErrorBuf == nil { .flagErrorBuf = new(bytes.Buffer) } .pflags.SetOutput(.flagErrorBuf) }return .pflags}// ResetFlags deletes all flags from command.func ( *Command) () { .flagErrorBuf = new(bytes.Buffer) .flagErrorBuf.Reset() .flags = flag.NewFlagSet(.displayName(), flag.ContinueOnError) .flags.SetOutput(.flagErrorBuf) .pflags = flag.NewFlagSet(.displayName(), flag.ContinueOnError) .pflags.SetOutput(.flagErrorBuf) .lflags = nil .iflags = nil .parentsPflags = nil}// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).func ( *Command) () bool {return .Flags().HasFlags()}// HasPersistentFlags checks if the command contains persistent flags.func ( *Command) () bool {return .PersistentFlags().HasFlags()}// HasLocalFlags checks if the command has flags specifically declared locally.func ( *Command) () bool {return .LocalFlags().HasFlags()}// HasInheritedFlags checks if the command has flags inherited from its parent command.func ( *Command) () bool {return .InheritedFlags().HasFlags()}// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire// structure) which are not hidden or deprecated.func ( *Command) () bool {return .Flags().HasAvailableFlags()}// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.func ( *Command) () bool {return .PersistentFlags().HasAvailableFlags()}// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden// or deprecated.func ( *Command) () bool {return .LocalFlags().HasAvailableFlags()}// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are// not hidden or deprecated.func ( *Command) () bool {return .InheritedFlags().HasAvailableFlags()}// Flag climbs up the command tree looking for matching flag.func ( *Command) ( string) ( *flag.Flag) { = .Flags().Lookup()if == nil { = .persistentFlag() }return}// Recursively find matching persistent flag.func ( *Command) ( string) ( *flag.Flag) {if .HasPersistentFlags() { = .PersistentFlags().Lookup() }if == nil { .updateParentsPflags() = .parentsPflags.Lookup() }return}// ParseFlags parses persistent flag tree and local flags.func ( *Command) ( []string) error {if .DisableFlagParsing {returnnil }if .flagErrorBuf == nil { .flagErrorBuf = new(bytes.Buffer) } := .flagErrorBuf.Len() .mergePersistentFlags()// do it here after merging all flags and just before parse .Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(.FParseErrWhitelist) := .Flags().Parse()// Print warnings if they occurred (e.g. deprecated flag messages).if .flagErrorBuf.Len()- > 0 && == nil { .Print(.flagErrorBuf.String()) }return}// Parent returns a commands parent command.func ( *Command) () *Command {return .parent}// mergePersistentFlags merges c.PersistentFlags() to c.Flags()// and adds missing persistent flags of all parents.func ( *Command) () { .updateParentsPflags() .Flags().AddFlagSet(.PersistentFlags()) .Flags().AddFlagSet(.parentsPflags)}// updateParentsPflags updates c.parentsPflags by adding// new persistent flags of all parents.// If c.parentsPflags == nil, it makes new.func ( *Command) () {if .parentsPflags == nil { .parentsPflags = flag.NewFlagSet(.displayName(), flag.ContinueOnError) .parentsPflags.SetOutput(.flagErrorBuf) .parentsPflags.SortFlags = false }if .globNormFunc != nil { .parentsPflags.SetNormalizeFunc(.globNormFunc) } .Root().PersistentFlags().AddFlagSet(flag.CommandLine) .VisitParents(func( *Command) { .parentsPflags.AddFlagSet(.PersistentFlags()) })}// commandNameMatches checks if two command names are equal// taking into account case sensitivity according to// EnableCaseInsensitive global configuration.func commandNameMatches( string, string) bool {ifEnableCaseInsensitive {returnstrings.EqualFold(, ) }return == }
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.