feat(tui): open subagents with down
This commit is contained in:
@@ -86,6 +86,12 @@ test("resolves a session move keybind", () => {
|
||||
expect(config.keybinds.get("session.move")).toMatchObject([{ key: "ctrl+o" }])
|
||||
})
|
||||
|
||||
test("opens the subagent picker with down", () => {
|
||||
const config = resolve({}, { terminalSuspend: true })
|
||||
|
||||
expect(config.keybinds.get("session.child.first")).toMatchObject([{ key: "down" }])
|
||||
})
|
||||
|
||||
test("disables suspend and assigns ctrl+z to undo when unsupported", () => {
|
||||
const config = resolve({}, { terminalSuspend: false })
|
||||
|
||||
|
||||
@@ -5,7 +5,13 @@ import { testRender, useRenderer } from "@opentui/solid"
|
||||
import { expect, test } from "bun:test"
|
||||
import { onCleanup } from "solid-js"
|
||||
import { TuiKeybind } from "../src/config/keybind"
|
||||
import { getOpencodeModeStack, OPENCODE_BASE_MODE, OpencodeKeymapProvider, registerOpencodeKeymap } from "../src/keymap"
|
||||
import {
|
||||
formatKeySequence,
|
||||
getOpencodeModeStack,
|
||||
OPENCODE_BASE_MODE,
|
||||
OpencodeKeymapProvider,
|
||||
registerOpencodeKeymap,
|
||||
} from "../src/keymap"
|
||||
|
||||
function createResolvedKeymapConfig(input: TuiKeybind.KeybindOverrides = {}) {
|
||||
const keybinds = TuiKeybind.parse(input)
|
||||
@@ -63,6 +69,47 @@ test("legacy page key aliases compile as page keys", async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("formats navigation keys as arrows", async () => {
|
||||
const shortcuts: Record<string, string> = {}
|
||||
|
||||
function Harness() {
|
||||
const renderer = useRenderer()
|
||||
const keymap = createDefaultOpenTuiKeymap(renderer)
|
||||
const config = createResolvedKeymapConfig()
|
||||
const offKeymap = registerOpencodeKeymap(keymap, renderer, config)
|
||||
const commands = ["session.parent", "session.child.first", "session.child.previous", "session.child.next"]
|
||||
const offLayer = keymap.registerLayer({
|
||||
bindings: config.keybinds.gather("test.arrows", commands),
|
||||
})
|
||||
const bindings = keymap.getCommandBindings({ visibility: "registered", commands })
|
||||
commands.forEach((command) => {
|
||||
shortcuts[command] = formatKeySequence(bindings.get(command)?.[0]?.sequence, config)
|
||||
})
|
||||
onCleanup(() => {
|
||||
offLayer()
|
||||
offKeymap()
|
||||
})
|
||||
|
||||
return (
|
||||
<OpencodeKeymapProvider keymap={keymap}>
|
||||
<box />
|
||||
</OpencodeKeymapProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const app = await testRender(() => <Harness />)
|
||||
try {
|
||||
expect(shortcuts).toEqual({
|
||||
"session.parent": "↑",
|
||||
"session.child.first": "↓",
|
||||
"session.child.previous": "←",
|
||||
"session.child.next": "→",
|
||||
})
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
test("mode-less bindings stay active when opencode mode changes", async () => {
|
||||
const counts: Record<string, Record<string, number>> = {}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/** @jsxImportSource @opentui/solid */
|
||||
import { testRender } from "@opentui/solid"
|
||||
import { expect, test } from "bun:test"
|
||||
import { mkdir } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import { TuiPathsProvider } from "../../src/context/runtime"
|
||||
import { PromptHistoryProvider, usePromptHistory } from "../../src/prompt/history"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
||||
test("down rejects at the newest history item with an empty prompt", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
const state = path.join(tmp.path, "state")
|
||||
await mkdir(state, { recursive: true })
|
||||
let history: ReturnType<typeof usePromptHistory>
|
||||
|
||||
function Consumer() {
|
||||
history = usePromptHistory()
|
||||
return <box />
|
||||
}
|
||||
|
||||
const app = await testRender(() => (
|
||||
<TuiPathsProvider value={{ cwd: tmp.path, home: tmp.path, state, worktree: tmp.path }}>
|
||||
<PromptHistoryProvider>
|
||||
<Consumer />
|
||||
</PromptHistoryProvider>
|
||||
</TuiPathsProvider>
|
||||
))
|
||||
try {
|
||||
await app.renderOnce()
|
||||
history!.append({ text: "previous", files: [], agents: [], pasted: [] })
|
||||
|
||||
expect(history!.move(1, "")).toBeUndefined()
|
||||
expect(history!.move(-1, "")?.text).toBe("previous")
|
||||
expect(history!.move(1, "previous")?.text).toBe("")
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user