feat(tui): add managed config interface
This commit is contained in:
parent
1e17202413
commit
3568dd1b99
52 changed files with 848 additions and 266 deletions
|
|
@ -4,7 +4,6 @@ import { createTestRenderer } from "@opentui/core/testing"
|
|||
import { Effect } from "effect"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { createTuiResolvedConfig } from "./fixture/tui-runtime"
|
||||
import { createEventStream, createFetch, directory, json } from "./fixture/tui-sdk"
|
||||
|
||||
test("SIGHUP clears title and disposes scoped resources once", async () => {
|
||||
|
|
@ -32,7 +31,7 @@ test("SIGHUP clears title and disposes scoped resources once", async () => {
|
|||
const task = Effect.runPromise(
|
||||
run({
|
||||
server: { endpoint: { url: server.url.toString() } },
|
||||
config: createTuiResolvedConfig({ plugin_enabled: {} }),
|
||||
config: { get: async () => ({}), update: async () => ({}) },
|
||||
args: {},
|
||||
log: () => {},
|
||||
pluginHost: {
|
||||
|
|
@ -118,7 +117,7 @@ test("session lifecycle updates the terminal title and prints the epilogue after
|
|||
const task = Effect.runPromise(
|
||||
run({
|
||||
server: { endpoint: { url: server.url.toString() } },
|
||||
config: createTuiResolvedConfig({ plugin_enabled: {} }),
|
||||
config: { get: async () => ({}), update: async () => ({}) },
|
||||
args: { sessionID: "dummy" },
|
||||
log: () => {},
|
||||
pluginHost: {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import path from "node:path"
|
|||
import { onCleanup } from "solid-js"
|
||||
import { tmpdir } from "../../fixture/fixture"
|
||||
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
|
||||
import type { TuiKeybind } from "../../../src/config/v1/keybind"
|
||||
import type { TuiKeybind } from "../../../src/config/keybind"
|
||||
import { TestTuiContexts } from "../../fixture/tui-environment"
|
||||
|
||||
async function wait(fn: () => boolean, timeout = 2000) {
|
||||
|
|
@ -41,7 +41,7 @@ async function mountPrompt(input: {
|
|||
import("../../../src/ui/dialog-prompt"),
|
||||
import("../../../src/context/kv"),
|
||||
import("../../../src/context/theme"),
|
||||
import("../../../src/config/v1"),
|
||||
import("../../../src/config"),
|
||||
import("../../../src/ui/toast"),
|
||||
import("../../../src/keymap"),
|
||||
])
|
||||
|
|
@ -51,7 +51,7 @@ async function mountPrompt(input: {
|
|||
const keymap = createDefaultOpenTuiKeymap(renderer)
|
||||
const resolvedConfig = createTuiResolvedConfig({
|
||||
keybinds: input.keybinds,
|
||||
leader_timeout: 1000,
|
||||
leader: { timeout: 1000 },
|
||||
})
|
||||
const off = registerOpencodeKeymap(keymap, renderer, resolvedConfig)
|
||||
onCleanup(off)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type { JSX } from "solid-js"
|
|||
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
|
||||
import { KVProvider } from "../../../src/context/kv"
|
||||
import { ThemeProvider } from "../../../src/context/theme"
|
||||
import { TuiConfigProvider } from "../../../src/config/v1"
|
||||
import { TuiConfigProvider } from "../../../src/config"
|
||||
import { DiffViewerFileTree } from "../../../src/feature-plugins/system/diff-viewer-file-tree"
|
||||
import { TestTuiContexts } from "../../fixture/tui-environment"
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import type { TuiPluginApi, TuiPluginMeta, TuiRouteCurrent, TuiRouteDefinition }
|
|||
import type { Session } from "@opencode-ai/sdk/v2"
|
||||
import { KVProvider } from "../../../src/context/kv"
|
||||
import { ThemeProvider } from "../../../src/context/theme"
|
||||
import { TuiConfigProvider } from "../../../src/config/v1"
|
||||
import { TuiConfigProvider } from "../../../src/config"
|
||||
import { SDKProvider } from "../../../src/context/sdk"
|
||||
import { TuiKeybind } from "../../../src/config/v1/keybind"
|
||||
import { TuiKeybind } from "../../../src/config/keybind"
|
||||
import { OpencodeKeymapProvider } from "../../../src/keymap"
|
||||
import diffViewerPlugin from "../../../src/feature-plugins/system/diff-viewer"
|
||||
import { createTuiPluginApi } from "../../fixture/tui-plugin"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import type { FormWithLocation } from "../../../src/context/data"
|
|||
import { KVProvider } from "../../../src/context/kv"
|
||||
import { SDKProvider } from "../../../src/context/sdk"
|
||||
import { ThemeProvider } from "../../../src/context/theme"
|
||||
import { TuiConfigProvider } from "../../../src/config/v1"
|
||||
import { TuiConfigProvider } from "../../../src/config"
|
||||
import { OpencodeKeymapProvider, registerOpencodeKeymap } from "../../../src/keymap"
|
||||
import { ToastProvider } from "../../../src/ui/toast"
|
||||
import { tmpdir } from "../../fixture/fixture"
|
||||
|
|
|
|||
67
packages/tui/test/config-v2.test.tsx
Normal file
67
packages/tui/test/config-v2.test.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/** @jsxImportSource @opentui/solid */
|
||||
import { testRender } from "@opentui/solid"
|
||||
import { expect, test } from "bun:test"
|
||||
import {
|
||||
resolve,
|
||||
TuiConfigProvider,
|
||||
useTuiConfig,
|
||||
useTuiConfigService,
|
||||
type Interface,
|
||||
} from "../src/config"
|
||||
|
||||
test("resolves nested config and keybind defaults", () => {
|
||||
const config = resolve(
|
||||
{
|
||||
keybinds: { leader: "ctrl+o" },
|
||||
leader: { timeout: 500 },
|
||||
scroll: { speed: 2, acceleration: true },
|
||||
diffs: { view: "split" },
|
||||
},
|
||||
{ terminalSuspend: true },
|
||||
)
|
||||
|
||||
expect(config.leader.timeout).toBe(500)
|
||||
expect(config.keybinds.get("leader")?.[0]?.key).toBe("ctrl+o")
|
||||
expect(config.scroll).toEqual({ speed: 2, acceleration: true })
|
||||
expect(config.diffs).toEqual({ view: "split" })
|
||||
})
|
||||
|
||||
test("provides config and its host interface", async () => {
|
||||
const config = resolve({}, { terminalSuspend: true })
|
||||
let current = {}
|
||||
const service: Interface = {
|
||||
get: async () => current,
|
||||
update: async (update) => {
|
||||
const draft: Record<string, any> = { ...current }
|
||||
update(draft)
|
||||
current = draft
|
||||
return draft
|
||||
},
|
||||
}
|
||||
let configService: Interface | undefined
|
||||
|
||||
function Consumer() {
|
||||
const config = useTuiConfig()
|
||||
configService = useTuiConfigService()
|
||||
return <text>{`${config.mouse ? "mouse" : "none"} ${config.keybinds.get("leader")?.[0]?.key}`}</text>
|
||||
}
|
||||
|
||||
const app = await testRender(() => (
|
||||
<TuiConfigProvider config={config} service={service}>
|
||||
<Consumer />
|
||||
</TuiConfigProvider>
|
||||
))
|
||||
try {
|
||||
await app.renderOnce()
|
||||
expect(app.captureCharFrame()).toContain("mouse ctrl+x")
|
||||
if (!configService) throw new Error("Config service was not provided")
|
||||
await configService.update((draft) => {
|
||||
draft.mouse = false
|
||||
draft.keybinds = { leader: "ctrl+o" }
|
||||
})
|
||||
await app.renderOnce()
|
||||
expect(app.captureCharFrame()).toContain("none ctrl+o")
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { resolve, type Info, type Resolved } from "../../src/config/v1"
|
||||
import { TuiKeybind } from "../../src/config/v1/keybind"
|
||||
import { resolve, type Info, type Resolved } from "../../src/config"
|
||||
import { TuiKeybind } from "../../src/config/keybind"
|
||||
|
||||
type ResolvedInput = Omit<Info, "attention" | "keybinds" | "leader_timeout"> & {
|
||||
type ResolvedInput = Omit<Info, "attention" | "keybinds" | "leader"> & {
|
||||
attention?: Partial<Resolved["attention"]>
|
||||
keybinds?: Partial<TuiKeybind.Keybinds>
|
||||
leader_timeout?: number
|
||||
leader?: { timeout?: number }
|
||||
}
|
||||
|
||||
export function createTuiResolvedConfig(input: ResolvedInput = {}) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { createBindingLookup } from "@opentui/keymap/extras"
|
|||
import { testRender, useRenderer } from "@opentui/solid"
|
||||
import { expect, test } from "bun:test"
|
||||
import { onCleanup } from "solid-js"
|
||||
import { TuiKeybind } from "../src/config/v1/keybind"
|
||||
import { TuiKeybind } from "../src/config/keybind"
|
||||
import {
|
||||
formatKeySequence,
|
||||
getOpencodeModeStack,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue