OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / spf13 / cobra / doc / man_docs.go
1 // Copyright 2015 Red Hat Inc. 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         "bytes"
18         "fmt"
19         "io"
20         "os"
21         "path/filepath"
22         "sort"
23         "strings"
24         "time"
25
26         "github.com/cpuguy83/go-md2man/md2man"
27         "github.com/spf13/cobra"
28         "github.com/spf13/pflag"
29 )
30
31 // GenManTree will generate a man page for this command and all descendants
32 // in the directory given. The header may be nil. This function may not work
33 // correctly if your command names have `-` in them. If you have `cmd` with two
34 // subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third`
35 // it is undefined which help output will be in the file `cmd-sub-third.1`.
36 func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
37         return GenManTreeFromOpts(cmd, GenManTreeOptions{
38                 Header:           header,
39                 Path:             dir,
40                 CommandSeparator: "-",
41         })
42 }
43
44 // GenManTreeFromOpts generates a man page for the command and all descendants.
45 // The pages are written to the opts.Path directory.
46 func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {
47         header := opts.Header
48         if header == nil {
49                 header = &GenManHeader{}
50         }
51         for _, c := range cmd.Commands() {
52                 if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
53                         continue
54                 }
55                 if err := GenManTreeFromOpts(c, opts); err != nil {
56                         return err
57                 }
58         }
59         section := "1"
60         if header.Section != "" {
61                 section = header.Section
62         }
63
64         separator := "_"
65         if opts.CommandSeparator != "" {
66                 separator = opts.CommandSeparator
67         }
68         basename := strings.Replace(cmd.CommandPath(), " ", separator, -1)
69         filename := filepath.Join(opts.Path, basename+"."+section)
70         f, err := os.Create(filename)
71         if err != nil {
72                 return err
73         }
74         defer f.Close()
75
76         headerCopy := *header
77         return GenMan(cmd, &headerCopy, f)
78 }
79
80 // GenManTreeOptions is the options for generating the man pages.
81 // Used only in GenManTreeFromOpts.
82 type GenManTreeOptions struct {
83         Header           *GenManHeader
84         Path             string
85         CommandSeparator string
86 }
87
88 // GenManHeader is a lot like the .TH header at the start of man pages. These
89 // include the title, section, date, source, and manual. We will use the
90 // current time if Date if unset and will use "Auto generated by spf13/cobra"
91 // if the Source is unset.
92 type GenManHeader struct {
93         Title   string
94         Section string
95         Date    *time.Time
96         date    string
97         Source  string
98         Manual  string
99 }
100
101 // GenMan will generate a man page for the given command and write it to
102 // w. The header argument may be nil, however obviously w may not.
103 func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
104         if header == nil {
105                 header = &GenManHeader{}
106         }
107         fillHeader(header, cmd.CommandPath())
108
109         b := genMan(cmd, header)
110         _, err := w.Write(md2man.Render(b))
111         return err
112 }
113
114 func fillHeader(header *GenManHeader, name string) {
115         if header.Title == "" {
116                 header.Title = strings.ToUpper(strings.Replace(name, " ", "\\-", -1))
117         }
118         if header.Section == "" {
119                 header.Section = "1"
120         }
121         if header.Date == nil {
122                 now := time.Now()
123                 header.Date = &now
124         }
125         header.date = (*header.Date).Format("Jan 2006")
126         if header.Source == "" {
127                 header.Source = "Auto generated by spf13/cobra"
128         }
129 }
130
131 func manPreamble(buf *bytes.Buffer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
132         description := cmd.Long
133         if len(description) == 0 {
134                 description = cmd.Short
135         }
136
137         buf.WriteString(fmt.Sprintf(`%% %s(%s)%s
138 %% %s
139 %% %s
140 # NAME
141 `, header.Title, header.Section, header.date, header.Source, header.Manual))
142         buf.WriteString(fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short))
143         buf.WriteString("# SYNOPSIS\n")
144         buf.WriteString(fmt.Sprintf("**%s**\n\n", cmd.UseLine()))
145         buf.WriteString("# DESCRIPTION\n")
146         buf.WriteString(description + "\n\n")
147 }
148
149 func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
150         flags.VisitAll(func(flag *pflag.Flag) {
151                 if len(flag.Deprecated) > 0 || flag.Hidden {
152                         return
153                 }
154                 format := ""
155                 if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {
156                         format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name)
157                 } else {
158                         format = fmt.Sprintf("**--%s**", flag.Name)
159                 }
160                 if len(flag.NoOptDefVal) > 0 {
161                         format += "["
162                 }
163                 if flag.Value.Type() == "string" {
164                         // put quotes on the value
165                         format += "=%q"
166                 } else {
167                         format += "=%s"
168                 }
169                 if len(flag.NoOptDefVal) > 0 {
170                         format += "]"
171                 }
172                 format += "\n\t%s\n\n"
173                 buf.WriteString(fmt.Sprintf(format, flag.DefValue, flag.Usage))
174         })
175 }
176
177 func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
178         flags := command.NonInheritedFlags()
179         if flags.HasFlags() {
180                 buf.WriteString("# OPTIONS\n")
181                 manPrintFlags(buf, flags)
182                 buf.WriteString("\n")
183         }
184         flags = command.InheritedFlags()
185         if flags.HasFlags() {
186                 buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n")
187                 manPrintFlags(buf, flags)
188                 buf.WriteString("\n")
189         }
190 }
191
192 func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
193         cmd.InitDefaultHelpCmd()
194         cmd.InitDefaultHelpFlag()
195
196         // something like `rootcmd-subcmd1-subcmd2`
197         dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1)
198
199         buf := new(bytes.Buffer)
200
201         manPreamble(buf, header, cmd, dashCommandName)
202         manPrintOptions(buf, cmd)
203         if len(cmd.Example) > 0 {
204                 buf.WriteString("# EXAMPLE\n")
205                 buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example))
206         }
207         if hasSeeAlso(cmd) {
208                 buf.WriteString("# SEE ALSO\n")
209                 seealsos := make([]string, 0)
210                 if cmd.HasParent() {
211                         parentPath := cmd.Parent().CommandPath()
212                         dashParentPath := strings.Replace(parentPath, " ", "-", -1)
213                         seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section)
214                         seealsos = append(seealsos, seealso)
215                         cmd.VisitParents(func(c *cobra.Command) {
216                                 if c.DisableAutoGenTag {
217                                         cmd.DisableAutoGenTag = c.DisableAutoGenTag
218                                 }
219                         })
220                 }
221                 children := cmd.Commands()
222                 sort.Sort(byName(children))
223                 for _, c := range children {
224                         if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
225                                 continue
226                         }
227                         seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
228                         seealsos = append(seealsos, seealso)
229                 }
230                 buf.WriteString(strings.Join(seealsos, ", ") + "\n")
231         }
232         if !cmd.DisableAutoGenTag {
233                 buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")))
234         }
235         return buf.Bytes()
236 }