From 29b78715528f3dff8398b2f8a94020f2d030e1f2 Mon Sep 17 00:00:00 2001 From: Sebastian Herrlinger Date: Thu, 7 May 2026 22:42:45 +0200 Subject: [PATCH] structure --- packages/opencode/src/cli/cmd/tui/app.tsx | 5 +- .../cli/cmd/tui/component/command-palette.tsx | 53 ++++--------------- .../cmd/tui/component/prompt/autocomplete.tsx | 3 +- packages/opencode/src/cli/cmd/tui/keymap.tsx | 47 +++++++++++++++- 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 8c868db0bc..1ed522e999 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -64,8 +64,9 @@ import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime" import { createTuiApi } from "@/cli/cmd/tui/plugin/api" import type { RouteMap } from "@/cli/cmd/tui/plugin/api" import { FormatError, FormatUnknownError } from "@/cli/error" -import { COMMAND_PALETTE_DIALOG, CommandPaletteDialog } from "./component/command-palette" +import { CommandPaletteDialog } from "./component/command-palette" import { + COMMAND_PALETTE_COMMAND, OPENCODE_BASE_MODE, OpencodeKeymapProvider, createOpencodeModeStack, @@ -403,7 +404,7 @@ function App(props: { onSnapshot?: () => Promise }) { const appCommands = createMemo(() => [ { - name: COMMAND_PALETTE_DIALOG, + name: COMMAND_PALETTE_COMMAND, title: "Show command palette", hidden: true, run: () => { diff --git a/packages/opencode/src/cli/cmd/tui/component/command-palette.tsx b/packages/opencode/src/cli/cmd/tui/component/command-palette.tsx index 684c408bdb..ba2b1ebdc7 100644 --- a/packages/opencode/src/cli/cmd/tui/component/command-palette.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/command-palette.tsx @@ -1,21 +1,19 @@ -import { createMemo, type Accessor } from "solid-js" +import { createMemo } from "solid-js" import { DialogSelect, type DialogSelectRef } from "@tui/ui/dialog-select" import { type DialogContext } from "@tui/ui/dialog" -import { formatKeyBindings, type OpenTuiKeymap, useKeymapSelector, useOpencodeKeymap } from "../keymap" +import { + COMMAND_PALETTE_COMMAND, + formatKeyBindings, + type OpenTuiKeymap, + useKeymapSelector, + useOpencodeKeymap, +} from "../keymap" import { useTuiConfig } from "../context/tui-config" -type SlashEntry = { - display: string - description?: string - aliases?: string[] - onSelect: () => void -} - -export const COMMAND_PALETTE_DIALOG = "command.palette.show" type PaletteCommandEntry = ReturnType[number] function isVisiblePaletteCommand(entry: PaletteCommandEntry) { - return entry.command.hidden !== true && entry.command.name !== COMMAND_PALETTE_DIALOG + return entry.command.hidden !== true && entry.command.name !== COMMAND_PALETTE_COMMAND } function isSuggestedPaletteCommand(entry: PaletteCommandEntry) { @@ -80,36 +78,3 @@ export function CommandPaletteDialog() { return (ref = value)} title="Commands" options={list()} /> } - -export function useCommandSlashes(): Accessor { - const keymap = useOpencodeKeymap() - const entries = useKeymapSelector((keymap: OpenTuiKeymap) => - keymap - .getCommandEntries({ - visibility: "reachable", - namespace: "palette", - }) - .filter(isVisiblePaletteCommand), - ) - - return createMemo(() => - entries().flatMap((entry) => { - const slashName = entry.command.slashName - if (typeof slashName !== "string" || !slashName) return [] - const slashAliases = entry.command.slashAliases - return { - display: `/${slashName}`, - description: - typeof entry.command.desc === "string" - ? entry.command.desc - : typeof entry.command.title === "string" - ? entry.command.title - : undefined, - aliases: Array.isArray(slashAliases) - ? slashAliases.filter((alias): alias is string => typeof alias === "string").map((alias) => `/${alias}`) - : undefined, - onSelect: () => keymap.dispatchCommand(entry.command.name), - } - }), - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 052f1af63a..d8f9d1f977 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -12,12 +12,11 @@ import { getScrollAcceleration } from "../../util/scroll" import { useTuiConfig } from "../../context/tui-config" import { useTheme, selectedForeground } from "@tui/context/theme" import { SplitBorder } from "@tui/component/border" -import { useCommandSlashes } from "../command-palette" import { useTerminalDimensions } from "@opentui/solid" import { Locale } from "@/util/locale" import type { PromptInfo } from "./history" import { useFrecency } from "./frecency" -import { useBindings, useOpencodeModeStack } from "../../keymap" +import { useBindings, useCommandSlashes, useOpencodeModeStack } from "../../keymap" function removeLineRange(input: string) { const hashIndex = input.lastIndexOf("#") diff --git a/packages/opencode/src/cli/cmd/tui/keymap.tsx b/packages/opencode/src/cli/cmd/tui/keymap.tsx index 554f79ce54..165fbf0085 100644 --- a/packages/opencode/src/cli/cmd/tui/keymap.tsx +++ b/packages/opencode/src/cli/cmd/tui/keymap.tsx @@ -10,12 +10,13 @@ import { useKeymap, useKeymapSelector, } from "@opentui/keymap/solid" -import type { Accessor } from "solid-js" +import { createMemo, type Accessor } from "solid-js" import type { TuiConfig } from "./config/tui" import { useTuiConfig } from "./context/tui-config" export const LEADER_TOKEN = "leader" export const OPENCODE_BASE_MODE = "base" +export const COMMAND_PALETTE_COMMAND = "command.palette.show" const OPENCODE_MODE_KEY = "opencode.mode" @@ -26,9 +27,20 @@ export { useBindings, useKeymapSelector } export type OpenTuiKeymap = ReturnType type OpencodeModeStack = ReturnType +type CommandSlashEntry = { + display: string + description?: string + aliases?: string[] + onSelect: () => void +} +type CommandEntry = ReturnType[number] const modeStacks = new WeakMap() +function isVisiblePaletteCommand(entry: CommandEntry) { + return entry.command.hidden !== true && entry.command.name !== COMMAND_PALETTE_COMMAND +} + export function createOpencodeModeStack(keymap: OpenTuiKeymap) { keymap.setData(OPENCODE_MODE_KEY, OPENCODE_BASE_MODE) @@ -145,3 +157,36 @@ export function useCommandShortcut(command: string): Accessor { export function useLeaderActive(): Accessor { return useKeymapSelector((keymap: OpenTuiKeymap) => keymap.getPendingSequence()[0]?.tokenName === LEADER_TOKEN) } + +export function useCommandSlashes(): Accessor { + const keymap = useOpencodeKeymap() + const entries = useKeymapSelector((keymap: OpenTuiKeymap) => + keymap + .getCommandEntries({ + visibility: "reachable", + namespace: "palette", + }) + .filter(isVisiblePaletteCommand), + ) + + return createMemo(() => + entries().flatMap((entry) => { + const slashName = entry.command.slashName + if (typeof slashName !== "string" || !slashName) return [] + const slashAliases = entry.command.slashAliases + return { + display: `/${slashName}`, + description: + typeof entry.command.desc === "string" + ? entry.command.desc + : typeof entry.command.title === "string" + ? entry.command.title + : undefined, + aliases: Array.isArray(slashAliases) + ? slashAliases.filter((alias): alias is string => typeof alias === "string").map((alias) => `/${alias}`) + : undefined, + onSelect: () => keymap.dispatchCommand(entry.command.name), + } + }), + ) +}