Files
prevara/pkg/opts/cmds/commands.go

107 lines
2.4 KiB
Go

package cmds
// Commands are a slice of Command entries
type Commands []Command
// Command is a specification for a command and can include any number of subcommands
type Command struct {
Name string
Title string
Description string
Entrypoint func(c interface{}) error
Commands Commands
Colorizer func(a ...interface{}) string
AppText string
Parent *Command
}
func (c Commands) PopulateParents(parent *Command) {
if parent != nil {
T.Ln("backlinking children of", parent.Name)
}
for i := range c {
c[i].Parent = parent
c[i].Commands.PopulateParents(&c[i])
}
}
// GetAllCommands returns all of the available command names
func (c Commands) GetAllCommands() (o []string) {
c.ForEach(func(cm Command) bool {
o = append(o, cm.Name)
o = append(o, cm.Commands.GetAllCommands()...)
return true
}, 0, 0,
)
return
}
var tabs = "\t\t\t\t\t"
// Find the Command you are looking for. Note that the namespace is assumed to be flat, no duplicated names on different
// levels, as it returns on the first one it finds, which goes depth-first recursive
func (c Commands) Find(
name string, hereDepth, hereDist int, skipFirst bool,
) (found bool, depth, dist int, cm *Command, e error) {
if c == nil {
dist = hereDist
depth = hereDepth
return
}
if hereDist == 0 {
D.Ln("searching for command:", name)
}
depth = hereDepth + 1
T.Ln(tabs[:depth]+"->", depth)
dist = hereDist
for i := range c {
T.Ln(tabs[:depth]+"walking", c[i].Name, depth, dist)
dist++
if c[i].Name == name {
if skipFirst {
continue
}
dist--
T.Ln(tabs[:depth]+"found", name, "at depth", depth, "distance", dist)
found = true
cm = &c[i]
e = nil
return
}
if found, depth, dist, cm, e = c[i].Commands.Find(name, depth, dist, false); E.Chk(e) {
T.Ln(tabs[:depth]+"error", c[i].Name)
return
}
if found {
return
}
}
T.Ln(tabs[:hereDepth]+"<-", hereDepth)
if hereDepth == 0 {
D.Ln("search text", name, "not found")
}
depth--
return
}
func (c Commands) ForEach(fn func(Command) bool, hereDepth, hereDist int) (ret bool, depth, dist int, e error) {
if c == nil {
dist = hereDist
depth = hereDepth
return
}
depth = hereDepth + 1
T.Ln(tabs[:depth]+"->", depth)
dist = hereDist
for i := range c {
T.Ln(tabs[:depth]+"walking", c[i].Name, depth, dist)
if !fn(c[i]) {
// if the closure returns false break out of the loop
return
}
}
T.Ln(tabs[:hereDepth]+"<-", hereDepth)
depth--
return
}