@@ -3,23 +3,25 @@ package commandsgen
33import (
44 "bytes"
55 "fmt"
6+ "regexp"
67 "sort"
78 "strings"
89)
910
10- type DocsFile struct {
11- FileName string
12- }
13-
1411func GenerateDocsFiles (commands Commands ) (map [string ][]byte , error ) {
12+
1513 optionSetMap := make (map [string ]OptionSets )
1614 for i , optionSet := range commands .OptionSets {
1715 optionSetMap [optionSet .Name ] = commands .OptionSets [i ]
1816 }
1917
20- w := & docWriter {fileMap : make (map [string ]* bytes.Buffer ), optionSetMap : optionSetMap }
18+ w := & docWriter {
19+ fileMap : make (map [string ]* bytes.Buffer ),
20+ optionSetMap : optionSetMap ,
21+ allCommands : commands .CommandList ,
22+ }
2123
22- // sort by parent command (activity, batch, etc)
24+ // sorted ascending by full name of command (activity complete , batch list , etc)
2325 for _ , cmd := range commands .CommandList {
2426 if err := cmd .writeDoc (w ); err != nil {
2527 return nil , fmt .Errorf ("failed writing docs for command %s: %w" , cmd .FullName , err )
@@ -35,33 +37,35 @@ func GenerateDocsFiles(commands Commands) (map[string][]byte, error) {
3537}
3638
3739type docWriter struct {
40+ allCommands []Command
3841 fileMap map [string ]* bytes.Buffer
3942 optionSetMap map [string ]OptionSets
4043 optionsStack [][]Option
4144}
4245
4346func (c * Command ) writeDoc (w * docWriter ) error {
44- commandLength := len (strings .Split (c .FullName , " " ))
4547 w .processOptions (c )
4648
4749 // If this is a root command, write a new file
48- if commandLength == 2 {
50+ depth := c .depth ()
51+ if depth == 1 {
4952 w .writeCommand (c )
50- } else if commandLength > 2 {
53+ } else if depth > 1 {
5154 w .writeSubcommand (c )
5255 }
5356 return nil
5457}
5558
5659func (w * docWriter ) writeCommand (c * Command ) {
57- fileName := strings . Split ( c . FullName , " " )[ 1 ]
60+ fileName := c . fileName ()
5861 w .fileMap [fileName ] = & bytes.Buffer {}
5962 w .fileMap [fileName ].WriteString ("---\n " )
6063 w .fileMap [fileName ].WriteString ("id: " + fileName + "\n " )
6164 w .fileMap [fileName ].WriteString ("title: " + c .FullName + "\n " )
6265 w .fileMap [fileName ].WriteString ("sidebar_label: " + c .FullName + "\n " )
6366 w .fileMap [fileName ].WriteString ("description: " + c .Docs .DescriptionHeader + "\n " )
6467 w .fileMap [fileName ].WriteString ("toc_max_heading_level: 4\n " )
68+
6569 w .fileMap [fileName ].WriteString ("keywords:\n " )
6670 for _ , keyword := range c .Docs .Keywords {
6771 w .fileMap [fileName ].WriteString (" - " + keyword + "\n " )
@@ -75,27 +79,75 @@ func (w *docWriter) writeCommand(c *Command) {
7579}
7680
7781func (w * docWriter ) writeSubcommand (c * Command ) {
78- fileName := strings . Split ( c . FullName , " " )[ 1 ]
79- subCommand := strings .Join ( strings . Split ( c . FullName , " " )[ 2 :], "" )
80- w .fileMap [fileName ].WriteString ("## " + subCommand + "\n \n " )
82+ fileName := c . fileName ()
83+ prefix := strings .Repeat ( "#" , c . depth () )
84+ w .fileMap [fileName ].WriteString (prefix + " " + c . leafName () + "\n \n " )
8185 w .fileMap [fileName ].WriteString (c .Description + "\n \n " )
82- w .fileMap [fileName ].WriteString ("Use the following options to change the behavior of this command.\n \n " )
8386
84- // gather options from command and all options aviailable from parent commands
85- var allOptions = make ([]Option , 0 )
86- for _ , options := range w .optionsStack {
87- allOptions = append (allOptions , options ... )
87+ if w .isLeafCommand (c ) {
88+ w .fileMap [fileName ].WriteString ("Use the following options to change the behavior of this command.\n \n " )
89+
90+ // gather options from command and all options aviailable from parent commands
91+ var options = make ([]Option , 0 )
92+ var globalOptions = make ([]Option , 0 )
93+ for i , o := range w .optionsStack {
94+ if i == len (w .optionsStack )- 1 {
95+ options = append (options , o ... )
96+ } else {
97+ globalOptions = append (globalOptions , o ... )
98+ }
99+ }
100+
101+ // alphabetize options
102+ sort .Slice (options , func (i , j int ) bool {
103+ return options [i ].Name < options [j ].Name
104+ })
105+
106+ sort .Slice (globalOptions , func (i , j int ) bool {
107+ return globalOptions [i ].Name < globalOptions [j ].Name
108+ })
109+
110+ w .writeOptions ("Flags" , options , c )
111+ w .writeOptions ("Global Flags" , globalOptions , c )
112+
113+ }
114+ }
115+
116+ func (w * docWriter ) writeOptions (prefix string , options []Option , c * Command ) {
117+ if len (options ) == 0 {
118+ return
88119 }
89120
90- // alphabetize options
91- sort .Slice (allOptions , func (i , j int ) bool {
92- return allOptions [i ].Name < allOptions [j ].Name
93- })
121+ fileName := c .fileName ()
94122
95- for _ , option := range allOptions {
96- w .fileMap [fileName ].WriteString (fmt .Sprintf ("## %s\n \n " , option .Name ))
97- w .fileMap [fileName ].WriteString (option .Description + "\n \n " )
123+ w .fileMap [fileName ].WriteString (fmt .Sprintf ("**%s:**\n \n " , prefix ))
98124
125+ for _ , o := range options {
126+ // option name and alias
127+ w .fileMap [fileName ].WriteString (fmt .Sprintf ("**--%s**" , o .Name ))
128+ if len (o .Short ) > 0 {
129+ w .fileMap [fileName ].WriteString (fmt .Sprintf (", **-%s**" , o .Short ))
130+ }
131+ w .fileMap [fileName ].WriteString (fmt .Sprintf (" _%s_\n \n " , o .Type ))
132+
133+ // description
134+ w .fileMap [fileName ].WriteString (encodeJSONExample (o .Description ))
135+ if o .Required {
136+ w .fileMap [fileName ].WriteString (" Required." )
137+ }
138+ if len (o .EnumValues ) > 0 {
139+ w .fileMap [fileName ].WriteString (fmt .Sprintf (" Accepted values: %s." , strings .Join (o .EnumValues , ", " )))
140+ }
141+ if len (o .Default ) > 0 {
142+ w .fileMap [fileName ].WriteString (fmt .Sprintf (` (default "%s")` , o .Default ))
143+ }
144+ w .fileMap [fileName ].WriteString ("\n \n " )
145+
146+ if o .Experimental {
147+ w .fileMap [fileName ].WriteString (":::note" + "\n \n " )
148+ w .fileMap [fileName ].WriteString ("Option is experimental." + "\n \n " )
149+ w .fileMap [fileName ].WriteString (":::" + "\n \n " )
150+ }
99151 }
100152}
101153
@@ -115,3 +167,21 @@ func (w *docWriter) processOptions(c *Command) {
115167
116168 w .optionsStack = append (w .optionsStack , options )
117169}
170+
171+ func (w * docWriter ) isLeafCommand (c * Command ) bool {
172+ for _ , maybeSubCmd := range w .allCommands {
173+ if maybeSubCmd .isSubCommand (c ) {
174+ return false
175+ }
176+ }
177+ return true
178+ }
179+
180+ func encodeJSONExample (v string ) string {
181+ // example: 'YourKey={"your": "value"}'
182+ // results in an mdx acorn rendering error
183+ // and wrapping in backticks lets it render
184+ re := regexp .MustCompile (`('[a-zA-Z0-9]*={.*}')` )
185+ v = re .ReplaceAllString (v , "`$1`" )
186+ return v
187+ }
0 commit comments