fix: replace selected characters with visual r

This commit is contained in:
2026-10-13 23:43:49 +02:00
parent 11b31d2621
commit cd427f74dc
5 changed files with 209 additions and 24 deletions
+83
View File
@@ -42,6 +42,89 @@ fn keys(editor: &mut Editor, text: &str) {
}
}
#[test]
fn visual_r_replaces_selected_graphemes_as_one_undo_edit() {
let fixture = Fixture::new();
let source = "ae\u{301}👩‍🚀z\nrest\n";
let mut editor = fixture.editor(source);
keys(&mut editor, "lv2l");
assert_eq!(editor.mode(), Mode::Visual);
keys(&mut editor, "r界");
assert_eq!(editor.context().text, "a界界界\nrest\n");
assert_eq!(editor.mode(), Mode::Normal);
keys(&mut editor, "u");
assert_eq!(editor.context().text, source);
assert!(!editor.dirty());
keys(&mut editor, "U");
assert_eq!(editor.context().text, "a界界界\nrest\n");
}
#[test]
fn visual_r_preserves_selected_newlines_in_both_directions_and_shapes() {
for (source, selection, expected) in [
("ae\u{301}👩‍🚀z\n\nbc\nlast\n", "v2j", "QQQQ\n\nQc\nlast\n"),
("ae\u{301}👩‍🚀z\n\nbc\nlast\n", "2jv2k", "QQQQ\n\nQc\nlast\n"),
("ae\u{301}👩‍🚀z\n\nbc\nlast\n", "V2j", "QQQQ\n\nQQ\nlast\n"),
("ab\ncd", "Vj", "QQ\nQQ"),
("\n\n", "Vj", "\n\n"),
] {
let fixture = Fixture::new();
let mut editor = fixture.editor(source);
keys(&mut editor, selection);
keys(&mut editor, "rQ");
assert_eq!(editor.context().text, expected, "{selection}");
assert_eq!(editor.mode(), Mode::Normal);
assert_eq!(editor.dirty(), source != expected);
keys(&mut editor, "u");
assert_eq!(editor.context().text, source);
}
}
#[test]
fn visual_r_replaces_every_selection_and_restores_carets_on_undo() {
let fixture = Fixture::new();
let source = "abcd\nwxyz\n";
let mut editor = fixture.editor(source);
keys(&mut editor, "vl");
editor.handle(Input::Ctrl('e'));
let carets = editor.carets();
assert_eq!(editor.selection_count(), 2);
keys(&mut editor, "r界");
assert_eq!(editor.context().text, "界界cd\n界界yz\n");
assert_eq!(editor.selection_count(), 2);
keys(&mut editor, "u");
assert_eq!(editor.context().text, source);
assert_eq!(editor.carets(), carets);
}
#[test]
fn visual_r_repeats_selection_intent_without_overwriting_the_clipboard() {
let fixture = Fixture::new();
let mut editor = fixture.editor("abc\nuvwxyz\n");
keys(&mut editor, "yyvlrQj0.");
assert_eq!(editor.context().text, "QQc\nQQwxyz\n");
keys(&mut editor, "4lv.");
assert_eq!(editor.context().text, "QQc\nQQwxQz\n");
keys(&mut editor, "P");
assert_eq!(editor.context().text, "QQc\nabc\nQQwxQz\n");
}
#[test]
fn cancelled_and_identical_visual_replacements_preserve_redo() {
let fixture = Fixture::new();
let mut editor = fixture.editor("abc\n");
keys(&mut editor, "rQulvr");
editor.handle(Input::Escape);
assert_eq!(editor.mode(), Mode::Visual);
assert_eq!(editor.line_operator_pending(), None);
keys(&mut editor, "rb");
assert_eq!(editor.context().text, "abc\n");
assert_eq!(editor.mode(), Mode::Normal);
assert!(!editor.dirty());
keys(&mut editor, "U");
assert_eq!(editor.context().text, "Qbc\n");
}
#[test]
fn change_and_delete_line_suffix_preserve_newlines_and_group_insert_undo() {
for operation in ["C", "D", "9C", "9D"] {