Make Copy and Trim ignore empty lines, and fix vim line selections (cherry-pick #29019) (#29023)

gcp-cherry-pick-bot[bot] and redforks created

Cherry-picked Make Copy and Trim ignore empty lines, and fix vim line
selections (#29019)

Close #28519 

Release Notes:

Update `editor: copy and trim` command:

1. Ignore empty lines in the middle:

    ```
      Line 1

      Line 2
    ```

    Will copy text to clipboard:

    ```
    Line 1

    Line 2
    ```

    Before this commit trim not performed

1. Fix select use vim line selections, trim not works

Co-authored-by: redforks <redforks@gmail.com>

Change summary

crates/editor/src/editor.rs       | 12 ++++++++++--
crates/editor/src/editor_tests.rs | 30 ++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)

Detailed changes

crates/editor/src/editor.rs πŸ”—

@@ -10122,11 +10122,19 @@ impl Editor {
                                 ..Point::new(row.0, buffer.line_len(row)),
                         );
                         for row in start.row + 1..=end.row {
+                            let mut line_len = buffer.line_len(MultiBufferRow(row));
+                            if row == end.row {
+                                line_len = end.column;
+                            }
+                            if line_len == 0 {
+                                trimmed_selections
+                                    .push(Point::new(row, 0)..Point::new(row, line_len));
+                                continue;
+                            }
                             let row_indent_size = buffer.indent_size_for_line(MultiBufferRow(row));
                             if row_indent_size.len >= first_indent.len {
                                 trimmed_selections.push(
-                                    Point::new(row, first_indent.len)
-                                        ..Point::new(row, buffer.line_len(MultiBufferRow(row))),
+                                    Point::new(row, first_indent.len)..Point::new(row, line_len),
                                 );
                             } else {
                                 trimmed_selections.clear();

crates/editor/src/editor_tests.rs πŸ”—

@@ -5121,6 +5121,36 @@ if is_entire_line {
         ),
         "When selecting past the indent, nothing is trimmed"
     );
+
+    cx.set_state(
+        r#"            Β«for selection in selections.iter() {
+            let mut start = selection.start;
+
+            let mut end = selection.end;
+            let is_entire_line = selection.is_empty();
+            if is_entire_line {
+                start = Point::new(start.row, 0);
+Λ‡Β»                end = cmp::min(max_point, Point::new(end.row + 1, 0));
+            }
+        "#,
+    );
+    cx.update_editor(|e, window, cx| e.copy_and_trim(&CopyAndTrim, window, cx));
+    assert_eq!(
+        cx.read_from_clipboard()
+            .and_then(|item| item.text().as_deref().map(str::to_string)),
+        Some(
+            "for selection in selections.iter() {
+let mut start = selection.start;
+
+let mut end = selection.end;
+let is_entire_line = selection.is_empty();
+if is_entire_line {
+    start = Point::new(start.row, 0);
+"
+            .to_string()
+        ),
+        "Copying with stripping should ignore empty lines"
+    );
 }
 
 #[gpui::test]