Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 29 additions & 32 deletions docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,10 @@ func prepareFlags(
// flagDetails returns a string containing the flags metadata
func flagDetails(flag cli.DocGenerationFlag) string {
description := flag.GetUsage()
value := getFlagDefaultValue(flag)
if value != "" {
value, defaultText := getFlagDefaultValue(flag)
if defaultText != "" {
description += " (default: " + defaultText + ")"
} else if value != "" {
description += " (default: " + value + ")"
}
return ": " + description
Expand Down Expand Up @@ -402,18 +404,22 @@ func (tt tabularTemplate) PrepareFlags(flags []cli.Flag) []cliTabularFlagTemplat
continue
}

value, defaultText := getFlagDefaultValue(flag)
defaultValue := ""
if defaultText != "" {
defaultValue = defaultText
} else if value != "" {
defaultValue = fmt.Sprintf("`%s`", value)
}

f := cliTabularFlagTemplate{
Usage: tt.PrepareMultilineString(flag.GetUsage()),
EnvVars: flag.GetEnvVars(),
TakesValue: flag.TakesValue(),
Default: getFlagDefaultValue(flag),
Default: defaultValue,
Type: flag.TypeName(),
}

if boolFlag, isBool := appFlag.(*cli.BoolFlag); isBool {
f.Default = strconv.FormatBool(boolFlag.Value)
}

for i, name := range appFlag.Names() {
name = strings.TrimSpace(name)

Expand Down Expand Up @@ -558,33 +564,24 @@ func (tabularTemplate) Prettify(s string) string {
return s + "\n" // add an extra newline
}

// getFlagDefaultValue returns the default value of a flag. Previously, the [cli.DocGenerationFlag] interface included
// a GetValue string method, but it was removed in https://github.com/urfave/cli/pull/1988.
// This function serves as a workaround, attempting to retrieve the value using the removed method; if that fails, it
// tries to obtain it via reflection (the [cli.FlagBase] still has a Value field).
func getFlagDefaultValue(f cli.DocGenerationFlag) string {
if !f.TakesValue() {
return ""
}

if v, ok := f.(interface{ GetValue() string }); ok {
return v.GetValue()
}

ref := reflect.ValueOf(f)
if ref.Kind() != reflect.Ptr {
return ""
} else {
ref = ref.Elem()
}

if ref.Kind() != reflect.Struct {
return ""
// getFlagDefaultValue returns the default text or default value of a flag.
// cli.BoolFlag will always return an default.
func getFlagDefaultValue(f cli.DocGenerationFlag) (value, text string) {
// GetDefaultText also returns GetValue so we have to use reflection
if ref := reflect.ValueOf(f); ref.Kind() == reflect.Ptr && ref.Elem().Kind() == reflect.Struct {
if val := ref.Elem().FieldByName("DefaultText"); val.IsValid() && val.Type().Kind() == reflect.String {
if defaultText := val.Interface().(string); defaultText != "" {
return "", defaultText
}
}
}

if val := ref.FieldByName("Value"); val.IsValid() && val.Type().Kind() != reflect.Bool {
return fmt.Sprintf("%v", val.Interface())
if !f.TakesValue() {
if boolFlag, isBool := f.(*cli.BoolFlag); isBool {
return strconv.FormatBool(boolFlag.Value), ""
}
return "", ""
}

return ""
return f.GetValue(), ""
}
35 changes: 20 additions & 15 deletions docs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ func expectFileContent(t *testing.T, file, got string) {
r := require.New(t)
r.NoError(err)
r.Equal(
string(normalizeNewlines([]byte(got))),
string(normalizeNewlines(data)),
string(normalizeNewlines([]byte(got))),
)
}

Expand All @@ -37,7 +37,7 @@ func normalizeNewlines(d []byte) []byte {
)
}

func buildExtendedTestCommand() *cli.Command {
func buildExtendedTestCommand(t *testing.T) *cli.Command {
return &cli.Command{
Writer: io.Discard,
Name: "greet",
Expand All @@ -60,6 +60,11 @@ func buildExtendedTestCommand() *cli.Command {
Name: "hidden-flag",
Hidden: true,
},
&cli.StringFlag{
Name: "temp-dir",
Value: t.TempDir(),
DefaultText: "test temp dir",
},
},
Commands: []*cli.Command{{
Aliases: []string{"c"},
Expand Down Expand Up @@ -152,14 +157,14 @@ Should be a part of the same code block
}

func TestToMarkdownFull(t *testing.T) {
cmd := buildExtendedTestCommand()
cmd := buildExtendedTestCommand(t)
res, err := ToMarkdown(cmd)
require.NoError(t, err)
expectFileContent(t, "testdata/expected-doc-full.md", res)
}

func TestToTabularMarkdown(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)

t.Run("full", func(t *testing.T) {
res, err := ToTabularMarkdown(app, "app")
Expand All @@ -186,7 +191,7 @@ func TestToTabularMarkdownFailed(t *testing.T) {

MarkdownTabularDocTemplate = "{{ .Foo }}"

app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)

res, err := ToTabularMarkdown(app, "")

Expand Down Expand Up @@ -221,7 +226,7 @@ Some other text`)
r.NoError(err)
_ = tmpFile.Close()

r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(), "app", tmpFile.Name()))
r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(t), "app", tmpFile.Name()))

content, err := os.ReadFile(tmpFile.Name())
r.NoError(err)
Expand Down Expand Up @@ -261,7 +266,7 @@ Some other text`)
r.NoError(err)
_ = tmpFile.Close()

r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(), "app", tmpFile.Name(), "foo_BAR|baz", "lorem+ipsum"))
r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(t), "app", tmpFile.Name(), "foo_BAR|baz", "lorem+ipsum"))

content, err := os.ReadFile(tmpFile.Name())
r.NoError(err)
Expand Down Expand Up @@ -291,15 +296,15 @@ Some other text`))

r.NoError(os.Remove(tmpFile.Name()))

err = ToTabularToFileBetweenTags(buildExtendedTestCommand(), "app", tmpFile.Name())
err = ToTabularToFileBetweenTags(buildExtendedTestCommand(t), "app", tmpFile.Name())

r.ErrorIs(err, fs.ErrNotExist)
})
}

func TestToMarkdown(t *testing.T) {
t.Run("no flags", func(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)
app.Flags = nil

res, err := ToMarkdown(app)
Expand All @@ -309,7 +314,7 @@ func TestToMarkdown(t *testing.T) {
})

t.Run("no commands", func(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)
app.Commands = nil

res, err := ToMarkdown(app)
Expand All @@ -319,7 +324,7 @@ func TestToMarkdown(t *testing.T) {
})

t.Run("no authors", func(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)
app.Authors = []any{}

res, err := ToMarkdown(app)
Expand All @@ -329,7 +334,7 @@ func TestToMarkdown(t *testing.T) {
})

t.Run("no usage text", func(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)
app.UsageText = ""

res, err := ToMarkdown(app)
Expand All @@ -340,7 +345,7 @@ func TestToMarkdown(t *testing.T) {
}

func TestToMan(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)

res, err := ToMan(app)

Expand All @@ -349,7 +354,7 @@ func TestToMan(t *testing.T) {
}

func TestToManParseError(t *testing.T) {
app := buildExtendedTestCommand()
app := buildExtendedTestCommand(t)

tmp := MarkdownDocTemplate
t.Cleanup(func() { MarkdownDocTemplate = tmp })
Expand All @@ -361,7 +366,7 @@ func TestToManParseError(t *testing.T) {
}

func TestToManWithSection(t *testing.T) {
cmd := buildExtendedTestCommand()
cmd := buildExtendedTestCommand(t)

res, err := ToManWithSection(cmd, 8)

Expand Down
2 changes: 1 addition & 1 deletion markdown_tabular.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{- /**/ -}} | `{{ $flag.Name }}{{ if $flag.TakesValue }}="…"{{ end }}` {{ if $flag.Aliases }}(`{{ join $flag.Aliases "`, `" }}`) {{ end }}
{{- /**/ -}} | {{ $flag.Usage }}
{{- /**/ -}} | {{ $flag.Type }}
{{- /**/ -}} | {{ if $flag.Default }}`{{ $flag.Default }}`{{ end }}
{{- /**/ -}} | {{ if $flag.Default }}{{ $flag.Default }}{{ end }}
{{- if $hasEnvVars -}}
{{- /**/ -}} | {{ if $flag.EnvVars }}`{{ join $flag.EnvVars "`, `" }}`{{ else }}*none*{{ end }}
{{- end -}}
Expand Down
14 changes: 9 additions & 5 deletions testdata/expected-doc-full.man
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ greet
[--another-flag|-b]
[--flag|--fl|-f]=[value]
[--socket|-s]=[value]
[--temp-dir]=[value]

.fi
.RE
Expand All @@ -41,22 +42,25 @@ app [first_arg] [second_arg]

.SH GLOBAL OPTIONS
.PP
\fB--another-flag, -b\fP: another usage text
\fB--another-flag, -b\fP: another usage text (default: false)

.PP
\fB--flag, --fl, -f\fP="":

.PP
\fB--socket, -s\fP="": some 'usage' text (default: value)

.PP
\fB--temp-dir\fP="": (default: test temp dir)


.SH COMMANDS
.SH config, c
.PP
another usage test

.PP
\fB--another-flag, -b\fP: another usage text
\fB--another-flag, -b\fP: another usage text (default: false)

.PP
\fB--flag, --fl, -f\fP="":
Expand All @@ -66,7 +70,7 @@ another usage test
another usage test

.PP
\fB--sub-command-flag, -s\fP: some usage text
\fB--sub-command-flag, -s\fP: some usage text (default: false)

.PP
\fB--sub-flag, --sub-fl, -s\fP="":
Expand Down Expand Up @@ -99,7 +103,7 @@ Should be a part of the same code block
.RE

.PP
\fB--another-flag, -b\fP: another usage text
\fB--another-flag, -b\fP: another usage text (default: false)

.PP
\fB--flag, --fl, -f\fP="":
Expand All @@ -117,4 +121,4 @@ Single line of UsageText
.RE

.PP
\fB--sub-command-flag, -s\fP: some usage text
\fB--sub-command-flag, -s\fP: some usage text (default: false)
13 changes: 8 additions & 5 deletions testdata/expected-doc-full.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ greet
[--another-flag|-b]
[--flag|--fl|-f]=[value]
[--socket|-s]=[value]
[--temp-dir]=[value]
```

# DESCRIPTION
Expand All @@ -24,28 +25,30 @@ app [first_arg] [second_arg]

# GLOBAL OPTIONS

**--another-flag, -b**: another usage text
**--another-flag, -b**: another usage text (default: false)

**--flag, --fl, -f**="":

**--socket, -s**="": some 'usage' text (default: value)

**--temp-dir**="": (default: test temp dir)


# COMMANDS

## config, c

another usage test

**--another-flag, -b**: another usage text
**--another-flag, -b**: another usage text (default: false)

**--flag, --fl, -f**="":

### sub-config, s, ss

another usage test

**--sub-command-flag, -s**: some usage text
**--sub-command-flag, -s**: some usage text (default: false)

**--sub-flag, --sub-fl, -s**="":

Expand All @@ -71,7 +74,7 @@ standard usage text

Should be a part of the same code block

**--another-flag, -b**: another usage text
**--another-flag, -b**: another usage text (default: false)

**--flag, --fl, -f**="":

Expand All @@ -81,4 +84,4 @@ standard usage text

>Single line of UsageText

**--sub-command-flag, -s**: some usage text
**--sub-command-flag, -s**: some usage text (default: false)
Loading
Loading