OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / spf13 / cobra / doc / yaml_docs.go
1 // Copyright 2016 French Ben. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package doc
15
16 import (
17         "fmt"
18         "io"
19         "os"
20         "path/filepath"
21         "sort"
22         "strings"
23
24         "github.com/spf13/cobra"
25         "github.com/spf13/pflag"
26         "gopkg.in/yaml.v2"
27 )
28
29 type cmdOption struct {
30         Name         string
31         Shorthand    string `yaml:",omitempty"`
32         DefaultValue string `yaml:"default_value,omitempty"`
33         Usage        string `yaml:",omitempty"`
34 }
35
36 type cmdDoc struct {
37         Name             string
38         Synopsis         string      `yaml:",omitempty"`
39         Description      string      `yaml:",omitempty"`
40         Options          []cmdOption `yaml:",omitempty"`
41         InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
42         Example          string      `yaml:",omitempty"`
43         SeeAlso          []string    `yaml:"see_also,omitempty"`
44 }
45
46 // GenYamlTree creates yaml structured ref files for this command and all descendants
47 // in the directory given. This function may not work
48 // correctly if your command names have `-` in them. If you have `cmd` with two
49 // subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third`
50 // it is undefined which help output will be in the file `cmd-sub-third.1`.
51 func GenYamlTree(cmd *cobra.Command, dir string) error {
52         identity := func(s string) string { return s }
53         emptyStr := func(s string) string { return "" }
54         return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
55 }
56
57 // GenYamlTreeCustom creates yaml structured ref files.
58 func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
59         for _, c := range cmd.Commands() {
60                 if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
61                         continue
62                 }
63                 if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
64                         return err
65                 }
66         }
67
68         basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml"
69         filename := filepath.Join(dir, basename)
70         f, err := os.Create(filename)
71         if err != nil {
72                 return err
73         }
74         defer f.Close()
75
76         if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
77                 return err
78         }
79         if err := GenYamlCustom(cmd, f, linkHandler); err != nil {
80                 return err
81         }
82         return nil
83 }
84
85 // GenYaml creates yaml output.
86 func GenYaml(cmd *cobra.Command, w io.Writer) error {
87         return GenYamlCustom(cmd, w, func(s string) string { return s })
88 }
89
90 // GenYamlCustom creates custom yaml output.
91 func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
92         cmd.InitDefaultHelpCmd()
93         cmd.InitDefaultHelpFlag()
94
95         yamlDoc := cmdDoc{}
96         yamlDoc.Name = cmd.CommandPath()
97
98         yamlDoc.Synopsis = forceMultiLine(cmd.Short)
99         yamlDoc.Description = forceMultiLine(cmd.Long)
100
101         if len(cmd.Example) > 0 {
102                 yamlDoc.Example = cmd.Example
103         }
104
105         flags := cmd.NonInheritedFlags()
106         if flags.HasFlags() {
107                 yamlDoc.Options = genFlagResult(flags)
108         }
109         flags = cmd.InheritedFlags()
110         if flags.HasFlags() {
111                 yamlDoc.InheritedOptions = genFlagResult(flags)
112         }
113
114         if hasSeeAlso(cmd) {
115                 result := []string{}
116                 if cmd.HasParent() {
117                         parent := cmd.Parent()
118                         result = append(result, parent.CommandPath()+" - "+parent.Short)
119                 }
120                 children := cmd.Commands()
121                 sort.Sort(byName(children))
122                 for _, child := range children {
123                         if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {
124                                 continue
125                         }
126                         result = append(result, child.Name()+" - "+child.Short)
127                 }
128                 yamlDoc.SeeAlso = result
129         }
130
131         final, err := yaml.Marshal(&yamlDoc)
132         if err != nil {
133                 fmt.Println(err)
134                 os.Exit(1)
135         }
136
137         if _, err := w.Write(final); err != nil {
138                 return err
139         }
140         return nil
141 }
142
143 func genFlagResult(flags *pflag.FlagSet) []cmdOption {
144         var result []cmdOption
145
146         flags.VisitAll(func(flag *pflag.Flag) {
147                 // Todo, when we mark a shorthand is deprecated, but specify an empty message.
148                 // The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
149                 // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
150                 if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
151                         opt := cmdOption{
152                                 flag.Name,
153                                 flag.Shorthand,
154                                 flag.DefValue,
155                                 forceMultiLine(flag.Usage),
156                         }
157                         result = append(result, opt)
158                 } else {
159                         opt := cmdOption{
160                                 Name:         flag.Name,
161                                 DefaultValue: forceMultiLine(flag.DefValue),
162                                 Usage:        forceMultiLine(flag.Usage),
163                         }
164                         result = append(result, opt)
165                 }
166         })
167
168         return result
169 }