@@ -422,7 +422,7 @@ impl Object {
/// If the selection spans multiple lines and is preceded by an opening brace (`{`),
/// this function will trim the selection to exclude the final newline
/// in order to preserve a properly indented line.
-fn preserve_indented_newline(map: &DisplaySnapshot, selection: &mut Selection<DisplayPoint>) {
+pub fn preserve_indented_newline(map: &DisplaySnapshot, selection: &mut Selection<DisplayPoint>) {
let (start_point, end_point) = (selection.start.to_point(map), selection.end.to_point(map));
if start_point.row == end_point.row {
@@ -446,6 +446,7 @@ fn preserve_indented_newline(map: &DisplaySnapshot, selection: &mut Selection<Di
match ch {
'\n' => {
selection.end = offset.to_display_point(map);
+ selection.reversed = true;
break;
}
ch if !ch.is_whitespace() => break,
@@ -1759,6 +1760,17 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes("v i {");
+ cx.assert_state(
+ indoc! {
+ "func empty(a string) bool {
+ «ˇif a == \"\" {
+ return true
+ }
+ return false»
+ }"
+ },
+ Mode::Visual,
+ );
cx.set_state(
indoc! {
@@ -1772,6 +1784,17 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes("v i {");
+ cx.assert_state(
+ indoc! {
+ "func empty(a string) bool {
+ if a == \"\" {
+ «ˇreturn true»
+ }
+ return false
+ }"
+ },
+ Mode::Visual,
+ );
cx.set_state(
indoc! {
@@ -1785,6 +1808,41 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes("v i {");
+ cx.assert_state(
+ indoc! {
+ "func empty(a string) bool {
+ if a == \"\" {
+ «ˇreturn true»
+ }
+ return false
+ }"
+ },
+ Mode::Visual,
+ );
+
+ cx.set_state(
+ indoc! {
+ "func empty(a string) bool {
+ if a == \"\" {
+ return true
+ }
+ return false
+ ˇ}"
+ },
+ Mode::Normal,
+ );
+ cx.simulate_keystrokes("v i {");
+ cx.assert_state(
+ indoc! {
+ "func empty(a string) bool {
+ «ˇif a == \"\" {
+ return true
+ }
+ return false»
+ }"
+ },
+ Mode::Visual,
+ );
}
#[gpui::test]
@@ -16,7 +16,7 @@ use workspace::searchable::Direction;
use crate::{
motion::{first_non_whitespace, next_line_end, start_of_line, Motion},
- object::Object,
+ object::{self, Object},
state::{Mode, Operator},
Vim,
};
@@ -375,6 +375,9 @@ impl Vim {
} else {
selection.end = range.end;
}
+ if !around && object.is_multiline() {
+ object::preserve_indented_newline(map, selection);
+ }
}
// In the visual selection result of a paragraph object, the cursor is
@@ -1,15 +1,20 @@
-{"Put":{"state":"func empty(a string) bool {\n if a == \"\" {\n return true\n }\n ˇreturn false\n}"}}
+{"Put":{"state":"func empty(a string) bool {\n if a == \"\" {\n return true\n }\n ˇreturn false\n}"}}
{"Key":"v"}
{"Key":"i"}
{"Key":"{"}
-{"Get":{"state":"func empty(a string) bool {\n« if a == \"\" {\n return true\n }\n return false\nˇ»}","mode":"Visual"}}
+{"Get":{"state":"func empty(a string) bool {\n «ˇif a == \"\" {\n return true\n }\n return false»\n}","mode":"Visual"}}
{"Put":{"state":"func empty(a string) bool {\n if a == \"\" {\n ˇreturn true\n }\n return false\n}"}}
{"Key":"v"}
{"Key":"i"}
{"Key":"{"}
-{"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n« return true\nˇ» }\n return false\n}","mode":"Visual"}}
+{"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n «ˇreturn true»\n }\n return false\n}","mode":"Visual"}}
{"Put":{"state":"func empty(a string) bool {\n if a == \"\" ˇ{\n return true\n }\n return false\n}"}}
{"Key":"v"}
{"Key":"i"}
{"Key":"{"}
-{"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n« return true\nˇ» }\n return false\n}","mode":"Visual"}}
+{"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n «ˇreturn true»\n }\n return false\n}","mode":"Visual"}}
+{"Put":{"state":"func empty(a string) bool {\n if a == \"\" {\n return true\n }\n return false\nˇ}"}}
+{"Key":"v"}
+{"Key":"i"}
+{"Key":"{"}
+{"Get":{"state":"func empty(a string) bool {\n «ˇif a == \"\" {\n return true\n }\n return false»\n}","mode":"Visual"}}