mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-31 05:15:32 +00:00
keep session navigation active in prompt modes (#29464)
This commit is contained in:
parent
86dc66eae9
commit
94f2ed1b84
3 changed files with 112 additions and 9 deletions
|
|
@ -79,8 +79,7 @@ import {
|
|||
import type { EventSource } from "./context/sdk"
|
||||
import { DialogVariant } from "./component/dialog-variant"
|
||||
|
||||
const appBindingCommands = [
|
||||
"command.palette.show",
|
||||
const appGlobalBindingCommands = [
|
||||
"session.list",
|
||||
"session.new",
|
||||
"session.quick_switch.1",
|
||||
|
|
@ -92,6 +91,10 @@ const appBindingCommands = [
|
|||
"session.quick_switch.7",
|
||||
"session.quick_switch.8",
|
||||
"session.quick_switch.9",
|
||||
] as const
|
||||
|
||||
const appBindingCommands = [
|
||||
"command.palette.show",
|
||||
"model.list",
|
||||
"model.cycle_recent",
|
||||
"model.cycle_recent_reverse",
|
||||
|
|
@ -929,6 +932,10 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
|
|||
bindings: tuiConfig.keybinds.gather("app", appBindingCommands),
|
||||
}))
|
||||
|
||||
useBindings(() => ({
|
||||
bindings: tuiConfig.keybinds.gather("app.global", appGlobalBindingCommands),
|
||||
}))
|
||||
|
||||
useBindings(() => ({
|
||||
mode: OPENCODE_BASE_MODE,
|
||||
enabled: () => {
|
||||
|
|
|
|||
|
|
@ -134,12 +134,6 @@ const sessionBindingCommands = [
|
|||
"session.toggle.actions",
|
||||
"session.toggle.scrollbar",
|
||||
"session.toggle.generic_tool_output",
|
||||
"session.page.up",
|
||||
"session.page.down",
|
||||
"session.line.up",
|
||||
"session.line.down",
|
||||
"session.half.page.up",
|
||||
"session.half.page.down",
|
||||
"session.first",
|
||||
"session.last",
|
||||
"session.messages_last_user",
|
||||
|
|
@ -154,6 +148,17 @@ const sessionBindingCommands = [
|
|||
"session.child.previous",
|
||||
] as const
|
||||
|
||||
const sessionGlobalBindingCommands = [
|
||||
"session.page.up",
|
||||
"session.page.down",
|
||||
"session.line.up",
|
||||
"session.line.down",
|
||||
"session.half.page.up",
|
||||
"session.half.page.down",
|
||||
] as const
|
||||
|
||||
const sessionGlobalUnfocusedBindingCommands = ["session.first", "session.last"] as const
|
||||
|
||||
const context = createContext<{
|
||||
width: number
|
||||
sessionID: string
|
||||
|
|
@ -1067,6 +1072,15 @@ export function Session() {
|
|||
commands: sessionCommands(),
|
||||
}))
|
||||
|
||||
useBindings(() => ({
|
||||
bindings: tuiConfig.keybinds.gather("session.global", sessionGlobalBindingCommands),
|
||||
}))
|
||||
|
||||
useBindings(() => ({
|
||||
enabled: () => renderer.currentFocusedEditor === null,
|
||||
bindings: tuiConfig.keybinds.gather("session.global.unfocused", sessionGlobalUnfocusedBindingCommands),
|
||||
}))
|
||||
|
||||
useBindings(() => ({
|
||||
mode: OPENCODE_BASE_MODE,
|
||||
bindings: tuiConfig.keybinds.gather("session", sessionBindingCommands),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,12 @@ import { testRender, useRenderer } from "@opentui/solid"
|
|||
import { expect, test } from "bun:test"
|
||||
import { onCleanup } from "solid-js"
|
||||
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
|
||||
import { OpencodeKeymapProvider, registerOpencodeKeymap } from "@/cli/cmd/tui/keymap"
|
||||
import {
|
||||
getOpencodeModeStack,
|
||||
OPENCODE_BASE_MODE,
|
||||
OpencodeKeymapProvider,
|
||||
registerOpencodeKeymap,
|
||||
} from "@/cli/cmd/tui/keymap"
|
||||
|
||||
test("legacy page key aliases compile as page keys", async () => {
|
||||
const sequences: Record<string, string[][]> = {}
|
||||
|
|
@ -52,3 +57,80 @@ test("legacy page key aliases compile as page keys", async () => {
|
|||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
test("mode-less bindings stay active when opencode mode changes", async () => {
|
||||
const counts: Record<string, Record<string, number>> = {}
|
||||
|
||||
function Harness() {
|
||||
const renderer = useRenderer()
|
||||
const keymap = createDefaultOpenTuiKeymap(renderer)
|
||||
const config = createTuiResolvedConfig()
|
||||
const offKeymap = registerOpencodeKeymap(keymap, renderer, config)
|
||||
const offGlobal = keymap.registerLayer({
|
||||
commands: [
|
||||
{ name: "session.list", run() {} },
|
||||
{ name: "session.new", run() {} },
|
||||
{ name: "session.page.up", run() {} },
|
||||
{ name: "session.first", run() {} },
|
||||
],
|
||||
bindings: config.keybinds.gather("test.global", [
|
||||
"session.list",
|
||||
"session.new",
|
||||
"session.page.up",
|
||||
"session.first",
|
||||
]),
|
||||
})
|
||||
const offBase = keymap.registerLayer({
|
||||
mode: OPENCODE_BASE_MODE,
|
||||
commands: [{ name: "model.list", run() {} }],
|
||||
bindings: config.keybinds.gather("test.base", ["model.list"]),
|
||||
})
|
||||
const activeCounts = () =>
|
||||
Object.fromEntries(
|
||||
Array.from(
|
||||
keymap.getCommandBindings({
|
||||
visibility: "active",
|
||||
commands: ["session.list", "session.new", "session.page.up", "session.first", "model.list"],
|
||||
}),
|
||||
([command, bindings]) => [command, bindings.length],
|
||||
),
|
||||
)
|
||||
|
||||
counts.base = activeCounts()
|
||||
const popQuestion = getOpencodeModeStack(keymap).push("question")
|
||||
counts.question = activeCounts()
|
||||
popQuestion()
|
||||
const popAutocomplete = getOpencodeModeStack(keymap).push("autocomplete")
|
||||
counts.autocomplete = activeCounts()
|
||||
popAutocomplete()
|
||||
|
||||
onCleanup(() => {
|
||||
offBase()
|
||||
offGlobal()
|
||||
offKeymap()
|
||||
})
|
||||
|
||||
return (
|
||||
<OpencodeKeymapProvider keymap={keymap}>
|
||||
<box />
|
||||
</OpencodeKeymapProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const app = await testRender(() => <Harness />)
|
||||
try {
|
||||
expect(counts).toEqual({
|
||||
base: { "session.list": 1, "session.new": 1, "session.page.up": 2, "session.first": 2, "model.list": 1 },
|
||||
question: { "session.list": 1, "session.new": 1, "session.page.up": 2, "session.first": 2, "model.list": 0 },
|
||||
autocomplete: {
|
||||
"session.list": 1,
|
||||
"session.new": 1,
|
||||
"session.page.up": 2,
|
||||
"session.first": 2,
|
||||
"model.list": 0,
|
||||
},
|
||||
})
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue