diff --git a/cmd/command.go b/cmd/command.go index 830715e..bd8d4bb 100644 --- a/cmd/command.go +++ b/cmd/command.go @@ -15,8 +15,9 @@ const ( ) type Config struct { - AccessToken string `toml:"access_token"` - Colors map[string][]float32 `toml:"colors"` + AccessToken string `toml:"access_token"` + OutputFormat string `toml:"output_format"` + Colors map[string][]float32 `toml:"colors"` } type CmdArgs struct { @@ -43,19 +44,20 @@ type Command struct { var commandRegistry = make(map[string]Command) var ( - defaultSelector string = "all" - defaultDuration float64 = 1.0 - defaultPower string = "" - defaultColor string = "" - defaultBrightness string = "" - defaultInfrared string = "" - defaultFast bool = false - defaultWhiteKelvin string = "" - defaultWhiteName string = "" - defaultHue string = "" - defaultSaturation string = "" - defaultRGB string = "" - defaultName string = "" + defaultSelector string = "all" + defaultDuration float64 = 1.0 + defaultPower string = "" + defaultColor string = "" + defaultBrightness string = "" + defaultInfrared string = "" + defaultFast bool = false + defaultWhiteKelvin string = "" + defaultWhiteName string = "" + defaultHue string = "" + defaultSaturation string = "" + defaultRGB string = "" + defaultName string = "" + defaultOutputFormat string = "" ) func (f Flags) String(name string) string { diff --git a/cmd/ls.go b/cmd/ls.go index 09f9d44..ec71259 100644 --- a/cmd/ls.go +++ b/cmd/ls.go @@ -1,6 +1,8 @@ package lumecmd -import "flag" +import ( + "flag" +) func NewCmdLs() Command { return Command{ @@ -12,6 +14,8 @@ func NewCmdLs() Command { selector := fs.String("selector", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector=]", @@ -22,10 +26,23 @@ func NewCmdLs() Command { func LsCmd(args CmdArgs) (int, error) { c := args.Client selector := args.Flags.String("selector") + format := args.Flags.String("format") + + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } + lights, err := c.ListLights(selector) if err != nil { return ExitFailure, err } - PrintLights(lights) + + switch format { + case "table": + PrintLightsTable(lights) + default: + PrintLights(lights) + } + return ExitSuccess, nil } diff --git a/cmd/poweroff.go b/cmd/poweroff.go index c99ff0a..14667c4 100644 --- a/cmd/poweroff.go +++ b/cmd/poweroff.go @@ -19,6 +19,8 @@ func NewCmdPoweroff() Command { selector := fs.String("selector", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--duration ]", @@ -30,12 +32,24 @@ func PoweroffCmd(args CmdArgs) (int, error) { c := args.Client duration := args.Flags.Float64("duration") selector := args.Flags.String("selector") + format := args.Flags.String("format") state := lifx.State{Power: "off", Duration: duration} + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } + r, err := c.SetState(selector, state) if err != nil { return ExitFailure, err } - PrintResults(r.Results) + + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } + return ExitSuccess, nil } diff --git a/cmd/poweron.go b/cmd/poweron.go index 5a509fe..48dc886 100644 --- a/cmd/poweron.go +++ b/cmd/poweron.go @@ -19,6 +19,8 @@ func NewCmdPoweron() Command { selector := fs.String("selector", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--duration ]", @@ -30,12 +32,24 @@ func PoweronCmd(args CmdArgs) (int, error) { c := args.Client duration := args.Flags.Float64("duration") selector := args.Flags.String("selector") + format := args.Flags.String("format") state := lifx.State{Power: "on", Duration: duration} + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } + r, err := c.SetState(selector, state) if err != nil { return ExitFailure, err } - PrintResults(r.Results) + + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } + return ExitSuccess, nil } diff --git a/cmd/print.go b/cmd/print.go index 6346476..27de733 100644 --- a/cmd/print.go +++ b/cmd/print.go @@ -2,10 +2,12 @@ package lumecmd import ( "fmt" + "os" "time" "git.kill0.net/chill9/lifx-go" "github.com/fatih/color" + "github.com/olekukonko/tablewriter" ) func ColorizePower(s string) string { @@ -35,89 +37,109 @@ func PrintfWithIndent(indent int, format string, a ...interface{}) (n int, err e return fmt.Printf(format, a...) } -func PrintResults(res []lifx.Result) { - var length int - var widths map[string]int +func makeLightsTable(lights []lifx.Light) (hdr []string, rows [][]string) { + hdr = []string{"ID", "Location", "Group", "Label", "Last Seen", "Power"} - widths = make(map[string]int) + for _, l := range lights { + rows = append(rows, []string{ + fmt.Sprint(l.Id), + fmt.Sprint(l.Location.Name), + fmt.Sprint(l.Group.Name), + fmt.Sprint(l.Label), + fmt.Sprint(l.LastSeen.Local().Format(time.RFC3339)), + fmt.Sprint(ColorizePower(l.Power)), + }) - for _, r := range res { - length = len(r.Id) - if widths["id"] < length { - widths["id"] = length - } - - length = len(r.Label) - if widths["label"] < length { - widths["label"] = length - } - - length = len(r.Status) - if widths["status"] < length { - widths["status"] = length - } } - sortResults(res) + return +} + +func makeResultsTable(results []lifx.Result) (hdr []string, rows [][]string) { + hdr = []string{"ID", "Label", "Status"} + + for _, r := range results { + rows = append(rows, []string{ + fmt.Sprint(r.Id), + fmt.Sprint(r.Label), + fmt.Sprint(ColorizeStatus(r.Status)), + }) - for _, r := range res { - fmt.Printf("%*s %*s %*s\n", - widths["id"], r.Id, - widths["label"], r.Label, - widths["status"], ColorizeStatus(r.Status)) } + + return } func PrintLights(lights []lifx.Light) { - var length int - var widths map[string]int - - widths = make(map[string]int) - - for _, l := range lights { - length = len(l.Id) - if widths["id"] < length { - widths["id"] = length - } - - length = len(l.Location.Name) - if widths["location"] < length { - widths["location"] = length - } - - length = len(l.Group.Name) - if widths["group"] < length { - widths["group"] = length - } - - length = len(l.Label) - if widths["label"] < length { - widths["label"] = length - } - - length = len(l.LastSeen.Local().Format(time.RFC3339)) - if widths["last_seen"] < length { - widths["last_seen"] = length - } - - length = len(l.Power) - if widths["power"] < length { - widths["power"] = length - } - } - sortLights(lights) - fmt.Printf("total %d\n", len(lights)) - for _, l := range lights { - fmt.Printf( - "%*s %*s %*s %*s %*s %-*s\n", - widths["id"], l.Id, - widths["loction"], l.Location.Name, - widths["group"], l.Group.Name, - widths["label"], l.Label, - widths["last_seen"], l.LastSeen.Local().Format(time.RFC3339), - widths["power"], ColorizePower(l.Power), - ) + 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() } diff --git a/cmd/setcolor.go b/cmd/setcolor.go index eb6037d..0921162 100644 --- a/cmd/setcolor.go +++ b/cmd/setcolor.go @@ -41,6 +41,8 @@ func NewCmdSetColor() Command { fast := fs.Bool("fast", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--power (on|off)] [--hue ] [--saturation ] [--rgb ] [--name ] [--brightness ] [--duration ] [--fast]", @@ -52,6 +54,11 @@ func SetColorCmd(args CmdArgs) (int, error) { c := args.Client state := lifx.State{} selector := args.Flags.String("selector") + format := args.Flags.String("format") + + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } power := args.Flags.String("power") if power != "" { @@ -119,7 +126,12 @@ func SetColorCmd(args CmdArgs) (int, error) { } if !fast { - PrintResults(r.Results) + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } } return ExitSuccess, nil diff --git a/cmd/setstate.go b/cmd/setstate.go index 9886978..c4e7bfb 100644 --- a/cmd/setstate.go +++ b/cmd/setstate.go @@ -34,6 +34,8 @@ func NewCmdSetState() Command { fast := fs.Bool("fast", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--power (on|off)] [--color ] [--brightness ] [--duration ] [--infrared ] [--fast]", @@ -45,6 +47,11 @@ func SetStateCmd(args CmdArgs) (int, error) { c := args.Client state := lifx.State{} selector := args.Flags.String("selector") + format := args.Flags.String("format") + + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } power := args.Flags.String("power") if power != "" { @@ -85,7 +92,12 @@ func SetStateCmd(args CmdArgs) (int, error) { } if !fast { - PrintResults(r.Results) + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } } return ExitSuccess, nil diff --git a/cmd/setwhite.go b/cmd/setwhite.go index 4f8109b..0953ac2 100644 --- a/cmd/setwhite.go +++ b/cmd/setwhite.go @@ -37,6 +37,8 @@ func NewCmdSetWhite() Command { fast := fs.Bool("fast", defaultFast, "fast state") fs.BoolVar(fast, "f", defaultFast, "fast state") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--power (on|off)] [--kelvin ] [--name ] [--brightness ] [--duration ] [--infrared] [--fast]", @@ -48,6 +50,11 @@ func SetWhiteCmd(args CmdArgs) (int, error) { c := args.Client state := lifx.State{} selector := args.Flags.String("selector") + format := args.Flags.String("format") + + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } power := args.Flags.String("power") if power != "" { @@ -103,7 +110,12 @@ func SetWhiteCmd(args CmdArgs) (int, error) { } if !fast { - PrintResults(r.Results) + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } } return ExitSuccess, nil diff --git a/cmd/toggle.go b/cmd/toggle.go index 01151aa..1c79189 100644 --- a/cmd/toggle.go +++ b/cmd/toggle.go @@ -17,6 +17,8 @@ func NewCmdToggle() Command { selector := fs.String("selector", defaultSelector, "Set the selector") fs.StringVar(selector, "s", defaultSelector, "Set the selector") + fs.String("format", defaultOutputFormat, "Set the output format") + return fs }(), Use: "[--selector ] [--duration ]", @@ -28,10 +30,23 @@ func ToggleCmd(args CmdArgs) (int, error) { c := args.Client duration := args.Flags.Float64("duration") selector := args.Flags.String("selector") + format := args.Flags.String("format") + + if format == "" && args.Config.OutputFormat != "" { + format = args.Config.OutputFormat + } + r, err := c.Toggle(selector, duration) if err != nil { return ExitFailure, err } - PrintResults(r.Results) + + switch format { + case "table": + PrintResultsTable(r.Results) + default: + PrintResults(r.Results) + } + return ExitSuccess, nil } diff --git a/go.mod b/go.mod index 381f715..ca24a9d 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,6 @@ require ( git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef github.com/BurntSushi/toml v0.3.1 github.com/fatih/color v1.10.0 + github.com/olekukonko/tablewriter v0.0.5 golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 ) diff --git a/go.sum b/go.sum index e1b370c..9f70258 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,10 @@ github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 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/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 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-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=