cmdtree is a library which curates command and sub-command creation and execution.
You probably want to spend your time worrying about what the commands do, and not how to let user’s execute them. In that spirit, cmdtree provides the following:
- A simple command signature, extensible through closures.
- Composeable commands and sub-commands.
- Commands can be empty hosts to sub-commands, or commands in their own right.
- cmdtree distinguishes between a sub-command and arguments.
- Parsing of user-input.
- Built-in string representation of the entire command tree, or one of its branches.
package main
import (
"github.com/katco-/cmdtree"
"fmt"
)
func main() {
const delimiter = " "
cmd := cmdtree.NewCmd(delimiter, "help", func(arg string) error {
fmt.Printf(`You requested help for "%s".`, arg)
fmt.Println()
return nil
})
cmd.Execute("help cmdtree")
}
You requested help for "cmdtree".
package main
import (
"fmt"
"github.com/katco-/cmdtree"
)
func main() {
const delimiter = " "
cmd := cmdtree.NewCmd(delimiter, "help", func(arg string) error {
fmt.Printf(`You requested help for "%s".`, arg)
return nil
})
cmd.SubCmd("deep", func(arg string) error {
fmt.Printf(`You requested DEEP help for "%s".`, arg)
return nil
})
cmd.Execute("help cmdtree")
fmt.Println()
cmd.Execute("help deep cmdtree internals")
}
You requested help for "cmdtree". You requested DEEP help for "cmdtree internals".
The levels of sub-commands can be arbitrarily deep, but the complexity remains manageable because you can continually pick up from the previous level.
package main
import (
"bytes"
"fmt"
"github.com/katco-/cmdtree"
)
func main() {
const delimiter = " "
help := cmdtree.NewCmd(delimiter, "help", nil)
var with cmdtree.Command
with = help.SubCmd("with", func(string) error {
var buff bytes.Buffer
fmt.Fprint(&buff, "Available options:")
fmt.Fprintln(&buff)
fmt.Fprintln(&buff, with.String())
return fmt.Errorf(buff.String())
})
with.SubCmd("cmdtree", func(string) error {
fmt.Println("It makes cupcakes! ...I think.")
return nil
})
with.SubCmd("life", func(string) error {
fmt.Println("Whoa. A code example is the wrong place for that, friend.")
return nil
})
with.SubCmd("sleep", func(string) error {
fmt.Println("Is that what I'm supposed to be doing right now?")
return nil
})
if err := help.Execute("help with"); err != nil {
fmt.Println(err)
}
fmt.Println("What does cmdtree do for me?")
help.Execute("help with cmdtree")
}
Available options: with cmdtree life sleep
:
What does cmdtree do for me? It makes cupcakes! ...I think.
package main
import (
"fmt"
"github.com/katco-/cmdtree"
"strconv"
)
type User struct {
Name string
LevelOfLoveForCmdtree int
}
func main() {
var currentUser *User
users := []*User{
&User{"Wirt. Just Wirt.", 0},
&User{"Greg the frog catcher", 100},
&User{"Beatrice the Bluebird", 5},
}
root := cmdtree.Root(" ")
set := root.SubCmd("set", nil)
set.SubCmd("love", setLoveForUserFn(¤tUser))
print := root.SubCmd("print", nil)
print.SubCmd("users", func (name string) error{
fmt.Println("Users:")
for _, user := range users {
if name != "" && user.Name != name {
continue
}
fmt.Printf(`"%s" loves cmdtree %d%%!`, user.Name, user.LevelOfLoveForCmdtree)
fmt.Println()
}
fmt.Println()
return nil
})
root.Execute("print users")
for _, user := range users {
currentUser = user
root.Execute("set love 100")
}
root.Execute("print users Wirt. Just Wirt.")
root.Execute("print users")
}
func setLoveForUserFn(user **User) cmdtree.CommandExecutor {
return func(level string) error {
numericLevel, err := strconv.Atoi(level)
if err != nil {
return err
} else if numericLevel < 0 {
return fmt.Errorf("I'm sorry %s, I can't do that.", (*user).Name)
}
(*user).LevelOfLoveForCmdtree = numericLevel
return nil
}
}
Users: "Wirt. Just Wirt." loves cmdtree 0%! "Greg the frog catcher" loves cmdtree 100%! "Beatrice the Bluebird" loves cmdtree 5%! Users: "Wirt. Just Wirt." loves cmdtree 100%! Users: "Wirt. Just Wirt." loves cmdtree 100%! "Greg the frog catcher" loves cmdtree 100%! "Beatrice the Bluebird" loves cmdtree 100%!