package main import ( "fmt" "strings" "github.com/spf13/cobra" intrgb "netdome.biz/paul/qmk-rgb/internal/rgb" ) func NewColorCmd() *cobra.Command { return &cobra.Command{ Use: "color |rgb:|hsv:,,", Short: "Set RGB color", Long: "Set the color of the selected zones from one of three notations:\n" + " ff0000 six digit hex, hue and saturation only\n" + " rgb:ff0000 the same, written out\n" + " hsv:0,255,255 hue, saturation and value, each 0-255\n" + "\n" + "The hex notations say nothing about brightness, so they leave it alone.\n" + "The keyboard has no value register for a color: the value of an hsv:\n" + "notation is written to the brightness of the same zones, and the\n" + "brightness the keyboard ended up holding is reported.\n" + "\n" + "Every notation is read back, so a color the keyboard rounded or refused\n" + "is reported instead of being claimed as set.", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { spec, err := intrgb.ParseColorSpec(args[0]) if err != nil { return err } proto, target, channels, err := openTarget() if err != nil { return err } defer proto.Close() colors, err := setColorVerified(proto, channels, target.Display, spec.H, spec.S) if err != nil { return fmt.Errorf("set color: %w", err) } if !spec.HasValue() { printColorResult(cmd, colors, nil) return nil } brightness, err := setBrightnessVerified(proto, channels, target.Display, spec.V) if err != nil { return fmt.Errorf("set brightness from %s: %w", args[0], err) } printColorResult(cmd, colors, brightness) return nil }, } } // printColorResult states the color every zone actually holds. The brightness // results are nil for a notation that did not write one, and then no brightness // is mentioned: the command must not imply it set something it left alone. func printColorResult(cmd *cobra.Command, colors []colorResult, brightness []zoneResult) { request := "" if len(colors) > 0 { request = fmt.Sprintf("hue %d sat %d", colors[0].RequestedHue, colors[0].RequestedSaturation) if len(brightness) > 0 { request += fmt.Sprintf(" brightness %d", brightness[0].Requested) } } if !anyColorMismatch(colors) && !anyMismatch(brightness) { fmt.Fprintf(cmd.OutOrStdout(), "Color set to %s\n", request) return } var b strings.Builder b.WriteString("Color") for i, c := range colors { fmt.Fprintf(&b, " %s hue %d sat %d", c.Name, c.Hue, c.Saturation) if i < len(brightness) { fmt.Fprintf(&b, " brightness %d", brightness[i].Applied) } } fmt.Fprintf(&b, " (requested %s)", request) fmt.Fprintln(cmd.OutOrStdout(), b.String()) } // anyColorMismatch reports whether any zone stored another color. func anyColorMismatch(results []colorResult) bool { for _, r := range results { if r.Mismatch() { return true } } return false }