mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 00:03:01 +03:00
fix(tui): clear stale composer placeholder
This commit is contained in:
@@ -137,6 +137,30 @@ describe("NanobotTui layout", () => {
|
||||
expect(sent).toEqual(["你好"])
|
||||
})
|
||||
|
||||
test("clears the placeholder on the first typed character", async () => {
|
||||
setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" })
|
||||
const app = mount(setup)
|
||||
const composer = (app as unknown as { composer: TextareaRenderable }).composer
|
||||
await setup.renderOnce()
|
||||
expect(setup.captureCharFrame()).toContain("Ask nanobot anything")
|
||||
|
||||
setup.mockInput.typeText("bu")
|
||||
await setup.flush()
|
||||
const frame = setup.captureCharFrame()
|
||||
|
||||
expect(composer.plainText).toBe("bu")
|
||||
expect(composer.placeholder).toBeNull()
|
||||
expect(frame).toContain("bu")
|
||||
expect(frame).not.toContain("Ask nanobot anything")
|
||||
expect(frame).not.toContain("buAsk nanobot anything")
|
||||
|
||||
setup.mockInput.pressBackspace()
|
||||
setup.mockInput.pressBackspace()
|
||||
await setup.flush()
|
||||
expect(composer.placeholder).toBe("Ask nanobot anything")
|
||||
expect(setup.captureCharFrame()).toContain("Ask nanobot anything")
|
||||
})
|
||||
|
||||
test("recalls submitted prompts without stealing multiline cursor movement", async () => {
|
||||
const sent: string[] = []
|
||||
setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" })
|
||||
|
||||
+15
-2
@@ -82,6 +82,8 @@ const LIGHT: Palette = {
|
||||
cool: "#0F766E",
|
||||
}
|
||||
|
||||
const COMPOSER_PLACEHOLDER = "Ask nanobot anything"
|
||||
|
||||
function syntaxStyle(palette: Palette): SyntaxStyle {
|
||||
const color = (value: string) => {
|
||||
const parsed = RGBA.fromHex(value)
|
||||
@@ -231,7 +233,7 @@ export class NanobotTui {
|
||||
minHeight: 1,
|
||||
maxHeight: 8,
|
||||
wrapMode: "word",
|
||||
placeholder: "Ask nanobot anything",
|
||||
placeholder: COMPOSER_PLACEHOLDER,
|
||||
placeholderColor: this.palette.faint,
|
||||
textColor: this.palette.text,
|
||||
focusedTextColor: this.palette.text,
|
||||
@@ -243,7 +245,10 @@ export class NanobotTui {
|
||||
{ name: "return", action: "submit" },
|
||||
{ name: "return", meta: true, action: "newline" },
|
||||
],
|
||||
onContentChange: () => this.resizeComposer(),
|
||||
onContentChange: () => {
|
||||
this.syncComposerPlaceholder()
|
||||
this.resizeComposer()
|
||||
},
|
||||
// IMEs may commit their final composed glyph after Enter. Matching the
|
||||
// OpenCode/OpenTUI integration, defer twice before reading plainText.
|
||||
onSubmit: () => this.deferSubmit(),
|
||||
@@ -673,6 +678,14 @@ export class NanobotTui {
|
||||
this.composerFrame.maxHeight = maxHeight + 2
|
||||
}
|
||||
|
||||
private syncComposerPlaceholder(): void {
|
||||
// OpenTUI normally suppresses placeholder glyphs while the editor is not
|
||||
// empty. Explicitly removing them also invalidates their old cells, which
|
||||
// prevents stale placeholder text in differential/embedded terminals.
|
||||
const placeholder = this.composer.plainText ? null : COMPOSER_PLACEHOLDER
|
||||
if (this.composer.placeholder !== placeholder) this.composer.placeholder = placeholder
|
||||
}
|
||||
|
||||
private async copySelection(text: string): Promise<void> {
|
||||
if (!text) return
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user