Skip to content

Commit

Permalink
address feedback to use derieved state to keep the model small
Browse files Browse the repository at this point in the history
Signed-off-by: Phil Prasek <[email protected]>
  • Loading branch information
prasek committed Oct 31, 2024
1 parent 86ae3eb commit 8980ba2
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 102 deletions.
4 changes: 0 additions & 4 deletions temporalcli/commandsgen/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ func (c *codeWriter) importIsatty() string { return c.importPkg("github.com/matt

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

func (c *Command) isSubCommand(maybeParent *Command) bool {
return len(c.NamePath) == len(maybeParent.NamePath)+1 && strings.HasPrefix(c.FullName, maybeParent.FullName+" ")
}

func (o *OptionSets) writeCode(w *codeWriter) error {
if o.Name == "" {
return fmt.Errorf("missing option set name")
Expand Down
62 changes: 38 additions & 24 deletions temporalcli/commandsgen/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func GenerateDocsFiles(commands Commands) (map[string][]byte, error) {
w := &docWriter{
fileMap: make(map[string]*bytes.Buffer),
optionSetMap: optionSetMap,
allCommands: commands.CommandList,
}

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

type docWriter struct {
allCommands []Command
fileMap map[string]*bytes.Buffer
optionSetMap map[string]OptionSets
optionsStack [][]Option
Expand All @@ -45,16 +47,17 @@ func (c *Command) writeDoc(w *docWriter) error {
w.processOptions(c)

// If this is a root command, write a new file
if c.Depth == 1 {
depth := c.depth()
if depth == 1 {
w.writeCommand(c)
} else if c.Depth > 1 {
} else if depth > 1 {
w.writeSubcommand(c)
}
return nil
}

func (w *docWriter) writeCommand(c *Command) {
fileName := c.FileName
fileName := c.fileName()
w.fileMap[fileName] = &bytes.Buffer{}
w.fileMap[fileName].WriteString("---\n")
w.fileMap[fileName].WriteString("id: " + fileName + "\n")
Expand All @@ -76,12 +79,13 @@ func (w *docWriter) writeCommand(c *Command) {
}

func (w *docWriter) writeSubcommand(c *Command) {
prefix := strings.Repeat("#", c.Depth)
w.fileMap[c.FileName].WriteString(prefix + " " + c.LeafName + "\n\n")
w.fileMap[c.FileName].WriteString(c.Description + "\n\n")
fileName := c.fileName()
prefix := strings.Repeat("#", c.depth())
w.fileMap[fileName].WriteString(prefix + " " + c.leafName() + "\n\n")
w.fileMap[fileName].WriteString(c.Description + "\n\n")

if isLeafCommand(c) {
w.fileMap[c.FileName].WriteString("Use the following options to change the behavior of this command.\n\n")
if w.isLeafCommand(c) {
w.fileMap[fileName].WriteString("Use the following options to change the behavior of this command.\n\n")

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

func (w *docWriter) writeOptions(prefix string, options []Option, c *Command) {
if len(options) == 0 {
return
}

fileName := c.fileName()

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

for _, o := range options {
// option name and alias
w.fileMap[c.FileName].WriteString(fmt.Sprintf("**--%s** _%s_", o.Name, o.Type))
w.fileMap[fileName].WriteString(fmt.Sprintf("**--%s** _%s_", o.Name, o.Type))
if len(o.Short) > 0 {
w.fileMap[c.FileName].WriteString(fmt.Sprintf(", **-%s** _%s_", o.Short, o.Type))
w.fileMap[fileName].WriteString(fmt.Sprintf(", **-%s** _%s_", o.Short, o.Type))
}
w.fileMap[c.FileName].WriteString("\n\n")
w.fileMap[fileName].WriteString("\n\n")

// description
w.fileMap[c.FileName].WriteString(encodeJSONExample(o.Description))
w.fileMap[fileName].WriteString(encodeJSONExample(o.Description))
if o.Required {
w.fileMap[c.FileName].WriteString(" Required.")
w.fileMap[fileName].WriteString(" Required.")
}
if len(o.EnumValues) > 0 {
w.fileMap[c.FileName].WriteString(fmt.Sprintf(" Accepted values: %s.", strings.Join(o.EnumValues, ", ")))
w.fileMap[fileName].WriteString(fmt.Sprintf(" Accepted values: %s.", strings.Join(o.EnumValues, ", ")))
}
if len(o.Default) > 0 {
w.fileMap[c.FileName].WriteString(fmt.Sprintf(` (default "%s")`, o.Default))
w.fileMap[fileName].WriteString(fmt.Sprintf(` (default "%s")`, o.Default))
}
w.fileMap[c.FileName].WriteString("\n\n")
w.fileMap[fileName].WriteString("\n\n")

if o.Experimental {
w.fileMap[c.FileName].WriteString(":::note" + "\n\n")
w.fileMap[c.FileName].WriteString("Option is experimental." + "\n\n")
w.fileMap[c.FileName].WriteString(":::" + "\n\n")
w.fileMap[fileName].WriteString(":::note" + "\n\n")
w.fileMap[fileName].WriteString("Option is experimental." + "\n\n")
w.fileMap[fileName].WriteString(":::" + "\n\n")
}
}
}
Expand All @@ -159,6 +168,15 @@ func (w *docWriter) processOptions(c *Command) {
w.optionsStack = append(w.optionsStack, options)
}

func (w *docWriter) isLeafCommand(c *Command) bool {
for _, maybeSubCmd := range w.allCommands {
if maybeSubCmd.isSubCommand(c) {
return false
}
}
return true
}

func encodeJSONExample(v string) string {
// example: 'YourKey={"your": "value"}'
// results in an mdx acorn rendering error
Expand All @@ -167,7 +185,3 @@ func encodeJSONExample(v string) string {
v = re.ReplaceAllString(v, "`$1`")
return v
}

func isLeafCommand(c *Command) bool {
return len(c.Children) == 0
}
99 changes: 25 additions & 74 deletions temporalcli/commandsgen/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ type (
Options []Option `yaml:"options"`
OptionSets []string `yaml:"option-sets"`
Docs Docs `yaml:"docs"`
Index int
Parent *Command
Children []*Command
Depth int
FileName string
LeafName string
}

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

return enrichCommands(m)
// alphabetize commands
sort.Slice(m.CommandList, func(i, j int) bool {
return m.CommandList[i].FullName < m.CommandList[j].FullName
})

return m, nil
}

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

func (c *Command) isSubCommand(maybeParent *Command) bool {
return len(c.NamePath) == len(maybeParent.NamePath)+1 && strings.HasPrefix(c.FullName, maybeParent.FullName+" ")
}

func (c *Command) leafName() string {
return strings.Join(strings.Split(c.FullName, " ")[c.depth():], "")
}

func (c *Command) fileName() string {
if c.depth() <= 0 {
return ""
}
return strings.Split(c.FullName, " ")[1]
}

func (c *Command) depth() int {
return len(strings.Split(c.FullName, " ")) - 1
}

func (o *Option) processSection() error {
if o.Name == "" {
return fmt.Errorf("missing option name")
Expand Down Expand Up @@ -216,70 +234,3 @@ func (o *Option) processSection() error {
}
return nil
}

// enrichCommands populates additional fields on Commands
// beyond those read from commands.yml to make it easier
// for docs.go to generate docs
func enrichCommands(m Commands) (Commands, error) {
commandLookup := make(map[string]*Command)

for i, command := range m.CommandList {
m.CommandList[i].Index = i
commandLookup[command.FullName] = &m.CommandList[i]
}

var rootCommand *Command

//populate parent and basic meta
for i, c := range m.CommandList {
commandLength := len(strings.Split(c.FullName, " "))
if commandLength == 1 {
rootCommand = &m.CommandList[i]
continue
}
parentName := strings.Join(strings.Split(c.FullName, " ")[:commandLength-1], " ")
parent, ok := commandLookup[parentName]
if ok {
m.CommandList[i].Parent = &m.CommandList[parent.Index]
m.CommandList[i].Depth = len(strings.Split(c.FullName, " ")) - 1
m.CommandList[i].FileName = strings.Split(c.FullName, " ")[1]
m.CommandList[i].LeafName = strings.Join(strings.Split(c.FullName, " ")[m.CommandList[i].Depth:], "")
}
}

//populate children and base command
for _, c := range m.CommandList {
if c.Parent == nil {
continue
}

m.CommandList[c.Parent.Index].Children = append(m.CommandList[c.Parent.Index].Children, &m.CommandList[c.Index])
}

// sorted ascending by full name of command (activity complete, batch list, etc)
sortChildrenVisitor(rootCommand)

// pull flat list in same order as sorted children
m.CommandList = make([]Command, 0)
collectCommandVisitor(*rootCommand, &m)

return m, nil
}

func collectCommandVisitor(c Command, m *Commands) {

m.CommandList = append(m.CommandList, c)

for _, child := range c.Children {
collectCommandVisitor(*child, m)
}
}

func sortChildrenVisitor(c *Command) {
sort.Slice(c.Children, func(i, j int) bool {
return c.Children[i].FullName < c.Children[j].FullName
})
for _, command := range c.Children {
sortChildrenVisitor(command)
}
}

0 comments on commit 8980ba2

Please sign in to comment.