diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx index 66a312e5..b9ba4a9b 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx @@ -22,15 +22,16 @@ export type CommandOption = DialogSelectOption & { function init() { const [registrations, setRegistrations] = createSignal[]>([]) + const [suspendCount, setSuspendCount] = createSignal(0) const dialog = useDialog() const keybind = useKeybind() const options = createMemo(() => { return registrations().flatMap((x) => x()) }) + const suspended = () => suspendCount() > 0 - let keybinds = true useKeyboard((evt) => { - if (!keybinds) return + if (suspended()) return for (const option of options()) { if (option.keybind && keybind.match(option.keybind, evt)) { evt.preventDefault() @@ -50,8 +51,9 @@ function init() { } }, keybinds(enabled: boolean) { - keybinds = enabled + setSuspendCount((count) => count + (enabled ? -1 : 1)) }, + suspended, show() { dialog.replace(() => ) }, @@ -83,7 +85,10 @@ export function CommandProvider(props: ParentProps) { const keybind = useKeybind() useKeyboard((evt) => { - if (keybind.match("command_list", evt) && dialog.stack.length === 0) { + if (value.suspended()) return + if (dialog.stack.length > 0) return + if (evt.defaultPrevented) return + if (keybind.match("command_list", evt)) { evt.preventDefault() dialog.replace(() => ) return diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 812496dd..a4c1f33d 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -393,11 +393,31 @@ export function Autocomplete(props: { }, onKeyDown(e: KeyEvent) { if (store.visible) { - if (e.name === "up") move(-1) - if (e.name === "down") move(1) - if (e.name === "escape") hide() - if (e.name === "return" || e.name === "tab") select() - if (["up", "down", "return", "tab", "escape"].includes(e.name)) e.preventDefault() + const name = e.name?.toLowerCase() + const ctrlOnly = e.ctrl && !e.meta && !e.shift + const isNavUp = name === "up" || (ctrlOnly && name === "p") + const isNavDown = name === "down" || (ctrlOnly && name === "n") + + if (isNavUp) { + move(-1) + e.preventDefault() + return + } + if (isNavDown) { + move(1) + e.preventDefault() + return + } + if (name === "escape") { + hide() + e.preventDefault() + return + } + if (name === "return" || name === "tab") { + select() + e.preventDefault() + return + } } if (!store.visible) { if (e.name === "@") {