Skip to content

Commit bb68dcb

Browse files
committed
STASH 2
1 parent 8a8c630 commit bb68dcb

5 files changed

Lines changed: 61 additions & 85 deletions

File tree

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime"
6464
import { createTuiApi } from "@/cli/cmd/tui/plugin/api"
6565
import type { RouteMap } from "@/cli/cmd/tui/plugin/api"
6666
import { FormatError, FormatUnknownError } from "@/cli/error"
67-
import { CommandPaletteProvider, useCommandPalette } from "./context/command-palette"
67+
import { CommandPaletteProvider } from "./context/command-palette"
6868
import {
6969
OPENCODE_BASE_MODE,
7070
OpencodeKeymapProvider,
@@ -233,7 +233,6 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
233233
const dialog = useDialog()
234234
const local = useLocal()
235235
const kv = useKV()
236-
const command = useCommandPalette()
237236
const keymap = useOpencodeKeymap()
238237
const event = useEvent()
239238
const sdk = useSDK()
@@ -405,14 +404,6 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
405404
const connected = useConnected()
406405
const appCommands = createMemo(() =>
407406
[
408-
{
409-
name: "command.palette.show",
410-
title: "Show command palette",
411-
hidden: true,
412-
run: () => {
413-
command.show()
414-
},
415-
},
416407
{
417408
name: "session.list",
418409
title: "Switch session",
@@ -761,7 +752,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
761752
}))
762753

763754
event.on(TuiEvent.CommandExecute.type, (evt) => {
764-
command.run(evt.properties.command)
755+
keymap.dispatchCommand(evt.properties.command)
765756
})
766757

767758
event.on(TuiEvent.ToastShow.type, (evt) => {

packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getScrollAcceleration } from "../../util/scroll"
1212
import { useTuiConfig } from "../../context/tui-config"
1313
import { useTheme, selectedForeground } from "@tui/context/theme"
1414
import { SplitBorder } from "@tui/component/border"
15-
import { useCommandPalette } from "../../context/command-palette"
15+
import { useCommandSlashes } from "../../context/command-palette"
1616
import { useTerminalDimensions } from "@opentui/solid"
1717
import { Locale } from "@/util/locale"
1818
import type { PromptInfo } from "./history"
@@ -82,7 +82,7 @@ export function Autocomplete(props: {
8282
const editor = useEditorContext()
8383
const sdk = useSDK()
8484
const sync = useSync()
85-
const command = useCommandPalette()
85+
const slashes = useCommandSlashes()
8686
const modeStack = useOpencodeModeStack()
8787
const { theme } = useTheme()
8888
const dimensions = useTerminalDimensions()
@@ -407,7 +407,7 @@ export function Autocomplete(props: {
407407
})
408408

409409
const commands = createMemo((): AutocompleteOption[] => {
410-
const results: AutocompleteOption[] = [...command.slashes()]
410+
const results: AutocompleteOption[] = [...slashes()]
411411

412412
for (const serverCommand of sync.data.command) {
413413
if (serverCommand.source === "skill") continue
Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { createContext, createMemo, useContext, type Accessor, type ParentProps } from "solid-js"
1+
import { createMemo, type Accessor, type ParentProps } from "solid-js"
22
import { DialogSelect, type DialogSelectRef } from "@tui/ui/dialog-select"
33
import { useDialog, type DialogContext } from "@tui/ui/dialog"
44
import {
55
formatKeyBindings,
66
type OpenTuiKeymap,
7+
useBindings,
78
useKeymapSelector,
89
useOpencodeKeymap,
910
} from "../keymap"
@@ -16,14 +17,7 @@ type SlashEntry = {
1617
onSelect: () => void
1718
}
1819

19-
type CommandPaletteContext = {
20-
run(command: string): void
21-
show(): void
22-
slashes: Accessor<readonly SlashEntry[]>
23-
}
24-
2520
const COMMAND_PALETTE_DIALOG = "command.palette.show"
26-
const ctx = createContext<CommandPaletteContext>()
2721
type PaletteCommandEntry = ReturnType<OpenTuiKeymap["getCommandEntries"]>[number]
2822

2923
function isVisiblePaletteCommand(entry: PaletteCommandEntry) {
@@ -39,60 +33,25 @@ function isSuggestedPaletteCommand(entry: PaletteCommandEntry) {
3933

4034
export function CommandPaletteProvider(props: ParentProps) {
4135
const dialog = useDialog()
42-
const keymap = useOpencodeKeymap()
43-
const entries = useKeymapSelector((keymap: OpenTuiKeymap) =>
44-
keymap
45-
.getCommandEntries({
46-
visibility: "reachable",
47-
namespace: "palette",
48-
})
49-
.filter(isVisiblePaletteCommand),
50-
)
51-
52-
const run = (command: string) => {
53-
keymap.dispatchCommand(command)
54-
}
55-
56-
const slashes = createMemo<SlashEntry[]>(() =>
57-
entries().flatMap((entry) => {
58-
const slashName = entry.command.slashName
59-
if (typeof slashName !== "string" || !slashName) return []
60-
const slashAliases = entry.command.slashAliases
61-
return {
62-
display: `/${slashName}`,
63-
description:
64-
typeof entry.command.desc === "string"
65-
? entry.command.desc
66-
: typeof entry.command.title === "string"
67-
? entry.command.title
68-
: undefined,
69-
aliases: Array.isArray(slashAliases)
70-
? slashAliases.filter((alias): alias is string => typeof alias === "string").map((alias) => `/${alias}`)
71-
: undefined,
72-
onSelect: () => run(entry.command.name),
73-
}
74-
}),
75-
)
76-
77-
const value: CommandPaletteContext = {
78-
run,
79-
show() {
80-
dialog.replace(() => <CommandPaletteDialog run={run} />)
81-
},
82-
slashes,
83-
}
84-
85-
return <ctx.Provider value={value}>{props.children}</ctx.Provider>
86-
}
36+
useBindings(() => ({
37+
commands: [
38+
{
39+
name: COMMAND_PALETTE_DIALOG,
40+
title: "Show command palette",
41+
hidden: true,
42+
run() {
43+
dialog.replace(() => <CommandPaletteDialog />)
44+
},
45+
},
46+
],
47+
}))
8748

88-
export function useCommandPalette() {
89-
const value = useContext(ctx)
90-
if (!value) throw new Error("CommandPalette context must be used within a CommandPaletteProvider")
91-
return value
49+
return <>{props.children}</>
9250
}
9351

94-
function CommandPaletteDialog(props: { run(command: string): void }) {
52+
function CommandPaletteDialog() {
9553
const config = useTuiConfig()
54+
const keymap = useOpencodeKeymap()
9655
const entries = useKeymapSelector((keymap: OpenTuiKeymap) => {
9756
const query = {
9857
namespace: "palette",
@@ -123,7 +82,7 @@ function CommandPaletteDialog(props: { run(command: string): void }) {
12382
suggested: isSuggestedPaletteCommand(entry),
12483
onSelect: (dialog: DialogContext) => {
12584
dialog.clear()
126-
props.run(entry.command.name)
85+
keymap.dispatchCommand(entry.command.name)
12786
},
12887
})),
12988
)
@@ -147,5 +106,34 @@ function CommandPaletteDialog(props: { run(command: string): void }) {
147106
}
148107

149108
export function useCommandSlashes(): Accessor<readonly SlashEntry[]> {
150-
return useCommandPalette().slashes
109+
const keymap = useOpencodeKeymap()
110+
const entries = useKeymapSelector((keymap: OpenTuiKeymap) =>
111+
keymap
112+
.getCommandEntries({
113+
visibility: "reachable",
114+
namespace: "palette",
115+
})
116+
.filter(isVisiblePaletteCommand),
117+
)
118+
119+
return createMemo<SlashEntry[]>(() =>
120+
entries().flatMap((entry) => {
121+
const slashName = entry.command.slashName
122+
if (typeof slashName !== "string" || !slashName) return []
123+
const slashAliases = entry.command.slashAliases
124+
return {
125+
display: `/${slashName}`,
126+
description:
127+
typeof entry.command.desc === "string"
128+
? entry.command.desc
129+
: typeof entry.command.title === "string"
130+
? entry.command.title
131+
: undefined,
132+
aliases: Array.isArray(slashAliases)
133+
? slashAliases.filter((alias): alias is string => typeof alias === "string").map((alias) => `/${alias}`)
134+
: undefined,
135+
onSelect: () => keymap.dispatchCommand(entry.command.name),
136+
}
137+
}),
138+
)
151139
}

packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime"
8888
import { DialogGoUpsell } from "../../component/dialog-go-upsell"
8989
import { SessionRetry } from "@/session/retry"
9090
import { getRevertDiffFiles } from "../../util/revert-diff"
91-
import { useCommandPalette } from "../../context/command-palette"
92-
import { OPENCODE_BASE_MODE, useBindings, useCommandShortcut } from "../../keymap"
91+
import { OPENCODE_BASE_MODE, useBindings, useCommandShortcut, useOpencodeKeymap } from "../../keymap"
9392

9493
addDefaultParsers(parsers.parsers)
9594

@@ -253,7 +252,7 @@ export function Session() {
253252
seeded = true
254253
r.set(route.prompt)
255254
}
256-
const command = useCommandPalette()
255+
const keymap = useOpencodeKeymap()
257256
const dialog = useDialog()
258257
const renderer = useRenderer()
259258

@@ -1066,7 +1065,6 @@ export function Session() {
10661065
<Switch>
10671066
<Match when={message.id === revert()?.messageID}>
10681067
{(function () {
1069-
const command = useCommandPalette()
10701068
const redoShortcut = useCommandShortcut("session.redo")
10711069
const [hover, setHover] = createSignal(false)
10721070
const dialog = useDialog()
@@ -1078,7 +1076,7 @@ export function Session() {
10781076
"Are you sure you want to restore the reverted messages?",
10791077
)
10801078
if (confirmed) {
1081-
command.run("session.redo")
1079+
keymap.dispatchCommand("session.redo")
10821080
}
10831081
}
10841082

packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import { SplitBorder } from "@tui/component/border"
66
import type { AssistantMessage } from "@opencode-ai/sdk/v2"
77
import { Locale } from "@/util/locale"
88
import { useTerminalDimensions } from "@opentui/solid"
9-
import { useCommandPalette } from "../../context/command-palette"
10-
import { useCommandShortcut } from "../../keymap"
9+
import { useCommandShortcut, useOpencodeKeymap } from "../../keymap"
1110

1211
export function SubagentFooter() {
1312
const route = useRouteData("session")
@@ -56,7 +55,7 @@ export function SubagentFooter() {
5655
})
5756

5857
const { theme } = useTheme()
59-
const command = useCommandPalette()
58+
const keymap = useOpencodeKeymap()
6059
const parentShortcut = useCommandShortcut("session.parent")
6160
const previousShortcut = useCommandShortcut("session.child.previous")
6261
const nextShortcut = useCommandShortcut("session.child.next")
@@ -98,7 +97,7 @@ export function SubagentFooter() {
9897
<box
9998
onMouseOver={() => setHover("parent")}
10099
onMouseOut={() => setHover(null)}
101-
onMouseUp={() => command.run("session.parent")}
100+
onMouseUp={() => keymap.dispatchCommand("session.parent")}
102101
backgroundColor={hover() === "parent" ? theme.backgroundElement : theme.backgroundPanel}
103102
>
104103
<text fg={theme.text}>
@@ -108,7 +107,7 @@ export function SubagentFooter() {
108107
<box
109108
onMouseOver={() => setHover("prev")}
110109
onMouseOut={() => setHover(null)}
111-
onMouseUp={() => command.run("session.child.previous")}
110+
onMouseUp={() => keymap.dispatchCommand("session.child.previous")}
112111
backgroundColor={hover() === "prev" ? theme.backgroundElement : theme.backgroundPanel}
113112
>
114113
<text fg={theme.text}>
@@ -118,7 +117,7 @@ export function SubagentFooter() {
118117
<box
119118
onMouseOver={() => setHover("next")}
120119
onMouseOut={() => setHover(null)}
121-
onMouseUp={() => command.run("session.child.next")}
120+
onMouseUp={() => keymap.dispatchCommand("session.child.next")}
122121
backgroundColor={hover() === "next" ? theme.backgroundElement : theme.backgroundPanel}
123122
>
124123
<text fg={theme.text}>

0 commit comments

Comments
 (0)