Merge branch 'main' into issue_1500
This commit is contained in:
commit
fb23ff4aa2
2
.github/workflows/cli.yml
vendored
2
.github/workflows/cli.yml
vendored
@ -40,6 +40,8 @@ jobs:
|
||||
GFLAGS: -tags urfave_cli_no_docs
|
||||
- run: make check-binary-size
|
||||
- run: make yamlfmt
|
||||
- if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest'
|
||||
run: make generate
|
||||
- run: make diffcheck
|
||||
- if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest'
|
||||
run: make v2diff
|
||||
|
@ -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
|
||||
|
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
@ -129,6 +129,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
|
||||
}
|
||||
|
||||
// VisibleFlag is an interface that allows to check if a flag is visible
|
||||
type VisibleFlag interface {
|
||||
Flag
|
||||
@ -325,24 +333,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 {
|
||||
|
@ -83,7 +83,7 @@ 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)
|
||||
}
|
||||
|
||||
// TakesValue returns true if the flag takes a value, otherwise false
|
||||
@ -104,10 +104,13 @@ func (f *Float64SliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -123,6 +126,11 @@ func (f *Float64SliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *Float64SliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -169,18 +177,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 {
|
||||
|
@ -62,6 +62,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)
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ 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)
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
@ -105,10 +105,13 @@ func (f *Int64SliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -124,6 +127,11 @@ func (f *Int64SliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *Int64SliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -168,17 +176,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,7 +95,7 @@ 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)
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
@ -116,10 +116,13 @@ func (f *IntSliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -135,6 +138,11 @@ func (f *IntSliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *IntSliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -188,17 +196,6 @@ func (f *IntSliceFlag) RunAction(c *Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// IntSlice looks up the value of a local IntSliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) IntSlice(name string) []int {
|
||||
|
@ -74,7 +74,7 @@ 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)
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
@ -95,10 +95,15 @@ func (f *StringSliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -114,6 +119,11 @@ func (f *StringSliceFlag) GetEnvVars() []string {
|
||||
return f.EnvVars
|
||||
}
|
||||
|
||||
// IsSliceFlag implements DocGenerationSliceFlag.
|
||||
func (f *StringSliceFlag) IsSliceFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -158,19 +168,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 {
|
||||
|
67
flag_test.go
67
flag_test.go
@ -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()
|
||||
|
@ -88,7 +88,7 @@ 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())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
@ -109,10 +109,13 @@ func (f *Uint64SliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -128,6 +131,11 @@ 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
|
||||
func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -172,17 +180,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)
|
||||
}
|
||||
|
||||
// Uint64Slice looks up the value of a local Uint64SliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) Uint64Slice(name string) []uint64 {
|
||||
|
@ -99,7 +99,7 @@ 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())
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// TakesValue returns true of the flag takes a value, otherwise false
|
||||
@ -120,10 +120,13 @@ func (f *UintSliceFlag) GetCategory() string {
|
||||
// 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
|
||||
@ -139,6 +142,11 @@ 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
|
||||
func (f *UintSliceFlag) Apply(set *flag.FlagSet) error {
|
||||
// apply any default
|
||||
@ -183,17 +191,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)
|
||||
}
|
||||
|
||||
// UintSlice looks up the value of a local UintSliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) UintSlice(name string) []uint {
|
||||
|
@ -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.
|
||||
@ -585,6 +569,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
|
||||
@ -753,6 +740,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
|
||||
|
||||
@ -1071,6 +1066,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
|
||||
|
||||
@ -1306,6 +1304,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
|
||||
|
||||
@ -1471,6 +1472,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
|
||||
|
||||
@ -1810,6 +1814,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
|
||||
|
||||
@ -2071,6 +2078,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
|
||||
|
||||
@ -2227,6 +2237,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
|
||||
|
||||
|
17
help.go
17
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 {
|
||||
|
76
help_test.go
76
help_test.go
@ -1443,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)
|
||||
}
|
||||
}
|
||||
|
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 }}
|
||||
|
||||
|
83
testdata/godoc-v2.x.txt
vendored
83
testdata/godoc-v2.x.txt
vendored
@ -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.
|
||||
@ -585,6 +569,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
|
||||
@ -753,6 +740,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
|
||||
|
||||
@ -1071,6 +1066,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
|
||||
|
||||
@ -1306,6 +1304,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
|
||||
|
||||
@ -1471,6 +1472,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
|
||||
|
||||
@ -1810,6 +1814,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
|
||||
|
||||
@ -2071,6 +2078,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
|
||||
|
||||
@ -2227,6 +2237,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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user