fix(config): resolve enter key submission and keybinding issues (#89)

closes #88
closes #85
This commit is contained in:
VERSE
2026-07-31 18:38:31 +07:00
committed by GitHub
parent 85a9a7d55d
commit 235a7f98ea
3 changed files with 54 additions and 9 deletions
+26
View File
@@ -272,3 +272,29 @@ func TestMigration(t *testing.T) {
t.Errorf("expected backup file update_state.json.bak to exist") t.Errorf("expected backup file update_state.json.bak to exist")
} }
} }
func TestMatchKey(t *testing.T) {
tests := []struct {
input []byte
expected string
matched bool
consumed int
}{
{[]byte{0x19}, "ctrl+y", true, 1},
{[]byte{0x0b}, "ctrl+k", true, 1},
{[]byte{0x0a}, "ctrl+j", true, 1},
{[]byte{0x12}, "ctrl+r", true, 1},
{[]byte{'j'}, "j", true, 1},
{[]byte{'k'}, "k", true, 1},
{[]byte{0x09}, "tab", true, 1},
{[]byte{0x0d}, "enter", true, 1},
{[]byte{0x0d}, "ctrl+r", false, 0},
}
for _, tt := range tests {
m, c := MatchKey(tt.input, tt.expected)
if m != tt.matched || c != tt.consumed {
t.Errorf("MatchKey(%v, %q) = (%v, %d); want (%v, %d)", tt.input, tt.expected, m, c, tt.matched, tt.consumed)
}
}
}
+9
View File
@@ -15,6 +15,15 @@ func MatchKey(input []byte, expected string) (matched bool, consumed int) {
expected = strings.ToLower(strings.TrimSpace(expected)) expected = strings.ToLower(strings.TrimSpace(expected))
expected = strings.TrimPrefix(expected, "<") expected = strings.TrimPrefix(expected, "<")
expected = strings.TrimSuffix(expected, ">") expected = strings.TrimSuffix(expected, ">")
expected = strings.ReplaceAll(expected, "-", "+")
expected = strings.ReplaceAll(expected, "ctrk", "ctrl")
expected = strings.ReplaceAll(expected, "ctl", "ctrl")
if len(expected) == 1 {
if input[0] == expected[0] {
return true, 1
}
}
if strings.HasPrefix(expected, "ctrl+") && len(expected) == 6 { if strings.HasPrefix(expected, "ctrl+") && len(expected) == 6 {
char := expected[5] char := expected[5]
+18 -8
View File
@@ -747,18 +747,24 @@ func runWrapper() {
i += navConsumed - 1 i += navConsumed - 1
continue continue
} else if naiveBuffer == "" { } else {
// up/down arrow on empty prompt // up/down arrow or navigation key when overlay is closed
intercepted = true intercepted = true
activeModeMu.Lock() activeModeMu.Lock()
activeMode = "history" if activeMode == "" {
saveMode(activeMode) activeMode = loadMode()
}
activeModeMu.Unlock() activeModeMu.Unlock()
activeModeMu.RLock() activeModeMu.RLock()
currentMode := activeMode currentMode := activeMode
activeModeMu.RUnlock() activeModeMu.RUnlock()
results := MergeResults("", currentMode)
bufferMu.Lock()
bufQuery := naiveBuffer
bufferMu.Unlock()
results := MergeResults(bufQuery, currentMode)
if len(results) > 0 { if len(results) > 0 {
limit := min(len(results), 100) limit := min(len(results), 100)
var historyList []spec.Suggestion var historyList []spec.Suggestion
@@ -791,8 +797,8 @@ func runWrapper() {
} }
if matched, consumed := config.MatchKey(inputSlice[i:], config.Get().Keybindings.SelectSuggestion); matched && config.Get().Keybindings.SelectSuggestion != "" { if matched, consumed := config.MatchKey(inputSlice[i:], config.Get().Keybindings.SelectSuggestion); matched && config.Get().Keybindings.SelectSuggestion != "" {
intercepted = true
if overlay.IsVisible() { if overlay.IsVisible() {
intercepted = true
selected := overlay.GetCurrentCmd() selected := overlay.GetCurrentCmd()
if selected != "" { if selected != "" {
activeModeMu.RLock() activeModeMu.RLock()
@@ -816,18 +822,22 @@ func runWrapper() {
userNavigated.Store(false) userNavigated.Store(false)
writeStdout([]byte(overlay.Render())) writeStdout([]byte(overlay.Render()))
} }
}
i += consumed - 1 i += consumed - 1
continue continue
} }
}
if b == 0x0d || b == 0x0a { // enter if b == 0x0d || b == 0x0a { // enter
intercepted = true intercepted = true
logger.Debugf("Intercepted Enter key") logger.Debugf("Intercepted Enter key")
if b == 0x0d && i+1 < n && inputSlice[i+1] == 0x0a {
i++ // consume trailing \n in \r\n to prevent matching ctrl+j
}
var selectedCmd string var selectedCmd string
var shouldAutoExecute bool var shouldAutoExecute bool
if config.Get().Core.AutoExecute && overlay.IsVisible() { if overlay.IsVisible() && (config.Get().Core.AutoExecute || userNavigated.Load()) {
selectedCmd = overlay.GetCurrentCmd() selectedCmd = overlay.GetCurrentCmd()
if selectedCmd != "" { if selectedCmd != "" {
shouldAutoExecute = true shouldAutoExecute = true