Skip to content

Commit 8980ba2

Browse files
committed
address feedback to use derieved state to keep the model small
Signed-off-by: Phil Prasek <prasek@gmail.com>
1 parent 86ae3eb commit 8980ba2

3 files changed

Lines changed: 63 additions & 102 deletions

File tree

temporalcli/commandsgen/code.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,6 @@ func (c *codeWriter) importIsatty() string { return c.importPkg("github.com/matt
104104

105105
func (c *Command) structName() string { return namify(c.FullName, true) + "Command" }
106106

107-
func (c *Command) isSubCommand(maybeParent *Command) bool {
108-
return len(c.NamePath) == len(maybeParent.NamePath)+1 && strings.HasPrefix(c.FullName, maybeParent.FullName+" ")
109-
}
110-
111107
func (o *OptionSets) writeCode(w *codeWriter) error {
112108
if o.Name == "" {
113109
return fmt.Errorf("missing option set name")

temporalcli/commandsgen/docs.go

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func GenerateDocsFiles(commands Commands) (map[string][]byte, error) {
1818
w := &docWriter{
1919
fileMap: make(map[string]*bytes.Buffer),
2020
optionSetMap: optionSetMap,
21+
allCommands: commands.CommandList,
2122
}
2223

2324
// sorted ascending by full name of command (activity complete, batch list, etc)
@@ -36,6 +37,7 @@ func GenerateDocsFiles(commands Commands) (map[string][]byte, error) {
3637
}
3738

3839
type docWriter struct {
40+
allCommands []Command
3941
fileMap map[string]*bytes.Buffer
4042
optionSetMap map[string]OptionSets
4143
optionsStack [][]Option
@@ -45,16 +47,17 @@ func (c *Command) writeDoc(w *docWriter) error {
4547
w.processOptions(c)
4648

4749
// If this is a root command, write a new file
48-
if c.Depth == 1 {
50+
depth := c.depth()
51+
if depth == 1 {
4952
w.writeCommand(c)
50-
} else if c.Depth > 1 {
53+
} else if depth > 1 {
5154
w.writeSubcommand(c)
5255
}
5356
return nil
5457
}
5558

5659
func (w *docWriter) writeCommand(c *Command) {
57-
fileName := c.FileName
60+
fileName := c.fileName()
5861
w.fileMap[fileName] = &bytes.Buffer{}
5962
w.fileMap[fileName].WriteString("---\n")
6063
w.fileMap[fileName].WriteString("id: " + fileName + "\n")
@@ -76,12 +79,13 @@ func (w *docWriter) writeCommand(c *Command) {
7679
}
7780

7881
func (w *docWriter) writeSubcommand(c *Command) {
79-
prefix := strings.Repeat("#", c.Depth)
80-
w.fileMap[c.FileName].WriteString(prefix + " " + c.LeafName + "\n\n")
81-
w.fileMap[c.FileName].WriteString(c.Description + "\n\n")
82+
fileName := c.fileName()
83+
prefix := strings.Repeat("#", c.depth())
84+
w.fileMap[fileName].WriteString(prefix + " " + c.leafName() + "\n\n")
85+
w.fileMap[fileName].WriteString(c.Description + "\n\n")
8286

83-
if isLeafCommand(c) {
84-
w.fileMap[c.FileName].WriteString("Use the following options to change the behavior of this command.\n\n")
87+
if w.isLeafCommand(c) {
88+
w.fileMap[fileName].WriteString("Use the following options to change the behavior of this command.\n\n")
8589

8690
// gather options from command and all options aviailable from parent commands
8791
var options = make([]Option, 0)
@@ -110,34 +114,39 @@ func (w *docWriter) writeSubcommand(c *Command) {
110114
}
111115

112116
func (w *docWriter) writeOptions(prefix string, options []Option, c *Command) {
117+
if len(options) == 0 {
118+
return
119+
}
120+
121+
fileName := c.fileName()
113122

114-
w.fileMap[c.FileName].WriteString(fmt.Sprintf("**%s:**\n\n", prefix))
123+
w.fileMap[fileName].WriteString(fmt.Sprintf("**%s:**\n\n", prefix))
115124

116125
for _, o := range options {
117126
// option name and alias
118-
w.fileMap[c.FileName].WriteString(fmt.Sprintf("**--%s** _%s_", o.Name, o.Type))
127+
w.fileMap[fileName].WriteString(fmt.Sprintf("**--%s** _%s_", o.Name, o.Type))
119128
if len(o.Short) > 0 {
120-
w.fileMap[c.FileName].WriteString(fmt.Sprintf(", **-%s** _%s_", o.Short, o.Type))
129+
w.fileMap[fileName].WriteString(fmt.Sprintf(", **-%s** _%s_", o.Short, o.Type))
121130
}
122-
w.fileMap[c.FileName].WriteString("\n\n")
131+
w.fileMap[fileName].WriteString("\n\n")
123132

124133
// description
125-
w.fileMap[c.FileName].WriteString(encodeJSONExample(o.Description))
134+
w.fileMap[fileName].WriteString(encodeJSONExample(o.Description))
126135
if o.Required {
127-
w.fileMap[c.FileName].WriteString(" Required.")
136+
w.fileMap[fileName].WriteString(" Required.")
128137
}
129138
if len(o.EnumValues) > 0 {
130-
w.fileMap[c.FileName].WriteString(fmt.Sprintf(" Accepted values: %s.", strings.Join(o.EnumValues, ", ")))
139+
w.fileMap[fileName].WriteString(fmt.Sprintf(" Accepted values: %s.", strings.Join(o.EnumValues, ", ")))
131140
}
132141
if len(o.Default) > 0 {
133-
w.fileMap[c.FileName].WriteString(fmt.Sprintf(` (default "%s")`, o.Default))
142+
w.fileMap[fileName].WriteString(fmt.Sprintf(` (default "%s")`, o.Default))
134143
}
135-
w.fileMap[c.FileName].WriteString("\n\n")
144+
w.fileMap[fileName].WriteString("\n\n")
136145

137146
if o.Experimental {
138-
w.fileMap[c.FileName].WriteString(":::note" + "\n\n")
139-
w.fileMap[c.FileName].WriteString("Option is experimental." + "\n\n")
140-
w.fileMap[c.FileName].WriteString(":::" + "\n\n")
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")
141150
}
142151
}
143152
}
@@ -159,6 +168,15 @@ func (w *docWriter) processOptions(c *Command) {
159168
w.optionsStack = append(w.optionsStack, options)
160169
}
161170

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+
162180
func encodeJSONExample(v string) string {
163181
// example: 'YourKey={"your": "value"}'
164182
// results in an mdx acorn rendering error
@@ -167,7 +185,3 @@ func encodeJSONExample(v string) string {
167185
v = re.ReplaceAllString(v, "`$1`")
168186
return v
169187
}
170-
171-
func isLeafCommand(c *Command) bool {
172-
return len(c.Children) == 0
173-
}

temporalcli/commandsgen/parse.go

Lines changed: 25 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ type (
4747
Options []Option `yaml:"options"`
4848
OptionSets []string `yaml:"option-sets"`
4949
Docs Docs `yaml:"docs"`
50-
Index int
51-
Parent *Command
52-
Children []*Command
53-
Depth int
54-
FileName string
55-
LeafName string
5650
}
5751

5852
// Docs represents docs-only information that is not used in CLI generation.
@@ -97,7 +91,12 @@ func ParseCommands() (Commands, error) {
9791
}
9892
}
9993

100-
return enrichCommands(m)
94+
// alphabetize commands
95+
sort.Slice(m.CommandList, func(i, j int) bool {
96+
return m.CommandList[i].FullName < m.CommandList[j].FullName
97+
})
98+
99+
return m, nil
101100
}
102101

103102
var markdownLinkPattern = regexp.MustCompile(`\[(.*?)\]\((.*?)\)`)
@@ -180,6 +179,25 @@ func (c *Command) processSection() error {
180179
return nil
181180
}
182181

182+
func (c *Command) isSubCommand(maybeParent *Command) bool {
183+
return len(c.NamePath) == len(maybeParent.NamePath)+1 && strings.HasPrefix(c.FullName, maybeParent.FullName+" ")
184+
}
185+
186+
func (c *Command) leafName() string {
187+
return strings.Join(strings.Split(c.FullName, " ")[c.depth():], "")
188+
}
189+
190+
func (c *Command) fileName() string {
191+
if c.depth() <= 0 {
192+
return ""
193+
}
194+
return strings.Split(c.FullName, " ")[1]
195+
}
196+
197+
func (c *Command) depth() int {
198+
return len(strings.Split(c.FullName, " ")) - 1
199+
}
200+
183201
func (o *Option) processSection() error {
184202
if o.Name == "" {
185203
return fmt.Errorf("missing option name")
@@ -216,70 +234,3 @@ func (o *Option) processSection() error {
216234
}
217235
return nil
218236
}
219-
220-
// enrichCommands populates additional fields on Commands
221-
// beyond those read from commands.yml to make it easier
222-
// for docs.go to generate docs
223-
func enrichCommands(m Commands) (Commands, error) {
224-
commandLookup := make(map[string]*Command)
225-
226-
for i, command := range m.CommandList {
227-
m.CommandList[i].Index = i
228-
commandLookup[command.FullName] = &m.CommandList[i]
229-
}
230-
231-
var rootCommand *Command
232-
233-
//populate parent and basic meta
234-
for i, c := range m.CommandList {
235-
commandLength := len(strings.Split(c.FullName, " "))
236-
if commandLength == 1 {
237-
rootCommand = &m.CommandList[i]
238-
continue
239-
}
240-
parentName := strings.Join(strings.Split(c.FullName, " ")[:commandLength-1], " ")
241-
parent, ok := commandLookup[parentName]
242-
if ok {
243-
m.CommandList[i].Parent = &m.CommandList[parent.Index]
244-
m.CommandList[i].Depth = len(strings.Split(c.FullName, " ")) - 1
245-
m.CommandList[i].FileName = strings.Split(c.FullName, " ")[1]
246-
m.CommandList[i].LeafName = strings.Join(strings.Split(c.FullName, " ")[m.CommandList[i].Depth:], "")
247-
}
248-
}
249-
250-
//populate children and base command
251-
for _, c := range m.CommandList {
252-
if c.Parent == nil {
253-
continue
254-
}
255-
256-
m.CommandList[c.Parent.Index].Children = append(m.CommandList[c.Parent.Index].Children, &m.CommandList[c.Index])
257-
}
258-
259-
// sorted ascending by full name of command (activity complete, batch list, etc)
260-
sortChildrenVisitor(rootCommand)
261-
262-
// pull flat list in same order as sorted children
263-
m.CommandList = make([]Command, 0)
264-
collectCommandVisitor(*rootCommand, &m)
265-
266-
return m, nil
267-
}
268-
269-
func collectCommandVisitor(c Command, m *Commands) {
270-
271-
m.CommandList = append(m.CommandList, c)
272-
273-
for _, child := range c.Children {
274-
collectCommandVisitor(*child, m)
275-
}
276-
}
277-
278-
func sortChildrenVisitor(c *Command) {
279-
sort.Slice(c.Children, func(i, j int) bool {
280-
return c.Children[i].FullName < c.Children[j].FullName
281-
})
282-
for _, command := range c.Children {
283-
sortChildrenVisitor(command)
284-
}
285-
}

0 commit comments

Comments
 (0)