editor: Fix text manipulation on line mode selections (#37646)

Dino created

This commit updates the implementation for
`editor::Editor.manipulate_text` to use
`editor::selections_collection::SelectionsCollection.all_adjusted`
instead of `editor::selections_collection::SelectionsCollection.all`, as
the former takes into account the selection's `line_mode`, fixing the
issue where, if an user was in vim's visual line mode, running the
`editor: convert to upper case` command would not work as expected.

Closes #36953 

Release Notes:

- Fixed bug where using the editor's convert case commands while in
vim's Visual Line mode would not work as expected

Change summary

crates/editor/src/editor.rs       | 10 +++++++---
crates/editor/src/editor_tests.rs | 14 ++++++++++++++
2 files changed, 21 insertions(+), 3 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -11391,14 +11391,17 @@ impl Editor {
         let mut edits = Vec::new();
         let mut selection_adjustment = 0i32;
 
-        for selection in self.selections.all::<usize>(cx) {
+        for selection in self.selections.all_adjusted(cx) {
             let selection_is_empty = selection.is_empty();
 
             let (start, end) = if selection_is_empty {
                 let (word_range, _) = buffer.surrounding_word(selection.start, false);
                 (word_range.start, word_range.end)
             } else {
-                (selection.start, selection.end)
+                (
+                    buffer.point_to_offset(selection.start),
+                    buffer.point_to_offset(selection.end),
+                )
             };
 
             let text = buffer.text_for_range(start..end).collect::<String>();
@@ -11409,7 +11412,8 @@ impl Editor {
                 start: (start as i32 - selection_adjustment) as usize,
                 end: ((start + text.len()) as i32 - selection_adjustment) as usize,
                 goal: SelectionGoal::None,
-                ..selection
+                id: selection.id,
+                reversed: selection.reversed,
             });
 
             selection_adjustment += old_length - text.len() as i32;

crates/editor/src/editor_tests.rs 🔗

@@ -5363,6 +5363,20 @@ async fn test_manipulate_text(cx: &mut TestAppContext) {
     cx.assert_editor_state(indoc! {"
         «HeLlO, wOrLD!ˇ»
     "});
+
+    // Test selections with `line_mode = true`.
+    cx.update_editor(|editor, _window, _cx| editor.selections.line_mode = true);
+    cx.set_state(indoc! {"
+        «The quick brown
+        fox jumps over
+        tˇ»he lazy dog
+    "});
+    cx.update_editor(|e, window, cx| e.convert_to_upper_case(&ConvertToUpperCase, window, cx));
+    cx.assert_editor_state(indoc! {"
+        «THE QUICK BROWN
+        FOX JUMPS OVER
+        THE LAZY DOGˇ»
+    "});
 }
 
 #[gpui::test]