diff --git a/crates/vim/src/normal/substitute.rs b/crates/vim/src/normal/substitute.rs index 2f022dca98..57388710e9 100644 --- a/crates/vim/src/normal/substitute.rs +++ b/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, 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, 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::(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"}); } }