Skip to content

Commit 0333461

Browse files
authored
Merge pull request #17 from 6543-forks/DefaultText
Support DefaultText
2 parents 6d6ab09 + f25ae49 commit 0333461

11 files changed

+93
-73
lines changed

docs.go

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,10 @@ func prepareFlags(
278278
// flagDetails returns a string containing the flags metadata
279279
func flagDetails(flag cli.DocGenerationFlag) string {
280280
description := flag.GetUsage()
281-
value := getFlagDefaultValue(flag)
282-
if value != "" {
281+
value, defaultText := getFlagDefaultValue(flag)
282+
if defaultText != "" {
283+
description += " (default: " + defaultText + ")"
284+
} else if value != "" {
283285
description += " (default: " + value + ")"
284286
}
285287
return ": " + description
@@ -402,18 +404,22 @@ func (tt tabularTemplate) PrepareFlags(flags []cli.Flag) []cliTabularFlagTemplat
402404
continue
403405
}
404406

407+
value, defaultText := getFlagDefaultValue(flag)
408+
defaultValue := ""
409+
if defaultText != "" {
410+
defaultValue = defaultText
411+
} else if value != "" {
412+
defaultValue = fmt.Sprintf("`%s`", value)
413+
}
414+
405415
f := cliTabularFlagTemplate{
406416
Usage: tt.PrepareMultilineString(flag.GetUsage()),
407417
EnvVars: flag.GetEnvVars(),
408418
TakesValue: flag.TakesValue(),
409-
Default: getFlagDefaultValue(flag),
419+
Default: defaultValue,
410420
Type: flag.TypeName(),
411421
}
412422

413-
if boolFlag, isBool := appFlag.(*cli.BoolFlag); isBool {
414-
f.Default = strconv.FormatBool(boolFlag.Value)
415-
}
416-
417423
for i, name := range appFlag.Names() {
418424
name = strings.TrimSpace(name)
419425

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

561-
// getFlagDefaultValue returns the default value of a flag. Previously, the [cli.DocGenerationFlag] interface included
562-
// a GetValue string method, but it was removed in https://github.com/urfave/cli/pull/1988.
563-
// This function serves as a workaround, attempting to retrieve the value using the removed method; if that fails, it
564-
// tries to obtain it via reflection (the [cli.FlagBase] still has a Value field).
565-
func getFlagDefaultValue(f cli.DocGenerationFlag) string {
566-
if !f.TakesValue() {
567-
return ""
568-
}
569-
570-
if v, ok := f.(interface{ GetValue() string }); ok {
571-
return v.GetValue()
572-
}
573-
574-
ref := reflect.ValueOf(f)
575-
if ref.Kind() != reflect.Ptr {
576-
return ""
577-
} else {
578-
ref = ref.Elem()
579-
}
580-
581-
if ref.Kind() != reflect.Struct {
582-
return ""
567+
// getFlagDefaultValue returns the default text or default value of a flag.
568+
// cli.BoolFlag will always return an default.
569+
func getFlagDefaultValue(f cli.DocGenerationFlag) (value, text string) {
570+
// GetDefaultText also returns GetValue so we have to use reflection
571+
if ref := reflect.ValueOf(f); ref.Kind() == reflect.Ptr && ref.Elem().Kind() == reflect.Struct {
572+
if val := ref.Elem().FieldByName("DefaultText"); val.IsValid() && val.Type().Kind() == reflect.String {
573+
if defaultText := val.Interface().(string); defaultText != "" {
574+
return "", defaultText
575+
}
576+
}
583577
}
584578

585-
if val := ref.FieldByName("Value"); val.IsValid() && val.Type().Kind() != reflect.Bool {
586-
return fmt.Sprintf("%v", val.Interface())
579+
if !f.TakesValue() {
580+
if boolFlag, isBool := f.(*cli.BoolFlag); isBool {
581+
return strconv.FormatBool(boolFlag.Value), ""
582+
}
583+
return "", ""
587584
}
588585

589-
return ""
586+
return f.GetValue(), ""
590587
}

docs_test.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ func expectFileContent(t *testing.T, file, got string) {
2222
r := require.New(t)
2323
r.NoError(err)
2424
r.Equal(
25-
string(normalizeNewlines([]byte(got))),
2625
string(normalizeNewlines(data)),
26+
string(normalizeNewlines([]byte(got))),
2727
)
2828
}
2929

@@ -37,7 +37,7 @@ func normalizeNewlines(d []byte) []byte {
3737
)
3838
}
3939

40-
func buildExtendedTestCommand() *cli.Command {
40+
func buildExtendedTestCommand(t *testing.T) *cli.Command {
4141
return &cli.Command{
4242
Writer: io.Discard,
4343
Name: "greet",
@@ -60,6 +60,11 @@ func buildExtendedTestCommand() *cli.Command {
6060
Name: "hidden-flag",
6161
Hidden: true,
6262
},
63+
&cli.StringFlag{
64+
Name: "temp-dir",
65+
Value: t.TempDir(),
66+
DefaultText: "test temp dir",
67+
},
6368
},
6469
Commands: []*cli.Command{{
6570
Aliases: []string{"c"},
@@ -152,14 +157,14 @@ Should be a part of the same code block
152157
}
153158

154159
func TestToMarkdownFull(t *testing.T) {
155-
cmd := buildExtendedTestCommand()
160+
cmd := buildExtendedTestCommand(t)
156161
res, err := ToMarkdown(cmd)
157162
require.NoError(t, err)
158163
expectFileContent(t, "testdata/expected-doc-full.md", res)
159164
}
160165

161166
func TestToTabularMarkdown(t *testing.T) {
162-
app := buildExtendedTestCommand()
167+
app := buildExtendedTestCommand(t)
163168

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

187192
MarkdownTabularDocTemplate = "{{ .Foo }}"
188193

189-
app := buildExtendedTestCommand()
194+
app := buildExtendedTestCommand(t)
190195

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

@@ -221,7 +226,7 @@ Some other text`)
221226
r.NoError(err)
222227
_ = tmpFile.Close()
223228

224-
r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(), "app", tmpFile.Name()))
229+
r.NoError(ToTabularToFileBetweenTags(buildExtendedTestCommand(t), "app", tmpFile.Name()))
225230

226231
content, err := os.ReadFile(tmpFile.Name())
227232
r.NoError(err)
@@ -261,7 +266,7 @@ Some other text`)
261266
r.NoError(err)
262267
_ = tmpFile.Close()
263268

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

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

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

294-
err = ToTabularToFileBetweenTags(buildExtendedTestCommand(), "app", tmpFile.Name())
299+
err = ToTabularToFileBetweenTags(buildExtendedTestCommand(t), "app", tmpFile.Name())
295300

296301
r.ErrorIs(err, fs.ErrNotExist)
297302
})
298303
}
299304

300305
func TestToMarkdown(t *testing.T) {
301306
t.Run("no flags", func(t *testing.T) {
302-
app := buildExtendedTestCommand()
307+
app := buildExtendedTestCommand(t)
303308
app.Flags = nil
304309

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

311316
t.Run("no commands", func(t *testing.T) {
312-
app := buildExtendedTestCommand()
317+
app := buildExtendedTestCommand(t)
313318
app.Commands = nil
314319

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

321326
t.Run("no authors", func(t *testing.T) {
322-
app := buildExtendedTestCommand()
327+
app := buildExtendedTestCommand(t)
323328
app.Authors = []any{}
324329

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

331336
t.Run("no usage text", func(t *testing.T) {
332-
app := buildExtendedTestCommand()
337+
app := buildExtendedTestCommand(t)
333338
app.UsageText = ""
334339

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

342347
func TestToMan(t *testing.T) {
343-
app := buildExtendedTestCommand()
348+
app := buildExtendedTestCommand(t)
344349

345350
res, err := ToMan(app)
346351

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

351356
func TestToManParseError(t *testing.T) {
352-
app := buildExtendedTestCommand()
357+
app := buildExtendedTestCommand(t)
353358

354359
tmp := MarkdownDocTemplate
355360
t.Cleanup(func() { MarkdownDocTemplate = tmp })
@@ -361,7 +366,7 @@ func TestToManParseError(t *testing.T) {
361366
}
362367

363368
func TestToManWithSection(t *testing.T) {
364-
cmd := buildExtendedTestCommand()
369+
cmd := buildExtendedTestCommand(t)
365370

366371
res, err := ToManWithSection(cmd, 8)
367372

markdown_tabular.md.gotmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
{{- /**/ -}} | `{{ $flag.Name }}{{ if $flag.TakesValue }}="…"{{ end }}` {{ if $flag.Aliases }}(`{{ join $flag.Aliases "`, `" }}`) {{ end }}
1212
{{- /**/ -}} | {{ $flag.Usage }}
1313
{{- /**/ -}} | {{ $flag.Type }}
14-
{{- /**/ -}} | {{ if $flag.Default }}`{{ $flag.Default }}`{{ end }}
14+
{{- /**/ -}} | {{ if $flag.Default }}{{ $flag.Default }}{{ end }}
1515
{{- if $hasEnvVars -}}
1616
{{- /**/ -}} | {{ if $flag.EnvVars }}`{{ join $flag.EnvVars "`, `" }}`{{ else }}*none*{{ end }}
1717
{{- end -}}

testdata/expected-doc-full.man

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ greet
1717
[--another-flag|-b]
1818
[--flag|--fl|-f]=[value]
1919
[--socket|-s]=[value]
20+
[--temp-dir]=[value]
2021

2122
.fi
2223
.RE
@@ -41,22 +42,25 @@ app [first_arg] [second_arg]
4142

4243
.SH GLOBAL OPTIONS
4344
.PP
44-
\fB--another-flag, -b\fP: another usage text
45+
\fB--another-flag, -b\fP: another usage text (default: false)
4546

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

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

53+
.PP
54+
\fB--temp-dir\fP="": (default: test temp dir)
55+
5256

5357
.SH COMMANDS
5458
.SH config, c
5559
.PP
5660
another usage test
5761

5862
.PP
59-
\fB--another-flag, -b\fP: another usage text
63+
\fB--another-flag, -b\fP: another usage text (default: false)
6064

6165
.PP
6266
\fB--flag, --fl, -f\fP="":
@@ -66,7 +70,7 @@ another usage test
6670
another usage test
6771

6872
.PP
69-
\fB--sub-command-flag, -s\fP: some usage text
73+
\fB--sub-command-flag, -s\fP: some usage text (default: false)
7074

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

101105
.PP
102-
\fB--another-flag, -b\fP: another usage text
106+
\fB--another-flag, -b\fP: another usage text (default: false)
103107

104108
.PP
105109
\fB--flag, --fl, -f\fP="":
@@ -117,4 +121,4 @@ Single line of UsageText
117121
.RE
118122

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

testdata/expected-doc-full.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ greet
1010
[--another-flag|-b]
1111
[--flag|--fl|-f]=[value]
1212
[--socket|-s]=[value]
13+
[--temp-dir]=[value]
1314
```
1415

1516
# DESCRIPTION
@@ -24,28 +25,30 @@ app [first_arg] [second_arg]
2425

2526
# GLOBAL OPTIONS
2627

27-
**--another-flag, -b**: another usage text
28+
**--another-flag, -b**: another usage text (default: false)
2829

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

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

34+
**--temp-dir**="": (default: test temp dir)
35+
3336

3437
# COMMANDS
3538

3639
## config, c
3740

3841
another usage test
3942

40-
**--another-flag, -b**: another usage text
43+
**--another-flag, -b**: another usage text (default: false)
4144

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

4447
### sub-config, s, ss
4548

4649
another usage test
4750

48-
**--sub-command-flag, -s**: some usage text
51+
**--sub-command-flag, -s**: some usage text (default: false)
4952

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

@@ -71,7 +74,7 @@ standard usage text
7174

7275
Should be a part of the same code block
7376

74-
**--another-flag, -b**: another usage text
77+
**--another-flag, -b**: another usage text (default: false)
7578

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

@@ -81,4 +84,4 @@ standard usage text
8184

8285
>Single line of UsageText
8386
84-
**--sub-command-flag, -s**: some usage text
87+
**--sub-command-flag, -s**: some usage text (default: false)

0 commit comments

Comments
 (0)