Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/opencode/src/cli/cmd/tui/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
keybind: "terminal_suspend",
category: "System",
hidden: true,
enabled: process.platform !== "win32",
onSelect: () => {
process.once("SIGCONT", () => {
renderer.resume()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,7 @@ const TIPS = [
"Use {highlight}/review{/highlight} to review uncommitted changes, branches, or PRs",
"Run {highlight}/help{/highlight} or {highlight}Ctrl+X H{/highlight} to show the help dialog",
"Use {highlight}/rename{/highlight} to rename the current session",
"Press {highlight}Ctrl+Z{/highlight} to suspend the terminal and return to your shell",
...(process.platform === "win32"
? ["Press {highlight}Ctrl+Z{/highlight} to undo changes in your prompt"]
: ["Press {highlight}Ctrl+Z{/highlight} to suspend the terminal and return to your shell"]),
]
16 changes: 15 additions & 1 deletion packages/opencode/src/config/tui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,20 @@ export namespace TuiConfig {
}
}

function resolvePlatformKeybinds(keybinds?: z.input<typeof Config.Keybinds>) {
const result = { ...(keybinds ?? {}) }

if (process.platform === "win32") {
// Native Windows terminals do not support POSIX suspend, so prefer prompt undo.
if (result.terminal_suspend === undefined) result.terminal_suspend = "none"
if (result.input_undo === undefined) {
result.input_undo = result.terminal_suspend === "none" ? "ctrl+z,ctrl+-,super+z" : "ctrl+-,super+z"
Comment thread
Hona marked this conversation as resolved.
Outdated
}
}
Comment thread
Hona marked this conversation as resolved.
Outdated

return result
}

function installDeps(dir: string): Promise<void> {
return Config.installDependencies(dir)
}
Expand Down Expand Up @@ -111,7 +125,7 @@ export namespace TuiConfig {
}
}

acc.result.keybinds = Config.Keybinds.parse(acc.result.keybinds ?? {})
acc.result.keybinds = Config.Keybinds.parse(resolvePlatformKeybinds(acc.result.keybinds))

const deps: Promise<void>[] = []
if (acc.result.plugin?.length) {
Expand Down
48 changes: 48 additions & 0 deletions packages/opencode/test/config/tui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Global } from "../../src/global"
import { Filesystem } from "../../src/util/filesystem"

const managedConfigDir = process.env.OPENCODE_TEST_MANAGED_CONFIG_DIR!
const wintest = process.platform === "win32" ? test : test.skip

beforeEach(async () => {
await Config.invalidate(true)
Expand Down Expand Up @@ -441,6 +442,53 @@ test("merges keybind overrides across precedence layers", async () => {
})
})

wintest("defaults Ctrl+Z to input undo on Windows", async () => {
await using tmp = await tmpdir()

await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await TuiConfig.get()
expect(config.keybinds?.terminal_suspend).toBe("none")
expect(config.keybinds?.input_undo).toBe("ctrl+z,ctrl+-,super+z")
},
})
})

wintest("keeps explicit input undo overrides on Windows", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "tui.json"), JSON.stringify({ keybinds: { input_undo: "ctrl+y" } }))
},
})

await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await TuiConfig.get()
expect(config.keybinds?.terminal_suspend).toBe("none")
expect(config.keybinds?.input_undo).toBe("ctrl+y")
},
})
})

wintest("keeps explicit terminal suspend bindings on Windows", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "tui.json"), JSON.stringify({ keybinds: { terminal_suspend: "alt+z" } }))
},
})

await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await TuiConfig.get()
expect(config.keybinds?.terminal_suspend).toBe("alt+z")
expect(config.keybinds?.input_undo).toBe("ctrl+-,super+z")
},
})
})

Comment thread
Hona marked this conversation as resolved.
Outdated
test("OPENCODE_TUI_CONFIG provides settings when no project config exists", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
Expand Down
Loading