fix: keep counted word deletions within the current line

Word deletion reused cross-line word motion destinations. Constrain token traversal and boundary fallbacks to each caret’s current row while preserving cross-line navigation.
This commit is contained in:
2026-10-13 17:30:00 +02:00
parent 99fa5a2aff
commit 983f43e710
5 changed files with 89 additions and 29 deletions
+19 -20
View File
@@ -8220,11 +8220,8 @@ impl Editor {
.map(|(index, target)| {
let cursor = target.active;
let end = match action {
Action::DeleteWordForward => {
self.word_destination(cursor, Action::WordNext, count)
}
Action::DeleteWordBackward => {
self.word_destination(cursor, Action::WordPrevious, count)
Action::DeleteWordForward | Action::DeleteWordBackward => {
self.word_destination(cursor, action, count)
}
Action::SubstituteCharacter => Cursor {
row: cursor.row,
@@ -9313,9 +9310,16 @@ impl Editor {
action,
Action::BigWordNext | Action::BigWordPrevious | Action::BigWordEnd
);
let backward = matches!(action, Action::WordPrevious | Action::BigWordPrevious);
let start = if backward { 0 } else { row };
let end = if backward {
let backward = matches!(
action,
Action::WordPrevious | Action::BigWordPrevious | Action::DeleteWordBackward
);
let line_local = matches!(
action,
Action::DeleteWordForward | Action::DeleteWordBackward
);
let start = if line_local || !backward { row } else { 0 };
let end = if line_local || backward {
row + 1
} else {
self.active.lines.len()
@@ -9325,17 +9329,12 @@ impl Editor {
.map(move |(_, byte, kind)| (source_row, byte, kind))
});
let destination = match action {
Action::WordPrevious | Action::BigWordPrevious => {
Action::WordPrevious | Action::BigWordPrevious | Action::DeleteWordBackward => {
let mut tokens = tokens
.rev()
.skip_while(|(r, b, _)| (*r, *b) >= (row, byte))
.peekable();
let fallback = (
self.navigable_rows(0, self.active.lines.len())
.next()
.unwrap_or(row),
0,
);
let fallback = (self.navigable_rows(start, end).next().unwrap_or(row), 0);
let mut destination = fallback;
for _ in 0..count {
let Some(mut first) = tokens.find(|(_, _, kind)| *kind != WordKind::Whitespace)
@@ -9360,13 +9359,13 @@ impl Editor {
return cursor;
};
let mut current = first.2;
let last = self
.navigable_rows(0, self.active.lines.len())
.next_back()
.unwrap_or(row);
let last = self.navigable_rows(start, end).next_back().unwrap_or(row);
let mut destination = (last, self.active.lines[last].len());
for _ in 0..count {
let next_start = matches!(action, Action::WordNext | Action::BigWordNext);
let next_start = matches!(
action,
Action::WordNext | Action::BigWordNext | Action::DeleteWordForward
);
if next_start && current != WordKind::EmptyLine {
while tokens.peek().is_some_and(|(_, _, kind)| *kind == current) {
tokens.next();