Expand description
Simple multi-line input state management
Replaces tui-textarea with a lightweight implementation for the rolling terminal interface.
§Cursor indexing model (read this before editing)
cursor_col is a character index — a count of Unicode scalar values into the
current line — and never a byte offset. Every method in this file must agree on
that, and the renderer counts characters too.
This file previously mixed the two: insert_char, insert_newline, delete_char,
delete_char_forward and delete_to_end_of_line treated cursor_col as a byte
offset while the word-movement and word-delete methods treated it as a character
index. That is a crash, not a style problem: typing я once leaves cursor_col = 1
on a line that is 2 bytes long, and the second keystroke calls
String::insert(1, …) in the middle of a UTF-8 sequence, which panics. Any accented
Latin letter, any CJK character and any emoji did it, in the box the user types into.
Character index rather than byte index because cursor_col is what Left/Right move
by: one keypress should traverse one thing the user sees, and a byte is not one.
Known limitation of character (rather than grapheme cluster) semantics: a
multi-codepoint grapheme — a flag (🇺🇸 = 2 scalars), a family emoji joined with
ZWJ, a skin-tone modifier, or combining accents — takes one keypress per scalar to
cross or erase. That is a cosmetic annoyance; it cannot panic, because every scalar
boundary is also a valid UTF-8 boundary. Moving to grapheme semantics means adding a
segmentation dependency and changing only these helpers, not the call sites.
Structs§
- Input
State - Multi-line input state with cursor management
Enums§
- Direction
- Direction for cursor movement