diff --git a/README.md b/README.md index 8be3cee8..01766d18 100644 --- a/README.md +++ b/README.md @@ -5,28 +5,30 @@ A Commander for modern go CLI interactions [![Build Status](https://travis-ci.org/spf13/cobra.png)](https://travis-ci.org/spf13/cobra) ## Overview -Cobra provides a simple interface to create powerful modern CLI -interfaces similar to git & go tools. -Cobra was inspired by go, go-Commander, gh and subcommand +Cobra is a commander providing a simple interface to create powerful modern CLI +interfaces similar to git & go tools. In addition to providing an iterface, Cobra +simultaneously provides a controller to organize your application code. +Inspired by go, go-Commander, gh and subcommand, Cobra improves on these by +providing **fully posix compliant flags** (including short & long versions), +**nesting commands**, and the ability to **define your own help and usage** for any or +all commands. + +Cobra has an exceptionally clean interface and simple design without needless +constructors or initialization methods. ## Concepts -There are 3 different core objects to become familiar with to use Cobra. -To help illustrate these 3 items better use the following as an example: +Cobra is built on a structure of commands & flags. + +**Commands** represent actions and **Flags** are modifiers for those actions. + +In the following example 'server' is a command and 'port' is a flag. hugo server --port=1313 -### Commander - -The Commander is the head of your application. It holds the configuration -for your application. It also is responsible for all global flags. - -In the example above 'hugo' is the commander. - - -### Command +### Commands Command is the central point of the application. Each interaction that the application supports will be contained in a Command. A command can @@ -34,21 +36,37 @@ have children commands and optionally run an action. In the example above 'server' is the command +A Command has the following structure: + + type Command struct { + Use string // The one-line usage message. + Short string // The short description shown in the 'help' output. + Long string // The long message shown in the 'help ' output. + Run func(cmd *Command, args []string) // Run runs the command. + } ### Flags -A flag is a way to modify the behavior of an command. Cobra supports -fully posix compliant flags as well as remaining consistent with -the go flag package. A Cobra command has can define flags that -persist through to children commands and flags that are only available -to that command. +A Flag is a way to modify the behavior of an command. Cobra supports +fully posix compliant flags as well as the go flag package. +A Cobra command has can define flags that persist through to children commands +and flags that are only available to that command. In the example above 'port' is the flag. +Flag functionality is provided by the [pflag +libary](https://github.com/ogier/pflag), a fork of the flag standard library +which maintains the same interface while adding posix compliance. + ## Usage -### Implementing Cobra +Cobra works by creating a set of commands and then organizing them into a tree. +The tree defines the structure of the application. +Once each command is defined with it's corresponding flags, then the +tree is assigned to the commander which is finally executed. + +### Installing Using Cobra is easy. First use go get to install the latest version of the library. @@ -58,23 +76,81 @@ Next include cobra in your application. import "github.com/spf13/cobra" -Now you are ready to implement Cobra. +### Create the root command -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. +The root command represents your binary itself. -Once each command is defined with it's corresponding flags, then the -tree is assigned to the commander which is finally executed. +Cobra doesn't require any special constructors. Simply create your commands. -In the example below we have defined three commands. Two are at the top -level and one (cmdTimes) is a child of one of the top commands. + var HugoCmd = &cobra.Command{ + Use: "hugo", + Short: "Hugo is a very fast static site generator", + Long: `A Fast and Flexible Static Site Generator built with + love by spf13 and friends in Go. + Complete documentation is available at http://hugo.spf13.com`, + Run: func(cmd *cobra.Command, args []string) { + // Do Stuff Here + }, + } + +### Create additional commands + +Additional commands can be defined. + + var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the version number of Hugo", + Long: `All software has versions. This is Hugo's`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") + }, + } + +### Attach command to it's parent +In this example we are attaching it to the root, but commands can be attached at any level. + + HugoCmd.AddCommand(versionCmd) + +### Assign flags to a command + +Since the flags are defined and used in different locations, we need to define a variable outside with the correct scope to assign the flag to work with. + + var Verbose bool + var Source string + +There are two different approaches to assign a flag. + +#### Persistent Flags + +A flag can be 'persistent' meaning that this flag will be available to the +command it's assigned to as well as every command under that command. For +global flags assign a flag as a persistent flag on the root. + + HugoCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") + +#### Local Flags + +A flag can also be assigned locally which will only apply to that specific command. + + HugoCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") + +### Once all commands and flags are defined, Execute the commands + +Execute should be run on the root for clarity, though it can be called on any command. + + HugoCmd.Execute() + +## Example + +In the example below we have defined three commands. Two are at the top level +and one (cmdTimes) is a child of one of the top commands. In this case the root +is not executible meaning that a subcommand is required. This is accomplished +by not providing a 'Run' for the 'rootCmd'. We have only defined one flag for a single command. More documentation about flags is available at https://github.com/spf13/pflag -## Example - Import( "github.com/spf13/cobra" "fmt" @@ -119,17 +195,150 @@ More documentation about flags is available at https://github.com/spf13/pflag }, } - cmdTimes().Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - var commander = cobra.NewCommander() - commander.SetName("CobraExample") - commander.AddCommand(cmdPrint, cmdEcho) + var rootCmd = &cobra.Command{Use: "app"} + rootCmd.AddCommand(cmdPrint, cmdEcho) cmdEcho.AddCommand(cmdTimes) - commander.Execute() + rootCmd.Execute() } +For a more complete example of a larger application, please checkout [Hugo](http://hugo.spf13.com) + +## The Help Command + +Cobra automatically adds a help command to your application. +This will be called when a user runs 'app help'. Additionally help will also +support all other commands as input. Say for instance you have a command called +'create' without any additional configuration cobra will work when 'app help +create' is called. + +### Example + +The following output is automatically generated by cobra. Nothing beyond the +command and flag definitions are needed. + + > hugo help + + A Fast and Flexible Static Site Generator built with + love by spf13 and friends in Go. + + Complete documentation is available at http://hugo.spf13.com + + Usage: + hugo [flags] + hugo [command] + + Available Commands: + server :: Hugo runs it's own a webserver to render the files + version :: Print the version number of Hugo + check :: Check content in the source directory + benchmark :: Benchmark hugo by building a site a number of times + help [command] :: Help about any command + + Available Flags: + -b, --base-url="": hostname (and path) to the root eg. http://spf13.com/ + -D, --build-drafts=false: include content marked as draft + --config="": config file (default is path/config.yaml|json|toml) + -d, --destination="": filesystem path to write files to + -s, --source="": filesystem path to read files relative from + --stepAnalysis=false: display memory and timing of different steps of the program + --uglyurls=false: if true, use /filename.html instead of /filename/ + -v, --verbose=false: verbose output + -w, --watch=false: watch filesystem for changes and recreate as needed + + Use "hugo help [command]" for more information about that command. + + + +Help is just a command like any other. There is no special logic or behavior +around it. In fact you can provide your own if you want. + +### Defining your own help + +You can provide your own Help command or you own template for the default command to use. + +The default help command is + + func (c *Command) initHelp() { + if c.helpCommand == nil { + c.helpCommand = &Command{ + Use: "help [command]", + Short: "Help about any command", + Long: `Help provides help for any command in the application. + Simply type ` + c.Name() + ` help [path to command] for full details.`, + Run: c.HelpFunc(), + } + } + c.AddCommand(c.helpCommand) + } + +You can provide your own command, function or template through the following methods. + + command.SetHelpCommand(cmd *Command) + + command.SetHelpFunc(f func(*Command, []string)) + + command.SetHelpTemplate(s string) + +The latter two will also apply to any children commands. + + +## Usage + +When the user provides an invalid flag or invalid command Cobra responds by +showing the user the 'usage' + +### Example +You may recognize this from the help above. That's because the default help +embeds the usage as part of it's output. + + Usage: + hugo [flags] + hugo [command] + + Available Commands: + server :: Hugo runs it's own a webserver to render the files + version :: Print the version number of Hugo + check :: Check content in the source directory + benchmark :: Benchmark hugo by building a site a number of times + help [command] :: Help about any command + + Available Flags: + -b, --base-url="": hostname (and path) to the root eg. http://spf13.com/ + -D, --build-drafts=false: include content marked as draft + --config="": config file (default is path/config.yaml|json|toml) + -d, --destination="": filesystem path to write files to + -s, --source="": filesystem path to read files relative from + --stepAnalysis=false: display memory and timing of different steps of the program + --uglyurls=false: if true, use /filename.html instead of /filename/ + -v, --verbose=false: verbose output + -w, --watch=false: watch filesystem for changes and recreate as needed + +### Defining your own usage +You can provide your own usage function or template for cobra to use. + +The default usage function is + + return func(c *Command) error { + err := tmpl(c.Out(), c.UsageTemplate(), c) + return err + } + +Like help the function and template are over ridable through public methods. + + command.SetUsageFunc(f func(*Command) error) + + command.SetUsageTemplate(s string) + + ## Release Notes +* **0.8.0** Nov 5, 2013 + * Reworked interface to remove commander completely + * Command now primary structure + * No initialization needed + * Usage & Help templates & functions definable at any level + * Updated Readme * **0.7.0** Sept 24, 2013 * Needs more eyes * Test suite @@ -142,8 +351,6 @@ More documentation about flags is available at https://github.com/spf13/pflag * Implement first draft ## ToDo -* More testing of non-runnable -* More testing * Launch proper documentation site ## Contributing