Merge pull request #8395 from zsloane/trunk

Add default values to web manual and man pages
This commit is contained in:
Andy Feller 2024-02-06 09:27:49 -05:00 committed by GitHub
commit b817b1423a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 262 additions and 13 deletions

View file

@ -149,10 +149,15 @@ func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
} else {
buf.WriteString(fmt.Sprintf("`--%s`", flag.Name))
}
if varname == "" {
defval := getDefaultValueDisplayString(flag)
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))
})

View file

@ -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)
}
@ -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()

View file

@ -46,17 +46,43 @@ func hasNonHelpFlags(fs *pflag.FlagSet) (found bool) {
return
}
var hiddenFlagDefaults = map[string]bool{
"false": true,
"": true,
"[]": true,
"0s": true,
}
var defaultValFormats = map[string]string{
"string": " (default \"%s\")",
"duration": " (default \"%s\")",
}
func getDefaultValueDisplayString(f *pflag.Flag) string {
if hiddenFlagDefaults[f.DefValue] || hiddenFlagDefaults[f.Value.Type()] {
return ""
}
if dvf, found := defaultValFormats[f.Value.Type()]; found {
return fmt.Sprintf(dvf, f.Value)
}
return fmt.Sprintf(" (default %s)", f.Value)
}
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>
<dt>{{ if .Shorthand }}<code>-{{.Shorthand}}</code>, {{ end }}
<code>--{{.Name}}{{ if .Varname }} &lt;{{.Varname}}&gt;{{ end }}{{.DefValue}} </code></dt>
<dd>{{.Usage}}</dd>
{{ end }}</dl>
`
@ -70,10 +96,12 @@ func printFlagsHTML(w io.Writer, fs *pflag.FlagSet) error {
return
}
varname, usage := pflag.UnquoteUsage(f)
flags = append(flags, flagView{
Name: f.Name,
Varname: varname,
Shorthand: f.Shorthand,
DefValue: getDefaultValueDisplayString(f),
Usage: usage,
})
})

View file

@ -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 &#34;T1&#34;)")
// 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])")
}

View file

@ -19,8 +19,11 @@ func NewCmdConfig(f *cmdutil.Factory) *cobra.Command {
longDoc.WriteString("Current respected settings:\n")
for _, co := range config.ConfigOptions() {
longDoc.WriteString(fmt.Sprintf("- `%s`: %s", co.Key, co.Description))
if len(co.AllowedValues) > 0 {
longDoc.WriteString(fmt.Sprintf(" {%s}", strings.Join(co.AllowedValues, "|")))
}
if co.DefaultValue != "" {
longDoc.WriteString(fmt.Sprintf(" (default: %q)", co.DefaultValue))
longDoc.WriteString(fmt.Sprintf(" (default %s)", co.DefaultValue))
}
longDoc.WriteRune('\n')
}

View file

@ -96,7 +96,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
cmd.Flags().StringVarP(&opts.Description, "desc", "d", "", "A description for this gist")
cmd.Flags().BoolVarP(&opts.WebMode, "web", "w", false, "Open the web browser with created gist")
cmd.Flags().BoolVarP(&opts.Public, "public", "p", false, "List the gist publicly (default: secret)")
cmd.Flags().BoolVarP(&opts.Public, "public", "p", false, "List the gist publicly (default \"secret\")")
cmd.Flags().StringVarP(&opts.FilenameOverride, "filename", "f", "", "Provide a filename to be used when reading from standard input")
return cmd
}

View file

@ -65,7 +65,7 @@ func NewCmdCheckout(f *cmdutil.Factory, runF func(*CheckoutOptions) error) *cobr
cmd.Flags().BoolVarP(&opts.RecurseSubmodules, "recurse-submodules", "", false, "Update all submodules after checkout")
cmd.Flags().BoolVarP(&opts.Force, "force", "f", false, "Reset the existing local branch to the latest state of the pull request")
cmd.Flags().BoolVarP(&opts.Detach, "detach", "", false, "Checkout PR with a detached HEAD")
cmd.Flags().StringVarP(&opts.BranchName, "branch", "b", "", "Local branch name to use (default: the name of the head branch)")
cmd.Flags().StringVarP(&opts.BranchName, "branch", "b", "", "Local branch name to use (default [the name of the head branch])")
return cmd
}

View file

@ -203,7 +203,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
fl.StringVarP(&opts.Body, "body", "b", "", "Body for the pull request")
fl.StringVarP(&bodyFile, "body-file", "F", "", "Read body text from `file` (use \"-\" to read from standard input)")
fl.StringVarP(&opts.BaseBranch, "base", "B", "", "The `branch` into which you want your code merged")
fl.StringVarP(&opts.HeadBranch, "head", "H", "", "The `branch` that contains commits for your pull request (default: current branch)")
fl.StringVarP(&opts.HeadBranch, "head", "H", "", "The `branch` that contains commits for your pull request (default [current branch])")
fl.BoolVarP(&opts.WebMode, "web", "w", false, "Open the web browser to create a pull request")
fl.BoolVarP(&opts.FillVerbose, "fill-verbose", "", false, "Use commits msg+body for description")
fl.BoolVarP(&opts.Autofill, "fill", "f", false, "Use commit info for title and body")

View file

@ -178,14 +178,14 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
cmd.Flags().BoolVarP(&opts.Draft, "draft", "d", false, "Save the release as a draft instead of publishing it")
cmd.Flags().BoolVarP(&opts.Prerelease, "prerelease", "p", false, "Mark the release as a prerelease")
cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default: main branch)")
cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default [main branch])")
cmd.Flags().StringVarP(&opts.Name, "title", "t", "", "Release title")
cmd.Flags().StringVarP(&opts.Body, "notes", "n", "", "Release notes")
cmd.Flags().StringVarP(&notesFile, "notes-file", "F", "", "Read release notes from `file` (use \"-\" to read from standard input)")
cmd.Flags().StringVarP(&opts.DiscussionCategory, "discussion-category", "", "", "Start a discussion in the specified category")
cmd.Flags().BoolVarP(&opts.GenerateNotes, "generate-notes", "", false, "Automatically generate title and notes for the release")
cmd.Flags().StringVar(&opts.NotesStartTag, "notes-start-tag", "", "Tag to use as the starting point for generating release notes")
cmdutil.NilBoolFlag(cmd, &opts.IsLatest, "latest", "", "Mark this release as \"Latest\" (default: automatic based on date and version)")
cmdutil.NilBoolFlag(cmd, &opts.IsLatest, "latest", "", "Mark this release as \"Latest\" (default [automatic based on date and version])")
cmd.Flags().BoolVarP(&opts.VerifyTag, "verify-tag", "", false, "Abort in case the git tag doesn't already exist in the remote repository")
cmd.Flags().BoolVarP(&opts.NotesFromTag, "notes-from-tag", "", false, "Automatically generate notes from annotated tag")

View file

@ -79,7 +79,7 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman
cmdutil.NilStringFlag(cmd, &opts.Body, "notes", "n", "Release notes")
cmdutil.NilStringFlag(cmd, &opts.Name, "title", "t", "Release title")
cmdutil.NilStringFlag(cmd, &opts.DiscussionCategory, "discussion-category", "", "Start a discussion in the specified category when publishing a draft")
cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default: main branch)")
cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default [main branch])")
cmd.Flags().StringVar(&opts.TagName, "tag", "", "The name of the tag")
cmd.Flags().StringVarP(&notesFile, "notes-file", "F", "", "Read release notes from `file` (use \"-\" to read from standard input)")
cmd.Flags().BoolVar(&opts.VerifyTag, "verify-tag", false, "Abort in case the git tag doesn't already exist in the remote repository")

View file

@ -83,7 +83,7 @@ func NewCmdSync(f *cmdutil.Factory, runF func(*SyncOptions) error) *cobra.Comman
}
cmd.Flags().StringVarP(&opts.SrcArg, "source", "s", "", "Source repository")
cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Branch to sync (default: default branch)")
cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Branch to sync (default [default branch])")
cmd.Flags().BoolVarP(&opts.Force, "force", "", false, "Hard reset the branch of the destination repository to match the source repository")
return cmd
}