Skip to content

fix(tui): normalize CR and CRLF line endings in a paste - #41

Merged
TaewoooPark merged 2 commits into
TaewoooPark:mainfrom
nimbly1:fix/issue-30-normalize-paste-line-endings
Oct 4, 2026
Merged

TaewoooPark merged 2 commits into
TaewoooPark:mainfrom
nimbly1:fix/issue-30-normalize-paste-line-endings

Conversation

@nimbly1

@nimbly1 nimbly1 commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #30

Bracketed paste keeps the bytes the terminal sends. xterm.js turns a clipboard line break into CR before those markers, and Composer.paste() counted and inserted only on LF. A CR painted into a row moves the cursor to the start of that row, so later lines cover earlier ones and the cursor no longer matches the draft. A typed Enter is unchanged: the key decoder still reports a bare CR as enter.

paste() now converts CRLF and a lone CR to LF before it counts lines, collapses a long paste, or inserts text. The draft, the placeholder line count, and the text sent to the model all use that form.

Tests:

  • LF, CRLF, and CR pastes of the same Korean and emoji text produce the same draft, cursor movement, and submitted text.
  • A long paste counts normalized lines and expands to the normalized text. History recall of a CRLF paste stores that text.
  • A headless terminal decodes a real bracketed paste, hands it to the composer, and paints it with Screen. All three lines stay visible and the cursor stays on the last line for CR, CRLF, and LF. A short paste can still be edited and submitted.
  • tsc --noEmit passes.
  • vitest run packages/tui: 177 tests passed.

nimbly1 and others added 2 commits October 3, 2026 23:23
xterm.js turns a clipboard's line breaks into CR before bracketed paste,
so Composer.paste() inserted raw CRs. A CR moves the cursor to the start
of the row when drawn, so later lines overwrote earlier ones and the
cursor no longer matched the draft. paste() now converts CRLF and lone
CR to LF before counting lines, collapsing long pastes and inserting, so
all three line-ending variants produce the same draft, placeholder line
count and prompt-history entry. Ordinary Enter handling is unchanged.

Fixes TaewoooPark#30

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
xterm.js delivers a clipboard line break as CR inside bracketed paste. Drawing that byte moves the cursor to the start of the row, so later lines cover earlier ones. These tests decode a real bracketed paste, hand it to the composer, and paint it with Screen into a headless terminal. CR, CRLF, and LF stay on separate rows, the cursor stays on the last line, and a short paste can still be edited and submitted.
@TaewoooPark

Copy link
Copy Markdown
Owner

Thanks @nimbly1 for the focused fix and regression tests! Reviewed fa954995a2ba5b3e8b77f845443db69cb1f4a517 against #30.

Live Motif model testing is currently unavailable because the Infron endpoint is unavailable to us. This review did not make live model calls. The changed paste normalization, rendering, editing, history, and submitted-text behavior can be verified without a live model, so I have decided to merge based on that independent evidence.

All five new regressions failed on the unchanged base and passed on this head. The full local suite passed (1,644 tests), as did typecheck, build, and tool-schema lint. I also compared the actual built CLI on a macOS PTY in visible xterm.js 6: Korean/emoji multiline paste, cursor movement/deletion, history, and a 30-line collapsed paste worked correctly, with the full normalized text verified at a localhost response fixture. All five CI jobs passed: https://github.com/TaewoooPark/Motifcode/actions/runs/37177849187 . The Python job retains five optional GPU-only skips; this is not live-model or GPU inference validation.

No blocking regression or unrelated scope expansion found. Merging as a squash commit. This merges the fix into main; it does not publish an npm release.

@TaewoooPark
TaewoooPark merged commit c2adbb7 into TaewoooPark:main Oct 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Normalize CR and CRLF line endings in bracketed paste

2 participants