소스 검색

feat(tui): make prompt size responsive and configurable (#28255)

Braxton Schafer 3 달 전
부모
커밋
0de5f1ff36

+ 8 - 2
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

@@ -1464,11 +1464,15 @@ export function Prompt(props: PromptProps) {
       }),
     }
   })
+  const maxHeight = createMemo(
+    () => tuiConfig.prompt?.max_height ?? Math.max(6, Math.floor(dimensions().height / 3)),
+  )
 
   return (
     <>
-      <box ref={(r: BoxRenderable) => (anchor = r)} visible={props.visible !== false}>
+      <box ref={(r: BoxRenderable) => (anchor = r)} visible={props.visible !== false} width="100%">
         <box
+          width="100%"
           border={["left"]}
           borderColor={borderHighlight()}
           customBorderChars={{
@@ -1483,14 +1487,16 @@ export function Prompt(props: PromptProps) {
             flexShrink={0}
             backgroundColor={theme.backgroundElement}
             flexGrow={1}
+            width="100%"
           >
             <textarea
+              width="100%"
               placeholder={placeholderText()}
               placeholderColor={theme.textMuted}
               textColor={leader() ? theme.textMuted : theme.text}
               focusedTextColor={leader() ? theme.textMuted : theme.text}
               minHeight={1}
-              maxHeight={6}
+              maxHeight={maxHeight()}
               onContentChange={() => {
                 const value = input.plainText
                 setStore("prompt", "input", value)

+ 10 - 0
packages/opencode/src/cli/cmd/tui/config/tui-schema.ts

@@ -61,6 +61,15 @@ export const Attention = Schema.Struct({
   sounds: Schema.optional(TuiAttentionSounds),
 }).annotate({ description: "Attention notification and sound settings" })
 
+const PromptSize = Schema.Int.check(Schema.isGreaterThan(0))
+
+export const Prompt = Schema.Struct({
+  max_height: Schema.optional(PromptSize).annotate({ description: "Prompt textarea max height" }),
+  max_width: Schema.optional(Schema.Union([PromptSize, Schema.Literal("auto")])).annotate({
+    description: "Home prompt max width: a positive integer for a fixed cap, or 'auto' to scale with terminal width",
+  }),
+}).annotate({ description: "Prompt size settings" })
+
 export const TuiInfo = Schema.Struct({
   $schema: Schema.optional(Schema.String),
   theme: Schema.optional(Schema.String),
@@ -69,6 +78,7 @@ export const TuiInfo = Schema.Struct({
   plugin_enabled: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)),
   leader_timeout: Schema.optional(KeymapLeaderTimeout),
   attention: Schema.optional(Attention),
+  prompt: Schema.optional(Prompt),
   scroll_speed: Schema.optional(ScrollSpeed).annotate({
     description: "TUI scroll speed",
   }),

+ 11 - 2
packages/opencode/src/cli/cmd/tui/routes/home.tsx

@@ -1,5 +1,5 @@
 import { Prompt, type PromptRef } from "@tui/component/prompt"
-import { createEffect, createSignal, onMount } from "solid-js"
+import { createEffect, createMemo, createSignal, onMount } from "solid-js"
 import { Logo } from "../component/logo"
 import { useSync } from "../context/sync"
 import { Toast } from "../ui/toast"
@@ -9,6 +9,8 @@ import { usePromptRef } from "../context/prompt"
 import { useLocal } from "../context/local"
 import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime"
 import { useEditorContext } from "@tui/context/editor"
+import { useTerminalDimensions } from "@opentui/solid"
+import { useTuiConfig } from "../context/tui-config"
 
 let once = false
 const placeholder = {
@@ -24,6 +26,13 @@ export function Home() {
   const args = useArgs()
   const local = useLocal()
   const editor = useEditorContext()
+  const dimensions = useTerminalDimensions()
+  const tuiConfig = useTuiConfig()
+  const promptMaxWidth = createMemo(() => {
+    const configured = tuiConfig.prompt?.max_width
+    if (configured === "auto") return Math.max(75, Math.floor(dimensions().width * 0.7))
+    return configured ?? 75
+  })
   let sent = false
 
   onMount(() => {
@@ -67,7 +76,7 @@ export function Home() {
           </TuiPluginRuntime.Slot>
         </box>
         <box height={1} minHeight={0} flexShrink={1} />
-        <box width="100%" maxWidth={75} zIndex={1000} paddingTop={1} flexShrink={0}>
+        <box width="100%" maxWidth={promptMaxWidth()} zIndex={1000} paddingTop={1} flexShrink={0}>
           <TuiPluginRuntime.Slot name="home_prompt" mode="replace" ref={bind}>
             <Prompt ref={bind} right={<TuiPluginRuntime.Slot name="home_prompt_right" />} placeholders={placeholder} />
           </TuiPluginRuntime.Slot>