Merge branch 'master' into backport-json-support

This commit is contained in:
2018-02-25 16:09:48 -05:00
committed by GitHub
23 changed files with 1094 additions and 349 deletions

227
README.md
View File

@@ -9,9 +9,9 @@ cli
[![top level coverage](https://gocover.io/_badge/github.com/urfave/cli?0 "top level coverage")](http://gocover.io/github.com/urfave/cli) /
[![altsrc coverage](https://gocover.io/_badge/github.com/urfave/cli/altsrc?0 "altsrc coverage")](http://gocover.io/github.com/urfave/cli/altsrc)
**Notice:** This is the library formerly known as
`github.com/codegangsta/cli` -- Github will automatically redirect requests
to this repository, but we recommend updating your references for clarity.
This is the library formerly known as `github.com/codegangsta/cli` -- Github
will automatically redirect requests to this repository, but we recommend
updating your references for clarity.
cli is a simple, fast, and fun package for building command line apps in Go. The
goal is to enable developers to write fast and distributable command line
@@ -32,7 +32,9 @@ applications in an expressive way.
+ [Alternate Names](#alternate-names)
+ [Ordering](#ordering)
+ [Values from the Environment](#values-from-the-environment)
+ [Values from files](#values-from-files)
+ [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
+ [Precedence](#precedence)
* [Subcommands](#subcommands)
* [Subcommands categories](#subcommands-categories)
* [Exit code](#exit-code)
@@ -45,6 +47,7 @@ applications in an expressive way.
* [Version Flag](#version-flag)
+ [Customization](#customization-2)
+ [Full API Example](#full-api-example)
* [Combining short Bool options](#combining-short-bool-options)
- [Contribution Guidelines](#contribution-guidelines)
<!-- tocstop -->
@@ -138,13 +141,17 @@ discovery. So a cli app can be as little as one line of code in `main()`.
package main
import (
"log"
"os"
"github.com/urfave/cli"
)
func main() {
cli.NewApp().Run(os.Args)
err := cli.NewApp().Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -159,6 +166,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -173,7 +181,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -197,6 +208,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -211,7 +223,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -260,6 +275,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -273,7 +289,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -289,6 +308,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -318,7 +338,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -332,6 +355,7 @@ scanned.
package main
import (
"log"
"os"
"fmt"
@@ -365,7 +389,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -386,6 +413,7 @@ For example this:
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -401,7 +429,10 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -427,6 +458,7 @@ list for the `Name`. e.g.
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -443,7 +475,10 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -467,6 +502,7 @@ For example this:
package main
import (
"log"
"os"
"sort"
@@ -510,7 +546,10 @@ func main() {
sort.Sort(cli.FlagsByName(app.Flags))
sort.Sort(cli.CommandsByName(app.Commands))
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -533,6 +572,7 @@ You can also have the default value set from the environment via `EnvVar`. e.g.
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -550,7 +590,10 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -565,6 +608,7 @@ environment variable that resolves is used as the default.
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -582,10 +626,52 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
#### Values from files
You can also have the default value set from file via `FilePath`. e.g.
<!-- {
"args": ["&#45;&#45;help"],
"output": "password for the mysql database"
} -->
``` go
package main
import (
"log"
"os"
"github.com/urfave/cli"
)
func main() {
app := cli.NewApp()
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "password, p",
Usage: "password for the mysql database",
FilePath: "/etc/mysql/password",
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
Note that default values set from file (e.g. `FilePath`) take precedence over
default values set from the enviornment (e.g. `EnvVar`).
#### Values from alternate input sources (YAML, TOML, and others)
There is a separate package altsrc that adds support for getting flag values
@@ -630,6 +716,7 @@ package notmain
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -652,10 +739,22 @@ func main() {
app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
app.Flags = flags
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
#### Precedence
The precedence for flag value sources is as follows (highest to lowest):
0. Command line flag value from user
0. Environment variable (if specified)
0. Configuration file (if specified)
0. Default defined on the flag
### Subcommands
Subcommands can be defined for a more git-like command line app.
@@ -669,6 +768,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -721,7 +821,10 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -737,6 +840,7 @@ E.g.
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -751,15 +855,18 @@ func main() {
},
{
Name: "add",
Category: "template",
Category: "Template actions",
},
{
Name: "remove",
Category: "template",
Category: "Template actions",
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -785,6 +892,7 @@ may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -805,7 +913,10 @@ func main() {
return nil
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -825,6 +936,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -856,7 +968,10 @@ func main() {
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -896,6 +1011,7 @@ The default bash completion flag (`--generate-bash-completion`) is defined as
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -914,7 +1030,10 @@ func main() {
Name: "wat",
},
}
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -940,6 +1059,7 @@ package main
import (
"fmt"
"log"
"io"
"os"
@@ -983,7 +1103,10 @@ VERSION:
fmt.Println("Ha HA. I pwnd the help!!1")
}
cli.NewApp().Run(os.Args)
err := cli.NewApp().Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -998,6 +1121,7 @@ setting `cli.HelpFlag`, e.g.:
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -1010,7 +1134,10 @@ func main() {
EnvVar: "SHOW_HALP,HALPPLZ",
}
cli.NewApp().Run(os.Args)
err := cli.NewApp().Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -1033,6 +1160,7 @@ setting `cli.VersionFlag`, e.g.:
package main
import (
"log"
"os"
"github.com/urfave/cli"
@@ -1047,7 +1175,10 @@ func main() {
app := cli.NewApp()
app.Name = "partay"
app.Version = "19.99.0"
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -1062,6 +1193,7 @@ package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
@@ -1079,7 +1211,10 @@ func main() {
app := cli.NewApp()
app.Name = "partay"
app.Version = "19.99.0"
app.Run(os.Args)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
```
@@ -1341,7 +1476,7 @@ func main() {
ec := cli.NewExitError("ohwell", 86)
fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
fmt.Printf("made it!\n")
return ec
return nil
}
if os.Getenv("HEXY") != "" {
@@ -1355,7 +1490,9 @@ func main() {
"whatever-values": 19.99,
}
app.Run(os.Args)
// ignore error so we don't exit non-zero and break gfmrun README example tests
_ = app.Run(os.Args)
}
func wopAction(c *cli.Context) error {
@@ -1364,18 +1501,26 @@ func wopAction(c *cli.Context) error {
}
```
### Combining short Bool options
Traditional use of boolean options using their shortnames look like this:
```
# cmd foobar -s -o
```
Suppose you want users to be able to combine your bool options with their shortname. This
can be done using the **UseShortOptionHandling** bool in your commands. Suppose your program
has a two bool flags such as *serve* and *option* with the short options of *-o* and
*-s* respectively. With **UseShortOptionHandling** set to *true*, a user can use a syntax
like:
```
# cmd foobar -so
```
If you enable the **UseShortOptionHandling*, then you must not use any flags that have a single
leading *-* or this will result in failures. For example, **-option** can no longer be used. Flags
with two leading dashes (such as **--options**) are still valid.
## Contribution Guidelines
Feel free to put up a pull request to fix a bug or maybe add a feature. I will
give it a code review and make sure that it does not break backwards
compatibility. If I or any other collaborators agree that it is in line with
the vision of the project, we will work with you to get the code into
a mergeable state and merge it into the master branch.
If you have contributed something significant to the project, we will most
likely add you as a collaborator. As a collaborator you are given the ability
to merge others pull requests. It is very important that new code does not
break existing code, so be careful about what code you do choose to merge.
If you feel like you have contributed to the project but have not yet been
added as a collaborator, we probably forgot to add you, please open an issue.
See [./CONTRIBUTING.md](./CONTRIBUTING.md)