1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package doc
16
17 import (
18 "bytes"
19 "fmt"
20 "io"
21 "os"
22 "path/filepath"
23 "sort"
24 "strings"
25 "time"
26
27 "github.com/spf13/cobra"
28 )
29
30 func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
31 flags := cmd.NonInheritedFlags()
32 flags.SetOutput(buf)
33 if flags.HasAvailableFlags() {
34 buf.WriteString("Options\n")
35 buf.WriteString("~~~~~~~\n\n::\n\n")
36 flags.PrintDefaults()
37 buf.WriteString("\n")
38 }
39
40 parentFlags := cmd.InheritedFlags()
41 parentFlags.SetOutput(buf)
42 if parentFlags.HasAvailableFlags() {
43 buf.WriteString("Options inherited from parent commands\n")
44 buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n")
45 parentFlags.PrintDefaults()
46 buf.WriteString("\n")
47 }
48 return nil
49 }
50
51
52 func defaultLinkHandler(name, ref string) string {
53 return fmt.Sprintf("`%s <%s.rst>`_", name, ref)
54 }
55
56
57 func GenReST(cmd *cobra.Command, w io.Writer) error {
58 return GenReSTCustom(cmd, w, defaultLinkHandler)
59 }
60
61
62 func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, string) string) error {
63 cmd.InitDefaultHelpCmd()
64 cmd.InitDefaultHelpFlag()
65
66 buf := new(bytes.Buffer)
67 name := cmd.CommandPath()
68
69 short := cmd.Short
70 long := cmd.Long
71 if len(long) == 0 {
72 long = short
73 }
74 ref := strings.ReplaceAll(name, " ", "_")
75
76 buf.WriteString(".. _" + ref + ":\n\n")
77 buf.WriteString(name + "\n")
78 buf.WriteString(strings.Repeat("-", len(name)) + "\n\n")
79 buf.WriteString(short + "\n\n")
80 buf.WriteString("Synopsis\n")
81 buf.WriteString("~~~~~~~~\n\n")
82 buf.WriteString("\n" + long + "\n\n")
83
84 if cmd.Runnable() {
85 buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine()))
86 }
87
88 if len(cmd.Example) > 0 {
89 buf.WriteString("Examples\n")
90 buf.WriteString("~~~~~~~~\n\n")
91 buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " ")))
92 }
93
94 if err := printOptionsReST(buf, cmd, name); err != nil {
95 return err
96 }
97 if hasSeeAlso(cmd) {
98 buf.WriteString("SEE ALSO\n")
99 buf.WriteString("~~~~~~~~\n\n")
100 if cmd.HasParent() {
101 parent := cmd.Parent()
102 pname := parent.CommandPath()
103 ref = strings.ReplaceAll(pname, " ", "_")
104 buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short))
105 cmd.VisitParents(func(c *cobra.Command) {
106 if c.DisableAutoGenTag {
107 cmd.DisableAutoGenTag = c.DisableAutoGenTag
108 }
109 })
110 }
111
112 children := cmd.Commands()
113 sort.Sort(byName(children))
114
115 for _, child := range children {
116 if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {
117 continue
118 }
119 cname := name + " " + child.Name()
120 ref = strings.ReplaceAll(cname, " ", "_")
121 buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short))
122 }
123 buf.WriteString("\n")
124 }
125 if !cmd.DisableAutoGenTag {
126 buf.WriteString("*Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "*\n")
127 }
128 _, err := buf.WriteTo(w)
129 return err
130 }
131
132
133
134
135
136
137
138 func GenReSTTree(cmd *cobra.Command, dir string) error {
139 emptyStr := func(s string) string { return "" }
140 return GenReSTTreeCustom(cmd, dir, emptyStr, defaultLinkHandler)
141 }
142
143
144
145 func GenReSTTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error {
146 for _, c := range cmd.Commands() {
147 if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
148 continue
149 }
150 if err := GenReSTTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
151 return err
152 }
153 }
154
155 basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".rst"
156 filename := filepath.Join(dir, basename)
157 f, err := os.Create(filename)
158 if err != nil {
159 return err
160 }
161 defer f.Close()
162
163 if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
164 return err
165 }
166 if err := GenReSTCustom(cmd, f, linkHandler); err != nil {
167 return err
168 }
169 return nil
170 }
171
172
173 func indentString(s, p string) string {
174 var res []byte
175 b := []byte(s)
176 prefix := []byte(p)
177 bol := true
178 for _, c := range b {
179 if bol && c != '\n' {
180 res = append(res, prefix...)
181 }
182 res = append(res, c)
183 bol = c == '\n'
184 }
185 return string(res)
186 }
187
View as plain text