1517 lines · 41.8 KB · Go
RawDownload
// Copyright © 2013 Steve Francia <spf@spf13.com>.//// 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 cobra import (	"bytes"	"fmt"	"io"	"os"	"path/filepath"	"sort"	"strings" 	flag "github.com/spf13/pflag") // FParseErrWhitelist configures Flag parse errors to be ignoredtype FParseErrWhitelist flag.ParseErrorsWhitelist // 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.type Command struct {	// Use is the one-line usage message.	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 	// 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 bash completions	ValidArgs []string 	// Expected arguments	Args PositionalArgs 	// ArgAliases is List of aliases for ValidArgs.	// These are not suggested to the user in the bash completion,	// but accepted if entered manually.	ArgAliases []string 	// BashCompletionFunction is custom functions used by the bash autocompletion generator.	BashCompletionFunction string 	// Deprecated defines, if this command is deprecated and should print this string when used.	Deprecated string 	// Hidden defines, if this command is hidden and should NOT show up in the list of available commands.	Hidden bool 	// Annotations are key/value pairs that can be used by applications to identify or	// group commands.	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.	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.	//	// 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 	// 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 	// TraverseChildren parses flags on all parents before executing child command.	TraverseChildren bool 	//FParseErrWhitelist flag parse errors to be ignored	FParseErrWhitelist FParseErrWhitelist 	// 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	// 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	} 	// 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.	lflags *flag.FlagSet	// iflags contains inherited flags.	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 	// output is an output writer defined by user.	output io.Writer	// 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	// versionTemplate is the version template defined by user.	versionTemplate string} // 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 (c *Command) SetArgs(a []string) {	c.args = a} // SetOutput sets the destination for usage and error messages.// If output is nil, os.Stderr is used.func (c *Command) SetOutput(output io.Writer) {	c.output = output} // SetUsageFunc sets usage function. Usage can be defined by application.func (c *Command) SetUsageFunc(f func(*Command) error) {	c.usageFunc = f} // SetUsageTemplate sets usage template. Can be defined by Application.func (c *Command) SetUsageTemplate(s string) {	c.usageTemplate = s} // SetFlagErrorFunc sets a function to generate an error when flag parsing// fails.func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {	c.flagErrorFunc = f} // SetHelpFunc sets help function. Can be defined by Application.func (c *Command) SetHelpFunc(f func(*Command, []string)) {	c.helpFunc = f} // SetHelpCommand sets help command.func (c *Command) SetHelpCommand(cmd *Command) {	c.helpCommand = cmd} // SetHelpTemplate sets help template to be used. Application can use it to set custom template.func (c *Command) SetHelpTemplate(s string) {	c.helpTemplate = s} // SetVersionTemplate sets version template to be used. Application can use it to set custom template.func (c *Command) SetVersionTemplate(s string) {	c.versionTemplate = s} // 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 (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {	c.Flags().SetNormalizeFunc(n)	c.PersistentFlags().SetNormalizeFunc(n)	c.globNormFunc = n 	for _, command := range c.commands {		command.SetGlobalNormalizationFunc(n)	}} // OutOrStdout returns output to stdout.func (c *Command) OutOrStdout() io.Writer {	return c.getOut(os.Stdout)} // OutOrStderr returns output to stderrfunc (c *Command) OutOrStderr() io.Writer {	return c.getOut(os.Stderr)} func (c *Command) getOut(def io.Writer) io.Writer {	if c.output != nil {		return c.output	}	if c.HasParent() {		return c.parent.getOut(def)	}	return def} // UsageFunc returns either the function set by SetUsageFunc for this command// or a parent, or it returns a default usage function.func (c *Command) UsageFunc() (f func(*Command) error) {	if c.usageFunc != nil {		return c.usageFunc	}	if c.HasParent() {		return c.Parent().UsageFunc()	}	return func(c *Command) error {		c.mergePersistentFlags()		err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)		if err != nil {			c.Println(err)		}		return err	}} // Usage puts out the usage for the command.// Used when a user provides invalid input.// Can be defined by user by overriding UsageFunc.func (c *Command) Usage() error {	return c.UsageFunc()(c)} // HelpFunc returns either the function set by SetHelpFunc for this command// or a parent, or it returns a function with default help behavior.func (c *Command) HelpFunc() func(*Command, []string) {	if c.helpFunc != nil {		return c.helpFunc	}	if c.HasParent() {		return c.Parent().HelpFunc()	}	return func(c *Command, a []string) {		c.mergePersistentFlags()		err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)		if err != nil {			c.Println(err)		}	}} // Help puts out the help for the command.// Used when a user calls help [command].// Can be defined by user by overriding HelpFunc.func (c *Command) Help() error {	c.HelpFunc()(c, []string{})	return nil} // UsageString return usage string.func (c *Command) UsageString() string {	tmpOutput := c.output	bb := new(bytes.Buffer)	c.SetOutput(bb)	c.Usage()	c.output = tmpOutput	return bb.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 (c *Command) FlagErrorFunc() (f func(*Command, error) error) {	if c.flagErrorFunc != nil {		return c.flagErrorFunc	} 	if c.HasParent() {		return c.parent.FlagErrorFunc()	}	return func(c *Command, err error) error {		return err	}} var minUsagePadding = 25 // UsagePadding return padding for the usage.func (c *Command) UsagePadding() int {	if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {		return minUsagePadding	}	return c.parent.commandsMaxUseLen} var minCommandPathPadding = 11 // CommandPathPadding return padding for the command path.func (c *Command) CommandPathPadding() int {	if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {		return minCommandPathPadding	}	return c.parent.commandsMaxCommandPathLen} var minNamePadding = 11 // NamePadding returns padding for the name.func (c *Command) NamePadding() int {	if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {		return minNamePadding	}	return c.parent.commandsMaxNameLen} // UsageTemplate returns usage template for the command.func (c *Command) UsageTemplate() string {	if c.usageTemplate != "" {		return c.usageTemplate	} 	if c.HasParent() {		return c.parent.UsageTemplate()	}	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}} Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}  {{rpad .Name .NamePadding }} {{.Short}}{{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 (c *Command) HelpTemplate() string {	if c.helpTemplate != "" {		return c.helpTemplate	} 	if c.HasParent() {		return c.parent.HelpTemplate()	}	return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`} // VersionTemplate return version template for the command.func (c *Command) VersionTemplate() string {	if c.versionTemplate != "" {		return c.versionTemplate	} 	if c.HasParent() {		return c.parent.VersionTemplate()	}	return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}`} func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {	flag := fs.Lookup(name)	if flag == nil {		return false	}	return flag.NoOptDefVal != ""} func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {	if len(name) == 0 {		return false	} 	flag := fs.ShorthandLookup(name[:1])	if flag == nil {		return false	}	return flag.NoOptDefVal != ""} func stripFlags(args []string, c *Command) []string {	if len(args) == 0 {		return args	}	c.mergePersistentFlags() 	commands := []string{}	flags := c.Flags() Loop:	for len(args) > 0 {		s := args[0]		args = args[1:]		switch {		case s == "--":			// "--" terminates the flags			break Loop		case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):			// If '--flag arg' then			// delete arg from args.			fallthrough // (do the same as below)		case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):			// If '-f arg' then			// delete 'arg' from args or break the loop if len(args) <= 1.			if len(args) <= 1 {				break Loop			} else {				args = args[1:]				continue			}		case s != "" && !strings.HasPrefix(s, "-"):

Lines 1–500 of 1517.