CLI: implement help
This commit is contained in:
parent
40d8979ab9
commit
08b7a3f7ae
@ -23,7 +23,7 @@ var (
|
|||||||
extraDebug = false
|
extraDebug = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interpret is where we will actuall define our CLICommands
|
// Interpret is where we will actuall define our Commands
|
||||||
func executor(cmd string) {
|
func executor(cmd string) {
|
||||||
cmd = strings.TrimSpace(cmd)
|
cmd = strings.TrimSpace(cmd)
|
||||||
var args = strings.Fields(cmd)
|
var args = strings.Fields(cmd)
|
||||||
@ -60,7 +60,7 @@ func executor(cmd string) {
|
|||||||
}
|
}
|
||||||
case "help":
|
case "help":
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
getHelp("meta")
|
getHelp("")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
getHelp(args[len(args)-1])
|
getHelp(args[len(args)-1])
|
||||||
@ -77,7 +77,7 @@ func executor(cmd string) {
|
|||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bcmd, ok := CLICommands[args[0]]
|
bcmd, ok := Commands[args[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
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 {
|
func cmdScan(br *ziggy.Bridge, args []string) error {
|
||||||
r, err := br.FindLights()
|
r, err := br.FindLights()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -22,22 +22,23 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ziggsCommand struct {
|
type ziggsCommand struct {
|
||||||
reactor reactor
|
reactor reactor
|
||||||
aliases []string
|
description string
|
||||||
isAlias bool
|
aliases []string
|
||||||
|
isAlias bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type reactor func(bridge *ziggy.Bridge, args []string) error
|
type reactor func(bridge *ziggy.Bridge, args []string) error
|
||||||
|
|
||||||
func newZiggsCommand(
|
func newZiggsCommand(react reactor, desc string, aliases ...string) *ziggsCommand {
|
||||||
react reactor,
|
|
||||||
aliases ...string) *ziggsCommand {
|
|
||||||
ret := &ziggsCommand{
|
ret := &ziggsCommand{
|
||||||
reactor: react,
|
reactor: react,
|
||||||
isAlias: false,
|
aliases: aliases,
|
||||||
|
isAlias: false,
|
||||||
|
description: desc,
|
||||||
}
|
}
|
||||||
for _, alias := range aliases {
|
for _, alias := range aliases {
|
||||||
CLICommands[alias] = &ziggsCommand{
|
Commands[alias] = &ziggsCommand{
|
||||||
reactor: react,
|
reactor: react,
|
||||||
isAlias: true,
|
isAlias: true,
|
||||||
}
|
}
|
||||||
@ -45,21 +46,7 @@ func newZiggsCommand(
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
var CLICommands = make(map[string]*ziggsCommand)
|
var Commands = 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")
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdList(br *ziggy.Bridge, args []string) error {
|
func cmdList(br *ziggy.Bridge, args []string) error {
|
||||||
var runs = []reactor{cmdLights, cmdGroups, cmdScenes, cmdSensors}
|
var runs = []reactor{cmdLights, cmdGroups, cmdScenes, cmdSensors}
|
||||||
@ -91,7 +78,9 @@ func cmdScenes(br *ziggy.Bridge, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, scene := range scenes {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -99,8 +88,9 @@ func cmdScenes(br *ziggy.Bridge, args []string) error {
|
|||||||
func cmdLights(br *ziggy.Bridge, args []string) error {
|
func cmdLights(br *ziggy.Bridge, args []string) error {
|
||||||
for name, l := range ziggy.GetLightMap() {
|
for name, l := range ziggy.GetLightMap() {
|
||||||
log.Info().
|
log.Info().
|
||||||
Int("ID", l.ID).Str("type", l.ProductName).
|
Str("caller", strings.Split(br.Host, "://")[1]).Int("ID", l.ID).Str("type", l.ProductName).
|
||||||
Str("model", l.ModelID).Bool("on", l.IsOn()).Msgf("[+] %s", name)
|
Str("model", l.ModelID).Bool("on", l.IsOn()).Msgf("Light: %s", name)
|
||||||
|
log.Trace().Msgf("%v", spew.Sprint(l))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -114,7 +104,9 @@ func cmdRules(br *ziggy.Bridge, args []string) error {
|
|||||||
return errors.New("no rules found")
|
return errors.New("no rules found")
|
||||||
}
|
}
|
||||||
for _, r := range rules {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -128,7 +120,9 @@ func cmdSchedules(br *ziggy.Bridge, args []string) error {
|
|||||||
return errors.New("no schedules found")
|
return errors.New("no schedules found")
|
||||||
}
|
}
|
||||||
for _, s := range schedules {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -142,7 +136,9 @@ func cmdSensors(br *ziggy.Bridge, args []string) error {
|
|||||||
return errors.New("no sensors found")
|
return errors.New("no sensors found")
|
||||||
}
|
}
|
||||||
for _, s := range sensors {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -156,8 +152,10 @@ func cmdGroups(br *ziggy.Bridge, args []string) error {
|
|||||||
return errors.New("no groups found")
|
return errors.New("no groups found")
|
||||||
}
|
}
|
||||||
for n, g := range groupmap {
|
for n, g := range groupmap {
|
||||||
log.Info().Str("caller", g.Name).Str("mapname", n).Str("type", g.Type).Int("ID", g.ID).
|
log.Info().Str("caller", strings.Split(br.Host, "://")[1]).
|
||||||
Str("class", g.Class).Bool("on", g.IsOn()).Msgf("%v", g.GroupState)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
grn = "\033[32m"
|
grn = "\033[32m"
|
||||||
red = "\033[31m"
|
red = "\033[31m"
|
||||||
ylw = "\033[33m"
|
|
||||||
rst = "\033[0m"
|
rst = "\033[0m"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,6 +16,7 @@ type completion struct {
|
|||||||
cli.Suggest
|
cli.Suggest
|
||||||
inner *ziggsCommand
|
inner *ziggsCommand
|
||||||
requires map[int][]string
|
requires map[int][]string
|
||||||
|
isAlias bool
|
||||||
root bool
|
root bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,30 +65,61 @@ func (c completion) qualifies(line string) bool {
|
|||||||
return count >= len(c.requires)
|
return count >= len(c.requires)
|
||||||
}
|
}
|
||||||
|
|
||||||
var suggestions map[int][]completion
|
var suggestions map[int][]*completion
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
suggestions = make(map[int][]completion)
|
Commands["ls"] = newZiggsCommand(cmdList, "list all lights, groups, scenes, rules, and schedules")
|
||||||
suggestions[0] = []completion{
|
Commands["schedules"] = newZiggsCommand(cmdSchedules, "list schedules", "lssched", "crontab")
|
||||||
{Suggest: cli.Suggest{Text: "lights", Description: "print all known lights"}, inner: CLICommands["lights"], root: true},
|
Commands["rules"] = newZiggsCommand(cmdRules, "list rules", "lsrule")
|
||||||
{Suggest: cli.Suggest{Text: "groups", Description: "print all known groups"}, inner: CLICommands["groups"], root: true},
|
Commands["sensors"] = newZiggsCommand(cmdSensors, "list sensors", "lssens")
|
||||||
{Suggest: cli.Suggest{Text: "rules", Description: "print all known rules"}, inner: CLICommands["rules"], root: true},
|
Commands["scenes"] = newZiggsCommand(cmdScenes, "list scenes", "lsscene")
|
||||||
{Suggest: cli.Suggest{Text: "scenes", Description: "print all known scenes"}, inner: CLICommands["scenes"], root: true},
|
Commands["lights"] = newZiggsCommand(cmdLights, "list lights", "lslight")
|
||||||
{Suggest: cli.Suggest{Text: "schedules", Description: "print all known schedules"}, inner: CLICommands["schedules"], root: true},
|
Commands["groups"] = newZiggsCommand(cmdGroups, "list groups", "lsgrp")
|
||||||
{Suggest: cli.Suggest{Text: "sensors", Description: "print all known sensors"}, inner: CLICommands["sensors"], root: true},
|
Commands["create"] = newZiggsCommand(cmdCreate, "create a new object in bridge", "new", "mk")
|
||||||
{Suggest: cli.Suggest{Text: "set", Description: "set state of target"}, inner: CLICommands["set"], root: true},
|
Commands["delete"] = newZiggsCommand(cmdDelete, "delete objects from bridges", "del", "remove")
|
||||||
{Suggest: cli.Suggest{Text: "create", Description: "create object"}, inner: CLICommands["create"], root: true},
|
Commands["scan"] = newZiggsCommand(cmdScan, "scan for bridges/lights/sensors", "search", "find")
|
||||||
{Suggest: cli.Suggest{Text: "delete", Description: "delete object"}, inner: CLICommands["delete"], root: true},
|
Commands["rename"] = newZiggsCommand(cmdRename, "rename object in bridge", "mv")
|
||||||
{Suggest: cli.Suggest{Text: "clear", Description: "clear screen"}},
|
Commands["set"] = newZiggsCommand(cmdSet, "update object properties in bridge", "update")
|
||||||
{Suggest: cli.Suggest{Text: "scan", Description: "scan for bridges"}},
|
initCompletion()
|
||||||
{Suggest: cli.Suggest{Text: "exit", Description: "exit ziggs"}},
|
}
|
||||||
|
|
||||||
|
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: "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] {
|
for _, sug := range suggestions[0] {
|
||||||
sug.requires = map[int][]string{}
|
sug.requires = map[int][]string{}
|
||||||
sug.root = true
|
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: "group", Description: "target group"}},
|
||||||
{Suggest: cli.Suggest{Text: "light", Description: "target light"}},
|
{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.requires = map[int][]string{0: {"delete", "del", "set", "s"}}
|
||||||
sug.root = false
|
sug.root = false
|
||||||
}
|
}
|
||||||
delCompletion := []completion{
|
delCompletion := []*completion{
|
||||||
{Suggest: cli.Suggest{Text: "scene", Description: "target scene"}},
|
{Suggest: cli.Suggest{Text: "scene", Description: "target scene"}},
|
||||||
{Suggest: cli.Suggest{Text: "schedule", Description: "target schedule"}},
|
{Suggest: cli.Suggest{Text: "schedule", Description: "target schedule"}},
|
||||||
{Suggest: cli.Suggest{Text: "sensor", Description: "target sensor"}},
|
{Suggest: cli.Suggest{Text: "sensor", Description: "target sensor"}},
|
||||||
|
47
internal/cli/help.go
Normal file
47
internal/cli/help.go
Normal 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()
|
||||||
|
}
|
@ -14,7 +14,7 @@ func processGroups(grps map[string]*huego.Group) {
|
|||||||
suffix = " (" + g.Type + ")"
|
suffix = " (" + g.Type + ")"
|
||||||
}
|
}
|
||||||
suggestions[2] = append(suggestions[2],
|
suggestions[2] = append(suggestions[2],
|
||||||
completion{
|
&completion{
|
||||||
Suggest: cli.Suggest{
|
Suggest: cli.Suggest{
|
||||||
Text: grp,
|
Text: grp,
|
||||||
Description: "Group" + suffix,
|
Description: "Group" + suffix,
|
||||||
@ -35,7 +35,7 @@ func processLights() {
|
|||||||
suffix = " (" + l.Type + ")"
|
suffix = " (" + l.Type + ")"
|
||||||
}
|
}
|
||||||
suggestions[2] = append(suggestions[2],
|
suggestions[2] = append(suggestions[2],
|
||||||
completion{
|
&completion{
|
||||||
Suggest: cli.Suggest{
|
Suggest: cli.Suggest{
|
||||||
Text: lt,
|
Text: lt,
|
||||||
Description: "Light" + suffix,
|
Description: "Light" + suffix,
|
||||||
@ -52,7 +52,7 @@ func processLights() {
|
|||||||
func processBridges() {
|
func processBridges() {
|
||||||
for brd, b := range ziggy.Lucifer.Bridges {
|
for brd, b := range ziggy.Lucifer.Bridges {
|
||||||
suggestions[1] = append(suggestions[1],
|
suggestions[1] = append(suggestions[1],
|
||||||
completion{
|
&completion{
|
||||||
Suggest: cli.Suggest{
|
Suggest: cli.Suggest{
|
||||||
Text: brd,
|
Text: brd,
|
||||||
Description: "Bridge: " + b.Host,
|
Description: "Bridge: " + b.Host,
|
||||||
|
4
main.go
4
main.go
@ -125,6 +125,10 @@ func main() {
|
|||||||
data.Start()
|
data.Start()
|
||||||
defer data.Close()
|
defer data.Close()
|
||||||
|
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
cli.StartCLI()
|
||||||
|
}
|
||||||
|
|
||||||
for _, arg := range os.Args {
|
for _, arg := range os.Args {
|
||||||
switch arg {
|
switch arg {
|
||||||
case "discover":
|
case "discover":
|
||||||
|
Loading…
Reference in New Issue
Block a user