structure

This commit is contained in:
Sebastian Herrlinger
2026-05-07 22:42:45 +02:00
parent 968b6962bd
commit 29b7871552
4 changed files with 59 additions and 49 deletions

View File

@@ -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<string[]> }) {
const appCommands = createMemo(() =>
[
{
name: COMMAND_PALETTE_DIALOG,
name: COMMAND_PALETTE_COMMAND,
title: "Show command palette",
hidden: true,
run: () => {

View File

@@ -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<OpenTuiKeymap["getCommandEntries"]>[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 <DialogSelect ref={(value) => (ref = value)} title="Commands" options={list()} />
}
export function useCommandSlashes(): Accessor<readonly SlashEntry[]> {
const keymap = useOpencodeKeymap()
const entries = useKeymapSelector((keymap: OpenTuiKeymap) =>
keymap
.getCommandEntries({
visibility: "reachable",
namespace: "palette",
})
.filter(isVisiblePaletteCommand),
)
return createMemo<SlashEntry[]>(() =>
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),
}
}),
)
}

View File

@@ -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("#")

View File

@@ -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<typeof useKeymap>
type OpencodeModeStack = ReturnType<typeof createOpencodeModeStack>
type CommandSlashEntry = {
display: string
description?: string
aliases?: string[]
onSelect: () => void
}
type CommandEntry = ReturnType<OpenTuiKeymap["getCommandEntries"]>[number]
const modeStacks = new WeakMap<OpenTuiKeymap, OpencodeModeStack>()
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<string> {
export function useLeaderActive(): Accessor<boolean> {
return useKeymapSelector((keymap: OpenTuiKeymap) => keymap.getPendingSequence()[0]?.tokenName === LEADER_TOKEN)
}
export function useCommandSlashes(): Accessor<readonly CommandSlashEntry[]> {
const keymap = useOpencodeKeymap()
const entries = useKeymapSelector((keymap: OpenTuiKeymap) =>
keymap
.getCommandEntries({
visibility: "reachable",
namespace: "palette",
})
.filter(isVisiblePaletteCommand),
)
return createMemo<CommandSlashEntry[]>(() =>
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),
}
}),
)
}