Paul Klumpp 2 недель назад
Родитель
Сommit
52932bcafc
3 измененных файлов с 147 добавлено и 1 удалено
  1. 9 1
      cmd/wobkey/rgb/rgb.go
  2. 113 0
      cmd/wobkey/rgb/rgb_test.go
  3. 25 0
      cmd/wobkey/rgb/zones.go

+ 9 - 1
cmd/wobkey/rgb/rgb.go

@@ -9,9 +9,16 @@ import (
 	"github.com/wobkey/rgb/internal/via"
 	"github.com/wobkey/rgb/internal/via"
 )
 )
 
 
-var targetDevice string
+var (
+	targetDevice string
+	targetZone   string
+)
 
 
 func OpenDevice() (*via.Protocol, intdevice.Keyboard, error) {
 func OpenDevice() (*via.Protocol, intdevice.Keyboard, error) {
+	if _, err := selectedZones(); err != nil {
+		return nil, intdevice.Keyboard{}, err
+	}
+
 	keyboards, err := intdevice.LoadKeyboards()
 	keyboards, err := intdevice.LoadKeyboards()
 	if err != nil {
 	if err != nil {
 		return nil, intdevice.Keyboard{}, fmt.Errorf("load keyboards: %w", err)
 		return nil, intdevice.Keyboard{}, fmt.Errorf("load keyboards: %w", err)
@@ -69,5 +76,6 @@ func Init() *cobra.Command {
 		Short: "RGB lighting commands",
 		Short: "RGB lighting commands",
 	}
 	}
 	cmd.PersistentFlags().StringVar(&targetDevice, "device", "", "HID device path to use")
 	cmd.PersistentFlags().StringVar(&targetDevice, "device", "", "HID device path to use")
+	cmd.PersistentFlags().StringVar(&targetZone, "zone", "", "RGB lighting zone")
 	return cmd
 	return cmd
 }
 }

+ 113 - 0
cmd/wobkey/rgb/rgb_test.go

@@ -1,9 +1,13 @@
 package rgb
 package rgb
 
 
 import (
 import (
+	"reflect"
+	"strings"
 	"testing"
 	"testing"
 
 
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
+	intrgb "github.com/wobkey/rgb/internal/rgb"
+	"github.com/wobkey/rgb/internal/via"
 )
 )
 
 
 func TestLightingEnabledRequiresActiveEffectAndBrightness(t *testing.T) {
 func TestLightingEnabledRequiresActiveEffectAndBrightness(t *testing.T) {
@@ -52,3 +56,112 @@ func TestDeviceFlagIsInheritedByRGBCommands(t *testing.T) {
 		t.Errorf("targetDevice = %q, want %q", targetDevice, wantPath)
 		t.Errorf("targetDevice = %q, want %q", targetDevice, wantPath)
 	}
 	}
 }
 }
+
+func TestSelectedZonesDefaultsToAll(t *testing.T) {
+	originalTargetZone := targetZone
+	t.Cleanup(func() { targetZone = originalTargetZone })
+	targetZone = ""
+
+	got, err := selectedZones()
+	if err != nil {
+		t.Fatalf("selectedZones() unexpected error: %v", err)
+	}
+	want := []intrgb.Zone{intrgb.ZoneLogo, intrgb.ZoneBacklight, intrgb.ZoneSide}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("selectedZones() = %v, want %v", got, want)
+	}
+}
+
+func TestSelectedZonesRejectsUnknownZone(t *testing.T) {
+	originalTargetZone := targetZone
+	t.Cleanup(func() { targetZone = originalTargetZone })
+	targetZone = "matrix"
+
+	got, err := selectedZones()
+	if err == nil {
+		t.Fatal("selectedZones() expected error, got nil")
+	}
+	if got != nil {
+		t.Errorf("selectedZones() = %v, want nil", got)
+	}
+}
+
+func TestSelectedZonesExplicitZones(t *testing.T) {
+	originalTargetZone := targetZone
+	t.Cleanup(func() { targetZone = originalTargetZone })
+
+	cases := []struct {
+		name string
+		want intrgb.Zone
+	}{
+		{"logo", intrgb.ZoneLogo},
+		{"backlight", intrgb.ZoneBacklight},
+		{"side", intrgb.ZoneSide},
+	}
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			targetZone = tc.name
+			got, err := selectedZones()
+			if err != nil {
+				t.Fatalf("selectedZones() unexpected error: %v", err)
+			}
+			want := []intrgb.Zone{tc.want}
+			if !reflect.DeepEqual(got, want) {
+				t.Errorf("selectedZones() = %v, want %v", got, want)
+			}
+		})
+	}
+}
+
+func TestZoneChannels(t *testing.T) {
+	got := zoneChannels(intrgb.AllZones())
+	want := []via.LEDType{2, 3, 4}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("zoneChannels() = %v, want %v", got, want)
+	}
+}
+
+func TestZoneFlagIsInheritedByRGBCommands(t *testing.T) {
+	originalTargetDevice := targetDevice
+	originalTargetZone := targetZone
+	t.Cleanup(func() {
+		targetDevice = originalTargetDevice
+		targetZone = originalTargetZone
+	})
+
+	const wantPath = "/dev/hidraw5"
+	ran := false
+	cmd := Init()
+	cmd.AddCommand(&cobra.Command{
+		Use: "probe",
+		Run: func(*cobra.Command, []string) { ran = true },
+	})
+	cmd.SetArgs([]string{"--device", wantPath, "--zone", "backlight", "probe"})
+
+	if err := cmd.Execute(); err != nil {
+		t.Fatalf("Execute() error = %v", err)
+	}
+	if !ran {
+		t.Fatal("child command did not run")
+	}
+	if targetDevice != wantPath {
+		t.Errorf("targetDevice = %q, want %q", targetDevice, wantPath)
+	}
+	if targetZone != "backlight" {
+		t.Errorf("targetZone = %q, want %q", targetZone, "backlight")
+	}
+}
+
+func TestZoneValidationPrecedesDeviceOpening(t *testing.T) {
+	originalTargetZone := targetZone
+	t.Cleanup(func() { targetZone = originalTargetZone })
+	targetZone = "matrix"
+
+	_, _, err := OpenDevice()
+	if err == nil {
+		t.Fatal("OpenDevice() expected zone error, got nil")
+	}
+	if !strings.Contains(err.Error(), "unknown zone") {
+		t.Errorf("OpenDevice() error = %v, want unknown zone error", err)
+	}
+}

+ 25 - 0
cmd/wobkey/rgb/zones.go

@@ -0,0 +1,25 @@
+package rgb
+
+import (
+	intrgb "github.com/wobkey/rgb/internal/rgb"
+	"github.com/wobkey/rgb/internal/via"
+)
+
+func selectedZones() ([]intrgb.Zone, error) {
+	if targetZone == "" {
+		return intrgb.AllZones(), nil
+	}
+	zone, err := intrgb.ParseZone(targetZone)
+	if err != nil {
+		return nil, err
+	}
+	return []intrgb.Zone{zone}, nil
+}
+
+func zoneChannels(zones []intrgb.Zone) []via.LEDType {
+	var channels []via.LEDType
+	for _, zone := range zones {
+		channels = append(channels, via.LEDType(zone.Channel()))
+	}
+	return channels
+}