Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default values to web manual and man pages #8395

Merged
merged 12 commits into from Feb 6, 2024
17 changes: 15 additions & 2 deletions internal/docs/man.go
Expand Up @@ -149,10 +149,23 @@ func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
} else {
buf.WriteString(fmt.Sprintf("`--%s`", flag.Name))
}
if varname == "" {

defval := ""
hiddenDefs := map[string]bool{
"false": true,
"": true,
"[]": true,
}
if !hiddenDefs[flag.DefValue] {
defval = fmt.Sprintf(" (Default: %s)", flag.Value)
zsloane marked this conversation as resolved.
Show resolved Hide resolved
}

if varname == "" && defval != "" {
buf.WriteString(fmt.Sprintf(" `%s`\n", strings.TrimSpace(defval)))
} else if varname == "" {
buf.WriteString("\n")
} else {
buf.WriteString(fmt.Sprintf(" `<%s>`\n", varname))
buf.WriteString(fmt.Sprintf(" `<%s>%s`\n", varname, defval))
}
buf.WriteString(fmt.Sprintf(": %s\n\n", usage))
})
Expand Down
103 changes: 102 additions & 1 deletion internal/docs/man_test.go
Expand Up @@ -107,7 +107,7 @@ func TestManPrintFlagsHidesShortDeprecated(t *testing.T) {
manPrintFlags(buf, c.Flags())

got := buf.String()
expected := "`--foo` `<string>`\n: Foo flag\n\n"
expected := "`--foo` `<string> (Default: default)`\n: Foo flag\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}
Expand All @@ -130,6 +130,107 @@ func TestGenManTree(t *testing.T) {
}
}

func TestManPrintFlagsShowsDefaultValues(t *testing.T) {
type TestOptions struct {
Limit int
Template string
Fork bool
NoArchive bool
Topic []string
}
opts := TestOptions{}
// Int flag should show it
c := &cobra.Command{}
c.Flags().IntVar(&opts.Limit, "limit", 30, "Some limit")

buf := new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got := buf.String()
expected := "`--limit` `<int> (Default: 30)`\n: Some limit\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// Bool flag should hide it if default is false
c = &cobra.Command{}
c.Flags().BoolVar(&opts.Fork, "fork", false, "Show only forks")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--fork`\n: Show only forks\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// Bool flag should show it if default is true
c = &cobra.Command{}
c.Flags().BoolVar(&opts.NoArchive, "no-archived", true, "Hide archived")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--no-archived` `(Default: true)`\n: Hide archived\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// String flag should show it if default is not an empty string
c = &cobra.Command{}
c.Flags().StringVar(&opts.Template, "template", "T1", "Some template")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--template` `<string> (Default: T1)`\n: Some template\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// String flag should hide it if default is an empty string
c = &cobra.Command{}
c.Flags().StringVar(&opts.Template, "template", "", "Some template")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--template` `<string>`\n: Some template\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// String slice flag should hide it if default is an empty slice
c = &cobra.Command{}
c.Flags().StringSliceVar(&opts.Topic, "topic", nil, "Some topics")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--topic` `<strings>`\n: Some topics\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}

// String slice flag should show it if default is not an empty slice
c = &cobra.Command{}
c.Flags().StringSliceVar(&opts.Topic, "topic", []string{"apples", "oranges"}, "Some topics")

buf = new(bytes.Buffer)
manPrintFlags(buf, c.Flags())

got = buf.String()
expected = "`--topic` `<strings> (Default: [apples,oranges])`\n: Some topics\n\n"
if got != expected {
t.Errorf("Expected %q, got %q", expected, got)
}
}

func assertLineFound(scanner *bufio.Scanner, expectedLine string) error {
for scanner.Scan() {
line := scanner.Text()
Expand Down
4 changes: 3 additions & 1 deletion internal/docs/markdown.go
Expand Up @@ -50,13 +50,14 @@ type flagView struct {
Name string
Varname string
Shorthand string
DefValue string
Usage string
}

var flagsTemplate = `
<dl class="flags">{{ range . }}
<dt>{{ if .Shorthand }}<code>-{{.Shorthand}}</code>, {{ end -}}
<code>--{{.Name}}{{ if .Varname }} &lt;{{.Varname}}&gt;{{ end }}</code></dt>
<code>--{{.Name}}{{ if .Varname }} &lt;{{.Varname}}&gt;{{ end }}{{ if not (eq .DefValue "false" "" "[]") }} (Default: {{.DefValue}}){{ end }}</code></dt>
zsloane marked this conversation as resolved.
Show resolved Hide resolved
<dd>{{.Usage}}</dd>
{{ end }}</dl>
`
Expand All @@ -74,6 +75,7 @@ func printFlagsHTML(w io.Writer, fs *pflag.FlagSet) error {
Name: f.Name,
Varname: varname,
Shorthand: f.Shorthand,
DefValue: f.DefValue,
Usage: usage,
})
})
Expand Down
112 changes: 112 additions & 0 deletions internal/docs/markdown_test.go
Expand Up @@ -103,3 +103,115 @@ func BenchmarkGenMarkdownToFile(b *testing.B) {
}
}
}

func TestPrintFlagsHTMLShowsDefaultValues(t *testing.T) {

type TestOptions struct {
Limit int
Template string
Fork bool
NoArchive bool
Topic []string
}
opts := TestOptions{}

// Int flag should show it
c := &cobra.Command{}
c.Flags().IntVar(&opts.Limit, "limit", 30, "Some limit")
flags := c.NonInheritedFlags()
buf := new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output := buf.String()

checkStringContains(t, output, "(Default: 30)")

// Bool flag should hide it if default is false
c = &cobra.Command{}
c.Flags().BoolVar(&opts.Fork, "fork", false, "Show only forks")

flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringOmits(t, output, "(Default: ")

// Bool flag should show it if default is true
c = &cobra.Command{}
c.Flags().BoolVar(&opts.NoArchive, "no-archived", true, "Hide archived")
flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringContains(t, output, "(Default: true)")

// String flag should show it if default is not an empty string
c = &cobra.Command{}
c.Flags().StringVar(&opts.Template, "template", "T1", "Some template")
flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringContains(t, output, "(Default: T1)")

// String flag should hide it if default is an empty string
c = &cobra.Command{}
c.Flags().StringVar(&opts.Template, "template", "", "Some template")

flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringOmits(t, output, "(Default: ")

// String slice flag should hide it if default is an empty slice
c = &cobra.Command{}
c.Flags().StringSliceVar(&opts.Topic, "topic", nil, "Some topics")
flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringOmits(t, output, "(Default: ")

// String slice flag should show it if default is not an empty slice
c = &cobra.Command{}
c.Flags().StringSliceVar(&opts.Topic, "topic", []string{"apples", "oranges"}, "Some topics")
flags = c.NonInheritedFlags()
buf = new(bytes.Buffer)
flags.SetOutput(buf)

if err := printFlagsHTML(buf, flags); err != nil {
t.Fatalf("printFlagsHTML failed: %s", err.Error())
}
output = buf.String()

checkStringContains(t, output, "(Default: [apples,oranges])")
}