feat(tui): open subagents with down

This commit is contained in:
Dax Raad 2026-07-10 21:01:04 -04:00
commit 6ce62bd84a
10 changed files with 241 additions and 21 deletions

View file

@ -177,6 +177,7 @@ export function Prompt(props: PromptProps) {
const keymap = useOpencodeKeymap()
const agentShortcut = useCommandShortcut("agent.cycle")
const paletteShortcut = useCommandShortcut("command.palette.show")
const liveWorkShortcut = useCommandShortcut("session.child.first")
const renderer = useRenderer()
const exit = useExit()
const dimensions = useTerminalDimensions()
@ -864,6 +865,7 @@ export function Prompt(props: PromptProps) {
useBindings(() => {
return {
priority: 1,
target: inputTarget,
enabled: (() => {
cursorVersion()
@ -876,8 +878,12 @@ export function Prompt(props: PromptProps) {
category: "Prompt",
run() {
if (input.cursorOffset !== 0) {
if (input.scrollY + input.visualCursor.visualRow === 0) input.cursorOffset = 0
return false
if (input.scrollY + input.visualCursor.visualRow === 0) {
input.cursorOffset = 0
return
}
input.moveCursorUp()
return
}
const item = history.move(-1, input.plainText)
@ -896,6 +902,7 @@ export function Prompt(props: PromptProps) {
useBindings(() => {
return {
priority: 1,
target: inputTarget,
enabled: (() => {
cursorVersion()
@ -911,9 +918,12 @@ export function Prompt(props: PromptProps) {
if (
input.scrollY + input.visualCursor.visualRow ===
Math.max(0, input.editorView.getTotalVirtualLineCount() - 1)
)
) {
input.cursorOffset = input.plainText.length
return false
return
}
input.moveCursorDown()
return
}
const item = history.move(1, input.plainText)
@ -1608,6 +1618,9 @@ export function Prompt(props: PromptProps) {
<Switch>
<Match when={liveWorkStatusVisible() || statusItems().length > 0}>
<text fg={theme.textMuted} wrapMode="none">
<Show when={liveWorkStatusVisible() && liveWorkShortcut()}>
{(shortcut) => <span style={{ fg: theme.text }}>{shortcut()} </span>}
</Show>
<Show when={subagentStatusLabel()}>
{(label) => <span style={{ fg: theme.textMuted }}>{label()}</span>}
</Show>

View file

@ -100,7 +100,7 @@ export const Definitions = {
session_toggle_timestamps: keybind("none", "Toggle message timestamps"),
session_toggle_generic_tool_output: keybind("none", "Toggle generic tool output"),
session_queued_prompts: keybind("<leader>q", "Manage queued prompts"),
session_child_first: keybind("<leader>down", "Toggle subagent picker"),
session_child_first: keybind("down", "Toggle subagent picker"),
session_child_cycle: keybind("right", "Go to next child session"),
session_child_cycle_reverse: keybind("left", "Go to previous child session"),
session_parent: keybind("up", "Go to parent session"),

View file

@ -193,6 +193,10 @@ function formatOptions(config: FormatConfig) {
[LEADER_TOKEN]: leaderDisplay(config),
},
keyNameAliases: {
up: "↑",
down: "↓",
left: "←",
right: "→",
pageup: "pgup",
pagedown: "pgdn",
delete: "del",

View file

@ -82,16 +82,11 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create
const current = store.history.at(store.index)
if (!current) return undefined
if (current.text !== input && input.length) return
setStore(
produce((draft) => {
const next = store.index + direction
if (Math.abs(next) > store.history.length) return
if (next > 0) return
draft.index = next
}),
)
if (store.index === 0) return emptyPrompt()
return store.history.at(store.index)
const next = store.index + direction
if (Math.abs(next) > store.history.length || next > 0) return
setStore("index", next)
if (next === 0) return emptyPrompt()
return store.history.at(next)
},
append(item: PromptInfo) {
const entry = structuredClone(unwrap(item))