gemini-cli - ✅(Solved) Fix Bug: input prompt clips the last character of a line whose width exactly matches the prompt width [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
google-gemini/gemini-cli#26212Fetched 2026-04-30 06:44:25
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2labeled ×1

When the input line fills the prompt width exactly and the user keeps typing, the new character + cursor become invisible. The buffer is correct — pressing Enter submits the full text including the invisible suffix — so this is a pure rendering issue.

Root Cause

VirtualizedList (used by ScrollableList to render the input lines when ui.terminalBuffer: true) applies paddingRight: 1 for its scroll gutter (packages/cli/src/ui/components/shared/VirtualizedList.tsx:738). The input prompt was passing width={inputWidth} to ScrollableList (packages/cli/src/ui/components/InputPrompt.tsx:1865), so the inner content area was inputWidth - 1. A visual line exactly inputWidth chars wide had its last char clipped.

Fix Action

Fix

Compensate for the gutter by passing width={inputWidth + 1} to ScrollableList, so the inner content area equals inputWidth. The fix is staged on branch fix/inputprompt-wrap-truncates-last-char on my fork (commit e9f20f206) with a regression test; I'll open the PR once one of my existing open PRs is reviewed/merged.

PR fix notes

PR #26213: fix(cli): prevent last-char clip on input lines matching prompt width

Description (problem / solution / changelog)

Summary

Fixes #26212.

VirtualizedList (the engine behind ScrollableList) renders with paddingRight: 1 for its scroll gutter (shared/VirtualizedList.tsx:738). InputPrompt was passing width={inputWidth} to ScrollableList, so the inner content area was actually inputWidth - 1. A visual line exactly inputWidth chars wide had its last character clipped — at the wrap boundary the user saw the just-typed character and the cursor disappear, even though the buffer kept them.

Pass width={inputWidth + 1} so the inner content area equals the configured inputWidth.

Only the ui.terminalBuffer: true render path was affected; the fallback path renders directly through Text/Fragment and was already correct.

Test plan

  • Added a regression test in InputPrompt.test.tsx (describe('terminal buffer rendering')) that mocks a buffer with a visual line of exactly inputWidth chars ('1234567890', inputWidth = 10) and asserts the rendered frame contains the full string.
  • Verified the test fails on main (lastFrame() returns '> 123456789', missing the trailing 0) and passes with the fix applied.
  • Manually verified in PowerShell + Windows Terminal that the original repro (parola × 7 + par) now wraps correctly.
  • Pre-commit hooks (prettier, eslint) green.

Changed files

  • packages/cli/src/ui/components/InputPrompt.test.tsx (modified, +28/-0)
  • packages/cli/src/ui/components/InputPrompt.tsx (modified, +5/-1)

PR #26214: fix(cli): prevent last-char clip on input lines matching prompt width

Description (problem / solution / changelog)

Summary

Fixes #26212.

VirtualizedList (the engine behind ScrollableList) renders with paddingRight: 1 for its scroll gutter (shared/VirtualizedList.tsx:738). InputPrompt was passing width={inputWidth} to ScrollableList, so the inner content area was actually inputWidth - 1. A visual line exactly inputWidth chars wide had its last character clipped — at the wrap boundary the user saw the just-typed character and the cursor disappear, even though the buffer kept them.

Pass width={inputWidth + 1} so the inner content area equals the configured inputWidth.

Only the ui.terminalBuffer: true render path was affected; the fallback path renders directly through Text/Fragment and was already correct.

(This PR is a re-creation of the previous #26213 which was auto-closed by the rate limiter while my draft #25834 was still open. #25834 has now been closed to free a slot.)

Test plan

  • Added a regression test in InputPrompt.test.tsx (describe('terminal buffer rendering')) that mocks a buffer with a visual line of exactly inputWidth chars ('1234567890', inputWidth = 10) and asserts the rendered frame contains the full string.
  • Verified the test fails on main (lastFrame() returns '> 123456789', missing the trailing 0) and passes with the fix applied.
  • Manually verified in PowerShell + Windows Terminal that the original repro (parola × 7 + par) now wraps correctly.
  • Pre-commit hooks (prettier, eslint) green.

Changed files

  • packages/cli/src/ui/components/InputPrompt.test.tsx (modified, +28/-0)
  • packages/cli/src/ui/components/InputPrompt.tsx (modified, +5/-1)
RAW_BUFFERClick to expand / collapse

Summary

When the input line fills the prompt width exactly and the user keeps typing, the new character + cursor become invisible. The buffer is correct — pressing Enter submits the full text including the invisible suffix — so this is a pure rendering issue.

Environment

  • Gemini CLI: 0.39.1
  • OS: Windows 11
  • Shell: PowerShell (Windows Terminal)
  • Terminal size: 50 columns × 5 rows
  • Plan mode active
  • ui.terminalBuffer: true in ~/.gemini/settings.json

Reproduction

  1. Resize the terminal to ~50 columns (the exact width is not critical, only that the test string ends up matching inputWidth).
  2. At the input prompt type parola repeatedly until the line is full, then continue with pa. The cursor sits at the right edge.
  3. Type one more character (e.g. r).

Expected

The prompt grows to a second visual line and shows par plus the cursor on it.

Observed

The new character and cursor disappear; the visible line still ends with pa. The text is in the buffer — Enter submits the full string parola parola parola parola parola parola parola par.

Root cause

VirtualizedList (used by ScrollableList to render the input lines when ui.terminalBuffer: true) applies paddingRight: 1 for its scroll gutter (packages/cli/src/ui/components/shared/VirtualizedList.tsx:738). The input prompt was passing width={inputWidth} to ScrollableList (packages/cli/src/ui/components/InputPrompt.tsx:1865), so the inner content area was inputWidth - 1. A visual line exactly inputWidth chars wide had its last char clipped.

Fix

Compensate for the gutter by passing width={inputWidth + 1} to ScrollableList, so the inner content area equals inputWidth. The fix is staged on branch fix/inputprompt-wrap-truncates-last-char on my fork (commit e9f20f206) with a regression test; I'll open the PR once one of my existing open PRs is reviewed/merged.

Notes

  • Only the ui.terminalBuffer: true render path is affected. The fallback render path (InputPrompt.tsx:1875-1891) does not go through VirtualizedList and renders correctly.

extent analysis

TL;DR

To fix the rendering issue where the new character and cursor become invisible when typing beyond the input line width, update the ScrollableList component to account for the gutter width by passing width={inputWidth + 1}.

Guidance

  • Verify that the issue only occurs when ui.terminalBuffer is set to true in the ~/.gemini/settings.json file.
  • Check the VirtualizedList component in packages/cli/src/ui/components/shared/VirtualizedList.tsx to understand how the paddingRight: 1 for the scroll gutter affects the rendering.
  • Apply the proposed fix by updating the InputPrompt component in packages/cli/src/ui/components/InputPrompt.tsx to pass width={inputWidth + 1} to ScrollableList.
  • Test the fix by reproducing the issue and verifying that the new character and cursor are visible when typing beyond the input line width.

Example

No code snippet is provided as the issue already includes a clear explanation of the proposed fix.

Notes

The fix only applies to the render path when ui.terminalBuffer is true, and the fallback render path is not affected.

Recommendation

Apply the workaround by updating the InputPrompt component to pass width={inputWidth + 1} to ScrollableList, as this directly addresses the identified root cause of the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING