@@ -222,9 +222,14 @@ impl Command {
222222 undo,
223223 redo,
224224 yank,
225+ yank_joined_to_clipboard,
226+ yank_main_selection_to_clipboard,
225227 replace_with_yanked,
228+ replace_selections_with_clipboard,
226229 paste_after,
227230 paste_before,
231+ paste_clipboard_after,
232+ paste_clipboard_before,
228233 indent,
229234 unindent,
230235 format_selections,
@@ -1280,74 +1285,24 @@ mod cmd {
12801285 editor.set_theme_from_name(theme);
12811286 }
12821287
1283− fn yank_main_selection_to_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1284− let (view, doc) = current!(editor);
1285−
1286− // TODO: currently the main selection is the first one. This needs to be revisited later.
1287− let range = doc
1288− .selection(view.id)
1289− .ranges()
1290− .first()
1291− .expect("at least one selection");
1292−
1293− let value = range.fragment(doc.text().slice(..));
1294−
1295− if let Err(e) = editor.clipboard_provider.set_contents(value.into_owned()) {
1296− log::error!("Couldn't set system clipboard content: {:?}", e);
1297− }
1298−
1299− editor.set_status("yanked main selection to system clipboard".to_owned());
1288+ fn yank_main_selection_to_clipboard(editor: &mut Editor, _: &[&str], _: PromptEvent) {
1289+ yank_main_selection_to_clipboard_impl(editor);
13001290 }
13011291
1302− fn yank_joined_to_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1303− let (view, doc) = current!(editor);
1304−
1305− let values: Vec<String> = doc
1306− .selection(view.id)
1307− .fragments(doc.text().slice(..))
1308− .map(Cow::into_owned)
1309− .collect();
1310−
1311− let msg = format!(
1312− "joined and yanked {} selection(s) to system clipboard",
1313− values.len(),
1314− );
1315−
1316− let joined = values.join("\n");
1317−
1318− if let Err(e) = editor.clipboard_provider.set_contents(joined) {
1319− log::error!("Couldn't set system clipboard content: {:?}", e);
1320− }
1321−
1322− editor.set_status(msg);
1323− }
1324−
1325− fn paste_clipboard_impl(editor: &mut Editor, action: Paste) {
1326− let (view, doc) = current!(editor);
1327−
1328− match editor
1329− .clipboard_provider
1330− .get_contents()
1331− .map(|contents| paste_impl(&[contents], doc, view, action))
1332− {
1333− Ok(Some(transaction)) => {
1334− doc.apply(&transaction, view.id);
1335− doc.append_changes_to_history(view.id);
1336− }
1337− Ok(None) => {}
1338− Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e),
1339− }
1292+ fn yank_joined_to_clipboard(editor: &mut Editor, args: &[&str], _: PromptEvent) {
1293+ let separator = args.first().copied().unwrap_or("\n");
1294+ yank_joined_to_clipboard_impl(editor, separator);
13401295 }
13411296
13421297 fn paste_clipboard_after(editor: &mut Editor, _: &[&str], _: PromptEvent) {
13431298 paste_clipboard_impl(editor, Paste::After);
13441299 }
13451300
1346− fn paste_clipboard_before(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1301+ fn paste_clipboard_before(editor: &mut Editor, _: &[&str], _: PromptEvent) {
13471302 paste_clipboard_impl(editor, Paste::After);
13481303 }
13491304
1350− fn replace_selections_with_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1305+ fn replace_selections_with_clipboard(editor: &mut Editor, _: &[&str], _: PromptEvent) {
13511306 let (view, doc) = current!(editor);
13521307
13531308 match editor.clipboard_provider.get_contents() {
@@ -1500,7 +1455,7 @@ mod cmd {
15001455 TypableCommand {
15011456 name: "clipboard-yank-join",
15021457 alias: None,
1503− doc: "Yank joined selections into system clipboard.",
1458+ doc: "Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline.", // FIXME: current UI can't display long doc.
15041459 fun: yank_joined_to_clipboard,
15051460 completer: None,
15061461 },
@@ -2525,6 +2480,52 @@ fn yank(cx: &mut Context) {
25252480 cx.editor.set_status(msg)
25262481}
25272482
2483+fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) {
2484+ let (view, doc) = current!(editor);
2485+
2486+ let values: Vec<String> = doc
2487+ .selection(view.id)
2488+ .fragments(doc.text().slice(..))
2489+ .map(Cow::into_owned)
2490+ .collect();
2491+
2492+ let msg = format!(
2493+ "joined and yanked {} selection(s) to system clipboard",
2494+ values.len(),
2495+ );
2496+
2497+ let joined = values.join(separator);
2498+
2499+ if let Err(e) = editor.clipboard_provider.set_contents(joined) {
2500+ log::error!("Couldn't set system clipboard content: {:?}", e);
2501+ }
2502+
2503+ editor.set_status(msg);
2504+}
2505+
2506+fn yank_joined_to_clipboard(cx: &mut Context) {
2507+ yank_joined_to_clipboard_impl(&mut cx.editor, "\n");
2508+}
2509+
2510+fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) {
2511+ let (view, doc) = current!(editor);
2512+
2513+ let value = doc
2514+ .selection(view.id)
2515+ .primary()
2516+ .fragment(doc.text().slice(..));
2517+
2518+ if let Err(e) = editor.clipboard_provider.set_contents(value.into_owned()) {
2519+ log::error!("Couldn't set system clipboard content: {:?}", e);
2520+ }
2521+
2522+ editor.set_status("yanked main selection to system clipboard".to_owned());
2523+}
2524+
2525+fn yank_main_selection_to_clipboard(cx: &mut Context) {
2526+ yank_main_selection_to_clipboard_impl(&mut cx.editor);
2527+}
2528+
25282529#[derive(Copy, Clone)]
25292530enum Paste {
25302531 Before,
@@ -2568,6 +2569,31 @@ fn paste_impl(
25682569 Some(transaction)
25692570}
25702571
2572+fn paste_clipboard_impl(editor: &mut Editor, action: Paste) {
2573+ let (view, doc) = current!(editor);
2574+
2575+ match editor
2576+ .clipboard_provider
2577+ .get_contents()
2578+ .map(|contents| paste_impl(&[contents], doc, view, action))
2579+ {
2580+ Ok(Some(transaction)) => {
2581+ doc.apply(&transaction, view.id);
2582+ doc.append_changes_to_history(view.id);
2583+ }
2584+ Ok(None) => {}
2585+ Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e),
2586+ }
2587+}
2588+
2589+fn paste_clipboard_after(cx: &mut Context) {
2590+ paste_clipboard_impl(&mut cx.editor, Paste::After);
2591+}
2592+
2593+fn paste_clipboard_before(cx: &mut Context) {
2594+ paste_clipboard_impl(&mut cx.editor, Paste::Before);
2595+}
2596+
25712597fn replace_with_yanked(cx: &mut Context) {
25722598 let reg_name = cx.selected_register.name();
25732599 let (view, doc) = current!(cx.editor);
@@ -2588,6 +2614,29 @@ fn replace_with_yanked(cx: &mut Context) {
25882614 }
25892615}
25902616
2617+fn replace_selections_with_clipboard_impl(editor: &mut Editor) {
2618+ let (view, doc) = current!(editor);
2619+
2620+ match editor.clipboard_provider.get_contents() {
2621+ Ok(contents) => {
2622+ let transaction =
2623+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
2624+ let max_to = doc.text().len_chars().saturating_sub(1);
2625+ let to = std::cmp::min(max_to, range.to() + 1);
2626+ (range.from(), to, Some(contents.as_str().into()))
2627+ });
2628+
2629+ doc.apply(&transaction, view.id);
2630+ doc.append_changes_to_history(view.id);
2631+ }
2632+ Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e),
2633+ }
2634+}
2635+
2636+fn replace_selections_with_clipboard(cx: &mut Context) {
2637+ replace_selections_with_clipboard_impl(&mut cx.editor);
2638+}
2639+
25912640// alt-p => paste every yanked selection after selected text
25922641// alt-P => paste every yanked selection before selected text
25932642// R => replace selected text with yanked text
@@ -3108,6 +3157,11 @@ fn space_mode(cx: &mut Context) {
31083157 'b' => buffer_picker(cx),
31093158 's' => symbol_picker(cx),
31103159 'w' => window_mode(cx),
3160+ 'y' => yank_joined_to_clipboard(cx),
3161+ 'Y' => yank_main_selection_to_clipboard(cx),
3162+ 'p' => paste_clipboard_after(cx),
3163+ 'P' => paste_clipboard_before(cx),
3164+ 'R' => replace_selections_with_clipboard(cx),
31113165 // ' ' => toggle_alternate_buffer(cx),
31123166 // TODO: temporary since space mode took its old key
31133167 ' ' => keep_primary_selection(cx),