Merge remote-tracking branch 'origin/main' into michaeljs1990-add-flag-category-support
This commit is contained in:
commit
a78717f4f9
38
.github/workflows/cli.yml
vendored
38
.github/workflows/cli.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
- name: vet
|
||||
run: go run internal/build/build.go vet
|
||||
|
||||
- name: test with tags
|
||||
- name: test with urfave_cli_no_docs tag
|
||||
run: go run internal/build/build.go -tags urfave_cli_no_docs test
|
||||
|
||||
- name: test
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
run: go run internal/build/build.go check-binary-size
|
||||
|
||||
- name: check-binary-size with tags (informational only)
|
||||
run: go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size || true
|
||||
run: go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
if: success() && matrix.go == '1.18.x' && matrix.os == 'ubuntu-latest'
|
||||
@ -76,19 +76,37 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies
|
||||
run:
|
||||
mkdir -p "${GITHUB_WORKSPACE}/.local/bin" &&
|
||||
curl -fsSL -o "${GITHUB_WORKSPACE}/.local/bin/gfmrun" "https://github.com/urfave/gfmrun/releases/download/v1.3.0/gfmrun-$(go env GOOS)-$(go env GOARCH)-v1.3.0" &&
|
||||
chmod +x "${GITHUB_WORKSPACE}/.local/bin/gfmrun" &&
|
||||
npm install -g markdown-toc@1.2.0
|
||||
run: |
|
||||
mkdir -p "${GITHUB_WORKSPACE}/.local/bin"
|
||||
curl -fsSL -o "${GITHUB_WORKSPACE}/.local/bin/gfmrun" "https://github.com/urfave/gfmrun/releases/download/v1.3.0/gfmrun-$(go env GOOS)-$(go env GOARCH)-v1.3.0"
|
||||
chmod +x "${GITHUB_WORKSPACE}/.local/bin/gfmrun"
|
||||
|
||||
- name: gfmrun
|
||||
run: go run internal/build/build.go gfmrun docs/v2/manual.md
|
||||
|
||||
- name: toc
|
||||
run: go run internal/build/build.go toc docs/v2/manual.md
|
||||
|
||||
- name: diff check
|
||||
run: |
|
||||
git diff --exit-code
|
||||
git diff --cached --exit-code
|
||||
|
||||
publish:
|
||||
if: startswith(github.ref, 'refs/tags/')
|
||||
name: publish
|
||||
needs: [test-docs]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup mkdocs
|
||||
run: |
|
||||
pip install -U pip
|
||||
pip install -r mkdocs-requirements.txt
|
||||
git remote rm origin
|
||||
git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/urfave/cli.git
|
||||
|
||||
- name: Publish Docs
|
||||
run: |
|
||||
mkdocs gh-deploy --force
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,10 +1,10 @@
|
||||
*.coverprofile
|
||||
*.orig
|
||||
node_modules/
|
||||
vendor
|
||||
.idea
|
||||
internal/*/built-example
|
||||
coverage.txt
|
||||
/.local/
|
||||
/site/
|
||||
|
||||
*.exe
|
||||
|
16
Makefile
16
Makefile
@ -5,7 +5,7 @@
|
||||
# attention on files that are primarily Go.
|
||||
|
||||
.PHONY: all
|
||||
all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun toc v2diff
|
||||
all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun v2diff
|
||||
|
||||
# NOTE: this is a special catch-all rule to run any of the commands
|
||||
# defined in internal/build/build.go with optional arguments passed
|
||||
@ -27,6 +27,14 @@ tag-check-binary-size:
|
||||
gfmrun:
|
||||
go run internal/build/build.go gfmrun docs/v2/manual.md
|
||||
|
||||
.PHONY: toc
|
||||
toc:
|
||||
go run internal/build/build.go toc docs/v2/manual.md
|
||||
.PHONY: docs
|
||||
docs:
|
||||
mkdocs build
|
||||
|
||||
.PHONY: docs-deps
|
||||
docs-deps:
|
||||
pip install -r mkdocs-requirements.txt
|
||||
|
||||
.PHONY: serve-docs
|
||||
serve-docs:
|
||||
mkdocs serve
|
||||
|
@ -63,7 +63,7 @@ You can use the following build tags:
|
||||
|
||||
When set, this removes `ToMarkdown` and `ToMan` methods, so your application
|
||||
won't be able to call those. This reduces the resulting binary size by about
|
||||
300-400 KB (measured using Go 1.18.1 on Linux/amd64), due to less dependencies.
|
||||
300-400 KB (measured using Go 1.18.1 on Linux/amd64), due to fewer dependencies.
|
||||
|
||||
### GOPATH
|
||||
|
||||
|
12
app.go
12
app.go
@ -96,6 +96,8 @@ type App struct {
|
||||
// single-character bool arguments into one
|
||||
// i.e. foobar -o -v -> foobar -ov
|
||||
UseShortOptionHandling bool
|
||||
// Enable suggestions for commands and flags
|
||||
Suggest bool
|
||||
|
||||
didSetup bool
|
||||
}
|
||||
@ -275,6 +277,11 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||
if a.Suggest {
|
||||
if suggestion, err := a.suggestFlagFromError(err, ""); err == nil {
|
||||
fmt.Fprintf(a.Writer, suggestion)
|
||||
}
|
||||
}
|
||||
_ = ShowAppHelp(cCtx)
|
||||
return err
|
||||
}
|
||||
@ -394,6 +401,11 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||
if a.Suggest {
|
||||
if suggestion, err := a.suggestFlagFromError(err, cCtx.Command.Name); err == nil {
|
||||
fmt.Fprintf(a.Writer, suggestion)
|
||||
}
|
||||
}
|
||||
_ = ShowSubcommandHelp(cCtx)
|
||||
return err
|
||||
}
|
||||
|
@ -120,6 +120,11 @@ func (c *Command) Run(ctx *Context) (err error) {
|
||||
}
|
||||
_, _ = fmt.Fprintln(cCtx.App.Writer, "Incorrect Usage:", err.Error())
|
||||
_, _ = fmt.Fprintln(cCtx.App.Writer)
|
||||
if ctx.App.Suggest {
|
||||
if suggestion, err := ctx.App.suggestFlagFromError(err, c.Name); err == nil {
|
||||
fmt.Fprintf(cCtx.App.Writer, suggestion)
|
||||
}
|
||||
}
|
||||
_ = ShowCommandHelp(cCtx, c.Name)
|
||||
return err
|
||||
}
|
||||
@ -250,6 +255,7 @@ func (c *Command) startApp(ctx *Context) error {
|
||||
app.ErrWriter = ctx.App.ErrWriter
|
||||
app.ExitErrHandler = ctx.App.ExitErrHandler
|
||||
app.UseShortOptionHandling = ctx.App.UseShortOptionHandling
|
||||
app.Suggest = ctx.App.Suggest
|
||||
|
||||
app.categories = newCommandCategories()
|
||||
for _, command := range c.Subcommands {
|
||||
|
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
@ -0,0 +1 @@
|
||||
cli.urfave.org
|
1
docs/CODE_OF_CONDUCT.md
Symbolic link
1
docs/CODE_OF_CONDUCT.md
Symbolic link
@ -0,0 +1 @@
|
||||
../CODE_OF_CONDUCT.md
|
@ -98,6 +98,28 @@ line help system which may be consulted for further information, e.g.:
|
||||
go run internal/genflags/cmd/genflags/main.go --help
|
||||
```
|
||||
|
||||
#### docs output
|
||||
|
||||
The documentation in the `docs` directory is automatically built via `mkdocs` into a
|
||||
static site and published when releases are pushed (see [RELEASING](./RELEASING/)). There
|
||||
is no strict requirement to build the documentation when developing locally, but the
|
||||
following `make` targets may be used if desired:
|
||||
|
||||
```sh
|
||||
# install documentation dependencies with `pip`
|
||||
make docs-deps
|
||||
```
|
||||
|
||||
```sh
|
||||
# build the static site in `./site`
|
||||
make docs
|
||||
```
|
||||
|
||||
```sh
|
||||
# start an mkdocs development server
|
||||
make serve-docs
|
||||
```
|
||||
|
||||
### pull requests
|
||||
|
||||
Please feel free to open a pull request to fix a bug or add a feature. The @urfave/cli
|
||||
|
21
docs/index.md
Normal file
21
docs/index.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Welcome to urfave/cli
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://pkg.go.dev/github.com/urfave/cli/v2)
|
||||
[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli)
|
||||
[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli)
|
||||
[![codecov](https://codecov.io/gh/urfave/cli/branch/main/graph/badge.svg)](https://codecov.io/gh/urfave/cli)
|
||||
|
||||
`urfave/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 applications in
|
||||
an expressive way.
|
||||
|
||||
These are the guides for each major supported version:
|
||||
|
||||
- [`v2`](./v2/)
|
||||
- [`v1`](./v1/)
|
||||
|
||||
In addition to the version-specific guides, these other documents are available:
|
||||
|
||||
- [CONTRIBUTING](./CONTRIBUTING/)
|
||||
- [CODE OF CONDUCT](./CODE_OF_CONDUCT/)
|
||||
- [RELEASING](./RELEASING/)
|
@ -1,6 +1,4 @@
|
||||
Migration Guide: v1 to v2
|
||||
===
|
||||
|
||||
# Migration Guide: v1 to v2
|
||||
|
||||
v2 has a number of breaking changes but converting is relatively
|
||||
straightforward: make the changes documented below then resolve any
|
||||
@ -11,25 +9,6 @@ If you find any issues not covered by this document, please post a
|
||||
comment on [Issue 921](https://github.com/urfave/cli/issues/921) or
|
||||
consider sending a PR to help improve this guide.
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
* [Flags before args](#flags-before-args)
|
||||
* [Import string changed](#import-string-changed)
|
||||
* [Flag aliases are done differently](#flag-aliases-are-done-differently)
|
||||
* [EnvVar is now a list (EnvVars)](#envvar-is-now-a-list-envvars)
|
||||
* [Actions returns errors](#actions-returns-errors)
|
||||
* [cli.Flag changed](#cliflag-changed)
|
||||
* [Commands are now lists of pointers](#commands-are-now-lists-of-pointers)
|
||||
* [Lists of commands should be pointers](#lists-of-commands-should-be-pointers)
|
||||
* [Appending Commands](#appending-commands)
|
||||
* [GlobalString, GlobalBool and its likes are deprecated](#globalstring-globalbool-and-its-likes-are-deprecated)
|
||||
* [BoolTFlag and BoolT are deprecated](#booltflag-and-boolt-are-deprecated)
|
||||
* [&cli.StringSlice{""} replaced with cli.NewStringSlice("")](#clistringslice-replaced-with-clinewstringslice)
|
||||
* [Replace deprecated functions](#replace-deprecated-functions)
|
||||
* [Everything else](#everything-else)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
# Flags before args
|
||||
|
||||
In v2 flags must come before args. This is more POSIX-compliant. You
|
||||
|
1
docs/v1/index.md
Symbolic link
1
docs/v1/index.md
Symbolic link
@ -0,0 +1 @@
|
||||
manual.md
|
@ -1,35 +1,4 @@
|
||||
cli v1 manual
|
||||
===
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Getting Started](#getting-started)
|
||||
- [Examples](#examples)
|
||||
* [Arguments](#arguments)
|
||||
* [Flags](#flags)
|
||||
+ [Placeholder Values](#placeholder-values)
|
||||
+ [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)
|
||||
* [Combining short options](#combining-short-options)
|
||||
* [Bash Completion](#bash-completion)
|
||||
+ [Enabling](#enabling)
|
||||
+ [Distribution](#distribution)
|
||||
+ [Customization](#customization)
|
||||
* [Generated Help Text](#generated-help-text)
|
||||
+ [Customization](#customization-1)
|
||||
* [Version Flag](#version-flag)
|
||||
+ [Customization](#customization-2)
|
||||
+ [Full API Example](#full-api-example)
|
||||
* [Migrating to V2](#migrating-to-v2)
|
||||
|
||||
<!-- tocstop -->
|
||||
# v1 guide
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
1
docs/v2/index.md
Symbolic link
1
docs/v2/index.md
Symbolic link
@ -0,0 +1 @@
|
||||
manual.md
|
@ -1,51 +1,4 @@
|
||||
cli v2 manual
|
||||
===
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Migrating From Older Releases](#migrating-from-older-releases)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Examples](#examples)
|
||||
* [Arguments](#arguments)
|
||||
* [Flags](#flags)
|
||||
+ [Placeholder Values](#placeholder-values)
|
||||
+ [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)
|
||||
+ [Required Flags](#required-flags)
|
||||
+ [Default Values for help output](#default-values-for-help-output)
|
||||
+ [Precedence](#precedence)
|
||||
* [Subcommands](#subcommands)
|
||||
* [Subcommands categories](#subcommands-categories)
|
||||
* [Exit code](#exit-code)
|
||||
* [Combining short options](#combining-short-options)
|
||||
* [Bash Completion](#bash-completion)
|
||||
+ [Default auto-completion](#default-auto-completion)
|
||||
+ [Custom auto-completion](#custom-auto-completion)
|
||||
+ [Enabling](#enabling)
|
||||
+ [Distribution and Persistent Autocompletion](#distribution-and-persistent-autocompletion)
|
||||
+ [Customization](#customization)
|
||||
+ [ZSH Support](#zsh-support)
|
||||
+ [ZSH default auto-complete example](#zsh-default-auto-complete-example)
|
||||
+ [ZSH custom auto-complete example](#zsh-custom-auto-complete-example)
|
||||
+ [PowerShell Support](#powershell-support)
|
||||
* [Generated Help Text](#generated-help-text)
|
||||
+ [Customization](#customization-1)
|
||||
* [Version Flag](#version-flag)
|
||||
+ [Customization](#customization-2)
|
||||
* [Timestamp Flag](#timestamp-flag)
|
||||
* [Full API Example](#full-api-example)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## 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.
|
||||
# v2 guide
|
||||
|
||||
## Getting Started
|
||||
|
||||
@ -1457,6 +1410,13 @@ In this example the flag could be used like this :
|
||||
|
||||
Side note: quotes may be necessary around the date depending on your layout (if you have spaces for instance)
|
||||
|
||||
### Suggestions
|
||||
|
||||
To enable flag and command suggestions, set `app.Suggest = true`. If the suggest
|
||||
feature is enabled, then the help output of the corresponding command will
|
||||
provide an appropriate suggestion for the provided flag or subcommand if
|
||||
available.
|
||||
|
||||
### Full API Example
|
||||
|
||||
**Notice**: This is a contrived (functioning) example meant strictly for API
|
||||
@ -1714,3 +1674,11 @@ func wopAction(c *cli.Context) error {
|
||||
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.
|
||||
|
||||
|
10
flag_bool.go
10
flag_bool.go
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *BoolFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *BoolFlag) TakesValue() bool {
|
||||
return false
|
||||
@ -32,11 +27,6 @@ func (f *BoolFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *BoolFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *BoolFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -6,11 +6,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *DurationFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *DurationFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -32,11 +27,6 @@ func (f *DurationFlag) GetValue() string {
|
||||
return f.Value.String()
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *DurationFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *DurationFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Float64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *Float64Flag) TakesValue() bool {
|
||||
return true
|
||||
@ -45,11 +40,6 @@ func (f *Float64Flag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Float64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Float64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||
|
@ -81,11 +81,6 @@ func (f *Float64SliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), stringifyFloat64SliceFlag(f))
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Float64SliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true if the flag takes a value, otherwise false
|
||||
func (f *Float64SliceFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -110,11 +105,6 @@ func (f *Float64SliceFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Float64SliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Float64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -11,11 +11,6 @@ type Generic interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *GenericFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *GenericFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -40,11 +35,6 @@ func (f *GenericFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *GenericFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *GenericFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
10
flag_int.go
10
flag_int.go
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *IntFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *IntFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -32,11 +27,6 @@ func (f *IntFlag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *IntFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Int64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *Int64Flag) TakesValue() bool {
|
||||
return true
|
||||
@ -32,11 +27,6 @@ func (f *Int64Flag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Int64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -82,11 +82,6 @@ func (f *Int64SliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), stringifyInt64SliceFlag(f))
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Int64SliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *Int64SliceFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -111,11 +106,6 @@ func (f *Int64SliceFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Int64SliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -93,11 +93,6 @@ func (f *IntSliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), stringifyIntSliceFlag(f))
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *IntSliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *IntSliceFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -122,11 +117,6 @@ func (f *IntSliceFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *IntSliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
10
flag_path.go
10
flag_path.go
@ -7,11 +7,6 @@ import (
|
||||
|
||||
type Path = string
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *PathFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *PathFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -33,11 +28,6 @@ func (f *PathFlag) GetValue() string {
|
||||
return f.Value
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *PathFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *PathFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -5,11 +5,6 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *StringFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *StringFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -31,11 +26,6 @@ func (f *StringFlag) GetValue() string {
|
||||
return f.Value
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *StringFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *StringFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -76,11 +76,6 @@ func (f *StringSliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), stringifyStringSliceFlag(f))
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *StringSliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *StringSliceFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -105,11 +100,6 @@ func (f *StringSliceFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *StringSliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *StringSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
@ -58,11 +58,6 @@ func (t *Timestamp) Get() interface{} {
|
||||
return *t
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *TimestampFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *TimestampFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -87,11 +82,6 @@ func (f *TimestampFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *TimestampFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *TimestampFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
|
10
flag_uint.go
10
flag_uint.go
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *UintFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *UintFlag) TakesValue() bool {
|
||||
return true
|
||||
@ -26,11 +21,6 @@ func (f *UintFlag) GetCategory() string {
|
||||
return f.Category
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *UintFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *UintFlag) Apply(set *flag.FlagSet) error {
|
||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||
|
@ -6,11 +6,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Uint64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *Uint64Flag) TakesValue() bool {
|
||||
return true
|
||||
@ -26,11 +21,6 @@ func (f *Uint64Flag) GetCategory() string {
|
||||
return f.Category
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Uint64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.18
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.1.0
|
||||
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1
|
||||
golang.org/x/text v0.3.7
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
|
8
go.sum
8
go.sum
@ -1,9 +1,17 @@
|
||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/antzucaro/matchr v0.0.0-20180616170659-cbc221335f3c h1:CucViv7orgFBMkehuFFdkCVF5ERovbkRRyhvaYaHu/k=
|
||||
github.com/antzucaro/matchr v0.0.0-20180616170659-cbc221335f3c/go.mod h1:bV/CkX4+ANGDaBwbHkt9kK287al/i9BsB18PRBvyqYo=
|
||||
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 h1:R/qAiUxFT3mNgQaNqJe0IVznjKRNm23ohAIh9lgtlzc=
|
||||
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0/go.mod h1:v3ZDlfVAL1OrkKHbGSFFK60k0/7hruHPDq2XMs9Gu6U=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
|
@ -315,6 +315,8 @@ type App struct {
|
||||
// single-character bool arguments into one
|
||||
// i.e. foobar -o -v -> foobar -ov
|
||||
UseShortOptionHandling bool
|
||||
// Enable suggestions for commands and flags
|
||||
Suggest bool
|
||||
|
||||
// Has unexported fields.
|
||||
}
|
||||
|
21
help.go
21
help.go
@ -10,9 +10,14 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
helpName = "help"
|
||||
helpAlias = "h"
|
||||
)
|
||||
|
||||
var helpCommand = &Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Name: helpName,
|
||||
Aliases: []string{helpAlias},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(cCtx *Context) error {
|
||||
@ -27,8 +32,8 @@ var helpCommand = &Command{
|
||||
}
|
||||
|
||||
var helpSubcommand = &Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Name: helpName,
|
||||
Aliases: []string{helpAlias},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(cCtx *Context) error {
|
||||
@ -214,7 +219,13 @@ func ShowCommandHelp(ctx *Context, command string) error {
|
||||
}
|
||||
|
||||
if ctx.App.CommandNotFound == nil {
|
||||
return Exit(fmt.Sprintf("No help topic for '%v'", command), 3)
|
||||
errMsg := fmt.Sprintf("No help topic for '%v'", command)
|
||||
if ctx.App.Suggest {
|
||||
if suggestion := suggestCommand(ctx.App.Commands, command); suggestion != "" {
|
||||
errMsg += ". " + suggestion
|
||||
}
|
||||
}
|
||||
return Exit(errMsg, 3)
|
||||
}
|
||||
|
||||
ctx.App.CommandNotFound(ctx, command)
|
||||
|
@ -63,10 +63,6 @@ func main() {
|
||||
Name: "gfmrun",
|
||||
Action: GfmrunActionFunc,
|
||||
},
|
||||
{
|
||||
Name: "toc",
|
||||
Action: TocActionFunc,
|
||||
},
|
||||
{
|
||||
Name: "check-binary-size",
|
||||
Action: checkBinarySizeActionFunc,
|
||||
@ -216,15 +212,6 @@ func GfmrunActionFunc(c *cli.Context) error {
|
||||
return runCmd("gfmrun", "-c", fmt.Sprint(counter), "-s", filename)
|
||||
}
|
||||
|
||||
func TocActionFunc(c *cli.Context) error {
|
||||
filename := c.Args().Get(0)
|
||||
if filename == "" {
|
||||
filename = "README.md"
|
||||
}
|
||||
|
||||
return runCmd("markdown-toc", "-i", filename)
|
||||
}
|
||||
|
||||
// checkBinarySizeActionFunc checks the size of an example binary to ensure that we are keeping size down
|
||||
// this was originally inspired by https://github.com/urfave/cli/issues/1055, and followed up on as a part
|
||||
// of https://github.com/urfave/cli/issues/1057
|
||||
|
@ -32,7 +32,7 @@ type {{.TypeName}} struct {
|
||||
func (f *{{.TypeName}}) String() string {
|
||||
return {{$.UrfaveCLINamespace}}FlagStringer(f)
|
||||
}
|
||||
{{end}}
|
||||
{{end}}{{/* /if .GenerateFmtStringerInterface */}}
|
||||
|
||||
{{if .GenerateFlagInterface}}
|
||||
// IsSet returns whether or not the flag has been set through env or file
|
||||
@ -46,6 +46,20 @@ func (f *{{.TypeName}}) Names() []string {
|
||||
}
|
||||
|
||||
{{end}}{{/* /if .GenerateFlagInterface */}}
|
||||
|
||||
{{if .GenerateRequiredFlagInterface}}
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *{{.TypeName}}) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
{{end}}{{/* /if .GenerateRequiredFlagInterface */}}
|
||||
|
||||
{{if .GenerateVisibleFlagInterface}}
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *{{.TypeName}}) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
{{end}}{{/* /if .GenerateVisibleFlagInterface */}}
|
||||
{{end}}{{/* /range .SortedFlagTypes */}}
|
||||
|
||||
// vim{{/* 👻 */}}:ro
|
||||
|
@ -19,6 +19,22 @@ func Test{{.TypeName}}_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .GenerateRequiredFlagInterface}}
|
||||
func Test{{.TypeName}}_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f {{$.UrfaveCLITestNamespace}}RequiredFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .GenerateVisibleFlagInterface}}
|
||||
func Test{{.TypeName}}_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f {{$.UrfaveCLITestNamespace}}VisibleFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
// vim{{/* 👻 */}}:ro
|
||||
|
@ -83,6 +83,14 @@ func (ft *FlagType) GenerateFlagInterface() bool {
|
||||
return ft.skipInterfaceNamed("Flag")
|
||||
}
|
||||
|
||||
func (ft *FlagType) GenerateRequiredFlagInterface() bool {
|
||||
return ft.skipInterfaceNamed("RequiredFlag")
|
||||
}
|
||||
|
||||
func (ft *FlagType) GenerateVisibleFlagInterface() bool {
|
||||
return ft.skipInterfaceNamed("VisibleFlag")
|
||||
}
|
||||
|
||||
func (ft *FlagType) skipInterfaceNamed(name string) bool {
|
||||
if ft.Config == nil {
|
||||
return true
|
||||
|
5
mkdocs-requirements.txt
Normal file
5
mkdocs-requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
mkdocs-git-revision-date-localized-plugin~=1.0
|
||||
mkdocs-material-extensions~=1.0
|
||||
mkdocs-material~=8.2
|
||||
mkdocs~=1.3
|
||||
pygments~=2.12
|
62
mkdocs.yml
Normal file
62
mkdocs.yml
Normal file
@ -0,0 +1,62 @@
|
||||
# NOTE: the mkdocs dependencies will need to be installed out of
|
||||
# band until this whole thing gets more automated:
|
||||
#
|
||||
# pip install -r mkdocs-requirements.txt
|
||||
#
|
||||
|
||||
site_name: urfave/cli
|
||||
site_url: https://cli.urfave.org/
|
||||
repo_url: https://github.com/urfave/cli
|
||||
edit_uri: edit/main/docs/
|
||||
nav:
|
||||
- Home: index.md
|
||||
- v2 Manual: v2/index.md
|
||||
- v1 Manual: v1/index.md
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: light mode
|
||||
plugins:
|
||||
- git-revision-date-localized
|
||||
- search
|
||||
# NOTE: this is the recommended configuration from
|
||||
# https://squidfunk.github.io/mkdocs-material/setup/extensions/#recommended-configuration
|
||||
markdown_extensions:
|
||||
- abbr
|
||||
- admonition
|
||||
- attr_list
|
||||
- def_list
|
||||
- footnotes
|
||||
- meta
|
||||
- md_in_html
|
||||
- toc:
|
||||
permalink: true
|
||||
- pymdownx.arithmatex:
|
||||
generic: true
|
||||
- pymdownx.betterem:
|
||||
smart_enable: all
|
||||
- pymdownx.caret
|
||||
- pymdownx.details
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
- pymdownx.highlight
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.keys
|
||||
- pymdownx.mark
|
||||
- pymdownx.smartsymbols
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- pymdownx.tasklist:
|
||||
custom_checkbox: true
|
||||
- pymdownx.tilde
|
18
parse.go
18
parse.go
@ -26,9 +26,8 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple
|
||||
return err
|
||||
}
|
||||
|
||||
errStr := err.Error()
|
||||
trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -")
|
||||
if errStr == trimmed {
|
||||
trimmed, trimErr := flagFromError(err)
|
||||
if trimErr != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -67,6 +66,19 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple
|
||||
}
|
||||
}
|
||||
|
||||
const providedButNotDefinedErrMsg = "flag provided but not defined: -"
|
||||
|
||||
// flagFromError tries to parse a provided flag from an error message. If the
|
||||
// parsing fials, it returns the input error and an empty string
|
||||
func flagFromError(err error) (string, error) {
|
||||
errStr := err.Error()
|
||||
trimmed := strings.TrimPrefix(errStr, providedButNotDefinedErrMsg)
|
||||
if errStr == trimmed {
|
||||
return "", err
|
||||
}
|
||||
return trimmed, nil
|
||||
}
|
||||
|
||||
func splitShortOptions(set *flag.FlagSet, arg string) []string {
|
||||
shortFlagsExist := func(s string) bool {
|
||||
for _, c := range s[1:] {
|
||||
|
75
suggestions.go
Normal file
75
suggestions.go
Normal file
@ -0,0 +1,75 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/antzucaro/matchr"
|
||||
)
|
||||
|
||||
const didYouMeanTemplate = "Did you mean '%s'?"
|
||||
|
||||
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
|
||||
flag, parseErr := flagFromError(err)
|
||||
if parseErr != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
flags := a.Flags
|
||||
if command != "" {
|
||||
cmd := a.Command(command)
|
||||
if cmd == nil {
|
||||
return "", err
|
||||
}
|
||||
flags = cmd.Flags
|
||||
}
|
||||
|
||||
suggestion := a.suggestFlag(flags, flag)
|
||||
if len(suggestion) == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf(didYouMeanTemplate+"\n\n", suggestion), nil
|
||||
}
|
||||
|
||||
func (a *App) suggestFlag(flags []Flag, provided string) (suggestion string) {
|
||||
distance := 0.0
|
||||
|
||||
for _, flag := range flags {
|
||||
flagNames := flag.Names()
|
||||
if !a.HideHelp {
|
||||
flagNames = append(flagNames, HelpFlag.Names()...)
|
||||
}
|
||||
for _, name := range flagNames {
|
||||
newDistance := matchr.JaroWinkler(name, provided, true)
|
||||
if newDistance > distance {
|
||||
distance = newDistance
|
||||
suggestion = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(suggestion) == 1 {
|
||||
suggestion = "-" + suggestion
|
||||
} else if len(suggestion) > 1 {
|
||||
suggestion = "--" + suggestion
|
||||
}
|
||||
|
||||
return suggestion
|
||||
}
|
||||
|
||||
// suggestCommand takes a list of commands and a provided string to suggest a
|
||||
// command name
|
||||
func suggestCommand(commands []*Command, provided string) (suggestion string) {
|
||||
distance := 0.0
|
||||
for _, command := range commands {
|
||||
for _, name := range append(command.Names(), helpName, helpAlias) {
|
||||
newDistance := matchr.JaroWinkler(name, provided, true)
|
||||
if newDistance > distance {
|
||||
distance = newDistance
|
||||
suggestion = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf(didYouMeanTemplate, suggestion)
|
||||
}
|
188
suggestions_test.go
Normal file
188
suggestions_test.go
Normal file
@ -0,0 +1,188 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSuggestFlag(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
for _, testCase := range []struct {
|
||||
provided, expected string
|
||||
}{
|
||||
{"", ""},
|
||||
{"a", "--another-flag"},
|
||||
{"hlp", "--help"},
|
||||
{"k", ""},
|
||||
{"s", "-s"},
|
||||
} {
|
||||
// When
|
||||
res := app.suggestFlag(app.Flags, testCase.provided)
|
||||
|
||||
// Then
|
||||
expect(t, res, testCase.expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuggestFlagHideHelp(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
app.HideHelp = true
|
||||
|
||||
// When
|
||||
res := app.suggestFlag(app.Flags, "hlp")
|
||||
|
||||
// Then
|
||||
expect(t, res, "--fl")
|
||||
}
|
||||
|
||||
func TestSuggestFlagFromError(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
for _, testCase := range []struct {
|
||||
command, provided, expected string
|
||||
}{
|
||||
{"", "hel", "--help"},
|
||||
{"", "soccer", "--socket"},
|
||||
{"config", "anot", "--another-flag"},
|
||||
} {
|
||||
// When
|
||||
res, _ := app.suggestFlagFromError(
|
||||
errors.New(providedButNotDefinedErrMsg+testCase.provided),
|
||||
testCase.command,
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(t, res, fmt.Sprintf(didYouMeanTemplate+"\n\n", testCase.expected))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuggestFlagFromErrorWrongError(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
// When
|
||||
_, err := app.suggestFlagFromError(errors.New("invalid"), "")
|
||||
|
||||
// Then
|
||||
expect(t, true, err != nil)
|
||||
}
|
||||
|
||||
func TestSuggestFlagFromErrorWrongCommand(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
// When
|
||||
_, err := app.suggestFlagFromError(
|
||||
errors.New(providedButNotDefinedErrMsg+"flag"),
|
||||
"invalid",
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(t, true, err != nil)
|
||||
}
|
||||
|
||||
func TestSuggestFlagFromErrorNoSuggestion(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
// When
|
||||
_, err := app.suggestFlagFromError(
|
||||
errors.New(providedButNotDefinedErrMsg+""),
|
||||
"",
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(t, true, err != nil)
|
||||
}
|
||||
|
||||
func TestSuggestCommand(t *testing.T) {
|
||||
// Given
|
||||
app := testApp()
|
||||
|
||||
for _, testCase := range []struct {
|
||||
provided, expected string
|
||||
}{
|
||||
{"", ""},
|
||||
{"conf", "config"},
|
||||
{"i", "i"},
|
||||
{"information", "info"},
|
||||
{"not-existing", "info"},
|
||||
} {
|
||||
// When
|
||||
res := suggestCommand(app.Commands, testCase.provided)
|
||||
|
||||
// Then
|
||||
expect(t, res, fmt.Sprintf(didYouMeanTemplate, testCase.expected))
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleApp_Suggest() {
|
||||
app := &App{
|
||||
Name: "greet",
|
||||
Suggest: true,
|
||||
HideHelp: true,
|
||||
HideHelpCommand: true,
|
||||
CustomAppHelpTemplate: "(this space intentionally left blank)\n",
|
||||
Flags: []Flag{
|
||||
&StringFlag{Name: "name", Value: "squirrel", Usage: "a name to say"},
|
||||
},
|
||||
Action: func(cCtx *Context) error {
|
||||
fmt.Printf("Hello %v\n", cCtx.String("name"))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"greet", "--nema", "chipmunk"})
|
||||
// Output:
|
||||
// Incorrect Usage. flag provided but not defined: -nema
|
||||
//
|
||||
// Did you mean '--name'?
|
||||
//
|
||||
// (this space intentionally left blank)
|
||||
}
|
||||
|
||||
func ExampleApp_Suggest_command() {
|
||||
app := &App{
|
||||
Name: "greet",
|
||||
Suggest: true,
|
||||
HideHelp: true,
|
||||
HideHelpCommand: true,
|
||||
CustomAppHelpTemplate: "(this space intentionally left blank)\n",
|
||||
Flags: []Flag{
|
||||
&StringFlag{Name: "name", Value: "squirrel", Usage: "a name to say"},
|
||||
},
|
||||
Action: func(cCtx *Context) error {
|
||||
fmt.Printf("Hello %v\n", cCtx.String("name"))
|
||||
return nil
|
||||
},
|
||||
Commands: []*Command{
|
||||
{
|
||||
Name: "neighbors",
|
||||
CustomHelpTemplate: "(this space intentionally left blank)\n",
|
||||
Flags: []Flag{
|
||||
&BoolFlag{Name: "smiling"},
|
||||
},
|
||||
Action: func(cCtx *Context) error {
|
||||
if cCtx.Bool("smiling") {
|
||||
fmt.Println("😀")
|
||||
}
|
||||
fmt.Println("Hello, neighbors")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"greet", "neighbors", "--sliming"})
|
||||
// Output:
|
||||
// Incorrect Usage: flag provided but not defined: -sliming
|
||||
//
|
||||
// Did you mean '--smiling'?
|
||||
//
|
||||
// (this space intentionally left blank)
|
||||
}
|
2
testdata/godoc-v2.x.txt
vendored
2
testdata/godoc-v2.x.txt
vendored
@ -315,6 +315,8 @@ type App struct {
|
||||
// single-character bool arguments into one
|
||||
// i.e. foobar -o -v -> foobar -ov
|
||||
UseShortOptionHandling bool
|
||||
// Enable suggestions for commands and flags
|
||||
Suggest bool
|
||||
|
||||
// Has unexported fields.
|
||||
}
|
||||
|
@ -34,6 +34,16 @@ func (f *Float64SliceFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Float64SliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Float64SliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GenericFlag is a flag with type Generic
|
||||
type GenericFlag struct {
|
||||
Name string
|
||||
@ -71,6 +81,16 @@ func (f *GenericFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *GenericFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *GenericFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Int64SliceFlag is a flag with type *Int64Slice
|
||||
type Int64SliceFlag struct {
|
||||
Name string
|
||||
@ -101,6 +121,16 @@ func (f *Int64SliceFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Int64SliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Int64SliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// IntSliceFlag is a flag with type *IntSlice
|
||||
type IntSliceFlag struct {
|
||||
Name string
|
||||
@ -131,6 +161,16 @@ func (f *IntSliceFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *IntSliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *IntSliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// PathFlag is a flag with type Path
|
||||
type PathFlag struct {
|
||||
Name string
|
||||
@ -168,6 +208,16 @@ func (f *PathFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *PathFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *PathFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// StringSliceFlag is a flag with type *StringSlice
|
||||
type StringSliceFlag struct {
|
||||
Name string
|
||||
@ -200,6 +250,16 @@ func (f *StringSliceFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *StringSliceFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *StringSliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// TimestampFlag is a flag with type *Timestamp
|
||||
type TimestampFlag struct {
|
||||
Name string
|
||||
@ -237,6 +297,16 @@ func (f *TimestampFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *TimestampFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *TimestampFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// BoolFlag is a flag with type bool
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
@ -272,6 +342,16 @@ func (f *BoolFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *BoolFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *BoolFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Float64Flag is a flag with type float64
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
@ -307,6 +387,16 @@ func (f *Float64Flag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Float64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Float64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// IntFlag is a flag with type int
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
@ -342,6 +432,16 @@ func (f *IntFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *IntFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *IntFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Int64Flag is a flag with type int64
|
||||
type Int64Flag struct {
|
||||
Name string
|
||||
@ -377,6 +477,16 @@ func (f *Int64Flag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Int64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Int64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// StringFlag is a flag with type string
|
||||
type StringFlag struct {
|
||||
Name string
|
||||
@ -414,6 +524,16 @@ func (f *StringFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *StringFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *StringFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// DurationFlag is a flag with type time.Duration
|
||||
type DurationFlag struct {
|
||||
Name string
|
||||
@ -449,6 +569,16 @@ func (f *DurationFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *DurationFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *DurationFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// UintFlag is a flag with type uint
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
@ -484,6 +614,16 @@ func (f *UintFlag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *UintFlag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *UintFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// Uint64Flag is a flag with type uint64
|
||||
type Uint64Flag struct {
|
||||
Name string
|
||||
@ -519,4 +659,14 @@ func (f *Uint64Flag) Names() []string {
|
||||
return FlagNames(f.Name, f.Aliases)
|
||||
}
|
||||
|
||||
// IsRequired returns whether or not the flag is required
|
||||
func (f *Uint64Flag) IsRequired() bool {
|
||||
return f.Required
|
||||
}
|
||||
|
||||
// IsVisible returns true if the flag is not hidden, otherwise false
|
||||
func (f *Uint64Flag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// vim:ro
|
||||
|
@ -16,6 +16,18 @@ func TestFloat64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestFloat64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Float64SliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestFloat64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Float64SliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestGenericFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.GenericFlag{}
|
||||
|
||||
@ -29,6 +41,18 @@ func TestGenericFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestGenericFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.GenericFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestGenericFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.GenericFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestInt64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.Int64SliceFlag{}
|
||||
|
||||
@ -36,6 +60,18 @@ func TestInt64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestInt64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Int64SliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestInt64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Int64SliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestIntSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.IntSliceFlag{}
|
||||
|
||||
@ -43,6 +79,18 @@ func TestIntSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestIntSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.IntSliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestIntSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.IntSliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestPathFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.PathFlag{}
|
||||
|
||||
@ -56,6 +104,18 @@ func TestPathFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestPathFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.PathFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestPathFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.PathFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestStringSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.StringSliceFlag{}
|
||||
|
||||
@ -63,6 +123,18 @@ func TestStringSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestStringSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.StringSliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestStringSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.StringSliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestTimestampFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.TimestampFlag{}
|
||||
|
||||
@ -76,6 +148,18 @@ func TestTimestampFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestTimestampFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.TimestampFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestTimestampFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.TimestampFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestBoolFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.BoolFlag{}
|
||||
|
||||
@ -89,6 +173,18 @@ func TestBoolFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestBoolFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.BoolFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestBoolFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.BoolFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestFloat64Flag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.Float64Flag{}
|
||||
|
||||
@ -102,6 +198,18 @@ func TestFloat64Flag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestFloat64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Float64Flag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestFloat64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Float64Flag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestIntFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.IntFlag{}
|
||||
|
||||
@ -115,6 +223,18 @@ func TestIntFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestIntFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.IntFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestIntFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.IntFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestInt64Flag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.Int64Flag{}
|
||||
|
||||
@ -128,6 +248,18 @@ func TestInt64Flag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestInt64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Int64Flag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestInt64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Int64Flag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestStringFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.StringFlag{}
|
||||
|
||||
@ -141,6 +273,18 @@ func TestStringFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestStringFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.StringFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestStringFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.StringFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestDurationFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.DurationFlag{}
|
||||
|
||||
@ -154,6 +298,18 @@ func TestDurationFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestDurationFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.DurationFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestDurationFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.DurationFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestUintFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.UintFlag{}
|
||||
|
||||
@ -167,6 +323,18 @@ func TestUintFlag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestUintFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.UintFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestUintFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.UintFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestUint64Flag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.Uint64Flag{}
|
||||
|
||||
@ -180,4 +348,16 @@ func TestUint64Flag_SatisfiesFmtStringerInterface(t *testing.T) {
|
||||
_ = f.String()
|
||||
}
|
||||
|
||||
func TestUint64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Uint64Flag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestUint64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Uint64Flag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
// vim:ro
|
||||
|
Loading…
Reference in New Issue
Block a user