twitch-bot/cli.go
Knut Ahlers d8c6f8d221
[core] Split out cli commands
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2023-03-24 21:41:38 +01:00

85 lines
1.5 KiB
Go

package main
import (
"fmt"
"os"
"sort"
"strings"
"sync"
"github.com/pkg/errors"
)
type (
cliRegistry struct {
cmds map[string]cliRegistryEntry
sync.Mutex
}
cliRegistryEntry struct {
Description string
Name string
Params []string
Run func([]string) error
}
)
var (
cli = newCLIRegistry()
errHelpCalled = errors.New("help called")
)
func newCLIRegistry() *cliRegistry {
return &cliRegistry{
cmds: make(map[string]cliRegistryEntry),
}
}
func (c *cliRegistry) Add(e cliRegistryEntry) {
c.Lock()
defer c.Unlock()
c.cmds[e.Name] = e
}
func (c *cliRegistry) Call(args []string) error {
c.Lock()
defer c.Unlock()
cmdEntry := c.cmds[args[0]]
if cmdEntry.Name != args[0] {
c.help()
return errHelpCalled
}
return cmdEntry.Run(args)
}
func (c *cliRegistry) help() {
// Called from Call, does not need lock
var (
maxCmdLen int
cmds []cliRegistryEntry
)
for name := range c.cmds {
entry := c.cmds[name]
if l := len(entry.CommandDisplay()); l > maxCmdLen {
maxCmdLen = l
}
cmds = append(cmds, entry)
}
sort.Slice(cmds, func(i, j int) bool { return cmds[i].Name < cmds[j].Name })
tpl := fmt.Sprintf(" %%-%ds %%s\n", maxCmdLen)
fmt.Fprintln(os.Stdout, "Supported sub-commands are:")
for _, cmd := range cmds {
fmt.Fprintf(os.Stdout, tpl, cmd.CommandDisplay(), cmd.Description)
}
}
func (c cliRegistryEntry) CommandDisplay() string {
return strings.Join(append([]string{c.Name}, c.Params...), " ")
}