introduce opentui keymap as sole key/cmd engine (#26053)
This commit is contained in:
@@ -1,10 +1,27 @@
|
||||
import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
||||
import { createMemo, Show } from "solid-js"
|
||||
import { Tips } from "./tips-view"
|
||||
import { useBindings } from "../../keymap"
|
||||
|
||||
const id = "internal:home-tips"
|
||||
|
||||
function View(props: { show: boolean; connected: boolean }) {
|
||||
function View(props: { api: TuiPluginApi; hidden: boolean; show: boolean; connected: boolean }) {
|
||||
useBindings(() => ({
|
||||
commands: [
|
||||
{
|
||||
name: "tips.toggle",
|
||||
title: props.hidden ? "Show tips" : "Hide tips",
|
||||
category: "System",
|
||||
namespace: "palette",
|
||||
run() {
|
||||
props.api.kv.set("tips_hidden", !props.api.kv.get("tips_hidden", false))
|
||||
props.api.ui.dialog.clear()
|
||||
},
|
||||
},
|
||||
],
|
||||
bindings: props.api.tuiConfig.keymap.sections.home_tips,
|
||||
}))
|
||||
|
||||
return (
|
||||
<box height={4} minHeight={0} width="100%" maxWidth={75} alignItems="center" paddingTop={3} flexShrink={1}>
|
||||
<Show when={props.show}>
|
||||
@@ -15,20 +32,6 @@ function View(props: { show: boolean; connected: boolean }) {
|
||||
}
|
||||
|
||||
const tui: TuiPlugin = async (api) => {
|
||||
api.command.register(() => [
|
||||
{
|
||||
title: api.kv.get("tips_hidden", false) ? "Show tips" : "Hide tips",
|
||||
value: "tips.toggle",
|
||||
keybind: "tips_toggle",
|
||||
category: "System",
|
||||
hidden: api.route.current.name !== "home",
|
||||
onSelect() {
|
||||
api.kv.set("tips_hidden", !api.kv.get("tips_hidden", false))
|
||||
api.ui.dialog.clear()
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
api.slots.register({
|
||||
order: 100,
|
||||
slots: {
|
||||
@@ -41,7 +44,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
),
|
||||
)
|
||||
const show = createMemo(() => (!first() || !connected()) && !hidden())
|
||||
return <View show={show()} connected={connected()} />
|
||||
return <View api={api} hidden={hidden()} show={show()} connected={connected()} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { Keybind } from "@/util/keybind"
|
||||
import type { TuiPlugin, TuiPluginApi, TuiPluginModule, TuiPluginStatus } from "@opencode-ai/plugin/tui"
|
||||
import { useKeyboard, useTerminalDimensions } from "@opentui/solid"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { fileURLToPath } from "url"
|
||||
import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
|
||||
import { Show, createEffect, createMemo, createSignal } from "solid-js"
|
||||
import { useBindings } from "../../keymap"
|
||||
|
||||
const id = "internal:plugin-manager"
|
||||
const key = Keybind.parse("space").at(0)
|
||||
const add = Keybind.parse("shift+i").at(0)
|
||||
const tab = Keybind.parse("tab").at(0)
|
||||
|
||||
function state(api: TuiPluginApi, item: TuiPluginStatus) {
|
||||
if (!item.enabled) {
|
||||
@@ -41,13 +38,10 @@ function Install(props: { api: TuiPluginApi }) {
|
||||
const [global, setGlobal] = createSignal(false)
|
||||
const [busy, setBusy] = createSignal(false)
|
||||
|
||||
useKeyboard((evt) => {
|
||||
if (evt.name !== "tab") return
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
if (busy()) return
|
||||
setGlobal((x) => !x)
|
||||
})
|
||||
useBindings(() => ({
|
||||
enabled: !busy(),
|
||||
bindings: [{ key: "tab", cmd: () => setGlobal((value) => !value) }],
|
||||
}))
|
||||
|
||||
return (
|
||||
<props.api.ui.DialogPrompt
|
||||
@@ -62,7 +56,7 @@ function Install(props: { api: TuiPluginApi }) {
|
||||
{global() ? "global" : "local"}
|
||||
</text>
|
||||
<Show when={!busy()}>
|
||||
<text fg={props.api.theme.current.textMuted}>({Keybind.toString(tab)} toggle)</text>
|
||||
<text fg={props.api.theme.current.textMuted}>(tab toggle)</text>
|
||||
</Show>
|
||||
</box>
|
||||
)}
|
||||
@@ -209,10 +203,10 @@ function View(props: { api: TuiPluginApi }) {
|
||||
options={rows()}
|
||||
current={cur()}
|
||||
onMove={(item) => setCur(item.value)}
|
||||
keybind={[
|
||||
actions={[
|
||||
{
|
||||
title: "toggle",
|
||||
keybind: key,
|
||||
command: "dialog.action.toggle",
|
||||
disabled: lock(),
|
||||
onTrigger: (item) => {
|
||||
setCur(item.value)
|
||||
@@ -221,13 +215,14 @@ function View(props: { api: TuiPluginApi }) {
|
||||
},
|
||||
{
|
||||
title: "install",
|
||||
keybind: add,
|
||||
command: "plugin.dialog.install",
|
||||
disabled: lock(),
|
||||
onTrigger: () => {
|
||||
showInstall(props.api)
|
||||
},
|
||||
},
|
||||
]}
|
||||
bindings={props.api.tuiConfig.keymap.pick("plugins", ["plugin.dialog.install"])}
|
||||
onSelect={(item) => {
|
||||
setCur(item.value)
|
||||
flip(item.value)
|
||||
@@ -241,25 +236,29 @@ function show(api: TuiPluginApi) {
|
||||
}
|
||||
|
||||
const tui: TuiPlugin = async (api) => {
|
||||
api.command.register(() => [
|
||||
{
|
||||
title: "Plugins",
|
||||
value: "plugins.list",
|
||||
keybind: "plugin_manager",
|
||||
category: "System",
|
||||
onSelect() {
|
||||
show(api)
|
||||
api.keymap.registerLayer({
|
||||
commands: [
|
||||
{
|
||||
name: "plugins.list",
|
||||
title: "Plugins",
|
||||
category: "System",
|
||||
namespace: "palette",
|
||||
run() {
|
||||
show(api)
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Install plugin",
|
||||
value: "plugins.install",
|
||||
category: "System",
|
||||
onSelect() {
|
||||
showInstall(api)
|
||||
{
|
||||
name: "plugins.install",
|
||||
title: "Install plugin",
|
||||
category: "System",
|
||||
namespace: "palette",
|
||||
run() {
|
||||
showInstall(api)
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
],
|
||||
bindings: api.tuiConfig.keymap.omit("plugins", ["plugin.dialog.install"]),
|
||||
})
|
||||
}
|
||||
|
||||
const plugin: TuiPluginModule & { id: string } = {
|
||||
|
||||
@@ -4,8 +4,9 @@ import { SplitBorder } from "@tui/component/border"
|
||||
import { Spinner } from "@tui/component/spinner"
|
||||
import { useTheme } from "@tui/context/theme"
|
||||
import { useLocal } from "@tui/context/local"
|
||||
import { useKeyboard, useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
||||
import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
||||
import { TextAttributes, type BoxRenderable, type SyntaxStyle } from "@opentui/core"
|
||||
import { useBindings } from "../../keymap"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
|
||||
import path from "path"
|
||||
@@ -53,12 +54,16 @@ function View(props: { api: TuiPluginApi; sessionID: string }) {
|
||||
void sync.session.message.sync(props.sessionID)
|
||||
})
|
||||
|
||||
useKeyboard((event) => {
|
||||
if (event.name !== "escape") return
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
props.api.route.navigate("session", { sessionID: props.sessionID })
|
||||
})
|
||||
useBindings(() => ({
|
||||
bindings: [
|
||||
{
|
||||
key: "escape",
|
||||
cmd() {
|
||||
props.api.route.navigate("session", { sessionID: props.sessionID })
|
||||
},
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
return (
|
||||
<box width={dimensions().width} height={dimensions().height} backgroundColor={theme.background}>
|
||||
@@ -1113,21 +1118,24 @@ const tui: TuiPlugin = async (api) => {
|
||||
},
|
||||
])
|
||||
|
||||
api.command.register(() => [
|
||||
{
|
||||
title: "View v2 session messages",
|
||||
value: route,
|
||||
category: "Debug",
|
||||
suggested: api.route.current.name === "session",
|
||||
enabled: api.route.current.name === "session",
|
||||
onSelect() {
|
||||
const sessionID = currentSessionID(api)
|
||||
if (!sessionID) return
|
||||
api.route.navigate(route, { sessionID })
|
||||
api.ui.dialog.clear()
|
||||
api.keymap.registerLayer({
|
||||
commands: [
|
||||
{
|
||||
name: route,
|
||||
title: "View v2 session messages",
|
||||
category: "Debug",
|
||||
namespace: "palette",
|
||||
suggested: () => api.route.current.name === "session",
|
||||
enabled: () => api.route.current.name === "session",
|
||||
run() {
|
||||
const sessionID = currentSessionID(api)
|
||||
if (!sessionID) return
|
||||
api.route.navigate(route, { sessionID })
|
||||
api.ui.dialog.clear()
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const plugin: TuiPluginModule & { id: string } = {
|
||||
|
||||
Reference in New Issue
Block a user