Functioning argument parsing

This commit is contained in:
kayos@tcp.direct 2022-07-08 14:35:11 -07:00
parent cd0c68e8a2
commit a0c59bc8a3
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
2 changed files with 180 additions and 24 deletions

@ -53,8 +53,9 @@ func executor(cmd string) {
case "quit", "exit":
os.Exit(0)
case "use":
if len(args) <= 1 {
println()
if len(args) < 2 {
println("use: use <bridge>")
return
}
if br, ok := lights.Lucifer.Bridges[args[1]]; !ok {
println("invalid bridge: " + args[1])
@ -85,14 +86,16 @@ func executor(cmd string) {
println()
return
}
log.Trace().Msg("executor found for " + args[0])
br, ok := lights.Lucifer.Bridges[selectedBridge]
if selectedBridge == "" || !ok {
for _, br := range lights.Lucifer.Bridges {
go bcmd(br, args[1:])
}
} else {
bcmd(br, args[1:])
err := bcmd(br, args[1:])
if err != nil {
log.Error().Err(err).Msg("error executing command")
}
}
}

@ -2,6 +2,8 @@ package interactive
import (
"errors"
"fmt"
"image/color"
"strconv"
cli "git.tcp.direct/Mirrors/go-prompt"
@ -10,8 +12,45 @@ import (
"git.tcp.direct/kayos/ziggs/lights"
)
var errInvalidFormat = errors.New("invalid format")
func ParseHexColorFast(s string) (c color.RGBA, err error) {
c.A = 0xff
if s[0] != '#' {
return c, errInvalidFormat
}
hexToByte := func(b byte) byte {
switch {
case b >= '0' && b <= '9':
return b - '0'
case b >= 'a' && b <= 'f':
return b - 'a' + 10
case b >= 'A' && b <= 'F':
return b - 'A' + 10
}
err = errInvalidFormat
return 0
}
switch len(s) {
case 7:
c.R = hexToByte(s[1])<<4 + hexToByte(s[2])
c.G = hexToByte(s[3])<<4 + hexToByte(s[4])
c.B = hexToByte(s[5])<<4 + hexToByte(s[6])
case 4:
c.R = hexToByte(s[1]) * 17
c.G = hexToByte(s[2]) * 17
c.B = hexToByte(s[3]) * 17
default:
err = errInvalidFormat
}
return
}
func cmdLights(br *lights.Bridge, args []string) error {
if len(br.HueLights) <= 0 {
if len(br.HueLights) == 0 {
return errors.New("no lights found")
}
for _, l := range br.HueLights {
@ -22,35 +61,148 @@ func cmdLights(br *lights.Bridge, args []string) error {
return nil
}
func cmdGroups(br *lights.Bridge, args []string) error {
var groupmap = make(map[string]*huego.Group)
gs, err := br.Bridge.GetGroups()
if err != nil {
return err
}
for _, g := range gs {
groupmap[g.Name] = &g
func cmdSet(bridge *lights.Bridge, args []string) error {
if len(args) < 3 {
return errors.New("not enough arguments")
}
if len(args) > 0 {
switch {
case args[1] == "+":
return groupmap[args[0]].Bri(groupmap[args[0]].State.Bri + 25)
case args[1] == "-":
return groupmap[args[0]].Bri(groupmap[args[0]].State.Bri - 25)
default:
newBrightness, numErr := strconv.Atoi(args[1])
var target interface {
On() error
Off() error
Bri(uint8) error
Ct(uint16) error
Hue(uint16) error
Sat(uint8) error
Col(color.Color) error
SetState(huego.State) error
Alert(string) error
}
var groupmap map[string]huego.Group
var action func() error
var currentState *huego.State
var argHead = -1
for range args {
argHead++
if len(args) <= argHead {
break
}
log.Trace().Int("argHead", argHead).Msg(args[argHead])
switch args[argHead] {
case "group", "g", "grp":
var err error
groupmap, err = getGroupMap(bridge)
if err != nil {
return err
}
if len(args) <= argHead-1 {
return errors.New("no group specified")
}
argHead++
g, ok := groupmap[args[argHead]]
if !ok {
return errors.New("group not found")
}
target = &g
case "on":
action = target.On
case "off":
action = target.Off
case "brightness--", "dim":
action = func() error {
if currentState == nil {
return fmt.Errorf("no state found")
}
return fmt.Errorf("couldn't lower brightness: %w", target.Bri(currentState.Bri-5))
}
case "brightness++", "brighten":
action = func() error {
if currentState == nil {
return fmt.Errorf("no state found")
}
return fmt.Errorf("couldn't raise brightness: %w", target.Bri(currentState.Bri+5))
}
case "brightness":
if len(args) <= argHead-1 {
return errors.New("no brightness specified")
}
argHead++
newBrightness, numErr := strconv.Atoi(args[argHead])
if numErr != nil {
return numErr
}
return groupmap[args[0]].Bri(uint8(newBrightness))
action = func() error {
return fmt.Errorf("failed to set brightness: %w",
target.Bri(uint8(newBrightness)))
}
case "color":
if len(args) <= argHead-1 {
return errors.New("not enough arguments")
}
argHead++
newcolor, err := ParseHexColorFast(args[argHead])
if err != nil {
return err
}
action = func() error { return fmt.Errorf("failed to set color: %w", target.Col(newcolor)) }
case "alert":
action = func() error { return fmt.Errorf("failed to set alert: %w", target.Alert("select")) }
default:
return fmt.Errorf("unknown argument: " + args[argHead])
}
}
if action == nil {
return errors.New("no action specified")
}
if target == nil {
return errors.New("no target specified")
}
tg, tgok := target.(*huego.Group)
tl, tlok := target.(*huego.Light)
switch {
case tgok:
currentState = tg.State
case tlok:
currentState = tl.State
}
log.Trace().Msgf("current state: %v", currentState)
err := action()
if err != nil {
return err
}
switch {
case tgok:
currentState = tg.State
case tlok:
currentState = tl.State
}
log.Trace().Msgf("new state: %v", currentState)
return nil
}
if len(gs) == 0 {
return errors.New("no lights found")
func getGroupMap(br *lights.Bridge) (map[string]huego.Group, error) {
var groupmap = make(map[string]huego.Group)
gs, err := br.Bridge.GetGroups()
if err != nil {
return nil, err
}
for _, g := range gs {
groupmap[g.Name] = g
}
return groupmap, nil
}
func cmdGroups(br *lights.Bridge, args []string) error {
groupmap, err := getGroupMap(br)
if err != nil {
return err
}
if len(groupmap) == 0 {
return errors.New("no groups found")
}
for _, g := range groupmap {
log.Info().Str("caller", g.Name).Str("type", g.Type).Int("ID", g.ID).
Str("class", g.Class).Bool("on", g.IsOn()).Msgf("%v", g.GroupState)
}
@ -63,6 +215,7 @@ var bridgeCMD = map[string]reactor{
"scan": cmdScan,
"lights": cmdLights,
"groups": cmdGroups,
"set": cmdSet,
}
const use = "use"