CLI: implement help

This commit is contained in:
kayos@tcp.direct 2022-09-26 10:10:17 -07:00
parent 40d8979ab9
commit 08b7a3f7ae
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
6 changed files with 136 additions and 68 deletions

View File

@ -23,7 +23,7 @@ var (
extraDebug = false
)
// Interpret is where we will actuall define our CLICommands
// Interpret is where we will actuall define our Commands
func executor(cmd string) {
cmd = strings.TrimSpace(cmd)
var args = strings.Fields(cmd)
@ -60,7 +60,7 @@ func executor(cmd string) {
}
case "help":
if len(args) < 2 {
getHelp("meta")
getHelp("")
return
}
getHelp(args[len(args)-1])
@ -77,7 +77,7 @@ func executor(cmd string) {
if len(args) == 0 {
return
}
bcmd, ok := CLICommands[args[0]]
bcmd, ok := Commands[args[0]]
if !ok {
return
}
@ -109,18 +109,6 @@ func executor(cmd string) {
}
}
func getHelp(target string) {
/* if target == "" {
*/
for _, sug := range suggestions {
for _, su := range sug {
println(su.Text + "(" + strings.Join(su.inner.aliases, ", ") + ")\t" + su.Description)
}
}
return
// }
}
func cmdScan(br *ziggy.Bridge, args []string) error {
r, err := br.FindLights()
if err != nil {

View File

@ -22,22 +22,23 @@ var (
)
type ziggsCommand struct {
reactor reactor
aliases []string
isAlias bool
reactor reactor
description string
aliases []string
isAlias bool
}
type reactor func(bridge *ziggy.Bridge, args []string) error
func newZiggsCommand(
react reactor,
aliases ...string) *ziggsCommand {
func newZiggsCommand(react reactor, desc string, aliases ...string) *ziggsCommand {
ret := &ziggsCommand{
reactor: react,
isAlias: false,
reactor: react,
aliases: aliases,
isAlias: false,
description: desc,
}
for _, alias := range aliases {
CLICommands[alias] = &ziggsCommand{
Commands[alias] = &ziggsCommand{
reactor: react,
isAlias: true,
}
@ -45,21 +46,7 @@ func newZiggsCommand(
return ret
}
var CLICommands = make(map[string]*ziggsCommand)
func init() {
CLICommands["ls"] = newZiggsCommand(cmdList)
CLICommands["schedules"] = newZiggsCommand(cmdSchedules, "lssched", "crontab")
CLICommands["rules"] = newZiggsCommand(cmdRules, "lsrule")
CLICommands["sensors"] = newZiggsCommand(cmdSensors, "lssens")
CLICommands["scenes"] = newZiggsCommand(cmdScenes, "lsscene")
CLICommands["lights"] = newZiggsCommand(cmdLights, "lslight")
CLICommands["groups"] = newZiggsCommand(cmdGroups, "lsgrp")
CLICommands["delete"] = newZiggsCommand(cmdDelete, "del", "remove")
CLICommands["scan"] = newZiggsCommand(cmdScan, "search", "find")
CLICommands["rename"] = newZiggsCommand(cmdRename, "mv")
CLICommands["set"] = newZiggsCommand(cmdSet, "update")
}
var Commands = make(map[string]*ziggsCommand)
func cmdList(br *ziggy.Bridge, args []string) error {
var runs = []reactor{cmdLights, cmdGroups, cmdScenes, cmdSensors}
@ -91,7 +78,9 @@ func cmdScenes(br *ziggy.Bridge, args []string) error {
return err
}
for _, scene := range scenes {
log.Info().Str("caller", scene.Name).Msgf("%v", spew.Sprint(scene))
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).
Str("ID", scene.ID).Msgf("Scene: %s", scene.Name)
log.Trace().Msgf("%v", spew.Sprint(scene))
}
return nil
}
@ -99,8 +88,9 @@ func cmdScenes(br *ziggy.Bridge, args []string) error {
func cmdLights(br *ziggy.Bridge, args []string) error {
for name, l := range ziggy.GetLightMap() {
log.Info().
Int("ID", l.ID).Str("type", l.ProductName).
Str("model", l.ModelID).Bool("on", l.IsOn()).Msgf("[+] %s", name)
Str("caller", strings.Split(br.Host, "://")[1]).Int("ID", l.ID).Str("type", l.ProductName).
Str("model", l.ModelID).Bool("on", l.IsOn()).Msgf("Light: %s", name)
log.Trace().Msgf("%v", spew.Sprint(l))
}
return nil
}
@ -114,7 +104,9 @@ func cmdRules(br *ziggy.Bridge, args []string) error {
return errors.New("no rules found")
}
for _, r := range rules {
log.Info().Str("caller", r.Name).Int("ID", r.ID).Msgf("%v", spew.Sprint(r))
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).Int("ID", r.ID).
Str("status", r.Status).Msgf("Rule: %s", r.Name)
log.Trace().Msgf("%v", spew.Sprint(r))
}
return nil
}
@ -128,7 +120,9 @@ func cmdSchedules(br *ziggy.Bridge, args []string) error {
return errors.New("no schedules found")
}
for _, s := range schedules {
log.Info().Str("caller", s.Name).Int("ID", s.ID).Msgf("%v", spew.Sprint(s))
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).Int("ID", s.ID).
Str("desc", s.Description).Msgf("Schedule: %s", s.Name)
log.Trace().Msgf("%v", spew.Sprint(s))
}
return nil
}
@ -142,7 +136,9 @@ func cmdSensors(br *ziggy.Bridge, args []string) error {
return errors.New("no sensors found")
}
for _, s := range sensors {
log.Info().Str("caller", s.Name).Int("ID", s.ID).Msgf("%v", spew.Sprint(s))
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).Int("ID", s.ID).
Str("type", s.Type).Msgf("Sensor: %s", s.Name)
log.Trace().Msgf("%v", spew.Sprint(s))
}
return nil
}
@ -156,8 +152,10 @@ func cmdGroups(br *ziggy.Bridge, args []string) error {
return errors.New("no groups found")
}
for n, g := range groupmap {
log.Info().Str("caller", g.Name).Str("mapname", n).Str("type", g.Type).Int("ID", g.ID).
Str("class", g.Class).Bool("on", g.IsOn()).Msgf("%v", g.GroupState)
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).
Str("mapname", n).Str("type", g.Type).Int("ID", g.ID).
Str("class", g.Class).Bool("on", g.IsOn()).Msgf("Group: %s", g.Name)
log.Trace().Msgf("%v", spew.Sprint(g))
}
return nil
}

View File

@ -9,7 +9,6 @@ import (
const (
grn = "\033[32m"
red = "\033[31m"
ylw = "\033[33m"
rst = "\033[0m"
)
@ -17,6 +16,7 @@ type completion struct {
cli.Suggest
inner *ziggsCommand
requires map[int][]string
isAlias bool
root bool
}
@ -65,30 +65,61 @@ func (c completion) qualifies(line string) bool {
return count >= len(c.requires)
}
var suggestions map[int][]completion
var suggestions map[int][]*completion
func init() {
suggestions = make(map[int][]completion)
suggestions[0] = []completion{
{Suggest: cli.Suggest{Text: "lights", Description: "print all known lights"}, inner: CLICommands["lights"], root: true},
{Suggest: cli.Suggest{Text: "groups", Description: "print all known groups"}, inner: CLICommands["groups"], root: true},
{Suggest: cli.Suggest{Text: "rules", Description: "print all known rules"}, inner: CLICommands["rules"], root: true},
{Suggest: cli.Suggest{Text: "scenes", Description: "print all known scenes"}, inner: CLICommands["scenes"], root: true},
{Suggest: cli.Suggest{Text: "schedules", Description: "print all known schedules"}, inner: CLICommands["schedules"], root: true},
{Suggest: cli.Suggest{Text: "sensors", Description: "print all known sensors"}, inner: CLICommands["sensors"], root: true},
{Suggest: cli.Suggest{Text: "set", Description: "set state of target"}, inner: CLICommands["set"], root: true},
{Suggest: cli.Suggest{Text: "create", Description: "create object"}, inner: CLICommands["create"], root: true},
{Suggest: cli.Suggest{Text: "delete", Description: "delete object"}, inner: CLICommands["delete"], root: true},
{Suggest: cli.Suggest{Text: "clear", Description: "clear screen"}},
{Suggest: cli.Suggest{Text: "scan", Description: "scan for bridges"}},
{Suggest: cli.Suggest{Text: "exit", Description: "exit ziggs"}},
Commands["ls"] = newZiggsCommand(cmdList, "list all lights, groups, scenes, rules, and schedules")
Commands["schedules"] = newZiggsCommand(cmdSchedules, "list schedules", "lssched", "crontab")
Commands["rules"] = newZiggsCommand(cmdRules, "list rules", "lsrule")
Commands["sensors"] = newZiggsCommand(cmdSensors, "list sensors", "lssens")
Commands["scenes"] = newZiggsCommand(cmdScenes, "list scenes", "lsscene")
Commands["lights"] = newZiggsCommand(cmdLights, "list lights", "lslight")
Commands["groups"] = newZiggsCommand(cmdGroups, "list groups", "lsgrp")
Commands["create"] = newZiggsCommand(cmdCreate, "create a new object in bridge", "new", "mk")
Commands["delete"] = newZiggsCommand(cmdDelete, "delete objects from bridges", "del", "remove")
Commands["scan"] = newZiggsCommand(cmdScan, "scan for bridges/lights/sensors", "search", "find")
Commands["rename"] = newZiggsCommand(cmdRename, "rename object in bridge", "mv")
Commands["set"] = newZiggsCommand(cmdSet, "update object properties in bridge", "update")
initCompletion()
}
func initCompletion() {
suggestions = make(map[int][]*completion)
suggestions[0] = []*completion{
{Suggest: cli.Suggest{Text: "lights"}, inner: Commands["lights"]},
{Suggest: cli.Suggest{Text: "groups"}, inner: Commands["groups"]},
{Suggest: cli.Suggest{Text: "rules"}, inner: Commands["rules"]},
{Suggest: cli.Suggest{Text: "scenes"}, inner: Commands["scenes"]},
{Suggest: cli.Suggest{Text: "schedules"}, inner: Commands["schedules"]},
{Suggest: cli.Suggest{Text: "sensors"}, inner: Commands["sensors"]},
{Suggest: cli.Suggest{Text: "set"}, inner: Commands["set"]},
{Suggest: cli.Suggest{Text: "create"}, inner: Commands["create"]},
{Suggest: cli.Suggest{Text: "delete"}, inner: Commands["delete"]},
{Suggest: cli.Suggest{Text: "scan"}, inner: Commands["scan"]},
{Suggest: cli.Suggest{Text: "use", Description: "select bridge to perform actions on"}},
{Suggest: cli.Suggest{Text: "clear", Description: "clear screen"}},
{Suggest: cli.Suggest{Text: "exit", Description: "exit ziggs"}},
}
for _, sug := range suggestions[0] {
sug.requires = map[int][]string{}
sug.root = true
if sug.inner != nil {
sug.Suggest.Description = sug.inner.description
}
if sug.inner != nil && len(sug.inner.aliases) > 0 {
for _, a := range sug.inner.aliases {
suggestions[0] = append(suggestions[0], &completion{
Suggest: cli.Suggest{Text: a, Description: sug.Description},
inner: sug.inner,
root: true,
isAlias: true,
})
}
}
}
suggestions[1] = []completion{
suggestions[1] = []*completion{
{Suggest: cli.Suggest{Text: "group", Description: "target group"}},
{Suggest: cli.Suggest{Text: "light", Description: "target light"}},
}
@ -96,7 +127,7 @@ func init() {
sug.requires = map[int][]string{0: {"delete", "del", "set", "s"}}
sug.root = false
}
delCompletion := []completion{
delCompletion := []*completion{
{Suggest: cli.Suggest{Text: "scene", Description: "target scene"}},
{Suggest: cli.Suggest{Text: "schedule", Description: "target schedule"}},
{Suggest: cli.Suggest{Text: "sensor", Description: "target sensor"}},

47
internal/cli/help.go Normal file
View File

@ -0,0 +1,47 @@
package cli
import (
"fmt"
"os"
"strings"
"text/tabwriter"
)
var tabber = tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
func getHelp(target string) {
if target != "" && target != "meta" {
for _, su := range suggestions[0] {
if strings.Contains(strings.ToLower(su.Text), strings.ToLower(target)) {
println(su.Text + "\t" + su.Description)
}
}
return
}
for _, su := range suggestions[0] {
var desc string
if su.inner == nil {
desc = su.Description
} else {
desc = su.inner.description
if su.inner.isAlias || su.isAlias {
su.isAlias = true
if extraDebug {
log.Trace().Msgf("alias: %s", su.Text)
}
}
}
if su.isAlias {
continue
}
if extraDebug {
log.Trace().Interface("details", su).Send()
}
_, err := fmt.Fprintln(tabber, su.Text+"\t"+desc)
if err != nil {
panic(err.Error())
}
}
tabber.Flush()
}

View File

@ -14,7 +14,7 @@ func processGroups(grps map[string]*huego.Group) {
suffix = " (" + g.Type + ")"
}
suggestions[2] = append(suggestions[2],
completion{
&completion{
Suggest: cli.Suggest{
Text: grp,
Description: "Group" + suffix,
@ -35,7 +35,7 @@ func processLights() {
suffix = " (" + l.Type + ")"
}
suggestions[2] = append(suggestions[2],
completion{
&completion{
Suggest: cli.Suggest{
Text: lt,
Description: "Light" + suffix,
@ -52,7 +52,7 @@ func processLights() {
func processBridges() {
for brd, b := range ziggy.Lucifer.Bridges {
suggestions[1] = append(suggestions[1],
completion{
&completion{
Suggest: cli.Suggest{
Text: brd,
Description: "Bridge: " + b.Host,

View File

@ -125,6 +125,10 @@ func main() {
data.Start()
defer data.Close()
if len(os.Args) < 2 {
cli.StartCLI()
}
for _, arg := range os.Args {
switch arg {
case "discover":