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:
+66
-5
@@ -218,15 +218,13 @@ fn word_delete_counts_before_and_after_operator_multiply_in_both_directions() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn word_delete_uses_unicode_word_motion_boundaries_across_punctuation_and_rows() {
|
||||
fn word_delete_uses_unicode_word_motion_boundaries_across_punctuation() {
|
||||
for (source, command, expected) in [
|
||||
("e\u{301}lan 世界 fin\n", "d2w", "fin\n"),
|
||||
("e\u{301}lan 世界 fin\n", "2wd2b", "fin\n"),
|
||||
("alpha... beta gamma\n", "d2w", "beta gamma\n"),
|
||||
("alpha... beta gamma\n", "2wd2b", "beta gamma\n"),
|
||||
("👩🚀!!! next\n", "dw", "next\n"),
|
||||
("one\ntwo three\n", "d2w", "three\n"),
|
||||
("one\ntwo three\n", "2wd2b", "three\n"),
|
||||
] {
|
||||
let fixture = Fixture::new();
|
||||
let mut editor = fixture.editor(source);
|
||||
@@ -237,6 +235,56 @@ fn word_delete_uses_unicode_word_motion_boundaries_across_punctuation_and_rows()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn word_delete_stops_at_current_line_boundaries() {
|
||||
for (source, position, command, expected) in [
|
||||
("one\ntwo three\n", "", "dw", "\ntwo three\n"),
|
||||
("one\ntwo three\n", "", "d2w", "\ntwo three\n"),
|
||||
("one two\nthree four\n", "w", "2d3w", "one \nthree four\n"),
|
||||
("one\ntwo three\n", "2w", "d2b", "one\nthree\n"),
|
||||
("one\n two three\n", "jw", "2d3b", "one\ntwo three\n"),
|
||||
("one \ntwo\n", "", "d9w", "\ntwo\n"),
|
||||
("one\n \ntwo\n", "j", "dw", "one\n\ntwo\n"),
|
||||
("one\n\ntwo\n", "j", "d9w", "one\n\ntwo\n"),
|
||||
("one\n\ntwo\n", "j", "d9b", "one\n\ntwo\n"),
|
||||
("one\ntwo\n", "j0", "db", "one\ntwo\n"),
|
||||
("one\n two\n", "jl", "db", "one\n two\n"),
|
||||
(
|
||||
"one\ne\u{301}lan 世界\nnext\n",
|
||||
"j0",
|
||||
"d9w",
|
||||
"one\n\nnext\n",
|
||||
),
|
||||
(
|
||||
"one\ne\u{301}lan 世界\nnext\n",
|
||||
"j$",
|
||||
"d9b",
|
||||
"one\n界\nnext\n",
|
||||
),
|
||||
] {
|
||||
let fixture = Fixture::new();
|
||||
let mut editor = fixture.editor(source);
|
||||
keys(&mut editor, position);
|
||||
let caret = editor.cursor();
|
||||
keys(&mut editor, command);
|
||||
assert_eq!(
|
||||
editor.context().text,
|
||||
expected,
|
||||
"{position} {command} on {source:?}"
|
||||
);
|
||||
assert_eq!(editor.mode(), Mode::Normal);
|
||||
if source == expected {
|
||||
assert_eq!(editor.cursor(), caret);
|
||||
assert!(!editor.dirty());
|
||||
} else {
|
||||
keys(&mut editor, "u");
|
||||
assert_eq!(editor.context().text, source);
|
||||
assert_eq!(editor.cursor(), caret);
|
||||
assert!(!editor.dirty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn word_delete_handles_eof_and_saturating_counts_without_splitting_graphemes() {
|
||||
let source = "e\u{301}lan 世界";
|
||||
@@ -331,6 +379,14 @@ fn new_edit_recipes_repeat_against_the_current_text_and_undo_as_single_changes()
|
||||
"j02w",
|
||||
"keep\nstay\n",
|
||||
),
|
||||
("one\nthree four\n", "d9w", "\nthree four\n", "j0", "\n\n"),
|
||||
(
|
||||
"one keep\nthree four stay\n",
|
||||
"wd9b",
|
||||
"keep\nthree four stay\n",
|
||||
"j02w",
|
||||
"keep\nstay\n",
|
||||
),
|
||||
] {
|
||||
let fixture = Fixture::new();
|
||||
let mut editor = fixture.editor(source);
|
||||
@@ -413,13 +469,18 @@ fn native_multicarets_edit_whole_graphemes_and_yank_matching_suffix_fragments()
|
||||
assert_eq!(editor.context().text, source);
|
||||
assert_eq!(editor.carets(), carets);
|
||||
}
|
||||
for command in ["d2w", "2wd2b"] {
|
||||
for (command, expected) in [
|
||||
("d2w", "keep\nstay\n"),
|
||||
("2wd2b", "keep\nstay\n"),
|
||||
("d9w", "\n\n"),
|
||||
("2wd9b", "keep\nstay\n"),
|
||||
] {
|
||||
let fixture = Fixture::new();
|
||||
let source = "one two keep\nthree four stay\n";
|
||||
let mut editor = fixture.editor(source);
|
||||
editor.handle(Input::Ctrl('e'));
|
||||
keys(&mut editor, command);
|
||||
assert_eq!(editor.context().text, "keep\nstay\n", "{command}");
|
||||
assert_eq!(editor.context().text, expected, "{command}");
|
||||
assert_eq!(editor.selection_count(), 2);
|
||||
keys(&mut editor, "u");
|
||||
assert_eq!(editor.context().text, source);
|
||||
|
||||
Reference in New Issue
Block a user