Documentation
¶
Overview ¶
Package command defines plumbing for command dispatch. It is based on and similar in design to the "go" command-line tool.
Overview ¶
The command package allows a program to easily process a simple language of named commands, each of which may have its own flags, arguments, and nested subcommands. A command is represented by a *command.C value carrying help text, usage summaries, and a function to execute its behavior.
The Run and RunOrFail functions parse the raw argument list of a program against a tree of *command.C values, parsing flags as needed and executing the selected command or printing appropriate diagnostics. Flags are parsed using the standard "flag" package by default.
Example ¶
package main import ( "flag" "fmt" "strings" "github.com/creachadair/command" ) func main() { // The environment passed to a command can carry an arbitrary config value. // Here we use a struct carrying information about options. type options struct { noNewline bool } root := &command.C{ Name: "example", // Usage may have multiple lines, and can omit the command name. Usage: "command args...", // The first line of the help text is used as "short" help. // Any subsequent lines are include in "long" help. Help: `Do interesting things with arguments. This program demonstrates the use of the command package. This help text is printed by the "help" subcommand.`, // Note that the "example" command does not have a Run function. // Executing it without a subcommand will print a help message and exit // with error. Commands: []*command.C{ // This function creates a basic "help" command that prints out // command help based on usage and help strings. // // This command can also have "help topics", which are stripped-down // commands with only help text (no flags, usage, or other behavior). command.HelpCommand([]command.HelpTopic{{ Name: "special", Help: "This is some useful information a user might care about.", }, { Name: "magic", Help: `The user can write "command help <topic>" to get this text.`, }}), // This is a typical user-defined command. { Name: "echo", Usage: "text ...", Help: "Concatenate the arguments with spaces and print to stdout.", SetFlags: func(env *command.Env, fs *flag.FlagSet) { // Pull the config value out of the environment and attach a flag to it. opt := env.Config.(*options) fs.BoolVar(&opt.noNewline, "n", false, "Do not print a trailing newline") }, Run: func(env *command.Env) error { opt := env.Config.(*options) fmt.Print(strings.Join(env.Args, " ")) if !opt.noNewline { fmt.Println() } return nil }, }, }, } // Demonstrate help output. // // Note that the argument to NewEnv is plumbed via the Config field of Env. opt := new(options) command.Run(root.NewEnv(opt), []string{"help"}) command.RunOrFail(root.NewEnv(opt), []string{"echo", "foo", "bar"}) command.RunOrFail(root.NewEnv(opt), []string{"echo", "-n", "baz"}) }
Output: foo bar baz
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrRequestHelp = errors.New("help requested")
ErrRequestHelp is returned from Run if the user requested help.
Functions ¶
func FailWithUsage ¶
FailWithUsage is a run function that logs a usage message for the command and returns ErrRequestHelp.
func Run ¶
Run traverses the given unprocessed arguments starting from env. See the documentation for type C for a description of argument traversal.
Run writes usage information to ctx and returns a UsageError if the command-line usage was incorrect or ErrRequestHelp if the user requested help via the --help flag.
func RunHelp ¶
RunHelp is a run function that implements long help. It displays the help for the enclosing command or subtopics of "help" itself.
Types ¶
type C ¶
type C struct { // The name of the command, preferably one word. The name is during argument // processing to choose which command or subcommand to execute. Name string // A terse usage summary for the command. Multiple lines are allowed. // Each line should be self-contained for a particular usage sense. Usage string // A detailed description of the command. Multiple lines are allowed. // The first non-blank line of this text is used as a synopsis; the whole // string is printed for long help. Help string // Flags parsed from the raw argument list. This will be initialized before // Init or Run is called unless CustomFlags is true. Flags flag.FlagSet // If false, Flags is used to parse the argument list. Otherwise, the Run // function is responsible for parsing flags from the argument list. CustomFlags bool // Perform the action of the command. If nil, calls FailWithUsage. Run func(env *Env) error // If set, this will be called before flags are parsed, to give the command // an opportunity to set flags. SetFlags func(env *Env, fs *flag.FlagSet) // If set, this will be called after flags are parsed (if any) but before // any subcommands are processed. If it reports an error, execution stops // and that error is returned to the caller. // // The Init callback is permitted to modify env, and any such modifications // will persist through the rest of the invocation. Init func(env *Env) error // Subcommands of this command. Commands []*C // contains filtered or unexported fields }
C carries the description and invocation function for a command.
To process a command-line, the Run function walks through the arguments starting from a root command to discover which command should be run and what flags it requires. This argument traversal proceeds in phases:
When a command is first discovered during argument traversal, its SetFlags hook is executed (if defined) to prepare its flag set. Then, unless the CustomFlags option is true, the rest of the argument list is parsed using the FlagSet to separate command-specific flags from further arguments and/or subcommands.
After flags are parsed and before attempting to explore subcommands, the current command's Init hook is called (if defined). If Init reports an error it terminates argument traversal, and that error is reported back to the user.
Next, if there are any remaining non-flag arguments, Run checks whether the current command has a subcommand matching the first argument. If so argument traversal recurs into that subcommand to process the rest of the command-line.
Otherwise, if the command defines a Run hook, that hook is executed with the remaining unconsumed arguments. If no Run hook is defined, the traversal stops, logs a help message, and reports an error.
func HelpCommand ¶
HelpCommand constructs a standardized help command with optional topics. The caller is free to edit the resulting command, each call returns a separate value.
func VersionCommand ¶
func VersionCommand() *C
VersionCommand constructs a standardized version command that prints version metadata from the running binary to stdout. The caller can safely modify the returned command to customize its behavior.
func (*C) FindSubcommand ¶
FindSubcommand returns the subcommand of c matching name, or nil.
func (*C) HasRunnableSubcommands ¶
HasRunnableSubcommands reports whether c has any runnable subcommands.
func (*C) HelpInfo ¶
HelpInfo returns help details for c. If includeCommands is true and c has subcommands, their help is also generated.
A command or subcommand with no Run function and no subcommands of its own is considered a help topic, and listed separately.
type Env ¶
type Env struct { Parent *Env // if this is a subcommand, its parent environment (or nil) Command *C // the C value that carries the Run function Config any // configuration data Args []string // the unclaimed command-line arguments Log io.Writer // where to write diagnostic output (nil for os.Stderr) // contains filtered or unexported fields }
Env is the environment passed to the Run function of a command. An Env implements the io.Writer interface, and should be used as the target of any diagnostic output the command wishes to emit. Primary command output should be sent to stdout.
func (*Env) Cancel ¶ added in v0.0.2
Cancel cancels the context associated with e with the given cause. If e does not have its own context, the cancellation is propagated to its parent if one exists. If e has no parent and no context, Cancel does nothing without error.
func (*Env) Context ¶ added in v0.0.2
Context returns the context associated with e. If e does not have its own context, it returns the context of its parent, or if e has no parent it returns a new background context.
func (*Env) SetContext ¶ added in v0.0.2
SetContext sets the context of e to ctx and returns e. If ctx == nil it clears the context of e so that it efaults to its parent (see Context).
type HelpInfo ¶
type HelpInfo struct { Name string Synopsis string Usage string Help string Flags string // Help for subcommands (populated if requested) Commands []HelpInfo // Help for subtopics (populated if requested) Topics []HelpInfo }
HelpInfo records synthesized help details for a command.
func (HelpInfo) WriteLong ¶
WriteLong writes a complete help description to w, including a usage summary, full help text, flag summary, and subcommands.
func (HelpInfo) WriteSynopsis ¶
WriteSynopsis writes a usage summary and command synopsis to w. If the command defines flags, the flag summary is also written.
func (HelpInfo) WriteUsage ¶
WriteUsage writes a usage summary to w.
type HelpTopic ¶
A HelpTopic specifies a name and some help text for use in constructing help topic commands.
type UsageError ¶
UsageError is the concrete type of errors reported by the Usagef function, indicating an error in the usage of a command.
func (UsageError) Error ¶
func (u UsageError) Error() string