Fix substitute in visual line mode

Conrad Irwin created

Change summary

crates/vim/src/normal/substitute.rs | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

Detailed changes

crates/vim/src/normal/substitute.rs 🔗

@@ -4,6 +4,7 @@ use language::Point;
 use crate::{motion::Motion, Mode, Vim};
 
 pub fn substitute(vim: &mut Vim, count: Option<usize>, cx: &mut WindowContext) {
+    let line_mode = vim.state.mode == Mode::Visual { line: true };
     vim.switch_mode(Mode::Insert, true, cx);
     vim.update_active_editor(cx, |editor, cx| {
         editor.transact(cx, |editor, cx| {
@@ -12,6 +13,17 @@ pub fn substitute(vim: &mut Vim, count: Option<usize>, cx: &mut WindowContext) {
                     if selection.start == selection.end {
                         Motion::Right.expand_selection(map, selection, count, true);
                     }
+                    if line_mode {
+                        Motion::CurrentLine.expand_selection(map, selection, None, false);
+                        if let Some((point, _)) = Motion::FirstNonWhitespace.move_point(
+                            map,
+                            selection.start,
+                            selection.goal,
+                            None,
+                        ) {
+                            selection.start = point;
+                        }
+                    }
                 })
             });
             let selections = editor.selections.all::<Point>(cx);
@@ -67,5 +79,19 @@ mod test {
         // should transactionally undo selection changes
         cx.simulate_keystrokes(["escape", "u"]);
         cx.assert_editor_state("ˇcàfé\n");
+
+        // it handles visual line mode
+        cx.set_state(
+            indoc! {"
+            alpha
+              beˇta
+            gamma"},
+            Mode::Normal,
+        );
+        cx.simulate_keystrokes(["shift-v", "s"]);
+        cx.assert_editor_state(indoc! {"
+            alpha
+              ˇ
+            gamma"});
     }
 }