You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The CLI rendered a visual caret but did not move the real terminal hardware cursor to the input position. CJK IMEs use the terminal cursor position to anchor their composition and candidate windows, which caused the popup to appear at unrelated screen locations.
This change:
synchronizes the real terminal cursor with the MultilineInput caret
accounts for CJK terminal-cell width using string-width
handles tabs, wrapped lines, viewport offsets, and vertical scrolling
hides the hardware cursor when the input loses focus or unmounts
keeps the existing visual cursor behavior unchanged
Tests
Added regression coverage for:
ASCII cursor positioning
CJK wide characters
mixed ASCII/CJK input
tab expansion
wrapped visual lines
viewport and vertical scroll offsets
cursor visibility on focus/unmount
component-level OpenTUI renderer cursor positioning after a CJK character
Validation:
bun test cli/src/components/__tests__/multiline-input.test.tsx — 80 passed
repeated test run (--rerun-each 3) — 240 passed
git diff --check — passed
The full CLI test command is currently blocked by the pre-existing missing preload ../test/setup-scm-loader.ts.
CLI typecheck is currently blocked by pre-existing missing tar and react-dom/server typings; no errors were reported in the changed files.
Manual Windows Terminal / CJK IME verification was not completed.
Good instinct and unusually thorough test coverage (unit tests for calculateMultilineInputCursorPosition covering ASCII, CJK width, tabs, wrapping, scroll, plus renderer-level lifecycle tests for cursor visibility on focus/unmount). That alone puts this above most first-time-contributor PRs.
Concerns before this is portable as-is:
syncHardwareCursor in multiline-input.tsx reaches into (textRef.current as any).textBufferView as TextBufferView — an any-cast into what looks like a private/internal OpenTUI renderable field, not part of its declared type surface. If TextBufferView or textBufferView isn't actually an exported/stable API, this will silently break on the next OpenTUI bump, and there's no fallback beyond the null check. Worth confirming this is intended public surface, or exposing it properly upstream.
The line-info-change event listener is attached/detached each render via the useEffect dependency array [focused, displayValue, cursorPosition, lineInfo, syncHardwareCursor] — since syncHardwareCursor is recreated whenever renderer changes (stable) but the effect itself re-runs on every keystroke (displayValue/cursorPosition change every input), this re-subscribes the listener on every keystroke. Not necessarily wrong, but worth confirming there's no listener leak/thrash under rapid typing.
Recommend keeping the calculation logic (calculateMultilineInputCursorPosition is clean and well-tested) but validating the textBufferView access is safe and doing the manual IME test pass before porting.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bot:triagedClassified by the community triage botpr:needs-workRight idea, not mergeable as written
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1128.
The CLI rendered a visual caret but did not move the real terminal hardware cursor to the input position. CJK IMEs use the terminal cursor position to anchor their composition and candidate windows, which caused the popup to appear at unrelated screen locations.
This change:
MultilineInputcaretstring-widthTests
Added regression coverage for:
Validation:
bun test cli/src/components/__tests__/multiline-input.test.tsx— 80 passed--rerun-each 3) — 240 passedgit diff --check— passedThe full CLI test command is currently blocked by the pre-existing missing preload
../test/setup-scm-loader.ts.CLI typecheck is currently blocked by pre-existing missing
tarandreact-dom/servertypings; no errors were reported in the changed files.Manual Windows Terminal / CJK IME verification was not completed.