Compare commits

...

33 Commits

Author SHA1 Message Date
a9936a0f1b Add make install 2021-04-07 01:38:00 +00:00
c229df8506 Change Makefile variable make 2021-04-07 01:37:19 +00:00
9c92d7945d Add visual power indicator character 2021-04-04 23:34:52 +00:00
a4c305c2e9 Fix bug where configuration is being overridden by a default configuration 2021-04-04 22:53:35 +00:00
e66f6358a9 Remove debug output from ls 2021-04-04 03:09:59 +00:00
100b585663 Add ~/.config/lume/lume.conf to configuration file search paths 2021-03-31 00:19:03 -05:00
f0cf3e12b6 Declare variables at the top of function 2021-03-31 00:18:00 -05:00
ce5f14db5d Fix access token validation
The access token was not be validated when there were additional
validations errors with the named colors
2021-03-31 00:13:49 -05:00
9b20413d64 Compile binary to ./bin 2021-03-30 23:57:52 -05:00
9c024454f2 Refactor global flags 2021-03-30 23:54:05 -05:00
05db35cdfe Remove global flags 2021-03-30 21:04:57 -05:00
bb95abdec6 Ignore lume binary 2021-03-30 21:01:07 -05:00
de93716b20 Fix context variable name 2021-03-30 13:33:36 -05:00
53bc7fa320 format 2021-03-30 13:31:26 -05:00
77c5f5ce18 Fix typo in Makefile 2021-03-30 13:27:58 -05:00
cf30eaae9b Update go modules 2021-03-29 17:37:00 -05:00
9338631de9 Add debug output support 2021-03-29 17:22:22 -05:00
a4638db773 Make configuration global, add helper functions 2021-03-29 17:21:12 -05:00
3c0254c9a1 Fix go.sum 2021-03-28 21:38:04 -05:00
b1a5844b6b Add support for parsing global flags 2021-03-28 21:33:43 -05:00
1ef900c44c Add breathe effect command 2021-03-25 09:46:58 -05:00
29552f7a69 Update dependencies 2021-03-22 23:49:43 -05:00
57983b5a52 s/CmdArgs/Context/g 2021-03-16 19:23:50 -05:00
88d7d7a0b4 Adding strings is not necessary 2021-03-16 19:21:59 -05:00
1f87c72e34 Fix syntax error 2021-03-16 19:20:19 -05:00
454bfbf61d Merge environment variables into Config 2021-03-16 19:09:53 -05:00
d5db68dbfa Change version format 2021-03-15 23:18:19 -05:00
dfa5d41a6d Add a default configuration 2021-03-15 22:26:19 -05:00
32bce4eaba Add functions to load configuration 2021-03-14 22:11:12 -05:00
e86ce1aeaf Add VSCode workspace 2021-03-14 17:08:02 -05:00
b3a6dfbe07 Move more configuration related code 2021-03-14 13:51:55 -05:00
804ec99021 Move configuration code to seperate file 2021-03-13 23:51:08 -06:00
ff05f8e2f3 Add printer object to format output 2021-03-13 16:20:18 -06:00
21 changed files with 572 additions and 337 deletions

2
.gitignore vendored
View File

@ -6,6 +6,8 @@
*.so *.so
*.dylib *.dylib
/bin
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test

View File

@ -1,13 +1,15 @@
V ?= 0 V ?= 0
Q = $(if $(filter 1, $V),, @) Q = $(if $(filter 1, $V),, @)
BINDIR=$(CURDIR)/bin
DESTDIR=/usr/local/bin
ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
EXE=lume.exe EXE=$(BINDIR)/lume.exe
RM=del /f /q RM=del /f /q
BUILD_DATE=$(shell powershell Get-Date -Format "yyyy-MM-ddThh:mm:sszzz") BUILD_DATE=$(shell powershell Get-Date -Format "yyyy-MM-ddThh:mm:sszzz")
else else
EXE=lume EXE=$(BINDIR)/lume
EXE=rm -f RM=rm -f
BUILD_DATE=$(shell date --iso-8601=seconds) BUILD_DATE=$(shell date --iso-8601=seconds)
endif endif
@ -24,4 +26,8 @@ build:
.PHONY: clean .PHONY: clean
clean: clean:
$(Q) $(RM) $(EXE) $(Q) $(RM) $(EXE)
.PHONY: install
install:
$(Q) install -p -D -m 0755 $(EXE) $(DESTDIR)

104
cmd/breathe.go Normal file
View File

@ -0,0 +1,104 @@
package lumecmd
import (
"flag"
"git.kill0.net/chill9/lifx-go"
)
func NewCmdBreathe() Command {
return Command{
Name: "breathe",
Func: BreatheCmd,
Flags: func() *flag.FlagSet {
fs := flag.NewFlagSet("breathe", flag.ExitOnError)
selector := fs.String("selector", defaultSelector, "Set the selector")
fs.StringVar(selector, "s", defaultSelector, "Set the selector")
fs.String("color", defaultColor, "The color to use for the breathe effect")
fs.String("from-color", defaultColor, "The color to start the effect from")
fs.Float64("period", lifx.DefaultBreathePeriod, "The time in seconds for one cycle of the effect")
fs.Float64("cycles", lifx.DefaultBreatheCycles, "The number of times to repeat the effect")
fs.Bool("persist", lifx.DefaultBreathePersist, "If false set the light back to its previous value when effect ends, if true leave the last effect color")
fs.Bool("power-on", lifx.DefaultBreathePowerOn, "If true, turn the bulb on if it is not already on")
fs.Float64("peak", lifx.DefaultBreathePeak, "Defines where in a period the target color is at its maximum (min: 0.0, max: 1.0)")
return fs
}(),
Use: "[--selector <selector>] --color <color> [--from-color <color>] [--period <period>] [--cycles <cycles>] [--persist <persist>] [--power-on] [--peak <peak>]",
Short: "The breathe effect",
}
}
func BreatheCmd(ctx Context) (int, error) {
var p Printer
c := ctx.Client
breathe := lifx.NewBreathe()
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
}
color := ctx.Flags.String("color")
if color != "" {
breathe.Color = lifx.NamedColor(color)
}
from_color := ctx.Flags.String("from-color")
if from_color != "" {
breathe.FromColor = lifx.NamedColor(from_color)
}
periodFlag := ctx.Flags.String("period")
if periodFlag != "" {
period := ctx.Flags.Float64("period")
breathe.Period = period
}
cyclesFlag := ctx.Flags.String("cycles")
if cyclesFlag != "" {
cycles := ctx.Flags.Float64("cycles")
breathe.Cycles = cycles
}
persist := ctx.Flags.Bool("persist")
breathe.Persist = persist
power_on := ctx.Flags.Bool("power-on")
breathe.PowerOn = power_on
peakFlag := ctx.Flags.String("peak")
if peakFlag != "" {
peak := ctx.Flags.Float64("peak")
breathe.Peak = peak
}
if color == "" {
printCmdHelp(ctx.Name)
return ExitFailure, nil
}
if err := breathe.Valid(); err != nil {
return ExitFailure, err
}
r, err := c.Breathe(selector, breathe)
if err != nil {
return ExitFailure, err
}
p = NewPrinter(format)
p.Results(r.Results)
return ExitSuccess, nil
}

View File

@ -1,7 +1,6 @@
package lumecmd package lumecmd
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"strconv" "strconv"
@ -14,13 +13,7 @@ const (
ExitFailure ExitFailure
) )
type Config struct { type Context struct {
AccessToken string `toml:"access_token"`
OutputFormat string `toml:"output_format"`
Colors map[string][]float32 `toml:"colors"`
}
type CmdArgs struct {
Flags Flags Flags Flags
Args []string Args []string
Client *lifx.Client Client *lifx.Client
@ -34,7 +27,7 @@ type Flags struct {
type Command struct { type Command struct {
Name string Name string
Func func(CmdArgs) (int, error) Func func(Context) (int, error)
Flags *flag.FlagSet Flags *flag.FlagSet
Use string Use string
Short string Short string
@ -88,6 +81,13 @@ func RegisterCommand(cmd Command) error {
if _, ok := commandRegistry[cmd.Name]; ok { if _, ok := commandRegistry[cmd.Name]; ok {
return fmt.Errorf("%s command is already registered") return fmt.Errorf("%s command is already registered")
} }
if cmd.Flags == nil {
cmd.Flags = flag.NewFlagSet(cmd.Name, flag.ExitOnError)
}
mergeGlobalFlags(cmd.Flags)
commandRegistry[cmd.Name] = cmd commandRegistry[cmd.Name] = cmd
return nil return nil
} }
@ -97,37 +97,9 @@ func GetCommand(name string) (Command, bool) {
return cmd, ok return cmd, ok
} }
// Validate configuration struct func mergeGlobalFlags(fs *flag.FlagSet) {
func (c *Config) Validate() error { fs.Bool("debug", false, "Enable debug mode")
var err error
if c.AccessToken == "" {
err = errors.New("access_token is not set")
}
if err = c.validateColors(); err != nil { outputFormat := fs.String("output-format", defaultOutputFormat, "Set the output format")
return err fs.StringVar(outputFormat, "o", defaultOutputFormat, "Set the output format")
}
return err
}
func (c *Config) validateColors() (err error) {
if len(c.Colors) > 0 {
for name, hsb := range c.Colors {
if len(hsb) != 3 {
return fmt.Errorf("color '%s' needs three values", name)
}
h, s, b := hsb[0], hsb[1], hsb[2]
if h < 0 || h > 360 {
return fmt.Errorf("color '%s' hue value must be between 0.0-360.0", name)
}
if s < 0 || b > 1 {
return fmt.Errorf("color '%s' saturation value must be between 0.0-1.0", name)
}
if b < 0 || b > 1 {
return fmt.Errorf("color '%s' brightness value must be between 0.0-1.0", name)
}
}
}
return err
} }

157
cmd/config.go Normal file
View File

@ -0,0 +1,157 @@
package lumecmd
import (
"errors"
"fmt"
"os"
"path"
"strings"
"github.com/BurntSushi/toml"
)
const lumercFile string = ".lumerc"
const lumeConfigFile string = "lume.conf"
const defaultPowerIndicator rune = '●'
type Config struct {
AccessToken string `toml:"access_token"`
OutputFormat string `toml:"output_format"`
Colors map[string][]float32 `toml:"colors"`
userAgent string
Debug bool `toml:"debug"`
Indicator string `toml:"indicator"`
}
var (
DefaultConfig = Config{
userAgent: initUserAgent(),
}
globalConfig *Config = NewConfig()
)
func NewConfig() *Config {
c := new(Config)
c.userAgent = initUserAgent()
c.Debug = false
c.OutputFormat = "simple"
c.Indicator = string(defaultPowerIndicator)
return c
}
func GetConfig() *Config {
return globalConfig
}
// Validate configuration struct
func (c *Config) Validate() error {
var err error
if c.AccessToken == "" {
return errors.New("access_token is not set")
}
if len([]rune(c.Indicator)) != 1 {
return errors.New("indicator must be a single rune")
}
if err = c.validateColors(); err != nil {
return err
}
return err
}
func (c *Config) validateColors() (err error) {
if len(c.Colors) > 0 {
for name, hsb := range c.Colors {
if len(hsb) != 3 {
return fmt.Errorf("color '%s' needs three values", name)
}
h, s, b := hsb[0], hsb[1], hsb[2]
if h < 0 || h > 360 {
return fmt.Errorf("color '%s' hue value must be between 0.0-360.0", name)
}
if s < 0 || b > 1 {
return fmt.Errorf("color '%s' saturation value must be between 0.0-1.0", name)
}
if b < 0 || b > 1 {
return fmt.Errorf("color '%s' brightness value must be between 0.0-1.0", name)
}
}
}
return err
}
func (c *Config) MergeWithEnv() {
envAccessToken := os.Getenv("LIFX_ACCESS_TOKEN")
if envAccessToken != "" {
c.AccessToken = envAccessToken
}
}
func LoadConfig(s string) (*Config, error) {
var err error
var c *Config = GetConfig()
if _, err := toml.Decode(s, &c); err != nil {
err = fmt.Errorf("fatal: failed to parse; %w", err)
}
return c, err
}
func LoadConfigFile(configPath string) (*Config, error) {
var err error
var c *Config = GetConfig()
if _, err := toml.DecodeFile(configPath, &c); err != nil {
err = fmt.Errorf("fatal: failed to parse %s; %w", configPath, err)
}
return c, err
}
func getConfigPath() string {
var tryPath, configPath, homeDir, cwd string
var err error
// ~/.lumerc
homeDir, err = os.UserHomeDir()
if err == nil {
tryPath = path.Join(homeDir, lumercFile)
if _, err := os.Stat(tryPath); !os.IsNotExist(err) {
configPath = tryPath
}
}
// ~/.config/lume/lume.conf
homeDir, err = os.UserHomeDir()
if err == nil {
tryPath = path.Join(homeDir, ".config/lume", lumeConfigFile)
if _, err := os.Stat(tryPath); !os.IsNotExist(err) {
configPath = tryPath
}
}
// ./.lumerc
cwd, err = os.Getwd()
if err == nil {
tryPath = path.Join(cwd, lumercFile)
if _, err := os.Stat(tryPath); !os.IsNotExist(err) {
configPath = tryPath
}
}
return configPath
}
func initUserAgent() string {
var b strings.Builder
b.WriteString("lume")
b.WriteRune('/')
b.WriteString(Version)
return b.String()
}

View File

@ -14,11 +14,11 @@ func NewCmdHelp() Command {
} }
} }
func HelpCmd(args CmdArgs) (int, error) { func HelpCmd(ctx Context) (int, error) {
if len(args.Args) == 0 { if len(ctx.Args) == 0 {
printHelp(commandRegistry) printHelp(commandRegistry)
} else if len(args.Args) >= 1 { } else if len(ctx.Args) >= 1 {
printCmdHelp(args.Args[0]) printCmdHelp(ctx.Args[0])
} }
return ExitSuccess, nil return ExitSuccess, nil

View File

@ -14,8 +14,6 @@ func NewCmdLs() Command {
selector := fs.String("selector", defaultSelector, "Set the selector") selector := fs.String("selector", defaultSelector, "Set the selector")
fs.StringVar(selector, "s", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector=<selector>]", Use: "[--selector=<selector>]",
@ -23,26 +21,25 @@ func NewCmdLs() Command {
} }
} }
func LsCmd(args CmdArgs) (int, error) { func LsCmd(ctx Context) (int, error) {
c := args.Client var p Printer
selector := args.Flags.String("selector")
format := args.Flags.String("format")
if format == "" && args.Config.OutputFormat != "" { c := ctx.Client
format = args.Config.OutputFormat selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
} }
lights, err := c.ListLights(selector) lights, err := c.ListLights(selector)
if err != nil { if err != nil {
return ExitFailure, err return ExitFailure, err
} }
switch format { p = NewPrinter(format)
case "table": p.Lights(lights)
PrintLightsTable(lights)
default:
PrintLights(lights)
}
return ExitSuccess, nil return ExitSuccess, nil
} }

View File

@ -4,19 +4,11 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"os"
"path"
"strings"
"git.kill0.net/chill9/lifx-go" "git.kill0.net/chill9/lifx-go"
"github.com/BurntSushi/toml"
) )
var userAgent string
func init() { func init() {
userAgent = initUserAgent()
RegisterCommand(NewCmdHelp()) RegisterCommand(NewCmdHelp())
RegisterCommand(NewCmdLs()) RegisterCommand(NewCmdLs())
RegisterCommand(NewCmdPoweroff()) RegisterCommand(NewCmdPoweroff())
@ -27,18 +19,19 @@ func init() {
RegisterCommand(NewCmdShow()) RegisterCommand(NewCmdShow())
RegisterCommand(NewCmdToggle()) RegisterCommand(NewCmdToggle())
RegisterCommand(NewCmdVersion()) RegisterCommand(NewCmdVersion())
RegisterCommand(NewCmdBreathe())
} }
var Version string var Version string
var BuildDate string var BuildDate string
var GitCommit string var GitCommit string
const lumercFile string = ".lumerc"
func Main(args []string) (int, error) { func Main(args []string) (int, error) {
var config Config var config *Config = GetConfig()
var err error var err error
flag.Parse()
if len(args) == 1 { if len(args) == 1 {
args = append(args, "help") args = append(args, "help")
} }
@ -49,32 +42,26 @@ func Main(args []string) (int, error) {
return ExitFailure, err return ExitFailure, err
} }
if _, err := toml.DecodeFile(configPath, &config); err != nil { if config, err = LoadConfigFile(configPath); err != nil {
err = fmt.Errorf("fatal: failed to parse %s; %w", configPath, err)
return ExitFailure, err return ExitFailure, err
} }
config.MergeWithEnv()
envAccessToken := os.Getenv("LIFX_ACCESS_TOKEN")
if envAccessToken != "" {
config.AccessToken = envAccessToken
}
if err = config.Validate(); err != nil { if err = config.Validate(); err != nil {
return ExitFailure, fmt.Errorf("fatal: %s", err) return ExitFailure, fmt.Errorf("fatal: %s", err)
} }
flag.Parse()
command := args[1] command := args[1]
c := lifx.NewClient( c := lifx.NewClient(
config.AccessToken, config.AccessToken,
lifx.WithUserAgent(userAgent), lifx.WithUserAgent(config.userAgent),
lifx.WithDebug(config.Debug),
) )
cmdArgs := CmdArgs{ ctx := Context{
Client: c, Client: c,
Config: config, Config: *config,
Args: args[2:], Args: args[2:],
} }
@ -87,47 +74,14 @@ func Main(args []string) (int, error) {
fs := cmd.Flags fs := cmd.Flags
if fs != nil { if fs != nil {
fs.Parse(args[2:]) fs.Parse(args[2:])
cmdArgs.Flags = Flags{FlagSet: fs} ctx.Flags = Flags{FlagSet: fs}
} }
cmdArgs.Name = command ctx.Name = command
exitCode, err := cmd.Func(cmdArgs) exitCode, err := cmd.Func(ctx)
if err != nil { if err != nil {
err = fmt.Errorf("fatal: %s", err) err = fmt.Errorf("fatal: %s", err)
} }
return exitCode, err return exitCode, err
} }
func getConfigPath() string {
var tryPath, configPath string
// ~/.lumerc
homeDir, err := os.UserHomeDir()
if err == nil {
tryPath = path.Join(homeDir, lumercFile)
if _, err := os.Stat(tryPath); !os.IsNotExist(err) {
configPath = tryPath
}
}
// ./.lumerc
cwd, err := os.Getwd()
if err == nil {
tryPath = path.Join(cwd, lumercFile)
if _, err := os.Stat(tryPath); !os.IsNotExist(err) {
configPath = tryPath
}
}
return configPath
}
func initUserAgent() string {
var b strings.Builder
b.WriteString("lume")
b.WriteRune('/')
b.WriteString(Version)
return b.String()
}

View File

@ -19,8 +19,6 @@ func NewCmdPoweroff() Command {
selector := fs.String("selector", defaultSelector, "Set the selector") selector := fs.String("selector", defaultSelector, "Set the selector")
fs.StringVar(selector, "s", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--duration <sec>]", Use: "[--selector <selector>] [--duration <sec>]",
@ -28,15 +26,17 @@ func NewCmdPoweroff() Command {
} }
} }
func PoweroffCmd(args CmdArgs) (int, error) { func PoweroffCmd(ctx Context) (int, error) {
c := args.Client var p Printer
duration := args.Flags.Float64("duration")
selector := args.Flags.String("selector") c := ctx.Client
format := args.Flags.String("format") duration := ctx.Flags.Float64("duration")
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
state := lifx.State{Power: "off", Duration: duration} state := lifx.State{Power: "off", Duration: duration}
if format == "" && args.Config.OutputFormat != "" { if format == "" && ctx.Config.OutputFormat != "" {
format = args.Config.OutputFormat format = ctx.Config.OutputFormat
} }
r, err := c.SetState(selector, state) r, err := c.SetState(selector, state)
@ -44,12 +44,8 @@ func PoweroffCmd(args CmdArgs) (int, error) {
return ExitFailure, err return ExitFailure, err
} }
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
return ExitSuccess, nil return ExitSuccess, nil
} }

View File

@ -19,8 +19,6 @@ func NewCmdPoweron() Command {
selector := fs.String("selector", defaultSelector, "Set the selector") selector := fs.String("selector", defaultSelector, "Set the selector")
fs.StringVar(selector, "s", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--duration <sec>]", Use: "[--selector <selector>] [--duration <sec>]",
@ -28,15 +26,17 @@ func NewCmdPoweron() Command {
} }
} }
func PoweronCmd(args CmdArgs) (int, error) { func PoweronCmd(ctx Context) (int, error) {
c := args.Client var p Printer
duration := args.Flags.Float64("duration")
selector := args.Flags.String("selector") c := ctx.Client
format := args.Flags.String("format") duration := ctx.Flags.Float64("duration")
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
state := lifx.State{Power: "on", Duration: duration} state := lifx.State{Power: "on", Duration: duration}
if format == "" && args.Config.OutputFormat != "" { if format == "" && ctx.Config.OutputFormat != "" {
format = args.Config.OutputFormat format = ctx.Config.OutputFormat
} }
r, err := c.SetState(selector, state) r, err := c.SetState(selector, state)
@ -44,12 +44,8 @@ func PoweronCmd(args CmdArgs) (int, error) {
return ExitFailure, err return ExitFailure, err
} }
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
return ExitSuccess, nil return ExitSuccess, nil
} }

View File

@ -10,6 +10,107 @@ import (
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
) )
type Printer interface {
Results(results []lifx.Result)
Lights(lights []lifx.Light)
}
type defaultPrinter struct{}
type tablePrinter struct{}
func NewPrinter(format string) Printer {
switch format {
case "table":
return &tablePrinter{}
default:
return &defaultPrinter{}
}
}
func (dp *defaultPrinter) Results(results []lifx.Result) {
sortResults(results)
table := tablewriter.NewWriter(os.Stdout)
_, rows := makeResultsTable(results)
for _, v := range rows {
table.Append(v)
}
fmt.Printf("total %d\n", len(results))
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetAutoWrapText(false)
table.SetBorder(false)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetHeaderLine(false)
table.SetNoWhiteSpace(true)
table.SetRowSeparator("")
table.SetTablePadding(" ")
table.Render()
}
func (tp *tablePrinter) Results(results []lifx.Result) {
sortResults(results)
table := tablewriter.NewWriter(os.Stdout)
hdr, rows := makeResultsTable(results)
for _, v := range rows {
table.Append(v)
}
table.SetHeader(hdr)
table.Render()
}
func (dp *defaultPrinter) Lights(lights []lifx.Light) {
sortLights(lights)
table := tablewriter.NewWriter(os.Stdout)
_, rows := makeLightsTable(lights)
for _, v := range rows {
table.Append(v)
}
fmt.Printf("total %d\n", len(lights))
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetAutoWrapText(false)
table.SetBorder(false)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetHeaderLine(false)
table.SetNoWhiteSpace(true)
table.SetRowSeparator("")
table.SetTablePadding(" ")
table.Render()
}
func (tp *tablePrinter) Lights(lights []lifx.Light) {
sortLights(lights)
table := tablewriter.NewWriter(os.Stdout)
hdr, rows := makeLightsTable(lights)
for _, v := range rows {
table.Append(v)
}
table.SetHeader(hdr)
table.Render()
}
func ColorizeIndicator(s string) string {
c := color.New(color.FgRed)
if s == "on" {
c = color.New(color.FgGreen)
}
return c.Sprint(GetConfig().Indicator)
}
func ColorizePower(s string) string { func ColorizePower(s string) string {
c := color.New(color.FgRed) c := color.New(color.FgRed)
if s == "on" { if s == "on" {
@ -38,10 +139,11 @@ func PrintfWithIndent(indent int, format string, a ...interface{}) (n int, err e
} }
func makeLightsTable(lights []lifx.Light) (hdr []string, rows [][]string) { func makeLightsTable(lights []lifx.Light) (hdr []string, rows [][]string) {
hdr = []string{"ID", "Location", "Group", "Label", "Last Seen", "Power"} hdr = []string{"", "ID", "Location", "Group", "Label", "Last Seen", "Power"}
for _, l := range lights { for _, l := range lights {
rows = append(rows, []string{ rows = append(rows, []string{
fmt.Sprint(ColorizeIndicator(l.Power)),
fmt.Sprint(l.Id), fmt.Sprint(l.Id),
fmt.Sprint(l.Location.Name), fmt.Sprint(l.Location.Name),
fmt.Sprint(l.Group.Name), fmt.Sprint(l.Group.Name),
@ -69,77 +171,3 @@ func makeResultsTable(results []lifx.Result) (hdr []string, rows [][]string) {
return return
} }
func PrintLights(lights []lifx.Light) {
sortLights(lights)
table := tablewriter.NewWriter(os.Stdout)
_, rows := makeLightsTable(lights)
for _, v := range rows {
table.Append(v)
}
fmt.Printf("total %d\n", len(lights))
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetAutoWrapText(false)
table.SetBorder(false)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetHeaderLine(false)
table.SetNoWhiteSpace(true)
table.SetRowSeparator("")
table.SetTablePadding(" ")
table.Render()
}
func PrintLightsTable(lights []lifx.Light) {
sortLights(lights)
table := tablewriter.NewWriter(os.Stdout)
hdr, rows := makeLightsTable(lights)
for _, v := range rows {
table.Append(v)
}
table.SetHeader(hdr)
table.Render()
}
func PrintResults(results []lifx.Result) {
sortResults(results)
table := tablewriter.NewWriter(os.Stdout)
_, rows := makeResultsTable(results)
for _, v := range rows {
table.Append(v)
}
fmt.Printf("total %d\n", len(results))
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetAutoWrapText(false)
table.SetBorder(false)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetHeaderLine(false)
table.SetNoWhiteSpace(true)
table.SetRowSeparator("")
table.SetTablePadding(" ")
table.Render()
}
func PrintResultsTable(results []lifx.Result) {
sortResults(results)
table := tablewriter.NewWriter(os.Stdout)
hdr, rows := makeResultsTable(results)
for _, v := range rows {
table.Append(v)
}
table.SetHeader(hdr)
table.Render()
}

View File

@ -41,8 +41,6 @@ func NewCmdSetColor() Command {
fast := fs.Bool("fast", defaultFast, "fast state") fast := fs.Bool("fast", defaultFast, "fast state")
fs.BoolVar(fast, "f", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--power (on|off)] [--hue <hue>] [--saturation <saturation>] [--rgb <rbg>] [--name <color>] [--brightness <brightness>] [--duration <sec>] [--fast]", Use: "[--selector <selector>] [--power (on|off)] [--hue <hue>] [--saturation <saturation>] [--rgb <rbg>] [--name <color>] [--brightness <brightness>] [--duration <sec>] [--fast]",
@ -50,28 +48,30 @@ func NewCmdSetColor() Command {
} }
} }
func SetColorCmd(args CmdArgs) (int, error) { func SetColorCmd(ctx Context) (int, error) {
c := args.Client var p Printer
state := lifx.State{}
selector := args.Flags.String("selector")
format := args.Flags.String("format")
if format == "" && args.Config.OutputFormat != "" { c := ctx.Client
format = args.Config.OutputFormat state := lifx.State{}
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
} }
power := args.Flags.String("power") power := ctx.Flags.String("power")
if power != "" { if power != "" {
state.Power = power state.Power = power
} }
hueFlag := args.Flags.String("hue") hueFlag := ctx.Flags.String("hue")
saturationFlag := args.Flags.String("saturation") saturationFlag := ctx.Flags.String("saturation")
rgbFlag := args.Flags.String("rgb") rgbFlag := ctx.Flags.String("rgb")
name := args.Flags.String("name") name := ctx.Flags.String("name")
if (hueFlag == "" || saturationFlag == "") && rgbFlag == "" && name == "" { if (hueFlag == "" || saturationFlag == "") && rgbFlag == "" && name == "" {
printCmdHelp(args.Name) printCmdHelp(ctx.Name)
return ExitFailure, nil return ExitFailure, nil
} }
@ -79,12 +79,12 @@ func SetColorCmd(args CmdArgs) (int, error) {
color := lifx.HSBKColor{} color := lifx.HSBKColor{}
if hueFlag != "" { if hueFlag != "" {
hue := args.Flags.Float32("hue") hue := ctx.Flags.Float32("hue")
color.H = lifx.Float32Ptr(hue) color.H = lifx.Float32Ptr(hue)
} }
if saturationFlag != "" { if saturationFlag != "" {
saturation := args.Flags.Float32("saturation") saturation := ctx.Flags.Float32("saturation")
color.S = lifx.Float32Ptr(saturation) color.S = lifx.Float32Ptr(saturation)
} }
state.Color = color state.Color = color
@ -96,7 +96,7 @@ func SetColorCmd(args CmdArgs) (int, error) {
} }
state.Color = color state.Color = color
} else if name != "" { } else if name != "" {
hsb, ok := args.Config.Colors[name] hsb, ok := ctx.Config.Colors[name]
if !ok { if !ok {
return ExitFailure, fmt.Errorf("%s is not a defined color", name) return ExitFailure, fmt.Errorf("%s is not a defined color", name)
} }
@ -107,16 +107,16 @@ func SetColorCmd(args CmdArgs) (int, error) {
state.Color = color state.Color = color
} }
brightnessFlag := args.Flags.String("brightness") brightnessFlag := ctx.Flags.String("brightness")
if brightnessFlag != "" { if brightnessFlag != "" {
brightness := args.Flags.Float64("brightness") brightness := ctx.Flags.Float64("brightness")
state.Brightness = brightness state.Brightness = brightness
} }
duration := args.Flags.Float64("duration") duration := ctx.Flags.Float64("duration")
state.Duration = duration state.Duration = duration
fast := args.Flags.Bool("fast") fast := ctx.Flags.Bool("fast")
state.Fast = fast state.Fast = fast
r, err := c.SetState(selector, state) r, err := c.SetState(selector, state)
@ -126,12 +126,8 @@ func SetColorCmd(args CmdArgs) (int, error) {
} }
if !fast { if !fast {
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
} }
return ExitSuccess, nil return ExitSuccess, nil

View File

@ -34,8 +34,6 @@ func NewCmdSetState() Command {
fast := fs.Bool("fast", defaultFast, "fast state") fast := fs.Bool("fast", defaultFast, "fast state")
fs.BoolVar(fast, "f", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--power (on|off)] [--color <color>] [--brightness <brightness>] [--duration <sec>] [--infrared <infrared>] [--fast]", Use: "[--selector <selector>] [--power (on|off)] [--color <color>] [--brightness <brightness>] [--duration <sec>] [--infrared <infrared>] [--fast]",
@ -43,46 +41,48 @@ func NewCmdSetState() Command {
} }
} }
func SetStateCmd(args CmdArgs) (int, error) { func SetStateCmd(ctx Context) (int, error) {
c := args.Client var p Printer
state := lifx.State{}
selector := args.Flags.String("selector")
format := args.Flags.String("format")
if format == "" && args.Config.OutputFormat != "" { c := ctx.Client
format = args.Config.OutputFormat state := lifx.State{}
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
} }
power := args.Flags.String("power") power := ctx.Flags.String("power")
if power != "" { if power != "" {
state.Power = power state.Power = power
} }
color := args.Flags.String("color") color := ctx.Flags.String("color")
if color != "" { if color != "" {
state.Color = lifx.NamedColor(color) state.Color = lifx.NamedColor(color)
} }
brightnessFlag := args.Flags.String("brightness") brightnessFlag := ctx.Flags.String("brightness")
if brightnessFlag != "" { if brightnessFlag != "" {
brightness := args.Flags.Float64("brightness") brightness := ctx.Flags.Float64("brightness")
state.Brightness = brightness state.Brightness = brightness
} }
duration := args.Flags.Float64("duration") duration := ctx.Flags.Float64("duration")
state.Duration = duration state.Duration = duration
infraredFlag := args.Flags.String("infrared") infraredFlag := ctx.Flags.String("infrared")
if infraredFlag != "" { if infraredFlag != "" {
infrared := args.Flags.Float64("infrared") infrared := ctx.Flags.Float64("infrared")
state.Infrared = infrared state.Infrared = infrared
} }
fast := args.Flags.Bool("fast") fast := ctx.Flags.Bool("fast")
state.Fast = fast state.Fast = fast
if power == "" && color == "" && brightnessFlag == "" && infraredFlag == "" { if power == "" && color == "" && brightnessFlag == "" && infraredFlag == "" {
printCmdHelp(args.Name) printCmdHelp(ctx.Name)
return ExitFailure, nil return ExitFailure, nil
} }
@ -92,12 +92,8 @@ func SetStateCmd(args CmdArgs) (int, error) {
} }
if !fast { if !fast {
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
} }
return ExitSuccess, nil return ExitSuccess, nil

View File

@ -37,8 +37,6 @@ func NewCmdSetWhite() Command {
fast := fs.Bool("fast", defaultFast, "fast state") fast := fs.Bool("fast", defaultFast, "fast state")
fs.BoolVar(fast, "f", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--power (on|off)] [--kelvin <kelvin>] [--name <color>] [--brightness <brightness>] [--duration <sec>] [--infrared] [--fast]", Use: "[--selector <selector>] [--power (on|off)] [--kelvin <kelvin>] [--name <color>] [--brightness <brightness>] [--duration <sec>] [--infrared] [--fast]",
@ -46,24 +44,26 @@ func NewCmdSetWhite() Command {
} }
} }
func SetWhiteCmd(args CmdArgs) (int, error) { func SetWhiteCmd(ctx Context) (int, error) {
c := args.Client var p Printer
state := lifx.State{}
selector := args.Flags.String("selector")
format := args.Flags.String("format")
if format == "" && args.Config.OutputFormat != "" { c := ctx.Client
format = args.Config.OutputFormat state := lifx.State{}
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
} }
power := args.Flags.String("power") power := ctx.Flags.String("power")
if power != "" { if power != "" {
state.Power = power state.Power = power
} }
kelvinFlag := args.Flags.String("kelvin") kelvinFlag := ctx.Flags.String("kelvin")
if kelvinFlag != "" { if kelvinFlag != "" {
kelvin := args.Flags.Int16("kelvin") kelvin := ctx.Flags.Int16("kelvin")
color, err := lifx.NewWhite(kelvin) color, err := lifx.NewWhite(kelvin)
if err != nil { if err != nil {
return ExitFailure, err return ExitFailure, err
@ -71,9 +71,9 @@ func SetWhiteCmd(args CmdArgs) (int, error) {
state.Color = color state.Color = color
} }
name := args.Flags.String("name") name := ctx.Flags.String("name")
if name != "" { if name != "" {
name := args.Flags.String("name") name := ctx.Flags.String("name")
color, err := lifx.NewWhiteString(name) color, err := lifx.NewWhiteString(name)
if err != nil { if err != nil {
return ExitFailure, err return ExitFailure, err
@ -81,26 +81,26 @@ func SetWhiteCmd(args CmdArgs) (int, error) {
state.Color = color state.Color = color
} }
brightnessFlag := args.Flags.String("brightness") brightnessFlag := ctx.Flags.String("brightness")
if brightnessFlag != "" { if brightnessFlag != "" {
brightness := args.Flags.Float64("brightness") brightness := ctx.Flags.Float64("brightness")
state.Brightness = brightness state.Brightness = brightness
} }
duration := args.Flags.Float64("duration") duration := ctx.Flags.Float64("duration")
state.Duration = duration state.Duration = duration
infraredFlag := args.Flags.String("infrared") infraredFlag := ctx.Flags.String("infrared")
if infraredFlag != "" { if infraredFlag != "" {
infrared := args.Flags.Float64("infrared") infrared := ctx.Flags.Float64("infrared")
state.Infrared = infrared state.Infrared = infrared
} }
fast := args.Flags.Bool("fast") fast := ctx.Flags.Bool("fast")
state.Fast = fast state.Fast = fast
if power == "" && kelvinFlag == "" && name == "" && brightnessFlag == "" && infraredFlag == "" { if power == "" && kelvinFlag == "" && name == "" && brightnessFlag == "" && infraredFlag == "" {
printCmdHelp(args.Name) printCmdHelp(ctx.Name)
return ExitFailure, nil return ExitFailure, nil
} }
@ -110,12 +110,8 @@ func SetWhiteCmd(args CmdArgs) (int, error) {
} }
if !fast { if !fast {
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
} }
return ExitSuccess, nil return ExitSuccess, nil

View File

@ -24,10 +24,10 @@ func NewCmdShow() Command {
} }
} }
func ShowCmd(args CmdArgs) (int, error) { func ShowCmd(ctx Context) (int, error) {
var indent int var indent int
c := args.Client c := ctx.Client
selector := args.Flags.String("selector") selector := ctx.Flags.String("selector")
lights, err := c.ListLights(selector) lights, err := c.ListLights(selector)
if err != nil { if err != nil {
@ -39,12 +39,13 @@ func ShowCmd(args CmdArgs) (int, error) {
for i, l := range lights { for i, l := range lights {
indent = 0 indent = 0
fmt.Printf( fmt.Printf(
"Light ID: %s, %s, Power: %s\n", "%s Light ID: %s, %s, Power: %s\n",
ColorizeIndicator(l.Power),
l.Id, l.Id,
connected(l.Connected), connected(l.Connected),
ColorizePower(l.Power), ColorizePower(l.Power),
) )
indent += Tabstop indent += Tabstop + 2
PrintfWithIndent(indent, "Label: %s, ID: %s\n", l.Label, l.Id) PrintfWithIndent(indent, "Label: %s, ID: %s\n", l.Label, l.Id)
PrintfWithIndent(indent, "UUID: %s\n", l.UUID) PrintfWithIndent(indent, "UUID: %s\n", l.UUID)
PrintfWithIndent(indent, "Location: %s, ID: %s\n", l.Location.Name, l.Location.Id) PrintfWithIndent(indent, "Location: %s, ID: %s\n", l.Location.Name, l.Location.Id)

View File

@ -17,8 +17,6 @@ func NewCmdToggle() Command {
selector := fs.String("selector", defaultSelector, "Set the selector") selector := fs.String("selector", defaultSelector, "Set the selector")
fs.StringVar(selector, "s", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector")
fs.String("format", defaultOutputFormat, "Set the output format")
return fs return fs
}(), }(),
Use: "[--selector <selector>] [--duration <sec>]", Use: "[--selector <selector>] [--duration <sec>]",
@ -26,14 +24,16 @@ func NewCmdToggle() Command {
} }
} }
func ToggleCmd(args CmdArgs) (int, error) { func ToggleCmd(ctx Context) (int, error) {
c := args.Client var p Printer
duration := args.Flags.Float64("duration")
selector := args.Flags.String("selector")
format := args.Flags.String("format")
if format == "" && args.Config.OutputFormat != "" { c := ctx.Client
format = args.Config.OutputFormat duration := ctx.Flags.Float64("duration")
selector := ctx.Flags.String("selector")
format := ctx.Flags.String("output-format")
if format == "" && ctx.Config.OutputFormat != "" {
format = ctx.Config.OutputFormat
} }
r, err := c.Toggle(selector, duration) r, err := c.Toggle(selector, duration)
@ -41,12 +41,8 @@ func ToggleCmd(args CmdArgs) (int, error) {
return ExitFailure, err return ExitFailure, err
} }
switch format { p = NewPrinter(format)
case "table": p.Results(r.Results)
PrintResultsTable(r.Results)
default:
PrintResults(r.Results)
}
return ExitSuccess, nil return ExitSuccess, nil
} }

View File

@ -60,3 +60,9 @@ func YesNo(v bool) string {
} }
return "no" return "no"
} }
func Debugf(format string, a ...interface{}) {
if GetConfig().Debug {
fmt.Printf(format, a...)
}
}

View File

@ -2,6 +2,7 @@ package lumecmd
import ( import (
"fmt" "fmt"
"runtime"
"strings" "strings"
) )
@ -15,19 +16,23 @@ func NewCmdVersion() Command {
} }
} }
func VersionCmd(args CmdArgs) (int, error) { func VersionCmd(ctx Context) (int, error) {
var b strings.Builder var b strings.Builder
fmt.Fprintf(&b, "lume %s", Version) fmt.Fprintf(&b, "lume, version %s\n", Version)
b.WriteString(" ")
if GitCommit != "" { if GitCommit != "" {
fmt.Fprintf(&b, "(git: %s)", GitCommit) fmt.Fprintf(&b, " revision: %s\n", GitCommit)
b.WriteString(" ")
}
if BuildDate != "" {
fmt.Fprintf(&b, "build_date: %s", BuildDate)
} }
fmt.Println(b.String()) if BuildDate != "" {
fmt.Fprintf(&b, " build date: %s\n", BuildDate)
}
fmt.Fprintf(&b, " go version: %s\n", runtime.Version())
fmt.Fprintf(&b, " platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
fmt.Print(b.String())
return ExitSuccess, nil return ExitSuccess, nil
} }

6
go.mod
View File

@ -3,9 +3,11 @@ module git.kill0.net/chill9/lume
go 1.15 go 1.15
require ( require (
git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef git.kill0.net/chill9/lifx-go v0.0.0-20210329222320-2107a0586447
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/fatih/color v1.10.0 github.com/fatih/color v1.10.0
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181
) )

13
go.sum
View File

@ -1,5 +1,9 @@
git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef h1:8yyXAk+qiRvrowTeHHAOBZqGXXCr8SxWFydez61ZGp8= git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef h1:8yyXAk+qiRvrowTeHHAOBZqGXXCr8SxWFydez61ZGp8=
git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef/go.mod h1:ZFKIcwdJ4Nqlrkn/eUHbeLt0NVhFsfxBREkVoA+jzUc= git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef/go.mod h1:ZFKIcwdJ4Nqlrkn/eUHbeLt0NVhFsfxBREkVoA+jzUc=
git.kill0.net/chill9/lifx-go v0.0.0-20210323044657-dbe1c40e1621 h1:koWq2W08HjmvsNm4D8kD0OjMZKCJ/3681P9XFMTj77I=
git.kill0.net/chill9/lifx-go v0.0.0-20210323044657-dbe1c40e1621/go.mod h1:jInpjEqTBhrFpQKk7zPIWISvgjjfS2djXeKB3yB/8dY=
git.kill0.net/chill9/lifx-go v0.0.0-20210329222320-2107a0586447 h1:tN+zR5aszesrZRrhS3uOqAIWLcADCIH7GFJ6SOQS9r0=
git.kill0.net/chill9/lifx-go v0.0.0-20210329222320-2107a0586447/go.mod h1:jInpjEqTBhrFpQKk7zPIWISvgjjfS2djXeKB3yB/8dY=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
@ -10,9 +14,18 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c= golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 h1:64ChN/hjER/taL4YJuA+gpLfIMT+/NFherRZixbxOhg=
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

12
lume.code-workspace Normal file
View File

@ -0,0 +1,12 @@
{
"folders": [
{
"path": "."
},
{
"name": "lifx-go",
"path": "..\\lifx-go"
}
],
"settings": {}
}