Skip to content

Commit d209891

Browse files
committed
Address Cursor and golangci-lint comments
Also restored accidentally moved nb_NO.kle.json file
1 parent 05dc88d commit d209891

4 files changed

Lines changed: 187 additions & 167 deletions

File tree

internal/keyboard/keyboard.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,9 @@ func sanitizeName(name string) string {
572572
return r
573573
}, name)
574574
cleaned = strings.TrimSpace(cleaned)
575-
if len(cleaned) > maxNameLength {
576-
cleaned = cleaned[:maxNameLength]
575+
if utf8.RuneCountInString(cleaned) > maxNameLength {
576+
runes := []rune(cleaned)
577+
cleaned = string(runes[:maxNameLength])
577578
}
578579
if cleaned == "" {
579580
return "Unnamed Layout"
@@ -619,13 +620,18 @@ func isDeadKey(legends KeyLegends, declaredDeadKeys map[rune]bool) bool {
619620
func buildCharMap(keys []TransportKey) map[string]HIDCombo {
620621
m := make(map[string]HIDCombo)
621622

622-
// Sort keys by position for deterministic first-occurrence behaviour
623-
slices.SortStableFunc(keys, func(a, b TransportKey) int {
623+
// Sort a copy by position for deterministic first-occurrence behaviour.
624+
// We must not mutate the original slice — it preserves KLE parse order,
625+
// which the scancodes metadata override uses (0-based index).
626+
sorted := make([]TransportKey, len(keys))
627+
copy(sorted, keys)
628+
slices.SortStableFunc(sorted, func(a, b TransportKey) int {
624629
if comp := cmp.Compare(a.Y, b.Y); comp != 0 {
625630
return comp
626631
}
627632
return cmp.Compare(a.X, b.X)
628633
})
634+
keys = sorted
629635

630636
for _, key := range keys {
631637
if key.Scancode == 0 {
@@ -680,8 +686,9 @@ func addDeadKeyCompositions(keys []TransportKey, charMap map[string]HIDCombo, de
680686
}
681687

682688
type deadKeyInfo struct {
683-
combo HIDCombo // scancode + modifiers to press the dead key
684-
combining rune // Unicode combining character
689+
combo HIDCombo // scancode + modifiers to press the dead key
690+
combining rune // Unicode combining character
691+
displayKey rune // the legend character as it appears on the keycap
685692
}
686693

687694
// Collect dead key legends that are both declared AND have a known
@@ -713,8 +720,9 @@ func addDeadKeyCompositions(keys []TransportKey, charMap map[string]HIDCombo, de
713720
continue
714721
}
715722
deadKeys = append(deadKeys, deadKeyInfo{
716-
combo: HIDCombo{Scancode: key.Scancode, Modifiers: layer.mods},
717-
combining: combining,
723+
combo: HIDCombo{Scancode: key.Scancode, Modifiers: layer.mods},
724+
combining: combining,
725+
displayKey: r,
718726
})
719727
}
720728
}
@@ -764,15 +772,11 @@ func addDeadKeyCompositions(keys []TransportKey, charMap map[string]HIDCombo, de
764772
}
765773
}
766774

767-
// Standalone dead key: dead key + Space → the dead key character itself
768-
deadChar := string([]rune{dk.combining})
769-
// Find the display character (not the combining form)
770-
for displayRune, combiningRune := range deadKeyToCombining {
771-
if combiningRune == dk.combining {
772-
deadChar = string(displayRune)
773-
break
774-
}
775-
}
775+
// Standalone dead key: dead key + Space → the dead key character itself.
776+
// Use the display rune captured from the actual key legend, not a
777+
// reverse lookup from deadKeyToCombining (which has duplicate values
778+
// and non-deterministic map iteration order).
779+
deadChar := string(dk.displayKey)
776780
if _, exists := charMap[deadChar]; exists {
777781
// Replace the simple entry with a prefixed one (dead key + space)
778782
charMap[deadChar] = HIDCombo{

internal/keyboard/keyboard_test.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"strings"
1313
"testing"
14+
"unicode/utf8"
1415
)
1516

1617
// ---------------------------------------------------------------------------
@@ -400,8 +401,18 @@ func TestSanitizeNameTrimsWhitespace(t *testing.T) {
400401
func TestSanitizeNameTruncates(t *testing.T) {
401402
long := strings.Repeat("x", 200)
402403
got := sanitizeName(long)
403-
if len(got) != maxNameLength {
404-
t.Errorf("expected length %d, got %d", maxNameLength, len(got))
404+
if utf8.RuneCountInString(got) != maxNameLength {
405+
t.Errorf("expected %d runes, got %d", maxNameLength, utf8.RuneCountInString(got))
406+
}
407+
408+
// Multi-byte: 200 CJK characters → truncate to maxNameLength runes, not bytes
409+
cjk := strings.Repeat("漢", 200)
410+
gotCJK := sanitizeName(cjk)
411+
if utf8.RuneCountInString(gotCJK) != maxNameLength {
412+
t.Errorf("CJK: expected %d runes, got %d", maxNameLength, utf8.RuneCountInString(gotCJK))
413+
}
414+
if !utf8.ValidString(gotCJK) {
415+
t.Error("CJK truncation produced invalid UTF-8")
405416
}
406417
}
407418

internal/keyboard/layouts/nb_NO.kle.json

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,25 @@
4444
"d": true,
4545
"w": 4
4646
},
47-
"Norsk bokmål\nnb-NO\n\n(ISO 105)"
47+
"nb-NO\nNorsk bokmål\n(ISO 105)\n"
4848
],
4949
[
5050
{
5151
"y": 0.5
5252
},
53-
"§\n|",
54-
"!\n1",
55-
"\"\n2\n\n@",
56-
"#\n3\n\n£",
57-
"¤\n4\n\n$",
58-
"%\n5\n\n",
59-
"&\n6",
60-
"/\n7\n\n{",
61-
"(\n8\n\n[",
62-
")\n9\n\n]",
63-
"=\n0\n\n}",
64-
"?\n+",
65-
"`\n\\\n\n´",
53+
"|\n§",
54+
"1\n!",
55+
"2\n\"\n@\n",
56+
"3\n#\n£\n",
57+
"4\n¤\n$\n",
58+
"5\n%\n\n",
59+
"6\n&",
60+
"7\n/\n{\n",
61+
"8\n(\n[\n",
62+
"9\n)\n]\n",
63+
"0\n=\n}\n",
64+
"+\n?",
65+
"\\\n`\n´\n",
6666
{
6767
"w": 2
6868
},
@@ -96,8 +96,8 @@
9696
"i",
9797
"o",
9898
"p",
99-
"Å\nå",
100-
"^\n¨\n\n~",
99+
"å\nÅ",
100+
"¨\n^\n~\n",
101101
{
102102
"x": 0.25,
103103
"w": 1.25,
@@ -144,9 +144,9 @@
144144
"j",
145145
"k",
146146
"l",
147-
"Ø\nø",
148-
"Æ\næ",
149-
"*\n'",
147+
"ø\nØ",
148+
"æ\nÆ",
149+
"'\n*",
150150
{
151151
"x": 4.75
152152
},
@@ -162,17 +162,17 @@
162162
"w": 1.25
163163
},
164164
"⇧ Shift",
165-
">\n<",
165+
"<\n>",
166166
"z",
167167
"x",
168168
"c",
169169
"v",
170170
"b",
171171
"n",
172172
"m",
173-
";\n,",
174-
":\n.",
175-
"_\n-",
173+
",\n;",
174+
".\n:",
175+
"-\n_",
176176
{
177177
"w": 2.75
178178
},

0 commit comments

Comments
 (0)