Skip to content

Commit 2943542

Browse files
committed
refactor: rework cli utilities
1 parent b445cac commit 2943542

File tree

9 files changed

+348
-191
lines changed

9 files changed

+348
-191
lines changed

Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ GOLANGCI_LINT_VERSION = v1.56.2
22
REVIVE_VERSION = v1.3.7
33
GIT_CHGLOG_VERSION = v0.15.4
44
GO_BIN_PATH := $(shell go env GOPATH)/bin
5-
TEST_MODULES := $(shell go list ./... | grep -v /examples/)
5+
TEST_MODULES := $(shell go list ./... | grep -v -e /examples/ -e /cmd/)
66

77
define build_app
8-
cd "examples/$1"; go build -o "../../build/nuga-$1"
8+
cd "cmd/$1"; go build -o "../../build/nuga-$1"
99
endef
1010

1111
.PHONY: setup
@@ -34,9 +34,7 @@ coverage:
3434

3535
.PHONY: build
3636
build:
37-
$(call build_app,custom-effect)
3837
$(call build_app,dump)
39-
$(call build_app,describe)
4038

4139
.PHONY: clean
4240
clean:

cmd/dump/main.go

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Example app for dumping and restoring device state
2+
package main
3+
4+
import (
5+
"encoding/json"
6+
"fmt"
7+
"os"
8+
9+
"github.com/mishamyrt/nuga-lib"
10+
"github.com/mishamyrt/nuga-lib/device"
11+
"github.com/mishamyrt/nuga-lib/dump"
12+
"github.com/mishamyrt/nuga-lib/features/keys"
13+
"github.com/mishamyrt/nuga-lib/features/light"
14+
"github.com/mishamyrt/nuga-lib/hid"
15+
"github.com/mishamyrt/nuga-lib/layout"
16+
"github.com/mishamyrt/nuga-lib/packages/cli"
17+
)
18+
19+
var app = cli.App{
20+
Name: "nuga-dump",
21+
Help: "Utility for workings with keyboard dumps",
22+
}
23+
24+
var (
25+
inputPath string
26+
outputPath string
27+
28+
cmdSave = cli.Command{
29+
Name: "save",
30+
Help: "Save device state to file",
31+
Usage: "<output_path>",
32+
Args: cli.Args{&outputPath},
33+
Run: func(_ []string) {
34+
dev, err := nuga.Open()
35+
cli.Must("open device", err)
36+
state, err := dump.Collect(dev.Handle, dev.Name)
37+
cli.Must("collect device state", err)
38+
data, err := json.Marshal(&state)
39+
cli.Must("marshal device state", err)
40+
_, err = dev.Features.Light.GetEffects()
41+
cli.Must("get effects", err)
42+
cli.Must("write file", os.WriteFile(outputPath, data, 0644))
43+
},
44+
}
45+
46+
cmdRestore = cli.Command{
47+
Name: "restore",
48+
Help: "Restore device state from file",
49+
Usage: "<input_path>",
50+
Args: cli.Args{&inputPath},
51+
Run: func(_ []string) {
52+
d, err := hid.Open()
53+
cli.Must("open device", err)
54+
state, err := readStateDump(inputPath)
55+
cli.Must("read state file", err)
56+
cli.Must("restore device state", dump.Restore(d, state))
57+
},
58+
}
59+
60+
cmdValidate = cli.Command{
61+
Name: "validate",
62+
Help: "Validate device state dump",
63+
Usage: "<input_path>",
64+
Args: cli.Args{&inputPath},
65+
Run: func(_ []string) {
66+
state, err := readStateDump(inputPath)
67+
mustHandleDump("read", err)
68+
{
69+
_, err := light.ParseBacklightColors(state.Data.Lights.Colors)
70+
mustHandleField("lights.colors", err)
71+
_, err = light.ParseEffects(state.Data.Lights.Params)
72+
mustHandleField("lights.params", err)
73+
tpl := layout.GetBacklightTemplate(state.Model)
74+
if tpl != nil {
75+
_, err = light.ParseCustomEffect(state.Data.Lights.CustomEffect, tpl)
76+
mustHandleField("lights.custom_effect", err)
77+
}
78+
}
79+
{
80+
_, err := keys.ParseMacros(state.Data.Keys.Macros)
81+
mustHandleField("keys.macros", err)
82+
tpl := layout.GetKeystrokeTemplate(state.Model)
83+
if tpl != nil {
84+
_, err = keys.ParseKeyMap(state.Data.Keys.Mac, tpl)
85+
mustHandleField("keys.mac", err)
86+
_, err = keys.ParseKeyMap(state.Data.Keys.Win, tpl)
87+
mustHandleField("keys.win", err)
88+
} else {
89+
fmt.Println("Keystroke template is not defined, skipping keymap validation")
90+
}
91+
}
92+
fmt.Println("🟩 Dump is valid")
93+
},
94+
}
95+
96+
cmdConvert = cli.Command{
97+
Name: "convert",
98+
Help: "Convert old JSON dump format to new nugafile",
99+
Usage: "<input_path> <output_path>",
100+
Args: cli.Args{&inputPath, &outputPath},
101+
Run: func(_ []string) {
102+
data, err := os.ReadFile(inputPath)
103+
cli.Must("read file", err)
104+
105+
var originalDump jsonDump
106+
err = json.Unmarshal(data, &originalDump)
107+
cli.Must("unmarshal file", err)
108+
109+
var nugafile dump.State
110+
nugafile.Model = device.Model(originalDump.Name)
111+
nugafile.Data.Lights = &light.StateData{
112+
Colors: originalDump.Lights.Colors[7:1031],
113+
Params: originalDump.Lights.Params[15:138],
114+
CustomEffect: make([]byte, 1024),
115+
}
116+
nugafile.Data.Keys = &keys.StateData{
117+
Mac: keys.UnpackKeyCodes(originalDump.Keys.Mac),
118+
Win: keys.UnpackKeyCodes(originalDump.Keys.Win),
119+
Macros: make([]byte, 1024),
120+
}
121+
data, err = json.Marshal(originalDump)
122+
cli.Must("marshal file", err)
123+
err = os.WriteFile(outputPath, data, 0644)
124+
cli.Must("write file", err)
125+
},
126+
}
127+
)
128+
129+
func main() {
130+
cli.Must("initialize connection", nuga.Init())
131+
app.RunWith(cmdSave, cmdRestore, cmdValidate, cmdConvert)
132+
cli.Must("close connection", nuga.Exit())
133+
}
134+
135+
type jsonDump struct {
136+
Name string `json:"name"`
137+
Firmware string `json:"firmware"`
138+
Lights struct {
139+
Colors []byte `json:"colors"`
140+
Params []byte `json:"params"`
141+
}
142+
Keys struct {
143+
Mac []uint32 `json:"mac"`
144+
Win []uint32 `json:"win"`
145+
}
146+
}
147+
148+
func readStateDump(path string) (*dump.State, error) {
149+
var state dump.State
150+
data, err := os.ReadFile(path)
151+
if err != nil {
152+
return nil, err
153+
}
154+
err = json.Unmarshal(data, &state)
155+
if err != nil {
156+
return nil, err
157+
}
158+
return &state, nil
159+
}
160+
161+
func mustHandleDump(m string, err error) {
162+
if err == nil {
163+
return
164+
}
165+
message := fmt.Sprintln("🟥 " + cli.Red("Dump is not valid"))
166+
if m != "" {
167+
message += fmt.Sprintln(m)
168+
}
169+
message += fmt.Sprintln(err)
170+
fmt.Println(message)
171+
os.Exit(1)
172+
}
173+
174+
func mustHandleField(k string, err error) {
175+
if err != nil {
176+
m := fmt.Sprintf("Problem with field %s: %v\n", k, err)
177+
mustHandleDump(m, err)
178+
}
179+
}

examples/cc/main.go

Lines changed: 0 additions & 98 deletions
This file was deleted.

examples/dump/main.go

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)