diff --git a/crates/vim/src/helix/paste.rs b/crates/vim/src/helix/paste.rs index d91b138853abb07dc10957a4ee1f5af158066e06..32f636b41046a5f8c8ade054594218890e23758f 100644 --- a/crates/vim/src/helix/paste.rs +++ b/crates/vim/src/helix/paste.rs @@ -66,7 +66,11 @@ impl Vim { let to_insert = if let Some(clip_sel) = clipboard_selections.get(ix) { let end_offset = start_offset + clip_sel.len; let text = text[start_offset..end_offset].to_string(); - start_offset = end_offset + 1; + start_offset = if clip_sel.is_entire_line { + end_offset + } else { + end_offset + 1 + }; text } else if let Some(last_text) = replacement_texts.last() { // We have more current selections than clipboard selections: repeat the last one. diff --git a/crates/vim/src/normal/paste.rs b/crates/vim/src/normal/paste.rs index 3143226b5afbfc75b61a3542552eae37f175b2a4..ec964ec9ae3af08b108aa027a0aa62883dbcbcc5 100644 --- a/crates/vim/src/normal/paste.rs +++ b/crates/vim/src/normal/paste.rs @@ -107,7 +107,11 @@ impl Vim { if let Some(clipboard_selection) = clipboard_selections.get(ix) { let end_offset = start_offset + clipboard_selection.len; let text = text[start_offset..end_offset].to_string(); - start_offset = end_offset + 1; + start_offset = if clipboard_selection.is_entire_line { + end_offset + } else { + end_offset + 1 + }; (text, Some(clipboard_selection.first_line_indent)) } else { ("".to_string(), first_selection_indent_column) @@ -1083,4 +1087,52 @@ mod test { Mode::Normal, ); } + + #[gpui::test] + async fn test_paste_entire_line_from_editor_copy(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state( + indoc! {" + ˇline one + line two + line three"}, + Mode::Normal, + ); + + // Simulate what the editor's do_copy produces for two entire-line selections: + // entire-line selections are NOT separated by an extra newline in the clipboard text. + let clipboard_text = "line one\nline two\n".to_string(); + let clipboard_selections = vec![ + editor::ClipboardSelection { + len: "line one\n".len(), + is_entire_line: true, + first_line_indent: 0, + file_path: None, + line_range: None, + }, + editor::ClipboardSelection { + len: "line two\n".len(), + is_entire_line: true, + first_line_indent: 0, + file_path: None, + line_range: None, + }, + ]; + cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata( + clipboard_text, + clipboard_selections, + )); + + cx.simulate_keystrokes("p"); + cx.assert_state( + indoc! {" + line one + ˇline one + line two + line two + line three"}, + Mode::Normal, + ); + } }