Merge pull request #1421 from urfave/docs-cleanups
Clean up the v2 manual a bit
This commit is contained in:
commit
7d21dda232
@ -44,14 +44,13 @@ func main() {
|
||||
app := &cli.App{
|
||||
Name: "boom",
|
||||
Usage: "make an explosive entrance",
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(*cli.Context) error {
|
||||
fmt.Println("boom! I say!")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -87,14 +86,13 @@ func main() {
|
||||
app := &cli.App{
|
||||
Name: "greet",
|
||||
Usage: "fight the loneliness!",
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(*cli.Context) error {
|
||||
fmt.Println("Hello friend!")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -102,20 +100,20 @@ func main() {
|
||||
|
||||
Install our command to the `$GOPATH/bin` directory:
|
||||
|
||||
```
|
||||
```sh-session
|
||||
$ go install
|
||||
```
|
||||
|
||||
Finally run our new command:
|
||||
|
||||
```
|
||||
```sh-session
|
||||
$ greet
|
||||
Hello friend!
|
||||
```
|
||||
|
||||
cli also generates neat help text:
|
||||
|
||||
```
|
||||
```sh-session
|
||||
$ greet help
|
||||
NAME:
|
||||
greet - fight the loneliness!
|
||||
@ -150,14 +148,13 @@ import (
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Printf("Hello %q", c.Args().Get(0))
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Printf("Hello %q", cCtx.Args().Get(0))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -190,12 +187,12 @@ func main() {
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
name := "Nefertiti"
|
||||
if c.NArg() > 0 {
|
||||
name = c.Args().Get(0)
|
||||
if cCtx.NArg() > 0 {
|
||||
name = cCtx.Args().Get(0)
|
||||
}
|
||||
if c.String("lang") == "spanish" {
|
||||
if cCtx.String("lang") == "spanish" {
|
||||
fmt.Println("Hola", name)
|
||||
} else {
|
||||
fmt.Println("Hello", name)
|
||||
@ -204,8 +201,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -221,9 +217,9 @@ scanned.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"fmt"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@ -240,10 +236,10 @@ func main() {
|
||||
Destination: &language,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
name := "someone"
|
||||
if c.NArg() > 0 {
|
||||
name = c.Args().Get(0)
|
||||
if cCtx.NArg() > 0 {
|
||||
name = cCtx.Args().Get(0)
|
||||
}
|
||||
if language == "spanish" {
|
||||
fmt.Println("Hola", name)
|
||||
@ -254,8 +250,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -295,8 +290,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -342,8 +336,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -396,7 +389,7 @@ func main() {
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(*cli.Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -404,7 +397,7 @@ func main() {
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(*cli.Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -414,8 +407,7 @@ func main() {
|
||||
sort.Sort(cli.FlagsByName(app.Flags))
|
||||
sort.Sort(cli.CommandsByName(app.Commands))
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -459,8 +451,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -496,8 +487,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -522,19 +512,18 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Flags = []cli.Flag {
|
||||
app := &cli.App{
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "password for the mysql database",
|
||||
FilePath: "/etc/mysql/password",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -549,14 +538,16 @@ There is a separate package altsrc that adds support for getting flag values
|
||||
from other file input sources.
|
||||
|
||||
Currently supported input source formats:
|
||||
* YAML
|
||||
* JSON
|
||||
* TOML
|
||||
|
||||
YAML
|
||||
JSON
|
||||
TOML
|
||||
|
||||
In order to get values for a flag from an alternate input source the following
|
||||
code would be added to wrap an existing cli.Flag like below:
|
||||
|
||||
```go
|
||||
// --- >8 ---
|
||||
altsrc.NewIntFlag(&cli.IntFlag{Name: "test"})
|
||||
```
|
||||
|
||||
@ -564,6 +555,7 @@ Initialization must also occur for these flags. Below is an example initializing
|
||||
getting data from a yaml file below.
|
||||
|
||||
```go
|
||||
// --- >8 ---
|
||||
command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
|
||||
```
|
||||
|
||||
@ -573,9 +565,9 @@ the yaml input source for any flags that are defined on that command. As a note
|
||||
the "load" flag used would also have to be defined on the command flags in order
|
||||
for this code snippet to work.
|
||||
|
||||
Currently only YAML, JSON, and TOML files are supported but developers can add support
|
||||
for other input sources by implementing the altsrc.InputSourceContext for their
|
||||
given sources.
|
||||
Currently only YAML, JSON, and TOML files are supported but developers can add
|
||||
support for other input sources by implementing the altsrc.InputSourceContext
|
||||
for their given sources.
|
||||
|
||||
Here is a more complete sample of a command using YAML support:
|
||||
|
||||
@ -601,7 +593,7 @@ func main() {
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Action: func(c *cli.Context) error {
|
||||
Action: func(*cli.Context) error {
|
||||
fmt.Println("--test value.*default: 0")
|
||||
return nil
|
||||
},
|
||||
@ -635,30 +627,26 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Flags = []cli.Flag {
|
||||
app := &cli.App{
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "lang",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
|
||||
app.Action = func(c *cli.Context) error {
|
||||
var output string
|
||||
if c.String("lang") == "spanish" {
|
||||
},
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
output := "Hello"
|
||||
if cCtx.String("lang") == "spanish" {
|
||||
output = "Hola"
|
||||
} else {
|
||||
output = "Hello"
|
||||
}
|
||||
fmt.Println(output)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -672,7 +660,9 @@ Required flag "lang" not set
|
||||
|
||||
#### Default Values for help output
|
||||
|
||||
Sometimes it's useful to specify a flag's default help-text value within the flag declaration. This can be useful if the default value for a flag is a computed value. The default value can be set via the `DefaultText` struct field.
|
||||
Sometimes it's useful to specify a flag's default help-text value within the
|
||||
flag declaration. This can be useful if the default value for a flag is a
|
||||
computed value. The default value can be set via the `DefaultText` struct field.
|
||||
|
||||
For example this:
|
||||
|
||||
@ -702,8 +692,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -750,8 +739,8 @@ func main() {
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("added task: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("added task: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -759,8 +748,8 @@ func main() {
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("completed task: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("completed task: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -772,16 +761,16 @@ func main() {
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "add a new template",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("new task template: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("new task template: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: "remove an existing template",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("removed task template: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("removed task template: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -790,8 +779,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -801,9 +789,7 @@ func main() {
|
||||
|
||||
For additional organization in apps that have many subcommands, you can
|
||||
associate a category for each command to group them together in the help
|
||||
output.
|
||||
|
||||
E.g.
|
||||
output, e.g.:
|
||||
|
||||
```go
|
||||
package main
|
||||
@ -832,8 +818,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -885,8 +870,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -896,7 +880,7 @@ func main() {
|
||||
|
||||
Traditional use of options using their shortnames look like this:
|
||||
|
||||
```
|
||||
```sh-session
|
||||
$ cmd -s -o -m "Some message"
|
||||
```
|
||||
|
||||
@ -921,9 +905,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{}
|
||||
app.UseShortOptionHandling = true
|
||||
app.Commands = []*cli.Command{
|
||||
app := &cli.App{
|
||||
UseShortOptionHandling: true,
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "short",
|
||||
Usage: "complete a task on the list",
|
||||
@ -932,17 +916,17 @@ func main() {
|
||||
&cli.BoolFlag{Name: "option", Aliases: []string{"o"}},
|
||||
&cli.StringFlag{Name: "message", Aliases: []string{"m"}},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("serve:", c.Bool("serve"))
|
||||
fmt.Println("option:", c.Bool("option"))
|
||||
fmt.Println("message:", c.String("message"))
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("serve:", cCtx.Bool("serve"))
|
||||
fmt.Println("option:", cCtx.Bool("option"))
|
||||
fmt.Println("message:", cCtx.String("message"))
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -953,7 +937,7 @@ optionally one non-bool flag `message`, with the short options of `-s`, `-o`,
|
||||
and `-m` respectively, setting `UseShortOptionHandling` will also support the
|
||||
following syntax:
|
||||
|
||||
```
|
||||
```sh-session
|
||||
$ cmd -som "Some message"
|
||||
```
|
||||
|
||||
@ -964,31 +948,34 @@ have a single leading `-` or this will result in failures. For example,
|
||||
|
||||
### Bash Completion
|
||||
|
||||
You can enable completion commands by setting the `EnableBashCompletion`
|
||||
flag on the `App` object to `true`. By default, this setting will allow auto-completion
|
||||
for an app's subcommands, but you can write your own completion methods for
|
||||
the App or its subcommands as well.
|
||||
You can enable completion commands by setting the `EnableBashCompletion` flag on
|
||||
the `App` object to `true`. By default, this setting will allow auto-completion
|
||||
for an app's subcommands, but you can write your own completion methods for the
|
||||
App or its subcommands as well.
|
||||
|
||||
#### Default auto-completion
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.EnableBashCompletion = true
|
||||
app.Commands = []*cli.Command{
|
||||
app := &cli.App{
|
||||
EnableBashCompletion: true,
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("added task: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("added task: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -996,8 +983,8 @@ func main() {
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("completed task: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("completed task: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@ -1009,24 +996,25 @@ func main() {
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "add a new template",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("new task template: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("new task template: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: "remove an existing template",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("removed task template: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("removed task template: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -1059,13 +1047,13 @@ func main() {
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("completed task: ", c.Args().First())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Println("completed task: ", cCtx.Args().First())
|
||||
return nil
|
||||
},
|
||||
BashComplete: func(c *cli.Context) {
|
||||
BashComplete: func(cCtx *cli.Context) {
|
||||
// This will complete if no args are passed
|
||||
if c.NArg() > 0 {
|
||||
if cCtx.NArg() > 0 {
|
||||
return
|
||||
}
|
||||
for _, t := range tasks {
|
||||
@ -1076,8 +1064,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -1089,14 +1076,18 @@ func main() {
|
||||
To enable auto-completion for the current shell session, a bash script,
|
||||
`autocomplete/bash_autocomplete` is included in this repo.
|
||||
|
||||
To use `autocomplete/bash_autocomplete` set an environment variable named `PROG` to
|
||||
the name of your program and then `source` the `autocomplete/bash_autocomplete` file.
|
||||
To use `autocomplete/bash_autocomplete` set an environment variable named `PROG`
|
||||
to the name of your program and then `source` the
|
||||
`autocomplete/bash_autocomplete` file.
|
||||
|
||||
For example, if your cli program is called `myprogram`:
|
||||
|
||||
`PROG=myprogram source path/to/cli/autocomplete/bash_autocomplete`
|
||||
```sh-session
|
||||
$ PROG=myprogram source path/to/cli/autocomplete/bash_autocomplete
|
||||
```
|
||||
|
||||
Auto-completion is now enabled for the current shell, but will not persist into a new shell.
|
||||
Auto-completion is now enabled for the current shell, but will not persist into
|
||||
a new shell.
|
||||
|
||||
#### Distribution and Persistent Autocompletion
|
||||
|
||||
@ -1105,28 +1096,30 @@ it to the name of the program you wish to add autocomplete support for (or
|
||||
automatically install it there if you are distributing a package). Don't forget
|
||||
to source the file or restart your shell to activate the auto-completion.
|
||||
|
||||
```
|
||||
sudo cp path/to/autocomplete/bash_autocomplete /etc/bash_completion.d/<myprogram>
|
||||
source /etc/bash_completion.d/<myprogram>
|
||||
```sh-session
|
||||
$ sudo cp path/to/autocomplete/bash_autocomplete /etc/bash_completion.d/<myprogram>
|
||||
$ source /etc/bash_completion.d/<myprogram>
|
||||
```
|
||||
|
||||
Alternatively, you can just document that users should `source` the generic
|
||||
`autocomplete/bash_autocomplete` and set `$PROG` within their bash configuration
|
||||
file, adding these lines:
|
||||
|
||||
```sh-session
|
||||
$ PROG=<myprogram>
|
||||
$ source path/to/cli/autocomplete/bash_autocomplete
|
||||
```
|
||||
PROG=<myprogram>
|
||||
source path/to/cli/autocomplete/bash_autocomplete
|
||||
```
|
||||
Keep in mind that if they are enabling auto-completion for more than one program,
|
||||
they will need to set `PROG` and source `autocomplete/bash_autocomplete` for each
|
||||
program, like so:
|
||||
|
||||
```
|
||||
PROG=<program1>
|
||||
source path/to/cli/autocomplete/bash_autocomplete
|
||||
PROG=<program2>
|
||||
source path/to/cli/autocomplete/bash_autocomplete
|
||||
Keep in mind that if they are enabling auto-completion for more than one
|
||||
program, they will need to set `PROG` and source
|
||||
`autocomplete/bash_autocomplete` for each program, like so:
|
||||
|
||||
```sh-session
|
||||
$ PROG=<program1>
|
||||
$ source path/to/cli/autocomplete/bash_autocomplete
|
||||
|
||||
$ PROG=<program2>
|
||||
$ source path/to/cli/autocomplete/bash_autocomplete
|
||||
```
|
||||
|
||||
#### Customization
|
||||
@ -1157,45 +1150,54 @@ func main() {
|
||||
},
|
||||
},
|
||||
}
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### ZSH Support
|
||||
Auto-completion for ZSH is also supported using the `autocomplete/zsh_autocomplete`
|
||||
file included in this repo. One environment variable is used, `PROG`. Set
|
||||
`PROG` to the program name as before, and then `source path/to/autocomplete/zsh_autocomplete`.
|
||||
Adding the following lines to your ZSH configuration file (usually `.zshrc`)
|
||||
will allow the auto-completion to persist across new shells:
|
||||
|
||||
Auto-completion for ZSH is also supported using the
|
||||
`autocomplete/zsh_autocomplete` file included in this repo. One environment
|
||||
variable is used, `PROG`. Set `PROG` to the program name as before, and then
|
||||
`source path/to/autocomplete/zsh_autocomplete`. Adding the following lines to
|
||||
your ZSH configuration file (usually `.zshrc`) will allow the auto-completion to
|
||||
persist across new shells:
|
||||
|
||||
```sh-session
|
||||
$ PROG=<myprogram>
|
||||
$ source path/to/autocomplete/zsh_autocomplete
|
||||
```
|
||||
PROG=<myprogram>
|
||||
source path/to/autocomplete/zsh_autocomplete
|
||||
```
|
||||
|
||||
#### ZSH default auto-complete example
|
||||
![](/docs/v2/images/default-zsh-autocomplete.gif)
|
||||
|
||||
#### ZSH custom auto-complete example
|
||||
![](/docs/v2/images/custom-zsh-autocomplete.gif)
|
||||
|
||||
#### PowerShell Support
|
||||
Auto-completion for PowerShell is also supported using the `autocomplete/powershell_autocomplete.ps1`
|
||||
file included in this repo.
|
||||
|
||||
Rename the script to `<my program>.ps1` and move it anywhere in your file system.
|
||||
The location of script does not matter, only the file name of the script has to match
|
||||
the your program's binary name.
|
||||
Auto-completion for PowerShell is also supported using the
|
||||
`autocomplete/powershell_autocomplete.ps1` file included in this repo.
|
||||
|
||||
To activate it, enter `& path/to/autocomplete/<my program>.ps1`
|
||||
Rename the script to `<my program>.ps1` and move it anywhere in your file
|
||||
system. The location of script does not matter, only the file name of the
|
||||
script has to match the your program's binary name.
|
||||
|
||||
To persist across new shells, open the PowerShell profile (with `code $profile` or `notepad $profile`)
|
||||
and add the line:
|
||||
```
|
||||
To activate it, enter:
|
||||
|
||||
```powershell
|
||||
& path/to/autocomplete/<my program>.ps1
|
||||
```
|
||||
|
||||
To persist across new shells, open the PowerShell profile (with `code $profile`
|
||||
or `notepad $profile`) and add the line:
|
||||
|
||||
```powershell
|
||||
& path/to/autocomplete/<my program>.ps1
|
||||
```
|
||||
|
||||
### Generated Help Text
|
||||
|
||||
@ -1333,7 +1335,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.:
|
||||
Alternatively, the version printer at `cli.VersionPrinter` may be overridden,
|
||||
e.g.:
|
||||
|
||||
<!-- {
|
||||
"args": ["--version"],
|
||||
@ -1354,8 +1357,8 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
|
||||
cli.VersionPrinter = func(cCtx *cli.Context) {
|
||||
fmt.Printf("version=%s revision=%s\n", cCtx.App.Version, Revision)
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
@ -1368,7 +1371,9 @@ func main() {
|
||||
|
||||
### Timestamp Flag
|
||||
|
||||
Using the timestamp flag is simple. Please refer to [`time.Parse`](https://golang.org/pkg/time/#example_Parse) to get possible formats.
|
||||
Using the timestamp flag is simple. Please refer to
|
||||
[`time.Parse`](https://golang.org/pkg/time/#example_Parse) to get possible
|
||||
formats.
|
||||
|
||||
<!-- {
|
||||
"args": ["--meeting", "2019-08-12T15:04:05"],
|
||||
@ -1390,14 +1395,13 @@ func main() {
|
||||
Flags: []cli.Flag{
|
||||
&cli.TimestampFlag{Name: "meeting", Layout: "2006-01-02T15:04:05"},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Printf("%s", c.Timestamp("meeting").String())
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
fmt.Printf("%s", cCtx.Timestamp("meeting").String())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -1405,9 +1409,12 @@ func main() {
|
||||
|
||||
In this example the flag could be used like this:
|
||||
|
||||
`myapp --meeting 2019-08-12T15:04:05`
|
||||
```sh-session
|
||||
$ myapp --meeting 2019-08-12T15:04:05
|
||||
```
|
||||
|
||||
Side note: quotes may be necessary around the date depending on your layout (if you have spaces for instance)
|
||||
Side note: quotes may be necessary around the date depending on your layout (if
|
||||
you have spaces for instance)
|
||||
|
||||
### Suggestions
|
||||
|
||||
@ -1450,11 +1457,11 @@ func init() {
|
||||
cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
|
||||
fmt.Fprintf(w, "best of luck to you\n")
|
||||
}
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version)
|
||||
cli.VersionPrinter = func(cCtx *cli.Context) {
|
||||
fmt.Fprintf(cCtx.App.Writer, "version=%s\n", cCtx.App.Version)
|
||||
}
|
||||
cli.OsExiter = func(c int) {
|
||||
fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c)
|
||||
cli.OsExiter = func(cCtx int) {
|
||||
fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", cCtx)
|
||||
}
|
||||
cli.ErrWriter = ioutil.Discard
|
||||
cli.FlagStringer = func(fl cli.Flag) string {
|
||||
@ -1524,30 +1531,30 @@ func main() {
|
||||
HideHelp: false,
|
||||
Hidden: false,
|
||||
HelpName: "doo!",
|
||||
BashComplete: func(c *cli.Context) {
|
||||
fmt.Fprintf(c.App.Writer, "--better\n")
|
||||
BashComplete: func(cCtx *cli.Context) {
|
||||
fmt.Fprintf(cCtx.App.Writer, "--better\n")
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
fmt.Fprintf(c.App.Writer, "brace for impact\n")
|
||||
Before: func(cCtx *cli.Context) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, "brace for impact\n")
|
||||
return nil
|
||||
},
|
||||
After: func(c *cli.Context) error {
|
||||
fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
|
||||
After: func(cCtx *cli.Context) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, "did we lose anyone?\n")
|
||||
return nil
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
c.Command.FullName()
|
||||
c.Command.HasName("wop")
|
||||
c.Command.Names()
|
||||
c.Command.VisibleFlags()
|
||||
fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
|
||||
if c.Bool("forever") {
|
||||
c.Command.Run(c)
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
cCtx.Command.FullName()
|
||||
cCtx.Command.HasName("wop")
|
||||
cCtx.Command.Names()
|
||||
cCtx.Command.VisibleFlags()
|
||||
fmt.Fprintf(cCtx.App.Writer, "dodododododoodododddooooododododooo\n")
|
||||
if cCtx.Bool("forever") {
|
||||
cCtx.Command.Run(cCtx)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
|
||||
fmt.Fprintf(c.App.Writer, "for shame\n")
|
||||
OnUsageError: func(cCtx *cli.Context, err error, isSubcommand bool) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, "for shame\n")
|
||||
return err
|
||||
},
|
||||
},
|
||||
@ -1570,60 +1577,60 @@ func main() {
|
||||
EnableBashCompletion: true,
|
||||
HideHelp: false,
|
||||
HideVersion: false,
|
||||
BashComplete: func(c *cli.Context) {
|
||||
fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
|
||||
BashComplete: func(cCtx *cli.Context) {
|
||||
fmt.Fprintf(cCtx.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
|
||||
Before: func(cCtx *cli.Context) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, "HEEEERE GOES\n")
|
||||
return nil
|
||||
},
|
||||
After: func(c *cli.Context) error {
|
||||
fmt.Fprintf(c.App.Writer, "Phew!\n")
|
||||
After: func(cCtx *cli.Context) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, "Phew!\n")
|
||||
return nil
|
||||
},
|
||||
CommandNotFound: func(c *cli.Context, command string) {
|
||||
fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
|
||||
CommandNotFound: func(cCtx *cli.Context, command string) {
|
||||
fmt.Fprintf(cCtx.App.Writer, "Thar be no %q here.\n", command)
|
||||
},
|
||||
OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
|
||||
OnUsageError: func(cCtx *cli.Context, err error, isSubcommand bool) error {
|
||||
if isSubcommand {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
|
||||
fmt.Fprintf(cCtx.App.Writer, "WRONG: %#v\n", err)
|
||||
return nil
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
cli.DefaultAppComplete(c)
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
cli.DefaultAppComplete(cCtx)
|
||||
cli.HandleExitCoder(errors.New("not an exit coder, though"))
|
||||
cli.ShowAppHelp(c)
|
||||
cli.ShowCommandCompletions(c, "nope")
|
||||
cli.ShowCommandHelp(c, "also-nope")
|
||||
cli.ShowCompletions(c)
|
||||
cli.ShowSubcommandHelp(c)
|
||||
cli.ShowVersion(c)
|
||||
cli.ShowAppHelp(cCtx)
|
||||
cli.ShowCommandCompletions(cCtx, "nope")
|
||||
cli.ShowCommandHelp(cCtx, "also-nope")
|
||||
cli.ShowCompletions(cCtx)
|
||||
cli.ShowSubcommandHelp(cCtx)
|
||||
cli.ShowVersion(cCtx)
|
||||
|
||||
fmt.Printf("%#v\n", c.App.Command("doo"))
|
||||
if c.Bool("infinite") {
|
||||
c.App.Run([]string{"app", "doo", "wop"})
|
||||
fmt.Printf("%#v\n", cCtx.App.Command("doo"))
|
||||
if cCtx.Bool("infinite") {
|
||||
cCtx.App.Run([]string{"app", "doo", "wop"})
|
||||
}
|
||||
|
||||
if c.Bool("forevar") {
|
||||
c.App.RunAsSubcommand(c)
|
||||
if cCtx.Bool("forevar") {
|
||||
cCtx.App.RunAsSubcommand(cCtx)
|
||||
}
|
||||
c.App.Setup()
|
||||
fmt.Printf("%#v\n", c.App.VisibleCategories())
|
||||
fmt.Printf("%#v\n", c.App.VisibleCommands())
|
||||
fmt.Printf("%#v\n", c.App.VisibleFlags())
|
||||
cCtx.App.Setup()
|
||||
fmt.Printf("%#v\n", cCtx.App.VisibleCategories())
|
||||
fmt.Printf("%#v\n", cCtx.App.VisibleCommands())
|
||||
fmt.Printf("%#v\n", cCtx.App.VisibleFlags())
|
||||
|
||||
fmt.Printf("%#v\n", c.Args().First())
|
||||
if c.Args().Len() > 0 {
|
||||
fmt.Printf("%#v\n", c.Args().Get(1))
|
||||
fmt.Printf("%#v\n", cCtx.Args().First())
|
||||
if cCtx.Args().Len() > 0 {
|
||||
fmt.Printf("%#v\n", cCtx.Args().Get(1))
|
||||
}
|
||||
fmt.Printf("%#v\n", c.Args().Present())
|
||||
fmt.Printf("%#v\n", c.Args().Tail())
|
||||
fmt.Printf("%#v\n", cCtx.Args().Present())
|
||||
fmt.Printf("%#v\n", cCtx.Args().Tail())
|
||||
|
||||
set := flag.NewFlagSet("contrive", 0)
|
||||
nc := cli.NewContext(c.App, set, c)
|
||||
nc := cli.NewContext(cCtx.App, set, cCtx)
|
||||
|
||||
fmt.Printf("%#v\n", nc.Args())
|
||||
fmt.Printf("%#v\n", nc.Bool("nope"))
|
||||
@ -1649,7 +1656,7 @@ func main() {
|
||||
nc.Set("wat", "also-nope")
|
||||
|
||||
ec := cli.Exit("ohwell", 86)
|
||||
fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
|
||||
fmt.Fprintf(cCtx.App.Writer, "%d", ec.ExitCode())
|
||||
fmt.Printf("made it!\n")
|
||||
return ec
|
||||
},
|
||||
@ -1668,16 +1675,16 @@ func main() {
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
||||
func wopAction(c *cli.Context) error {
|
||||
fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n")
|
||||
func wopAction(cCtx *cli.Context) error {
|
||||
fmt.Fprintf(cCtx.App.Writer, ":wave: over here, eh\n")
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Migrating From Older Releases
|
||||
|
||||
There are a small set of breaking changes between v1 and v2.
|
||||
Converting is relatively straightforward and typically takes less than
|
||||
an hour. Specific steps are included in
|
||||
[Migration Guide: v1 to v2](../migrate-v1-to-v2.md). Also see the [pkg.go.dev docs](https://pkg.go.dev/github.com/urfave/cli/v2) for v2 API documentation.
|
||||
|
||||
There are a small set of breaking changes between v1 and v2. Converting is
|
||||
relatively straightforward and typically takes less than an hour. Specific steps
|
||||
are included in [Migration Guide: v1 to v2](../migrate-v1-to-v2.md). Also see
|
||||
the [pkg.go.dev docs](https://pkg.go.dev/github.com/urfave/cli/v2) for v2 API
|
||||
documentation.
|
||||
|
Loading…
Reference in New Issue
Block a user