cli: fix flags usage

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2021-11-22 10:51:54 +01:00
parent bcfd434829
commit a0a7db127c
13 changed files with 109 additions and 48 deletions

View File

@ -0,0 +1,23 @@
// Copyright 2021 cli-docs-tool authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package annotation
const (
// ExternalURL specifies an external link annotation
ExternalURL = "docs.external.url"
// CodeDelimiter specifies the char that will be converted as code backtick.
// Can be used on cmd for inheritance or a specific flag.
CodeDelimiter = "docs.code-delimiter"
)

View File

@ -22,11 +22,6 @@ import (
"github.com/spf13/cobra"
)
const (
// AnnotationExternalUrl specifies an external link annotation
AnnotationExternalUrl = "docs.external.url"
)
// Options defines options for cli-docs-tool
type Options struct {
Root *cobra.Command

View File

@ -24,6 +24,7 @@ import (
"strings"
"text/template"
"github.com/docker/cli-docs-tool/annotation"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@ -51,6 +52,18 @@ func (c *Client) GenMarkdownTree(cmd *cobra.Command) error {
sourcePath := filepath.Join(c.source, mdFile)
targetPath := filepath.Join(c.target, mdFile)
// check recursively to handle inherited annotations
for curr := cmd; curr != nil; curr = curr.Parent() {
if _, ok := cmd.Annotations[annotation.CodeDelimiter]; !ok {
if cd, cok := curr.Annotations[annotation.CodeDelimiter]; cok {
if cmd.Annotations == nil {
cmd.Annotations = map[string]string{}
}
cmd.Annotations[annotation.CodeDelimiter] = cd
}
}
}
if !fileExists(sourcePath) {
var icBuf bytes.Buffer
icTpl, err := template.New("ic").Option("missingkey=error").Parse(`# {{ .Command }}
@ -120,7 +133,7 @@ func mdFilename(cmd *cobra.Command) string {
func mdMakeLink(txt, link string, f *pflag.Flag, isAnchor bool) string {
link = "#" + link
annotations, ok := f.Annotations[AnnotationExternalUrl]
annotations, ok := f.Annotations[annotation.ExternalURL]
if ok && len(annotations) > 0 {
link = annotations[0]
} else {
@ -186,7 +199,13 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) {
}
name += "`"
name = mdMakeLink(name, f.Name, f, isLink)
fmt.Fprintf(b, "%s | %s |\n", mdEscapePipe(name), mdEscapePipe(f.Usage))
usage := f.Usage
if cd, ok := f.Annotations[annotation.CodeDelimiter]; ok {
usage = strings.ReplaceAll(usage, cd[0], "`")
} else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok {
usage = strings.ReplaceAll(usage, cd, "`")
}
fmt.Fprintf(b, "%s | %s |\n", mdEscapePipe(name), mdEscapePipe(usage))
})
fmt.Fprintln(b, "")
}

View File

@ -24,6 +24,7 @@ import (
"sort"
"strings"
"github.com/docker/cli-docs-tool/annotation"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
@ -37,6 +38,7 @@ type cmdOption struct {
Description string `yaml:",omitempty"`
DetailsURL string `yaml:"details_url,omitempty"` // DetailsURL contains an anchor-id or link for more information on this flag
Deprecated bool
Hidden bool
MinAPIVersion string `yaml:"min_api_version,omitempty"`
Experimental bool
ExperimentalCLI bool
@ -164,7 +166,7 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
cliDoc.Usage = cmd.UseLine()
}
// Check recursively so that, e.g., `docker stack ls` returns the same output as `docker stack`
// check recursively to handle inherited annotations
for curr := cmd; curr != nil; curr = curr.Parent() {
if v, ok := curr.Annotations["version"]; ok && cliDoc.MinAPIVersion == "" {
cliDoc.MinAPIVersion = v
@ -184,6 +186,14 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
if o, ok := curr.Annotations["ostype"]; ok && cliDoc.OSType == "" {
cliDoc.OSType = o
}
if _, ok := cmd.Annotations[annotation.CodeDelimiter]; !ok {
if cd, cok := curr.Annotations[annotation.CodeDelimiter]; cok {
if cmd.Annotations == nil {
cmd.Annotations = map[string]string{}
}
cmd.Annotations[annotation.CodeDelimiter] = cd
}
}
}
anchors := make(map[string]struct{})
@ -195,11 +205,11 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
flags := cmd.NonInheritedFlags()
if flags.HasFlags() {
cliDoc.Options = genFlagResult(flags, anchors)
cliDoc.Options = genFlagResult(cmd, flags, anchors)
}
flags = cmd.InheritedFlags()
if flags.HasFlags() {
cliDoc.InheritedOptions = genFlagResult(flags, anchors)
cliDoc.InheritedOptions = genFlagResult(cmd, flags, anchors)
}
if hasSeeAlso(cmd) {
@ -237,7 +247,7 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
return nil
}
func genFlagResult(flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOption {
func genFlagResult(cmd *cobra.Command, flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOption {
var (
result []cmdOption
opt cmdOption
@ -262,11 +272,19 @@ func genFlagResult(flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOptio
Option: flag.Name,
ValueType: flag.Value.Type(),
DefaultValue: forceMultiLine(flag.DefValue, defaultValueMaxWidth),
Description: forceMultiLine(flag.Usage, descriptionMaxWidth),
Deprecated: len(flag.Deprecated) > 0,
Hidden: flag.Hidden,
}
if v, ok := flag.Annotations[AnnotationExternalUrl]; ok && len(v) > 0 {
usage := flag.Usage
if cd, ok := flag.Annotations[annotation.CodeDelimiter]; ok {
usage = strings.ReplaceAll(usage, cd[0], "`")
} else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok {
usage = strings.ReplaceAll(usage, cd, "`")
}
opt.Description = forceMultiLine(usage, descriptionMaxWidth)
if v, ok := flag.Annotations[annotation.ExternalURL]; ok && len(v) > 0 {
opt.DetailsURL = strings.TrimPrefix(v[0], "https://docs.docker.com")
} else if _, ok = anchors[flag.Name]; ok {
opt.DetailsURL = "#" + flag.Name