Skip to content

Fix undo/redo corruption when typing at the end of a final-newline file - #917

Open
user77 (hexbinoct) wants to merge 1 commit into
microsoft:mainfrom
hexbinoct:fix-834
Open

Fix undo/redo corruption when typing at the end of a final-newline file#917
user77 (hexbinoct) wants to merge 1 commit into
microsoft:mainfrom
hexbinoct:fix-834

Conversation

@hexbinoct

Copy link
Copy Markdown
Contributor

Fixes #834

What breaks

Typing at the end of a buffer that has the automatic POSIX final newline enabled (the default for new files on non-Windows, and enabled on any platform when an opened file ends in a newline), then pressing Ctrl+Z and Ctrl+Y, corrupts the text: ab plus trailing newline comes back as a, newline, b. Deterministic repro and full analysis are on the issue.

Root cause

The insert_final_newline branch at the end of TextBuffer::write() records the appended newline in the current undo entry and then moves the cursor back before it by assigning self.cursor directly. That bypasses the coalescing break in set_cursor(), so the next typed character coalesces into the same undo entry. Its bytes land before the final newline in the buffer while the entry's added vector records them after it: buffer ab\n, recorded a\nb. Undo deletes by byte count and works; redo replays added as one contiguous string and reproduces write order.

Fix

Stop coalescing after a final-newline insertion (self.last_history_type = HistoryType::Other; in that branch), so every undo entry's recorded bytes stay contiguous in buffer order. The cost is one extra undo step when typing begins at the end of such a file, since the first character and its automatic newline form their own entry.

Tests

crates/edit/tests/undo_redo_834.rs adds six round-trip tests: coalesced typing with the final newline (LF and CRLF), a double undo/redo cycle, a single multi-line write (LF and CRLF), and coalesced typing across a newline without the final-newline feature. The three final-newline tests fail on main and pass with this change. The multi-line write tests pass on main as well as here; they are included to pin down that the redo reinsert loop was not the problem (relevant to #852, where I left verification details).

Full workspace test suite and clippy pass locally on Windows; the fix itself is one line.

The automatic final-newline insertion in TextBuffer::write() moves the
cursor back internally, so the next coalesced write lands before that
newline while the undo entry appends its bytes after the newline's.
Redo replays the entry's recorded bytes as one contiguous string,
reproducing them in write order ("a<LF>b") instead of buffer order
("ab<LF>").

Stop coalescing after a final-newline insertion so every undo entry's
recorded bytes stay contiguous in buffer order.

Fixes microsoft#834
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.

Bug in undo/redo with additional new lines

1 participant