diff --git a/docs.go b/docs.go index 8ea5045..0c352b0 100644 --- a/docs.go +++ b/docs.go @@ -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 @@ -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) @@ -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(), "" } diff --git a/docs_test.go b/docs_test.go index d4085eb..e489751 100644 --- a/docs_test.go +++ b/docs_test.go @@ -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))), ) } @@ -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", @@ -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"}, @@ -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") @@ -186,7 +191,7 @@ func TestToTabularMarkdownFailed(t *testing.T) { MarkdownTabularDocTemplate = "{{ .Foo }}" - app := buildExtendedTestCommand() + app := buildExtendedTestCommand(t) res, err := ToTabularMarkdown(app, "") @@ -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) @@ -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) @@ -291,7 +296,7 @@ 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) }) @@ -299,7 +304,7 @@ Some other text`)) 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) @@ -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) @@ -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) @@ -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) @@ -340,7 +345,7 @@ func TestToMarkdown(t *testing.T) { } func TestToMan(t *testing.T) { - app := buildExtendedTestCommand() + app := buildExtendedTestCommand(t) res, err := ToMan(app) @@ -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 }) @@ -361,7 +366,7 @@ func TestToManParseError(t *testing.T) { } func TestToManWithSection(t *testing.T) { - cmd := buildExtendedTestCommand() + cmd := buildExtendedTestCommand(t) res, err := ToManWithSection(cmd, 8) diff --git a/markdown_tabular.md.gotmpl b/markdown_tabular.md.gotmpl index 4697d33..4535688 100644 --- a/markdown_tabular.md.gotmpl +++ b/markdown_tabular.md.gotmpl @@ -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 -}} diff --git a/testdata/expected-doc-full.man b/testdata/expected-doc-full.man index a2131f0..573893c 100644 --- a/testdata/expected-doc-full.man +++ b/testdata/expected-doc-full.man @@ -17,6 +17,7 @@ greet [--another-flag|-b] [--flag|--fl|-f]=[value] [--socket|-s]=[value] +[--temp-dir]=[value] .fi .RE @@ -41,7 +42,7 @@ 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="": @@ -49,6 +50,9 @@ app [first_arg] [second_arg] .PP \fB--socket, -s\fP="": some 'usage' text (default: value) +.PP +\fB--temp-dir\fP="": (default: test temp dir) + .SH COMMANDS .SH config, c @@ -56,7 +60,7 @@ app [first_arg] [second_arg] 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="": @@ -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="": @@ -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="": @@ -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) diff --git a/testdata/expected-doc-full.md b/testdata/expected-doc-full.md index 80ff6a7..d74511b 100644 --- a/testdata/expected-doc-full.md +++ b/testdata/expected-doc-full.md @@ -10,6 +10,7 @@ greet [--another-flag|-b] [--flag|--fl|-f]=[value] [--socket|-s]=[value] +[--temp-dir]=[value] ``` # DESCRIPTION @@ -24,12 +25,14 @@ 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 @@ -37,7 +40,7 @@ app [first_arg] [second_arg] another usage test -**--another-flag, -b**: another usage text +**--another-flag, -b**: another usage text (default: false) **--flag, --fl, -f**="": @@ -45,7 +48,7 @@ another usage test another usage test -**--sub-command-flag, -s**: some usage text +**--sub-command-flag, -s**: some usage text (default: false) **--sub-flag, --sub-fl, -s**="": @@ -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**="": @@ -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) diff --git a/testdata/expected-doc-no-authors.md b/testdata/expected-doc-no-authors.md index 80ff6a7..d74511b 100644 --- a/testdata/expected-doc-no-authors.md +++ b/testdata/expected-doc-no-authors.md @@ -10,6 +10,7 @@ greet [--another-flag|-b] [--flag|--fl|-f]=[value] [--socket|-s]=[value] +[--temp-dir]=[value] ``` # DESCRIPTION @@ -24,12 +25,14 @@ 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 @@ -37,7 +40,7 @@ app [first_arg] [second_arg] another usage test -**--another-flag, -b**: another usage text +**--another-flag, -b**: another usage text (default: false) **--flag, --fl, -f**="": @@ -45,7 +48,7 @@ another usage test another usage test -**--sub-command-flag, -s**: some usage text +**--sub-command-flag, -s**: some usage text (default: false) **--sub-flag, --sub-fl, -s**="": @@ -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**="": @@ -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) diff --git a/testdata/expected-doc-no-commands.md b/testdata/expected-doc-no-commands.md index 4db2a37..a22b02f 100644 --- a/testdata/expected-doc-no-commands.md +++ b/testdata/expected-doc-no-commands.md @@ -10,6 +10,7 @@ greet [--another-flag|-b] [--flag|--fl|-f]=[value] [--socket|-s]=[value] +[--temp-dir]=[value] ``` # DESCRIPTION @@ -24,9 +25,11 @@ 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) + diff --git a/testdata/expected-doc-no-flags.md b/testdata/expected-doc-no-flags.md index 33d1275..e8b64aa 100644 --- a/testdata/expected-doc-no-flags.md +++ b/testdata/expected-doc-no-flags.md @@ -22,7 +22,7 @@ app [first_arg] [second_arg] another usage test -**--another-flag, -b**: another usage text +**--another-flag, -b**: another usage text (default: false) **--flag, --fl, -f**="": @@ -30,7 +30,7 @@ another usage test another usage test -**--sub-command-flag, -s**: some usage text +**--sub-command-flag, -s**: some usage text (default: false) **--sub-flag, --sub-fl, -s**="": @@ -56,7 +56,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**="": @@ -66,4 +66,4 @@ standard usage text >Single line of UsageText -**--sub-command-flag, -s**: some usage text +**--sub-command-flag, -s**: some usage text (default: false) diff --git a/testdata/expected-doc-no-usagetext.md b/testdata/expected-doc-no-usagetext.md index fab4ba1..fb0c679 100644 --- a/testdata/expected-doc-no-usagetext.md +++ b/testdata/expected-doc-no-usagetext.md @@ -10,6 +10,7 @@ greet [--another-flag|-b] [--flag|--fl|-f]=[value] [--socket|-s]=[value] +[--temp-dir]=[value] ``` # DESCRIPTION @@ -24,12 +25,14 @@ greet [GLOBAL OPTIONS] [command [COMMAND OPTIONS]] [ARGUMENTS...] # 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 @@ -37,7 +40,7 @@ greet [GLOBAL OPTIONS] [command [COMMAND OPTIONS]] [ARGUMENTS...] another usage test -**--another-flag, -b**: another usage text +**--another-flag, -b**: another usage text (default: false) **--flag, --fl, -f**="": @@ -45,7 +48,7 @@ another usage test another usage test -**--sub-command-flag, -s**: some usage text +**--sub-command-flag, -s**: some usage text (default: false) **--sub-flag, --sub-fl, -s**="": @@ -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**="": @@ -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) diff --git a/testdata/expected-tabular-markdown-custom-app-path.md b/testdata/expected-tabular-markdown-custom-app-path.md index a972c06..5a1b583 100644 --- a/testdata/expected-tabular-markdown-custom-app-path.md +++ b/testdata/expected-tabular-markdown-custom-app-path.md @@ -19,6 +19,7 @@ Global flags: | `--socket="…"` (`-s`) | some 'usage' text | string | `value` | *none* | | `--flag="…"` (`--fl`, `-f`) | | string | | *none* | | `--another-flag` (`-b`) | another usage text | bool | `false` | `EXAMPLE_VARIABLE_NAME` | +| `--temp-dir="…"` | | string | test temp dir | *none* | ### `config` command (aliases: `c`) diff --git a/testdata/expected-tabular-markdown-full.md b/testdata/expected-tabular-markdown-full.md index 165371e..985a4c4 100644 --- a/testdata/expected-tabular-markdown-full.md +++ b/testdata/expected-tabular-markdown-full.md @@ -19,6 +19,7 @@ Global flags: | `--socket="…"` (`-s`) | some 'usage' text | string | `value` | *none* | | `--flag="…"` (`--fl`, `-f`) | | string | | *none* | | `--another-flag` (`-b`) | another usage text | bool | `false` | `EXAMPLE_VARIABLE_NAME` | +| `--temp-dir="…"` | | string | test temp dir | *none* | ### `config` command (aliases: `c`)