mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
feat: add Korean keyboard layout support for keybindings
This commit is contained in:
parent
3396d26d8b
commit
03c26a05e0
2 changed files with 160 additions and 1 deletions
|
|
@ -3,6 +3,7 @@ package gui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -609,7 +610,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return translateKeybindingsToKorean(bindings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) keybindings(g *gocui.Gui) error {
|
func (gui *Gui) keybindings(g *gocui.Gui) error {
|
||||||
|
|
@ -633,3 +634,86 @@ func wrappedHandler(f func() error) func(*gocui.Gui, *gocui.View) error {
|
||||||
return f()
|
return f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type koreanKey struct {
|
||||||
|
key rune
|
||||||
|
modifier gocui.Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
var englishToKorean = map[rune]koreanKey{
|
||||||
|
// Lowercase
|
||||||
|
'q': {key: 'ㅂ', modifier: gocui.ModNone},
|
||||||
|
'w': {key: 'ㅈ', modifier: gocui.ModNone},
|
||||||
|
'e': {key: 'ㄷ', modifier: gocui.ModNone},
|
||||||
|
'r': {key: 'ㄱ', modifier: gocui.ModNone},
|
||||||
|
't': {key: 'ㅅ', modifier: gocui.ModNone},
|
||||||
|
'y': {key: 'ㅛ', modifier: gocui.ModNone},
|
||||||
|
'u': {key: 'ㅕ', modifier: gocui.ModNone},
|
||||||
|
'i': {key: 'ㅑ', modifier: gocui.ModNone},
|
||||||
|
'o': {key: 'ㅐ', modifier: gocui.ModNone},
|
||||||
|
'p': {key: 'ㅔ', modifier: gocui.ModNone},
|
||||||
|
'a': {key: 'ㅁ', modifier: gocui.ModNone},
|
||||||
|
's': {key: 'ㄴ', modifier: gocui.ModNone},
|
||||||
|
'd': {key: 'ㅇ', modifier: gocui.ModNone},
|
||||||
|
'f': {key: 'ㄹ', modifier: gocui.ModNone},
|
||||||
|
'g': {key: 'ㅎ', modifier: gocui.ModNone},
|
||||||
|
'h': {key: 'ㅗ', modifier: gocui.ModNone},
|
||||||
|
'j': {key: 'ㅓ', modifier: gocui.ModNone},
|
||||||
|
'k': {key: 'ㅏ', modifier: gocui.ModNone},
|
||||||
|
'l': {key: 'ㅣ', modifier: gocui.ModNone},
|
||||||
|
'z': {key: 'ㅋ', modifier: gocui.ModNone},
|
||||||
|
'x': {key: 'ㅌ', modifier: gocui.ModNone},
|
||||||
|
'c': {key: 'ㅊ', modifier: gocui.ModNone},
|
||||||
|
'v': {key: 'ㅍ', modifier: gocui.ModNone},
|
||||||
|
'b': {key: 'ㅠ', modifier: gocui.ModNone},
|
||||||
|
'n': {key: 'ㅜ', modifier: gocui.ModNone},
|
||||||
|
'm': {key: 'ㅡ', modifier: gocui.ModNone},
|
||||||
|
|
||||||
|
// Uppercase (Double Consonants - ModNone)
|
||||||
|
'Q': {key: 'ㅃ', modifier: gocui.ModNone},
|
||||||
|
'W': {key: 'ㅉ', modifier: gocui.ModNone},
|
||||||
|
'E': {key: 'ㄸ', modifier: gocui.ModNone},
|
||||||
|
'R': {key: 'ㄲ', modifier: gocui.ModNone},
|
||||||
|
'T': {key: 'ㅆ', modifier: gocui.ModNone},
|
||||||
|
'O': {key: 'ㅒ', modifier: gocui.ModNone},
|
||||||
|
'P': {key: 'ㅖ', modifier: gocui.ModNone},
|
||||||
|
|
||||||
|
// Uppercase (No Double Consonant - ModShift)
|
||||||
|
'A': {key: 'ㅁ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'S': {key: 'ㄴ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'D': {key: 'ㅇ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'F': {key: 'ㄹ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'G': {key: 'ㅎ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'H': {key: 'ㅗ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'J': {key: 'ㅓ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'K': {key: 'ㅏ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'L': {key: 'ㅣ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'Z': {key: 'ㅋ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'X': {key: 'ㅌ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'C': {key: 'ㅊ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'V': {key: 'ㅍ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'B': {key: 'ㅠ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'N': {key: 'ㅜ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'M': {key: 'ㅡ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'Y': {key: 'ㅛ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'U': {key: 'ㅕ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
'I': {key: 'ㅑ', modifier: gocui.Modifier(tcell.ModShift)},
|
||||||
|
}
|
||||||
|
|
||||||
|
func translateKeybindingsToKorean(bindings []*Binding) []*Binding {
|
||||||
|
var translated []*Binding
|
||||||
|
for _, binding := range bindings {
|
||||||
|
if r, ok := binding.Key.(rune); ok {
|
||||||
|
if kor, exists := englishToKorean[r]; exists {
|
||||||
|
translated = append(translated, &Binding{
|
||||||
|
ViewName: binding.ViewName,
|
||||||
|
Handler: binding.Handler,
|
||||||
|
Key: kor.key,
|
||||||
|
Modifier: binding.Modifier | kor.modifier,
|
||||||
|
Description: binding.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return append(bindings, translated...)
|
||||||
|
}
|
||||||
|
|
|
||||||
75
pkg/gui/keybindings_test.go
Normal file
75
pkg/gui/keybindings_test.go
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTranslateKeybindingsToKorean(t *testing.T) {
|
||||||
|
inputBindings := []*Binding{
|
||||||
|
{
|
||||||
|
ViewName: "services",
|
||||||
|
Key: 's',
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ViewName: "services",
|
||||||
|
Key: 'S',
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ViewName: "services",
|
||||||
|
Key: 'l',
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ViewName: "global",
|
||||||
|
Key: gocui.KeyCtrlC,
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := translateKeybindingsToKorean(inputBindings)
|
||||||
|
|
||||||
|
// The original bindings must remain intact, and new ones should be appended
|
||||||
|
assert.Len(t, result, len(inputBindings)+3)
|
||||||
|
|
||||||
|
// Verify original bindings are still present and unaltered
|
||||||
|
for i, b := range inputBindings {
|
||||||
|
assert.Equal(t, b.Key, result[i].Key)
|
||||||
|
assert.Equal(t, b.Modifier, result[i].Modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify translated Korean bindings are appended correctly
|
||||||
|
// 's' -> 'ㄴ' (gocui.ModNone)
|
||||||
|
// 'S' -> 'ㄴ' (gocui.Modifier(tcell.ModShift))
|
||||||
|
// 'l' -> 'ㅣ' (gocui.ModNone)
|
||||||
|
|
||||||
|
// We expect translated bindings to be appended:
|
||||||
|
foundS := false
|
||||||
|
foundShiftS := false
|
||||||
|
foundL := false
|
||||||
|
|
||||||
|
for _, b := range result[len(inputBindings):] {
|
||||||
|
if b.Key == 'ㄴ' && b.Modifier == gocui.ModNone {
|
||||||
|
foundS = true
|
||||||
|
}
|
||||||
|
if b.Key == 'ㄴ' && b.Modifier == gocui.Modifier(tcell.ModShift) {
|
||||||
|
foundShiftS = true
|
||||||
|
}
|
||||||
|
if b.Key == 'ㅣ' && b.Modifier == gocui.ModNone {
|
||||||
|
foundL = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, foundS, "Expected to find translated Korean binding for 's'")
|
||||||
|
assert.True(t, foundShiftS, "Expected to find translated Korean binding for 'S'")
|
||||||
|
assert.True(t, foundL, "Expected to find translated Korean binding for 'l'")
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue