introduce opentui keymap as sole key/cmd engine (#26053)

This commit is contained in:
Sebastian
2026-05-07 20:35:31 +02:00
committed by GitHub
parent 474e311f6f
commit 98f5e6e713
67 changed files with 3858 additions and 2977 deletions

View File

@@ -22,19 +22,24 @@
"zod": "catalog:"
},
"peerDependencies": {
"@opentui/core": ">=0.2.2",
"@opentui/solid": ">=0.2.2"
"@opentui/core": ">=0.2.4",
"@opentui/keymap": ">=0.2.4",
"@opentui/solid": ">=0.2.4"
},
"peerDependenciesMeta": {
"@opentui/core": {
"optional": true
},
"@opentui/keymap": {
"optional": true
},
"@opentui/solid": {
"optional": true
}
},
"devDependencies": {
"@opentui/core": "catalog:",
"@opentui/keymap": "catalog:",
"@opentui/solid": "catalog:",
"@tsconfig/node22": "catalog:",
"@types/node": "catalog:",

View File

@@ -15,11 +15,39 @@ import type {
TextPart,
Config as SdkConfig,
} from "@opencode-ai/sdk/v2"
import type { CliRenderer, ParsedKey, RGBA, SlotMode } from "@opentui/core"
import type { CliRenderer, KeyEvent, RGBA, Renderable, SlotMode } from "@opentui/core"
import type { Binding, Keymap } from "@opentui/keymap"
import {
resolveBindingSections as resolveKeymapBindingSections,
type BindingSectionsConfig,
type KeySequenceFormatPart,
type SequenceBindingLike,
} from "@opentui/keymap/extras"
import type { JSX, SolidPlugin } from "@opentui/solid"
import type { Config as PluginConfig, PluginOptions } from "./index.js"
export type { CliRenderer, SlotMode } from "@opentui/core"
export type { CliRenderer, KeyEvent, Renderable, SlotMode } from "@opentui/core"
export { stringifyKeySequence, stringifyKeyStroke } from "@opentui/keymap"
export type { Binding, KeyLike, KeySequencePart, KeyStringifyInput, StringifyOptions } from "@opentui/keymap"
export { formatCommandBindings, formatKeySequence } from "@opentui/keymap/extras"
export type {
BindingSectionsConfig,
BindingValue,
FormatCommandBindingsOptions,
FormatKeySequenceOptions,
KeySequenceFormatPart,
SequenceBindingLike,
} from "@opentui/keymap/extras"
export function resolveBindingSections<Section extends string>(
config: BindingSectionsConfig<Renderable, KeyEvent> | undefined,
options: { sections: readonly Section[] },
) {
return resolveKeymapBindingSections<Renderable, KeyEvent, BindingSectionsConfig<Renderable, KeyEvent>, Section>(
config ?? {},
options,
)
}
export type TuiRouteCurrent =
| {
@@ -42,39 +70,12 @@ export type TuiRouteDefinition = {
render: (input: { params?: Record<string, unknown> }) => JSX.Element
}
export type TuiCommand = {
title: string
value: string
description?: string
category?: string
keybind?: string
suggested?: boolean
hidden?: boolean
enabled?: boolean
slash?: {
name: string
aliases?: string[]
}
onSelect?: () => void
export type TuiKeys = {
formatSequence: (parts: readonly KeySequenceFormatPart[] | undefined) => string
formatBindings: (bindings: readonly SequenceBindingLike[] | undefined) => string | undefined
}
export type TuiKeybind = {
name: string
ctrl: boolean
meta: boolean
shift: boolean
super?: boolean
leader: boolean
}
export type TuiKeybindMap = Record<string, string>
export type TuiKeybindSet = {
readonly all: TuiKeybindMap
get: (name: string) => string
match: (name: string, evt: ParsedKey) => boolean
print: (name: string) => string
}
export type TuiKeymap = Keymap<Renderable, KeyEvent>
export type TuiDialogProps = {
size?: "medium" | "large" | "xlarge"
@@ -288,6 +289,14 @@ export type TuiState = {
type TuiConfigView = Pick<PluginConfig, "$schema" | "theme" | "keybinds" | "plugin"> &
NonNullable<PluginConfig["tui"]> & {
plugin_enabled?: Record<string, boolean>
keymap: {
leader: string
leader_timeout: number
sections: Record<string, ReadonlyArray<Binding<Renderable, KeyEvent>>>
get: (section: string, cmd: string) => ReadonlyArray<Binding<Renderable, KeyEvent>> | undefined
pick: (section: string, commands: readonly string[]) => Binding<Renderable, KeyEvent>[]
omit: (section: string, commands: readonly string[]) => Binding<Renderable, KeyEvent>[]
}
}
export type TuiApp = {
@@ -448,11 +457,8 @@ export type TuiWorkspace = {
export type TuiPluginApi = {
app: TuiApp
command: {
register: (cb: () => TuiCommand[]) => () => void
trigger: (value: string) => void
show: () => void
}
keys: TuiKeys
keymap: TuiKeymap
route: {
register: (routes: TuiRouteDefinition[]) => () => void
navigate: (name: string, params?: Record<string, unknown>) => void
@@ -469,11 +475,6 @@ export type TuiPluginApi = {
toast: (input: TuiToast) => void
dialog: TuiDialogStack
}
keybind: {
match: (key: string, evt: ParsedKey) => boolean
print: (key: string) => string
create: (defaults: TuiKeybindMap, overrides?: Record<string, unknown>) => TuiKeybindSet
}
readonly tuiConfig: Frozen<TuiConfigView>
kv: TuiKV
state: TuiState