Merge pull request #1525 from urfave/v3-porting
Porting changes from `main` to `v3-dev-main` (circa 2022-10-09)
This commit is contained in:
commit
25897ce4dd
7
.github/workflows/cli.yml
vendored
7
.github/workflows/cli.yml
vendored
@ -43,9 +43,14 @@ jobs:
|
||||
GFLAGS: -tags urfave_cli_no_docs
|
||||
- run: make check-binary-size
|
||||
- run: make yamlfmt
|
||||
- run: make diffcheck
|
||||
- if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest'
|
||||
run: make generate
|
||||
- run: make diffcheck
|
||||
# TODO: switch once v3 is released {{
|
||||
# - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest'
|
||||
- if: 'false'
|
||||
run: make v2diff
|
||||
# }}
|
||||
- if: success() && matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest'
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
|
2
Makefile
2
Makefile
@ -7,7 +7,7 @@
|
||||
GO_RUN_BUILD := go run internal/build/build.go
|
||||
|
||||
.PHONY: all
|
||||
all: generate vet test check-binary-size gfmrun yamlfmt v2diff
|
||||
all: generate vet test check-binary-size gfmrun yamlfmt
|
||||
|
||||
# NOTE: this is a special catch-all rule to run any of the commands
|
||||
# defined in internal/build/build.go with optional arguments passed
|
||||
|
33
app_test.go
33
app_test.go
@ -177,7 +177,7 @@ func ExampleApp_Run_commandHelp() {
|
||||
// greet describeit - use it to see a description
|
||||
//
|
||||
// USAGE:
|
||||
// greet describeit [command options] [arguments...]
|
||||
// greet describeit [arguments...]
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// This is how we describe describeit the function
|
||||
@ -956,6 +956,37 @@ func TestApp_UseShortOptionHandlingSubCommand_missing_value(t *testing.T) {
|
||||
expect(t, err, errors.New("flag needs an argument: -n"))
|
||||
}
|
||||
|
||||
func TestApp_UseShortOptionAfterSliceFlag(t *testing.T) {
|
||||
var one, two bool
|
||||
var name string
|
||||
var sliceValDest StringSlice
|
||||
var sliceVal []string
|
||||
expected := "expectedName"
|
||||
|
||||
app := newTestApp()
|
||||
app.UseShortOptionHandling = true
|
||||
app.Flags = []Flag{
|
||||
&StringSliceFlag{Name: "env", Aliases: []string{"e"}, Destination: &sliceValDest},
|
||||
&BoolFlag{Name: "one", Aliases: []string{"o"}},
|
||||
&BoolFlag{Name: "two", Aliases: []string{"t"}},
|
||||
&StringFlag{Name: "name", Aliases: []string{"n"}},
|
||||
}
|
||||
app.Action = func(c *Context) error {
|
||||
sliceVal = c.StringSlice("env")
|
||||
one = c.Bool("one")
|
||||
two = c.Bool("two")
|
||||
name = c.String("name")
|
||||
return nil
|
||||
}
|
||||
|
||||
_ = app.Run([]string{"", "-e", "foo", "-on", expected})
|
||||
expect(t, sliceVal, []string{"foo"})
|
||||
expect(t, sliceValDest.Value(), []string{"foo"})
|
||||
expect(t, one, true)
|
||||
expect(t, two, false)
|
||||
expect(t, name, expected)
|
||||
}
|
||||
|
||||
func TestApp_Float64Flag(t *testing.T) {
|
||||
var meters float64
|
||||
|
||||
|
2
cli.go
2
cli.go
@ -22,4 +22,4 @@
|
||||
// }
|
||||
package cli
|
||||
|
||||
//go:generate go run cmd/urfave-cli-genflags/main.go
|
||||
//go:generate make -C cmd/urfave-cli-genflags run
|
||||
|
@ -1,6 +1,9 @@
|
||||
GOIMPORTS_BIN ?= $(shell which goimports || true)
|
||||
GOTEST_FLAGS ?= -v --coverprofile main.coverprofile --covermode count --cover github.com/urfave/cli/v2/cmd/urfave-cli-genflags
|
||||
GOBUILD_FLAGS ?= -x
|
||||
|
||||
export GOIMPORTS_BIN
|
||||
|
||||
.PHONY: all
|
||||
all: test build smoke-test
|
||||
|
||||
@ -19,3 +22,7 @@ smoke-test: build
|
||||
.PHONY: show-cover
|
||||
show-cover:
|
||||
go tool cover -func main.coverprofile
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
./urfave-cli-genflags
|
||||
|
@ -75,16 +75,6 @@ func (f *{{.TypeName}}) TakesValue() bool {
|
||||
return "{{.TypeName }}" != "BoolFlag"
|
||||
}
|
||||
|
||||
{{if .GenerateDefaultText}}
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *{{.TypeName}}) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}{{/* /if .GenerateFlagInterface */}}
|
||||
|
||||
{{end}}{{/* /range .SortedFlagTypes */}}
|
||||
|
@ -12,13 +12,13 @@ func Test{{.TypeName}}_SatisfiesFlagInterface(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test{{.TypeName}}_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f {{$.UrfaveCLITestNamespace}}Flag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
var f {{$.UrfaveCLITestNamespace}}RequiredFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func Test{{.TypeName}}_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f {{$.UrfaveCLITestNamespace}}Flag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
var f {{$.UrfaveCLITestNamespace}}VisibleFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -37,6 +38,9 @@ var (
|
||||
func sh(ctx context.Context, exe string, args ...string) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, exe, args...)
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
fmt.Fprintf(os.Stderr, "# ---> %s\n", cmd)
|
||||
|
||||
outBytes, err := cmd.Output()
|
||||
return string(outBytes), err
|
||||
}
|
||||
@ -89,10 +93,19 @@ func main() {
|
||||
Aliases: []string{"N"},
|
||||
Value: "cli.",
|
||||
},
|
||||
&cli.PathFlag{
|
||||
Name: "goimports",
|
||||
EnvVars: []string{"GOIMPORTS_BIN"},
|
||||
Value: filepath.Join(top, ".local/bin/goimports"),
|
||||
},
|
||||
},
|
||||
Action: runGenFlags,
|
||||
}
|
||||
|
||||
if err := os.Chdir(top); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := app.RunContext(ctx, os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -163,11 +176,11 @@ func runGenFlags(cCtx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sh(cCtx.Context, "goimports", "-w", cCtx.Path("generated-output")); err != nil {
|
||||
if _, err := sh(cCtx.Context, cCtx.Path("goimports"), "-w", cCtx.Path("generated-output")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sh(cCtx.Context, "goimports", "-w", cCtx.Path("generated-test-output")); err != nil {
|
||||
if _, err := sh(cCtx.Context, cCtx.Path("goimports"), "-w", cCtx.Path("generated-test-output")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
11
command.go
11
command.go
@ -295,6 +295,17 @@ func (c *Command) startApp(ctx *Context) error {
|
||||
return app.RunAsSubcommand(ctx)
|
||||
}
|
||||
|
||||
// VisibleCommands returns a slice of the Commands with Hidden=false
|
||||
func (c *Command) VisibleCommands() []*Command {
|
||||
var ret []*Command
|
||||
for _, command := range c.Subcommands {
|
||||
if !command.Hidden {
|
||||
ret = append(ret, command)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain
|
||||
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory {
|
||||
if c.flagCategories == nil {
|
||||
|
@ -422,3 +422,30 @@ func TestCommand_CanAddVFlagOnCommands(t *testing.T) {
|
||||
err := app.Run([]string{"foo", "bar"})
|
||||
expect(t, err, nil)
|
||||
}
|
||||
|
||||
func TestCommand_VisibleSubcCommands(t *testing.T) {
|
||||
|
||||
subc1 := &Command{
|
||||
Name: "subc1",
|
||||
Usage: "subc1 command1",
|
||||
}
|
||||
subc3 := &Command{
|
||||
Name: "subc3",
|
||||
Usage: "subc3 command2",
|
||||
}
|
||||
c := &Command{
|
||||
Name: "bar",
|
||||
Usage: "this is for testing",
|
||||
Subcommands: []*Command{
|
||||
subc1,
|
||||
{
|
||||
Name: "subc2",
|
||||
Usage: "subc2 command2",
|
||||
Hidden: true,
|
||||
},
|
||||
subc3,
|
||||
},
|
||||
}
|
||||
|
||||
expect(t, c.VisibleCommands(), []*Command{subc1, subc3})
|
||||
}
|
||||
|
29
flag.go
29
flag.go
@ -135,6 +135,14 @@ type DocGenerationFlag interface {
|
||||
GetEnvVars() []string
|
||||
}
|
||||
|
||||
// DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags.
|
||||
type DocGenerationSliceFlag interface {
|
||||
DocGenerationFlag
|
||||
|
||||
// IsSliceFlag returns true for flags that can be given multiple times.
|
||||
IsSliceFlag() bool
|
||||
}
|
||||
|
||||
// Countable is an interface to enable detection of flag values which support
|
||||
// repetitive flags
|
||||
type Countable interface {
|
||||
@ -332,24 +340,13 @@ func stringifyFlag(f Flag) string {
|
||||
|
||||
usageWithDefault := strings.TrimSpace(usage + defaultValueString)
|
||||
|
||||
return withEnvHint(df.GetEnvVars(),
|
||||
fmt.Sprintf("%s\t%s", prefixedNames(df.Names(), placeholder), usageWithDefault))
|
||||
}
|
||||
|
||||
func stringifySliceFlag(usage string, names, defaultVals []string) string {
|
||||
placeholder, usage := unquoteUsage(usage)
|
||||
if placeholder == "" {
|
||||
placeholder = defaultPlaceholder
|
||||
pn := prefixedNames(df.Names(), placeholder)
|
||||
sliceFlag, ok := f.(DocGenerationSliceFlag)
|
||||
if ok && sliceFlag.IsSliceFlag() {
|
||||
pn = pn + " [ " + pn + " ]"
|
||||
}
|
||||
|
||||
defaultVal := ""
|
||||
if len(defaultVals) > 0 {
|
||||
defaultVal = fmt.Sprintf(formatDefault("%s"), strings.Join(defaultVals, ", "))
|
||||
}
|
||||
|
||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
|
||||
pn := prefixedNames(names, placeholder)
|
||||
return fmt.Sprintf("%s [ %s ]\t%s", pn, pn, usageWithDefault)
|
||||
return withEnvHint(df.GetEnvVars(), fmt.Sprintf("%s\t%s", pn, usageWithDefault))
|
||||
}
|
||||
|
||||
func hasFlag(flags []Flag, fl Flag) bool {
|
||||
|
@ -12,6 +12,14 @@ func (f *DurationFlag) GetValue() string {
|
||||
return f.Value.String()
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *DurationFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *DurationFlag) Apply(set *flag.FlagSet) error {
|
||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||
|
@ -12,6 +12,14 @@ func (f *Float64Flag) GetValue() string {
|
||||
return fmt.Sprintf("%v", f.Value)
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Float64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Float64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||
|
@ -83,16 +83,32 @@ func (f *Float64Slice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *Float64SliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *Float64SliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), "."))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Float64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *Float64SliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -141,18 +157,6 @@ func (f *Float64SliceFlag) Get(ctx *Context) []float64 {
|
||||
return ctx.Float64Slice(f.Name)
|
||||
}
|
||||
|
||||
func (f *Float64SliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), "."))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Float64SliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
@ -20,6 +20,14 @@ func (f *GenericFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *GenericFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply takes the flagset and calls Set on the generic flag with the value
|
||||
// provided by the user for parsing by the flag
|
||||
func (f *GenericFlag) Apply(set *flag.FlagSet) error {
|
||||
@ -34,6 +42,10 @@ func (f *GenericFlag) Apply(set *flag.FlagSet) error {
|
||||
}
|
||||
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.Var(f.Destination, name, f.Usage)
|
||||
continue
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,14 @@ func (f *IntFlag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *IntFlag) Apply(set *flag.FlagSet) error {
|
||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||
|
@ -12,6 +12,14 @@ func (f *Int64Flag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Int64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||
|
@ -84,16 +84,32 @@ func (i *Int64Slice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *Int64SliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *Int64SliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatInt(i, 10))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *Int64SliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -140,17 +156,6 @@ func (f *Int64SliceFlag) Get(ctx *Context) []int64 {
|
||||
return ctx.Int64Slice(f.Name)
|
||||
}
|
||||
|
||||
func (f *Int64SliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatInt(i, 10))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Int64SliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
@ -95,16 +95,32 @@ func (i *IntSlice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *IntSliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *IntSliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *IntSliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -151,17 +167,6 @@ func (f *IntSliceFlag) Get(ctx *Context) []int {
|
||||
return ctx.IntSlice(f.Name)
|
||||
}
|
||||
|
||||
func (f *IntSliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *IntSliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
@ -74,16 +74,34 @@ func (s *StringSlice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *StringSliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *StringSliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, s := range f.Value.Value() {
|
||||
if len(s) > 0 {
|
||||
defaultVals = append(defaultVals, strconv.Quote(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *StringSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *StringSliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -130,19 +148,6 @@ func (f *StringSliceFlag) Get(ctx *Context) []string {
|
||||
return ctx.StringSlice(f.Name)
|
||||
}
|
||||
|
||||
func (f *StringSliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, s := range f.Value.Value() {
|
||||
if len(s) > 0 {
|
||||
defaultVals = append(defaultVals, strconv.Quote(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *StringSliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
69
flag_test.go
69
flag_test.go
@ -225,7 +225,7 @@ func TestFlagsFromEnv(t *testing.T) {
|
||||
|
||||
f, ok := test.flag.(DocGenerationFlag)
|
||||
if !ok {
|
||||
t.Errorf("flag %v needs to implement DocGenerationFlag to retrieve env vars", test.flag)
|
||||
t.Errorf("flag %[1]q (%[1]T) needs to implement DocGenerationFlag to retrieve env vars", test.flag)
|
||||
}
|
||||
envVarSlice := f.GetEnvVars()
|
||||
_ = os.Setenv(envVarSlice[0], test.input)
|
||||
@ -307,12 +307,12 @@ func TestFlagStringifying(t *testing.T) {
|
||||
{
|
||||
name: "float64-slice-flag",
|
||||
fl: &Float64SliceFlag{Name: "pizzas"},
|
||||
expected: "--pizzas value\t",
|
||||
expected: "--pizzas value [ --pizzas value ]\t",
|
||||
},
|
||||
{
|
||||
name: "float64-slice-flag-with-default-text",
|
||||
fl: &Float64SliceFlag{Name: "pepperonis", DefaultText: "shaved"},
|
||||
expected: "--pepperonis value\t(default: shaved)",
|
||||
expected: "--pepperonis value [ --pepperonis value ]\t(default: shaved)",
|
||||
},
|
||||
{
|
||||
name: "generic-flag",
|
||||
@ -337,7 +337,7 @@ func TestFlagStringifying(t *testing.T) {
|
||||
{
|
||||
name: "int-slice-flag",
|
||||
fl: &IntSliceFlag{Name: "pencils"},
|
||||
expected: "--pencils value\t",
|
||||
expected: "--pencils value [ --pencils value ]\t",
|
||||
},
|
||||
{
|
||||
name: "int-slice-flag-with-default-text",
|
||||
@ -347,7 +347,7 @@ func TestFlagStringifying(t *testing.T) {
|
||||
{
|
||||
name: "uint-slice-flag",
|
||||
fl: &UintSliceFlag{Name: "pencils"},
|
||||
expected: "--pencils value\t",
|
||||
expected: "--pencils value [ --pencils value ]\t",
|
||||
},
|
||||
{
|
||||
name: "uint-slice-flag-with-default-text",
|
||||
@ -367,22 +367,22 @@ func TestFlagStringifying(t *testing.T) {
|
||||
{
|
||||
name: "int64-slice-flag",
|
||||
fl: &Int64SliceFlag{Name: "drawers"},
|
||||
expected: "--drawers value\t",
|
||||
expected: "--drawers value [ --drawers value ]\t",
|
||||
},
|
||||
{
|
||||
name: "int64-slice-flag-with-default-text",
|
||||
fl: &Int64SliceFlag{Name: "handles", DefaultText: "-2"},
|
||||
expected: "--handles value\t(default: -2)",
|
||||
expected: "--handles value [ --handles value ]\t(default: -2)",
|
||||
},
|
||||
{
|
||||
name: "uint64-slice-flag",
|
||||
fl: &Uint64SliceFlag{Name: "drawers"},
|
||||
expected: "--drawers value\t",
|
||||
expected: "--drawers value [ --drawers value ]\t",
|
||||
},
|
||||
{
|
||||
name: "uint64-slice-flag-with-default-text",
|
||||
fl: &Uint64SliceFlag{Name: "handles", DefaultText: "-2"},
|
||||
expected: "--handles value\t(default: -2)",
|
||||
expected: "--handles value [ --handles value ]\t(default: -2)",
|
||||
},
|
||||
{
|
||||
name: "path-flag",
|
||||
@ -407,12 +407,12 @@ func TestFlagStringifying(t *testing.T) {
|
||||
{
|
||||
name: "string-slice-flag",
|
||||
fl: &StringSliceFlag{Name: "meow-sounds"},
|
||||
expected: "--meow-sounds value\t",
|
||||
expected: "--meow-sounds value [ --meow-sounds value ]\t",
|
||||
},
|
||||
{
|
||||
name: "string-slice-flag-with-default-text",
|
||||
fl: &StringSliceFlag{Name: "moo-sounds", DefaultText: "awoo"},
|
||||
expected: "--moo-sounds value\t(default: awoo)",
|
||||
expected: "--moo-sounds value [ --moo-sounds value ]\t(default: awoo)",
|
||||
},
|
||||
{
|
||||
name: "timestamp-flag",
|
||||
@ -2724,6 +2724,53 @@ func TestParseGeneric(t *testing.T) {
|
||||
}).Run([]string{"run", "-s", "10,20"})
|
||||
}
|
||||
|
||||
type genericType struct {
|
||||
s []string
|
||||
}
|
||||
|
||||
func (g *genericType) Set(value string) error {
|
||||
g.s = strings.Split(value, "-")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *genericType) String() string {
|
||||
return strings.Join(g.s, "-")
|
||||
}
|
||||
|
||||
func TestParseDestinationGeneric(t *testing.T) {
|
||||
expectedString := "abc1-123d"
|
||||
expectedGeneric := &genericType{[]string{"abc1", "123d"}}
|
||||
dest := &genericType{}
|
||||
|
||||
_ = (&App{
|
||||
Flags: []Flag{
|
||||
&GenericFlag{
|
||||
Name: "dest",
|
||||
Destination: dest,
|
||||
},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
|
||||
if !reflect.DeepEqual(dest, expectedGeneric) {
|
||||
t.Errorf(
|
||||
"expected destination generic: %+v, actual: %+v",
|
||||
expectedGeneric,
|
||||
dest,
|
||||
)
|
||||
}
|
||||
|
||||
if dest.String() != expectedString {
|
||||
t.Errorf(
|
||||
"expected destination string: %s, actual: %s",
|
||||
expectedString,
|
||||
dest.String(),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run", "--dest", expectedString})
|
||||
}
|
||||
|
||||
func TestParseGenericFromEnv(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
|
@ -81,6 +81,14 @@ func (f *TimestampFlag) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *TimestampFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
|
||||
if f.Layout == "" {
|
||||
|
@ -37,6 +37,14 @@ func (f *UintFlag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *UintFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Get returns the flag’s value in the given Context.
|
||||
func (f *UintFlag) Get(ctx *Context) uint {
|
||||
return ctx.Uint(f.Name)
|
||||
|
@ -37,6 +37,14 @@ func (f *Uint64Flag) GetValue() string {
|
||||
return fmt.Sprintf("%d", f.Value)
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Uint64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Get returns the flag’s value in the given Context.
|
||||
func (f *Uint64Flag) Get(ctx *Context) uint64 {
|
||||
return ctx.Uint64(f.Name)
|
||||
|
@ -88,31 +88,19 @@ func (i *Uint64Slice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *Uint64SliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *Uint64SliceFlag) TakesValue() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag
|
||||
func (f *Uint64SliceFlag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// GetCategory returns the category for the flag
|
||||
func (f *Uint64SliceFlag) GetCategory() string {
|
||||
return f.Category
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *Uint64SliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatUint(i, 10))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
@ -123,9 +111,9 @@ func (f *Uint64SliceFlag) GetDefaultText() string {
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// GetEnvVars returns the env vars for this flag
|
||||
func (f *Uint64SliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *Uint64SliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -172,17 +160,6 @@ func (f *Uint64SliceFlag) Get(ctx *Context) []uint64 {
|
||||
return ctx.Uint64Slice(f.Name)
|
||||
}
|
||||
|
||||
func (f *Uint64SliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatUint(i, 10))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Uint64SliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
@ -99,31 +99,19 @@ func (i *UintSlice) Get() interface{} {
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f *UintSliceFlag) String() string {
|
||||
return withEnvHint(f.GetEnvVars(), f.stringify())
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
func (f *UintSliceFlag) TakesValue() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag
|
||||
func (f *UintSliceFlag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// GetCategory returns the category for the flag
|
||||
func (f *UintSliceFlag) GetCategory() string {
|
||||
return f.Category
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
func (f *UintSliceFlag) GetValue() string {
|
||||
if f.Value != nil {
|
||||
return f.Value.String()
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return strings.Join(defaultVals, ", ")
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
@ -134,9 +122,9 @@ func (f *UintSliceFlag) GetDefaultText() string {
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// GetEnvVars returns the env vars for this flag
|
||||
func (f *UintSliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *UintSliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
@ -183,17 +171,6 @@ func (f *UintSliceFlag) Get(ctx *Context) []uint {
|
||||
return ctx.UintSlice(f.Name)
|
||||
}
|
||||
|
||||
func (f *UintSliceFlag) stringify() string {
|
||||
var defaultVals []string
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *UintSliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
|
@ -32,7 +32,7 @@ var (
|
||||
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
|
||||
)
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||
@ -41,52 +41,39 @@ VERSION:
|
||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}{{if len .Authors}}
|
||||
{{template "descriptionTemplate" .}}{{end}}
|
||||
{{- if len .Authors}}
|
||||
|
||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||
AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}}
|
||||
COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
{{end}}{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
|
||||
GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||
{{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}}
|
||||
GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}}
|
||||
|
||||
COPYRIGHT:
|
||||
{{wrap .Copyright 3}}{{end}}
|
||||
{{template "copyrightTemplate" .}}{{end}}
|
||||
`
|
||||
AppHelpTemplate is the text template for the Default help topic. cli.go
|
||||
uses text/template to render templates. You can render custom help text by
|
||||
setting this variable.
|
||||
|
||||
var CommandHelpTemplate = `NAME:
|
||||
{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
|
||||
{{template "usageTemplate" .}}{{if .Category}}
|
||||
|
||||
CATEGORY:
|
||||
{{.Category}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}}
|
||||
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
OPTIONS:{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
{{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}}
|
||||
OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}}
|
||||
`
|
||||
OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}`
|
||||
CommandHelpTemplate is the text template for the command help topic. cli.go
|
||||
uses text/template to render templates. You can render custom help text by
|
||||
setting this variable.
|
||||
@ -145,22 +132,19 @@ var OsExiter = os.Exit
|
||||
os.Exit.
|
||||
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}
|
||||
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}{{end}}{{end}}
|
||||
`
|
||||
OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}`
|
||||
SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||
cli.go uses text/template to render templates. You can render custom help
|
||||
text by setting this variable.
|
||||
@ -586,6 +570,9 @@ func (c *Command) Run(ctx *Context) (err error)
|
||||
Run invokes the command given the context, parses ctx.Args() to generate
|
||||
command-specific flags
|
||||
|
||||
func (c *Command) VisibleCommands() []*Command
|
||||
VisibleCommands returns a slice of the Commands with Hidden=false
|
||||
|
||||
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory
|
||||
VisibleFlagCategories returns a slice containing all the visible flag
|
||||
categories with the flags they contain
|
||||
@ -754,6 +741,14 @@ type DocGenerationFlag interface {
|
||||
DocGenerationFlag is an interface that allows documentation generation for
|
||||
the flag
|
||||
|
||||
type DocGenerationSliceFlag interface {
|
||||
DocGenerationFlag
|
||||
|
||||
// IsSliceFlag returns true for flags that can be given multiple times.
|
||||
IsSliceFlag() bool
|
||||
}
|
||||
DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags.
|
||||
|
||||
type DurationFlag struct {
|
||||
Name string
|
||||
|
||||
@ -1077,6 +1072,9 @@ func (f *Float64SliceFlag) IsRequired() bool
|
||||
func (f *Float64SliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *Float64SliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *Float64SliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -1312,6 +1310,9 @@ func (f *Int64SliceFlag) IsRequired() bool
|
||||
func (f *Int64SliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *Int64SliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *Int64SliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -1477,6 +1478,9 @@ func (f *IntSliceFlag) IsRequired() bool
|
||||
func (f *IntSliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *IntSliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *IntSliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -1817,6 +1821,9 @@ func (f *StringSliceFlag) IsRequired() bool
|
||||
func (f *StringSliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *StringSliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *StringSliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -2057,7 +2064,7 @@ func (f *Uint64SliceFlag) Get(ctx *Context) []uint64
|
||||
Get returns the flag’s value in the given Context.
|
||||
|
||||
func (f *Uint64SliceFlag) GetCategory() string
|
||||
GetCategory returns the category for the flag
|
||||
GetCategory returns the category of the flag
|
||||
|
||||
func (f *Uint64SliceFlag) GetDefaultText() string
|
||||
GetDefaultText returns the default text for this flag
|
||||
@ -2078,6 +2085,9 @@ func (f *Uint64SliceFlag) IsRequired() bool
|
||||
func (f *Uint64SliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *Uint64SliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *Uint64SliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -2091,7 +2101,7 @@ func (f *Uint64SliceFlag) String() string
|
||||
String returns a readable representation of this value (for usage defaults)
|
||||
|
||||
func (f *Uint64SliceFlag) TakesValue() bool
|
||||
TakesValue returns true of the flag takes a value, otherwise false
|
||||
TakesValue returns true if the flag takes a value, otherwise false
|
||||
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
@ -2216,7 +2226,7 @@ func (f *UintSliceFlag) Get(ctx *Context) []uint
|
||||
Get returns the flag’s value in the given Context.
|
||||
|
||||
func (f *UintSliceFlag) GetCategory() string
|
||||
GetCategory returns the category for the flag
|
||||
GetCategory returns the category of the flag
|
||||
|
||||
func (f *UintSliceFlag) GetDefaultText() string
|
||||
GetDefaultText returns the default text for this flag
|
||||
@ -2237,6 +2247,9 @@ func (f *UintSliceFlag) IsRequired() bool
|
||||
func (f *UintSliceFlag) IsSet() bool
|
||||
IsSet returns whether or not the flag has been set through env or file
|
||||
|
||||
func (f *UintSliceFlag) IsSliceFlag() bool
|
||||
IsSliceFlag implements DocGenerationSliceFlag.
|
||||
|
||||
func (f *UintSliceFlag) IsVisible() bool
|
||||
IsVisible returns true if the flag is not hidden, otherwise false
|
||||
|
||||
@ -2250,7 +2263,7 @@ func (f *UintSliceFlag) String() string
|
||||
String returns a readable representation of this value (for usage defaults)
|
||||
|
||||
func (f *UintSliceFlag) TakesValue() bool
|
||||
TakesValue returns true of the flag takes a value, otherwise false
|
||||
TakesValue returns true if the flag takes a value, otherwise false
|
||||
|
||||
type VisibleFlag interface {
|
||||
Flag
|
||||
|
36
help.go
36
help.go
@ -242,7 +242,11 @@ func ShowCommandHelp(ctx *Context, command string) error {
|
||||
c.Subcommands = append(c.Subcommands, helpCommandDontUse)
|
||||
}
|
||||
if !ctx.App.HideHelp && HelpFlag != nil {
|
||||
c.appendFlag(HelpFlag)
|
||||
if c.flagCategories == nil {
|
||||
c.flagCategories = newFlagCategoriesFromFlags([]Flag{HelpFlag})
|
||||
} else {
|
||||
c.flagCategories.AddFlag("", HelpFlag)
|
||||
}
|
||||
}
|
||||
templ := c.CustomHelpTemplate
|
||||
if templ == "" {
|
||||
@ -358,6 +362,17 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs
|
||||
|
||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||
t.New("helpNameTemplate").Parse(helpNameTemplate)
|
||||
t.New("usageTemplate").Parse(usageTemplate)
|
||||
t.New("descriptionTemplate").Parse(descriptionTemplate)
|
||||
t.New("visibleCommandTemplate").Parse(visibleCommandTemplate)
|
||||
t.New("copyrightTemplate").Parse(copyrightTemplate)
|
||||
t.New("versionTemplate").Parse(versionTemplate)
|
||||
t.New("visibleFlagCategoryTemplate").Parse(visibleFlagCategoryTemplate)
|
||||
t.New("visibleFlagTemplate").Parse(visibleFlagTemplate)
|
||||
t.New("visibleGlobalFlagCategoryTemplate").Parse(strings.Replace(visibleFlagCategoryTemplate, "OPTIONS", "GLOBAL OPTIONS", -1))
|
||||
t.New("authorsTemplate").Parse(authorsTemplate)
|
||||
t.New("visibleCommandCategoryTemplate").Parse(visibleCommandCategoryTemplate)
|
||||
|
||||
err := t.Execute(w, data)
|
||||
if err != nil {
|
||||
@ -468,25 +483,28 @@ func nindent(spaces int, v string) string {
|
||||
}
|
||||
|
||||
func wrap(input string, offset int, wrapAt int) string {
|
||||
var sb strings.Builder
|
||||
var ss []string
|
||||
|
||||
lines := strings.Split(input, "\n")
|
||||
|
||||
padding := strings.Repeat(" ", offset)
|
||||
|
||||
for i, line := range lines {
|
||||
if i != 0 {
|
||||
sb.WriteString(padding)
|
||||
}
|
||||
if line == "" {
|
||||
ss = append(ss, line)
|
||||
} else {
|
||||
wrapped := wrapLine(line, offset, wrapAt, padding)
|
||||
if i == 0 {
|
||||
ss = append(ss, wrapped)
|
||||
} else {
|
||||
ss = append(ss, padding+wrapped)
|
||||
|
||||
sb.WriteString(wrapLine(line, offset, wrapAt, padding))
|
||||
}
|
||||
|
||||
if i != len(lines)-1 {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
return strings.Join(ss, "\n")
|
||||
}
|
||||
|
||||
func wrapLine(input string, offset int, wrapAt int, padding string) string {
|
||||
|
89
help_test.go
89
help_test.go
@ -1213,6 +1213,13 @@ func TestDefaultCompleteWithFlags(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
emptywrap := wrap("", 4, 16)
|
||||
if emptywrap != "" {
|
||||
t.Errorf("Wrapping empty line should return empty line. Got '%s'.", emptywrap)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrappedHelp(t *testing.T) {
|
||||
|
||||
// Reset HelpPrinter after this test.
|
||||
@ -1276,7 +1283,7 @@ DESCRIPTION:
|
||||
App.Description string long
|
||||
enough that it should be
|
||||
wrapped in this test
|
||||
|
||||
|
||||
with a newline
|
||||
and an indented line
|
||||
|
||||
@ -1294,8 +1301,8 @@ COPYRIGHT:
|
||||
that it should be wrapped.
|
||||
Including newlines.
|
||||
And also indented lines.
|
||||
|
||||
|
||||
|
||||
|
||||
And then another long line.
|
||||
Blah blah blah does anybody
|
||||
ever read these things?
|
||||
@ -1436,3 +1443,79 @@ OPTIONS:
|
||||
output.String(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrappedHelpSubcommand(t *testing.T) {
|
||||
|
||||
// Reset HelpPrinter after this test.
|
||||
defer func(old helpPrinter) {
|
||||
HelpPrinter = old
|
||||
}(HelpPrinter)
|
||||
|
||||
output := new(bytes.Buffer)
|
||||
app := &App{
|
||||
Name: "cli.test",
|
||||
Writer: output,
|
||||
Commands: []*Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
UsageText: "this is an even longer way of describing adding a task to the list",
|
||||
Description: "and a description long enough to wrap in this test case",
|
||||
Action: func(c *Context) error {
|
||||
return nil
|
||||
},
|
||||
Subcommands: []*Command{
|
||||
{
|
||||
Name: "grok",
|
||||
Usage: "remove an existing template",
|
||||
UsageText: "longer usage text goes here, la la la, hopefully this is long enough to wrap even more",
|
||||
Action: func(c *Context) error {
|
||||
return nil
|
||||
},
|
||||
Flags: []Flag{
|
||||
&StringFlag{
|
||||
Name: "test-f",
|
||||
Usage: "my test usage",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
HelpPrinter = func(w io.Writer, templ string, data interface{}) {
|
||||
funcMap := map[string]interface{}{
|
||||
"wrapAt": func() int {
|
||||
return 30
|
||||
},
|
||||
}
|
||||
|
||||
HelpPrinterCustom(w, templ, data, funcMap)
|
||||
}
|
||||
|
||||
_ = app.Run([]string{"foo", "bar", "help", "grok"})
|
||||
|
||||
expected := `NAME:
|
||||
cli.test bar grok - remove
|
||||
an
|
||||
existing
|
||||
template
|
||||
|
||||
USAGE:
|
||||
longer usage text goes
|
||||
here, la la la, hopefully
|
||||
this is long enough to wrap
|
||||
even more
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
--test-f value my test usage
|
||||
`
|
||||
|
||||
if output.String() != expected {
|
||||
t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s",
|
||||
output.String(), expected)
|
||||
}
|
||||
}
|
||||
|
12
parse.go
12
parse.go
@ -46,7 +46,10 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple
|
||||
}
|
||||
|
||||
// swap current argument with the split version
|
||||
args = append(args[:i], append(shortOpts, args[i+1:]...)...)
|
||||
// do not include args that parsed correctly so far as it would
|
||||
// trigger Value.Set() on those args and would result in
|
||||
// duplicates for slice type flags
|
||||
args = append(shortOpts, args[i+1:]...)
|
||||
argsWereSplit = true
|
||||
break
|
||||
}
|
||||
@ -56,13 +59,6 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple
|
||||
if !argsWereSplit {
|
||||
return err
|
||||
}
|
||||
|
||||
// Since custom parsing failed, replace the flag set before retrying
|
||||
newSet, err := ip.newFlagSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*set = *newSet
|
||||
}
|
||||
}
|
||||
|
||||
|
82
template.go
82
template.go
@ -1,10 +1,38 @@
|
||||
package cli
|
||||
|
||||
var helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}`
|
||||
var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}`
|
||||
var descriptionTemplate = `{{wrap .Description 3}}`
|
||||
var authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}`
|
||||
var visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}`
|
||||
var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}`
|
||||
var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
|
||||
{{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}
|
||||
{{else}}{{$e}}
|
||||
{{end}}{{end}}{{end}}`
|
||||
|
||||
var visibleFlagTemplate = `{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}}
|
||||
{{wrap $option.String 6}}{{end}}`
|
||||
|
||||
var versionTemplate = `{{if .Version}}{{if not .HideVersion}}
|
||||
|
||||
VERSION:
|
||||
{{.Version}}{{end}}{{end}}`
|
||||
|
||||
var copyrightTemplate = `{{wrap .Copyright 3}}`
|
||||
|
||||
// AppHelpTemplate is the text template for the Default help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||
@ -13,73 +41,57 @@ VERSION:
|
||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}{{if len .Authors}}
|
||||
{{template "descriptionTemplate" .}}{{end}}
|
||||
{{- if len .Authors}}
|
||||
|
||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||
AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}}
|
||||
COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
{{end}}{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
|
||||
GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||
{{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}}
|
||||
GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}}
|
||||
|
||||
COPYRIGHT:
|
||||
{{wrap .Copyright 3}}{{end}}
|
||||
{{template "copyrightTemplate" .}}{{end}}
|
||||
`
|
||||
|
||||
// CommandHelpTemplate is the text template for the command help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var CommandHelpTemplate = `NAME:
|
||||
{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
|
||||
{{template "usageTemplate" .}}{{if .Category}}
|
||||
|
||||
CATEGORY:
|
||||
{{.Category}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}}
|
||||
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
OPTIONS:{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
{{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}}
|
||||
OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}}
|
||||
`
|
||||
OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}`
|
||||
|
||||
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{wrap .Description 3}}{{end}}
|
||||
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}{{end}}{{end}}
|
||||
`
|
||||
OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}`
|
||||
|
||||
var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }}
|
||||
|
||||
|
@ -66,14 +66,6 @@ func (f *Float64SliceFlag) TakesValue() bool {
|
||||
return "Float64SliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Float64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// GenericFlag is a flag with type Generic
|
||||
type GenericFlag struct {
|
||||
Name string
|
||||
@ -143,14 +135,6 @@ func (f *GenericFlag) TakesValue() bool {
|
||||
return "GenericFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *GenericFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Int64SliceFlag is a flag with type *Int64Slice
|
||||
type Int64SliceFlag struct {
|
||||
Name string
|
||||
@ -213,14 +197,6 @@ func (f *Int64SliceFlag) TakesValue() bool {
|
||||
return "Int64SliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64SliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IntSliceFlag is a flag with type *IntSlice
|
||||
type IntSliceFlag struct {
|
||||
Name string
|
||||
@ -283,14 +259,6 @@ func (f *IntSliceFlag) TakesValue() bool {
|
||||
return "IntSliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// PathFlag is a flag with type Path
|
||||
type PathFlag struct {
|
||||
Name string
|
||||
@ -424,14 +392,6 @@ func (f *StringSliceFlag) TakesValue() bool {
|
||||
return "StringSliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *StringSliceFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// TimestampFlag is a flag with type *Timestamp
|
||||
type TimestampFlag struct {
|
||||
Name string
|
||||
@ -503,14 +463,6 @@ func (f *TimestampFlag) TakesValue() bool {
|
||||
return "TimestampFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *TimestampFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Uint64SliceFlag is a flag with type *Uint64Slice
|
||||
type Uint64SliceFlag struct {
|
||||
Name string
|
||||
@ -553,6 +505,26 @@ func (f *Uint64SliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetCategory returns the category of the flag
|
||||
func (f *Uint64SliceFlag) GetCategory() string {
|
||||
return f.Category
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag
|
||||
func (f *Uint64SliceFlag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// GetEnvVars returns the env vars for this flag
|
||||
func (f *Uint64SliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// TakesValue returns true if the flag takes a value, otherwise false
|
||||
func (f *Uint64SliceFlag) TakesValue() bool {
|
||||
return "Uint64SliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// UintSliceFlag is a flag with type *UintSlice
|
||||
type UintSliceFlag struct {
|
||||
Name string
|
||||
@ -595,6 +567,26 @@ func (f *UintSliceFlag) IsVisible() bool {
|
||||
return !f.Hidden
|
||||
}
|
||||
|
||||
// GetCategory returns the category of the flag
|
||||
func (f *UintSliceFlag) GetCategory() string {
|
||||
return f.Category
|
||||
}
|
||||
|
||||
// GetUsage returns the usage string for the flag
|
||||
func (f *UintSliceFlag) GetUsage() string {
|
||||
return f.Usage
|
||||
}
|
||||
|
||||
// GetEnvVars returns the env vars for this flag
|
||||
func (f *UintSliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// TakesValue returns true if the flag takes a value, otherwise false
|
||||
func (f *UintSliceFlag) TakesValue() bool {
|
||||
return "UintSliceFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// BoolFlag is a flag with type bool
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
@ -731,14 +723,6 @@ func (f *Float64Flag) TakesValue() bool {
|
||||
return "Float64Flag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Float64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// IntFlag is a flag with type int
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
@ -808,14 +792,6 @@ func (f *IntFlag) TakesValue() bool {
|
||||
return "IntFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *IntFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Int64Flag is a flag with type int64
|
||||
type Int64Flag struct {
|
||||
Name string
|
||||
@ -885,14 +861,6 @@ func (f *Int64Flag) TakesValue() bool {
|
||||
return "Int64Flag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Int64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// StringFlag is a flag with type string
|
||||
type StringFlag struct {
|
||||
Name string
|
||||
@ -1029,14 +997,6 @@ func (f *DurationFlag) TakesValue() bool {
|
||||
return "DurationFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *DurationFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// UintFlag is a flag with type uint
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
@ -1106,14 +1066,6 @@ func (f *UintFlag) TakesValue() bool {
|
||||
return "UintFlag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *UintFlag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// Uint64Flag is a flag with type uint64
|
||||
type Uint64Flag struct {
|
||||
Name string
|
||||
@ -1183,12 +1135,4 @@ func (f *Uint64Flag) TakesValue() bool {
|
||||
return "Uint64Flag" != "BoolFlag"
|
||||
}
|
||||
|
||||
// GetDefaultText returns the default text for this flag
|
||||
func (f *Uint64Flag) GetDefaultText() string {
|
||||
if f.DefaultText != "" {
|
||||
return f.DefaultText
|
||||
}
|
||||
return f.GetValue()
|
||||
}
|
||||
|
||||
// vim:ro
|
||||
|
@ -167,6 +167,18 @@ func TestUint64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestUint64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.Uint64SliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestUint64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.Uint64SliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestUintSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.UintSliceFlag{}
|
||||
|
||||
@ -174,6 +186,18 @@ func TestUintSliceFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
_ = f.Names()
|
||||
}
|
||||
|
||||
func TestUintSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
|
||||
var f cli.RequiredFlag = &cli.UintSliceFlag{}
|
||||
|
||||
_ = f.IsRequired()
|
||||
}
|
||||
|
||||
func TestUintSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
|
||||
var f cli.VisibleFlag = &cli.UintSliceFlag{}
|
||||
|
||||
_ = f.IsVisible()
|
||||
}
|
||||
|
||||
func TestBoolFlag_SatisfiesFlagInterface(t *testing.T) {
|
||||
var f cli.Flag = &cli.BoolFlag{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user