fix: width-aware input/layout, prompt paste, and FCmd mapper guard#204
Merged
Conversation
Address code-review findings: - Prompt.handleKey now handles InputKey.Paste (was dropped); inserts the first pasted line at the cursor, mirroring TextField. (TextField and MultiLineInput already gained paste support in #203.) - AnsiRenderer.visibleInput sizes the input viewport by rendered cell width (WCWidth) instead of UTF-16 length, so CJK/emoji input no longer overflows the declared width or scrolls past the cursor. Adds takeCells / charIndexAtCell helpers; nodeExtents fallback measured the same way. - Layout.measureVNode measures TextNode/InputNode width via WCWidth so rows, columns, grids, fills, and hit-test zones place wide/combining text consistently with the renderer. - TuiRuntime FCmd now guards the success mapper: if toCmd(result) throws, it publishes a TermFlowError instead of dying silently on the EC and stranding the app in its loading state. Tests added for each. (The supplementary-emoji diff finding was already resolved by the RenderCell.glyph / renderedGlyph plumbing.)
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Addresses the code-review findings.
Findings addressed
High — Prompt drops bracketed paste.
Prompt.handleKeyhad noInputKey.Pastecase and fell through to no-op. It now inserts the first pasted line at the cursor, mirroringTextField's single-line paste behaviour. (TextFieldandMultiLineInputalready gained paste handling in #203, so onlyPromptremained.)High — Input viewport sized by char count, not cells.
AnsiRenderer.visibleInputbudgeted the fixed prefix and scrolled the editable suffix withlength/take/slice, while cursor placement already usedWCWidth. CJK/emoji text could overflow the declaredlineWidthor scroll incorrectly. The prefix is now clipped and the suffix scrolled by rendered cell width, with newtakeCells/charIndexAtCellhelpers. For pure-ASCII input the math reduces to the previous behaviour (existing goldens unchanged).nodeExtents' auto-size fallback measures the prompt the same way.Medium — Layout measured text by
String.length.Layout.measureVNodenow measuresTextNode/InputNodewidth viaWCWidth.stringWidth, so rows, columns, grids, fills, and hit-test zones place wide/combining text consistently with the renderer.Medium —
Cmd.FCmdsuccess mapper unguarded. A throwingtoCmd(result)died on the execution context, publishing neither the intended command nor an error and leaving the app stuck loading. The success branch now catchesNonFataland surfaces aTermFlowError.Unexpected, matching the existing failure path.Medium — supplementary-plane emoji in the diff renderer: already resolved on
mainby theRenderCell.glyph/renderedGlyphplumbing (drawStringstores the full glyph; the diff emitsrenderedGlyph). No change needed; noting for completeness.Tests
PromptSpec: paste inserts at cursor, keeps only the first line, empty paste is a no-op.AnsiRendererSpec: wide-char input viewport bounded to the declared cell width with the cursor landing correctly.LayoutSpec:measureVNodereturns rendered cell width for CJK / emoji / combining text.TuiRuntimeSpec: a throwing FCmd success mapper surfaces aTermFlowError.sbt ciCheckis green.