fix(grid): keep wide characters before the cursor when erasing to end of screen - #5575
Open
dylanpulver wants to merge 1 commit into
Open
fix(grid): keep wide characters before the cursor when erasing to end of screen#5575dylanpulver wants to merge 1 commit into
dylanpulver wants to merge 1 commit into
Conversation
… of screen Row::truncate takes a display column but converted it to a character index with `x - excess_width_until(x)`. excess_width_until counts the excess of the first `x` *characters*, so once more than one wide character precedes the column it over-counts and the row is cut short. Erasing to the end of the screen (CSI 0 J) with the cursor anywhere after a second wide character therefore deleted text before the cursor. Convert with position_accounting_for_widechars, the converter the rest of Row already uses.
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.
Row::truncatetakes a display column, but converted it to a character index withx - excess_width_until(x).excess_width_untilcounts the excess of the firstxcharacters (
columns.iter().take(x)), so as soon as more than one wide character precedes thecolumn it over-counts and the row is cut shorter than asked.
position_accounting_for_widechars,twenty lines below in the same
impl, is the converter that gets this right, andreplace_and_pad_endalready uses it.The visible effect is through
clear_all_after_cursor(CSI 0 J, which shells emit constantly):with the cursor anywhere past a second wide character, text before the cursor is deleted.
Measured on
main(af38660), first row after the sequence, 20-column grid:日本then CUP col 3,ESC[0J日a日本then CUP col 4,ESC[0Ja日aabthen CUP col 3,ESC[0JababNarrow-only rows are unaffected, which is why this has stayed invisible.
Nothing in the suite could see it: every wide-character test in
grid_tests.rs(
wide_characters,wide_characters_line_wrap,bash_delete_wide_characters,fish_wide_characters_override_clock) is anassert_snapshot!of a fixture replay, and thehand-written ED tests are all ASCII.
truncate's formula and those fixtures landed in the samecommit,
44d67de1(#535, 2021-05-26). Reverting onlygrid.rstomainfails the one new testand nothing else; all 1577 lib tests pass with the fix and no snapshot needed regenerating.
Worth saying: the naive version —
truncate_position = x, ignoring wide characters — also passesthe new test. It fails five existing ones (
delete_char_in_middle_of_line_with_widechar,insert_character_in_line_with_wide_character, and threesearch_tests), so the suite pinsover-truncation while being blind to under-truncation.
position_accounting_for_widecharsis whatsatisfies both directions.
Out of scope: the other
excess_width_until(x)call, inadd_character_at'sOrdering::Lessarm,is not affected — there
xis at or past the row's display width, so the two readings coincide.#5240 touches
replace_and_pad_end, nottruncate; no overlap.cargo test -p zellij-server --lib(1577 passed),cargo fmt --all --checkclean.cargo clippyat the pinned 1.95.0 already fails on
maininoutput/mod.rsandplugins/unit/plugin_tests.rs;nothing in the changed files is new.
Found by reading
Row's three display-column/character-index converters against each other, notfrom normal use. Written with AI assistance (Claude Opus 5,
claude-opus-5); every number abovecame from running the built test binary.