@@ -12,8 +12,8 @@ use helix_core::{
14use helix_view::{
14use helix_view::{
15− document::Mode, editor::Action, input::KeyEvent, keyboard::KeyCode, view::View, Document,
15+ clipboard::ClipboardType, document::Mode, editor::Action, input::KeyEvent, keyboard::KeyCode,
16− DocumentId, Editor, ViewId,
16+ view::View, Document, DocumentId, Editor, ViewId,
19use anyhow::{anyhow, bail, Context as _};
19use anyhow::{anyhow, bail, Context as _};
@@ -258,12 +258,17 @@ impl Command {
258 yank, "Yank selection",
258 yank, "Yank selection",
259 yank_joined_to_clipboard, "Join and yank selections to clipboard",
259 yank_joined_to_clipboard, "Join and yank selections to clipboard",
260 yank_main_selection_to_clipboard, "Yank main selection to clipboard",
260 yank_main_selection_to_clipboard, "Yank main selection to clipboard",
261+ yank_joined_to_primary_clipboard, "Join and yank selections to primary clipboard",
262+ yank_main_selection_to_primary_clipboard, "Yank main selection to primary clipboard",
261 replace_with_yanked, "Replace with yanked text",
263 replace_with_yanked, "Replace with yanked text",
262 replace_selections_with_clipboard, "Replace selections by clipboard content",
264 replace_selections_with_clipboard, "Replace selections by clipboard content",
265+ replace_selections_with_primary_clipboard, "Replace selections by primary clipboard content",
263 paste_after, "Paste after selection",
266 paste_after, "Paste after selection",
264 paste_before, "Paste before selection",
267 paste_before, "Paste before selection",
265 paste_clipboard_after, "Paste clipboard after selections",
268 paste_clipboard_after, "Paste clipboard after selections",
266 paste_clipboard_before, "Paste clipboard before selections",
269 paste_clipboard_before, "Paste clipboard before selections",
270+ paste_primary_clipboard_after, "Paste primary clipboard after selections",
271+ paste_primary_clipboard_before, "Paste primary clipboard before selections",
267 indent, "Indent selection",
272 indent, "Indent selection",
268 unindent, "Unindent selection",
273 unindent, "Unindent selection",
269 format_selections, "Format selection",
274 format_selections, "Format selection",
@@ -1705,7 +1710,7 @@ mod cmd {
1705 _args: &[&str],
1710 _args: &[&str],
1706 _event: PromptEvent,
1711 _event: PromptEvent,
1707 ) -> anyhow::Result<()> {
1712 ) -> anyhow::Result<()> {
1708− yank_main_selection_to_clipboard_impl(&mut cx.editor)
1713+ yank_main_selection_to_clipboard_impl(&mut cx.editor, ClipboardType::Clipboard)
1711 fn yank_joined_to_clipboard(
1716 fn yank_joined_to_clipboard(
@@ -1718,7 +1723,28 @@ mod cmd {
1718 .first()
1723 .first()
1719 .copied()
1724 .copied()
1720 .unwrap_or_else(|| doc.line_ending.as_str());
1725 .unwrap_or_else(|| doc.line_ending.as_str());
1721− yank_joined_to_clipboard_impl(&mut cx.editor, separator)
1726+ yank_joined_to_clipboard_impl(&mut cx.editor, separator, ClipboardType::Clipboard)
1729+ fn yank_main_selection_to_primary_clipboard(
1730+ cx: &mut compositor::Context,
1732+ _event: PromptEvent,
1733+ ) -> anyhow::Result<()> {
1734+ yank_main_selection_to_clipboard_impl(&mut cx.editor, ClipboardType::Selection)
1737+ fn yank_joined_to_primary_clipboard(
1738+ cx: &mut compositor::Context,
1740+ _event: PromptEvent,
1741+ ) -> anyhow::Result<()> {
1742+ let (_, doc) = current!(cx.editor);
1743+ let separator = args
1746+ .unwrap_or_else(|| doc.line_ending.as_str());
1747+ yank_joined_to_clipboard_impl(&mut cx.editor, separator, ClipboardType::Selection)
1724 fn paste_clipboard_after(
1750 fn paste_clipboard_after(
@@ -1726,7 +1752,7 @@ mod cmd {
1726 _args: &[&str],
1752 _args: &[&str],
1727 _event: PromptEvent,
1753 _event: PromptEvent,
1728 ) -> anyhow::Result<()> {
1754 ) -> anyhow::Result<()> {
1729− paste_clipboard_impl(&mut cx.editor, Paste::After)
1755+ paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Clipboard)
1732 fn paste_clipboard_before(
1758 fn paste_clipboard_before(
@@ -1734,17 +1760,32 @@ mod cmd {
1734 _args: &[&str],
1760 _args: &[&str],
1735 _event: PromptEvent,
1761 _event: PromptEvent,
1736 ) -> anyhow::Result<()> {
1762 ) -> anyhow::Result<()> {
1737− paste_clipboard_impl(&mut cx.editor, Paste::After)
1763+ paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Clipboard)
1740− fn replace_selections_with_clipboard(
1766+ fn paste_primary_clipboard_after(
1741 cx: &mut compositor::Context,
1767 cx: &mut compositor::Context,
1742 _args: &[&str],
1768 _args: &[&str],
1743 _event: PromptEvent,
1769 _event: PromptEvent,
1770+ ) -> anyhow::Result<()> {
1771+ paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Selection)
1774+ fn paste_primary_clipboard_before(
1775+ cx: &mut compositor::Context,
1777+ _event: PromptEvent,
1778+ ) -> anyhow::Result<()> {
1779+ paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Selection)
1782+ fn replace_selections_with_clipboard_impl(
1783+ cx: &mut compositor::Context,
1784+ clipboard_type: ClipboardType,
1744 ) -> anyhow::Result<()> {
1785 ) -> anyhow::Result<()> {
1745 let (view, doc) = current!(cx.editor);
1786 let (view, doc) = current!(cx.editor);
1747− match cx.editor.clipboard_provider.get_contents() {
1788+ match cx.editor.clipboard_provider.get_contents(clipboard_type) {
1748 Ok(contents) => {
1789 Ok(contents) => {
1749 let selection = doc.selection(view.id);
1790 let selection = doc.selection(view.id);
1750 let transaction =
1791 let transaction =
@@ -1760,13 +1801,29 @@ mod cmd {
1804+ fn replace_selections_with_clipboard(
1805+ cx: &mut compositor::Context,
1807+ _event: PromptEvent,
1808+ ) -> anyhow::Result<()> {
1809+ replace_selections_with_clipboard_impl(cx, ClipboardType::Clipboard)
1812+ fn replace_selections_with_primary_clipboard(
1813+ cx: &mut compositor::Context,
1815+ _event: PromptEvent,
1816+ ) -> anyhow::Result<()> {
1817+ replace_selections_with_clipboard_impl(cx, ClipboardType::Selection)
1763 fn show_clipboard_provider(
1820 fn show_clipboard_provider(
1764 cx: &mut compositor::Context,
1821 cx: &mut compositor::Context,
1765 _args: &[&str],
1822 _args: &[&str],
1766 _event: PromptEvent,
1823 _event: PromptEvent,
1767 ) -> anyhow::Result<()> {
1824 ) -> anyhow::Result<()> {
1768 cx.editor
1825 cx.editor
1769− .set_status(cx.editor.clipboard_provider.name().into());
1826+ .set_status(cx.editor.clipboard_provider.name().to_string());
@@ -1967,6 +2024,20 @@ mod cmd {
1967 fun: yank_joined_to_clipboard,
2024 fun: yank_joined_to_clipboard,
1968 completer: None,
2025 completer: None,
2028+ name: "primary-clipboard-yank",
2030+ doc: "Yank main selection into system primary clipboard.",
2031+ fun: yank_main_selection_to_primary_clipboard,
2035+ name: "primary-clipboard-yank-join",
2037+ doc: "Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline.", // FIXME: current UI can't display long doc.
2038+ fun: yank_joined_to_primary_clipboard,
1970 TypableCommand {
2041 TypableCommand {
1971 name: "clipboard-paste-after",
2042 name: "clipboard-paste-after",
1972 alias: None,
2043 alias: None,
@@ -1988,6 +2059,27 @@ mod cmd {
1988 fun: replace_selections_with_clipboard,
2059 fun: replace_selections_with_clipboard,
1989 completer: None,
2060 completer: None,
2063+ name: "primary-clipboard-paste-after",
2065+ doc: "Paste primary clipboard after selections.",
2066+ fun: paste_primary_clipboard_after,
2070+ name: "primary-clipboard-paste-before",
2072+ doc: "Paste primary clipboard before selections.",
2073+ fun: paste_primary_clipboard_before,
2077+ name: "primary-clipboard-paste-replace",
2079+ doc: "Replace selections with content of system primary clipboard.",
2080+ fun: replace_selections_with_primary_clipboard,
1991 TypableCommand {
2083 TypableCommand {
1992 name: "show-clipboard-provider",
2084 name: "show-clipboard-provider",
1993 alias: None,
2085 alias: None,
@@ -3209,7 +3301,11 @@ fn yank(cx: &mut Context) {
3209 exit_select_mode(cx);
3301 exit_select_mode(cx);
3212−fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) -> anyhow::Result<()> {
3304+fn yank_joined_to_clipboard_impl(
3305+ editor: &mut Editor,
3307+ clipboard_type: ClipboardType,
3308+) -> anyhow::Result<()> {
3213 let (view, doc) = current!(editor);
3309 let (view, doc) = current!(editor);
3214 let text = doc.text().slice(..);
3310 let text = doc.text().slice(..);
@@ -3228,7 +3324,7 @@ fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) -> anyhow
3230 .clipboard_provider
3326 .clipboard_provider
3231− .set_contents(joined)
3327+ .set_contents(joined, clipboard_type)
3232 .context("Couldn't set system clipboard content")?;
3328 .context("Couldn't set system clipboard content")?;
3234 editor.set_status(msg);
3330 editor.set_status(msg);
@@ -3238,17 +3334,27 @@ fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) -> anyhow
3239fn yank_joined_to_clipboard(cx: &mut Context) {
3335fn yank_joined_to_clipboard(cx: &mut Context) {
3240 let line_ending = current!(cx.editor).1.line_ending;
3336 let line_ending = current!(cx.editor).1.line_ending;
3241− let _ = yank_joined_to_clipboard_impl(&mut cx.editor, line_ending.as_str());
3337+ let _ = yank_joined_to_clipboard_impl(
3339+ line_ending.as_str(),
3340+ ClipboardType::Clipboard,
3242 exit_select_mode(cx);
3342 exit_select_mode(cx);
3245−fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) -> anyhow::Result<()> {
3345+fn yank_main_selection_to_clipboard_impl(
3346+ editor: &mut Editor,
3347+ clipboard_type: ClipboardType,
3348+) -> anyhow::Result<()> {
3246 let (view, doc) = current!(editor);
3349 let (view, doc) = current!(editor);
3247 let text = doc.text().slice(..);
3350 let text = doc.text().slice(..);
3249 let value = doc.selection(view.id).primary().fragment(text);
3352 let value = doc.selection(view.id).primary().fragment(text);
3354+ if let Err(e) = editor
3355+ .clipboard_provider
3251− if let Err(e) = editor.clipboard_provider.set_contents(value.into_owned()) {
3356+ .set_contents(value.into_owned(), clipboard_type)
3252 bail!("Couldn't set system clipboard content: {:?}", e);
3358 bail!("Couldn't set system clipboard content: {:?}", e);
@@ -3257,7 +3363,20 @@ fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) -> anyhow::Result<
3259fn yank_main_selection_to_clipboard(cx: &mut Context) {
3365fn yank_main_selection_to_clipboard(cx: &mut Context) {
3260− let _ = yank_main_selection_to_clipboard_impl(&mut cx.editor);
3366+ let _ = yank_main_selection_to_clipboard_impl(&mut cx.editor, ClipboardType::Clipboard);
3369+fn yank_joined_to_primary_clipboard(cx: &mut Context) {
3370+ let line_ending = current!(cx.editor).1.line_ending;
3371+ let _ = yank_joined_to_clipboard_impl(
3373+ line_ending.as_str(),
3374+ ClipboardType::Selection,
3378+fn yank_main_selection_to_primary_clipboard(cx: &mut Context) {
3379+ let _ = yank_main_selection_to_clipboard_impl(&mut cx.editor, ClipboardType::Selection);
3261 exit_select_mode(cx);
3380 exit_select_mode(cx);
@@ -3310,12 +3429,16 @@ fn paste_impl(
3310 Some(transaction)
3429 Some(transaction)
3313−fn paste_clipboard_impl(editor: &mut Editor, action: Paste) -> anyhow::Result<()> {
3432+fn paste_clipboard_impl(
3433+ editor: &mut Editor,
3435+ clipboard_type: ClipboardType,
3436+) -> anyhow::Result<()> {
3314 let (view, doc) = current!(editor);
3437 let (view, doc) = current!(editor);
3316 match editor
3439 match editor
3317 .clipboard_provider
3440 .clipboard_provider
3318− .get_contents()
3441+ .get_contents(clipboard_type)
3319 .map(|contents| paste_impl(&[contents], doc, view, action))
3442 .map(|contents| paste_impl(&[contents], doc, view, action))
3321 Ok(Some(transaction)) => {
3444 Ok(Some(transaction)) => {
@@ -3329,11 +3452,19 @@ fn paste_clipboard_impl(editor: &mut Editor, action: Paste) -> anyhow::Result<()
3331fn paste_clipboard_after(cx: &mut Context) {
3454fn paste_clipboard_after(cx: &mut Context) {
3332− let _ = paste_clipboard_impl(&mut cx.editor, Paste::After);
3455+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Clipboard);
3335fn paste_clipboard_before(cx: &mut Context) {
3458fn paste_clipboard_before(cx: &mut Context) {
3336− let _ = paste_clipboard_impl(&mut cx.editor, Paste::Before);
3459+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::Before, ClipboardType::Clipboard);
3462+fn paste_primary_clipboard_after(cx: &mut Context) {
3463+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::After, ClipboardType::Selection);
3466+fn paste_primary_clipboard_before(cx: &mut Context) {
3467+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::Before, ClipboardType::Selection);
3339fn replace_with_yanked(cx: &mut Context) {
3470fn replace_with_yanked(cx: &mut Context) {
@@ -3358,10 +3489,13 @@ fn replace_with_yanked(cx: &mut Context) {
3361−fn replace_selections_with_clipboard_impl(editor: &mut Editor) -> anyhow::Result<()> {
3492+fn replace_selections_with_clipboard_impl(
3493+ editor: &mut Editor,
3494+ clipboard_type: ClipboardType,
3495+) -> anyhow::Result<()> {
3362 let (view, doc) = current!(editor);
3496 let (view, doc) = current!(editor);
3364− match editor.clipboard_provider.get_contents() {
3498+ match editor.clipboard_provider.get_contents(clipboard_type) {
3365 Ok(contents) => {
3499 Ok(contents) => {
3366 let selection = doc.selection(view.id);
3500 let selection = doc.selection(view.id);
3367 let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
3501 let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
@@ -3377,7 +3511,11 @@ fn replace_selections_with_clipboard_impl(editor: &mut Editor) -> anyhow::Result
3379fn replace_selections_with_clipboard(cx: &mut Context) {
3513fn replace_selections_with_clipboard(cx: &mut Context) {
3380− let _ = replace_selections_with_clipboard_impl(&mut cx.editor);
3514+ let _ = replace_selections_with_clipboard_impl(&mut cx.editor, ClipboardType::Clipboard);
3517+fn replace_selections_with_primary_clipboard(cx: &mut Context) {
3518+ let _ = replace_selections_with_clipboard_impl(&mut cx.editor, ClipboardType::Selection);
3383fn paste_after(cx: &mut Context) {
3521fn paste_after(cx: &mut Context) {