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 f5116f03702..ae4f18d4cb3 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -55,6 +55,7 @@ export type AutocompleteOption = { aliases?: string[] disabled?: boolean description?: string + isDirectory?: boolean onSelect?: () => void } @@ -200,8 +201,10 @@ export function Autocomplete(props: { url = urlObj.toString() } + const isDir = item.endsWith("/") return { display: Locale.truncateMiddle(filename, width), + isDirectory: isDir, onSelect: () => { insertPart(filename, { type: "file", @@ -511,6 +514,27 @@ export function Autocomplete(props: { selected.onSelect?.() } + function expandDirectory() { + const selected = options()[store.selected] + if (!selected) return + + const input = props.input() + const currentCursorOffset = input.cursorOffset + + const displayText = selected.display.trimEnd() + const path = displayText.startsWith("@") ? displayText.slice(1) : displayText + + input.cursorOffset = store.index + const startCursor = input.logicalCursor + input.cursorOffset = currentCursorOffset + const endCursor = input.logicalCursor + + input.deleteRange(startCursor.row, startCursor.col, endCursor.row, endCursor.col) + input.insertText("@" + path) + + setStore("selected", 0) + } + function show(mode: "@" | "/") { command.keybinds(false) setStore({ @@ -575,11 +599,21 @@ export function Autocomplete(props: { e.preventDefault() return } - if (name === "return" || name === "tab") { + if (name === "return") { select() e.preventDefault() return } + if (name === "tab") { + const selected = options()[store.selected] + if (selected?.isDirectory) { + expandDirectory() + } else { + select() + } + e.preventDefault() + return + } } if (!store.visible) { if (e.name === "@") {