Add support for configuring clipboard used for mouse yank

Adds mouse_yank_clipboard configuration option under the
editor section:

[editor]
mouse-yank-clipboard = "system" / "primary" (default "primary")

This affects the following actions:
- Selecting text with mouse will yank to configured clipboard
- Pasting with middle mouse button will use configured clipboard
- Replacing selected text with ALT+middle mouse button will use
  configured clipboard

Without this option Helix will fallback to current behavior of using
the primary clipboard for the above mentioned actions.
This commit is contained in:
Daniel Åkerud 2023-05-31 10:19:56 +02:00 committed by Mathis Brossier
parent 0a4432b104
commit c0487fe23d
5 changed files with 33 additions and 18 deletions

View File

@ -24,6 +24,7 @@ ### `[editor]` Section
|--|--|---------| |--|--|---------|
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` | | `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` |
| `mouse` | Enable mouse mode | `true` | | `mouse` | Enable mouse mode | `true` |
| `mouse-yank-register` | Which register to use for mouse yanks. | `*` |
| `middle-click-paste` | Middle click paste support | `true` | | `middle-click-paste` | Middle click paste support | `true` |
| `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` | | `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` |
| `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` | | `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |

View File

@ -4174,7 +4174,7 @@ fn yank_joined_to_primary_clipboard(cx: &mut Context) {
exit_select_mode(cx); exit_select_mode(cx);
} }
fn yank_primary_selection_impl(editor: &mut Editor, register: char) { pub(crate) fn yank_main_selection_to_register(editor: &mut Editor, register: char) {
let (view, doc) = current!(editor); let (view, doc) = current!(editor);
let text = doc.text().slice(..); let text = doc.text().slice(..);
@ -4187,17 +4187,17 @@ fn yank_primary_selection_impl(editor: &mut Editor, register: char) {
} }
fn yank_main_selection_to_clipboard(cx: &mut Context) { fn yank_main_selection_to_clipboard(cx: &mut Context) {
yank_primary_selection_impl(cx.editor, '+'); yank_main_selection_to_register(cx.editor, '+');
exit_select_mode(cx); exit_select_mode(cx);
} }
fn yank_main_selection_to_primary_clipboard(cx: &mut Context) { fn yank_main_selection_to_primary_clipboard(cx: &mut Context) {
yank_primary_selection_impl(cx.editor, '*'); yank_main_selection_to_register(cx.editor, '*');
exit_select_mode(cx); exit_select_mode(cx);
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum Paste { pub(crate) enum Paste {
Before, Before,
After, After,
Cursor, Cursor,
@ -4314,11 +4314,11 @@ fn paste_primary_clipboard_before(cx: &mut Context) {
} }
fn replace_with_yanked(cx: &mut Context) { fn replace_with_yanked(cx: &mut Context) {
replace_with_yanked_impl(cx.editor, cx.register.unwrap_or('"'), cx.count()); replace_selections_with_register(cx.editor, cx.register.unwrap_or('"'), cx.count());
exit_select_mode(cx); exit_select_mode(cx);
} }
fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) { pub(crate) fn replace_selections_with_register(editor: &mut Editor, register: char, count: usize) {
let Some(values) = editor let Some(values) = editor
.registers .registers
.read(register, editor) .read(register, editor)
@ -4355,16 +4355,16 @@ fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) {
} }
fn replace_selections_with_clipboard(cx: &mut Context) { fn replace_selections_with_clipboard(cx: &mut Context) {
replace_with_yanked_impl(cx.editor, '+', cx.count()); replace_selections_with_register(cx.editor, '+', cx.count());
exit_select_mode(cx); exit_select_mode(cx);
} }
fn replace_selections_with_primary_clipboard(cx: &mut Context) { fn replace_selections_with_primary_clipboard(cx: &mut Context) {
replace_with_yanked_impl(cx.editor, '*', cx.count()); replace_selections_with_register(cx.editor, '*', cx.count());
exit_select_mode(cx); exit_select_mode(cx);
} }
fn paste(editor: &mut Editor, register: char, pos: Paste, count: usize) { pub(crate) fn paste(editor: &mut Editor, register: char, pos: Paste, count: usize) {
let Some(values) = editor.registers.read(register, editor) else { let Some(values) = editor.registers.read(register, editor) else {
return; return;
}; };

View File

@ -918,7 +918,7 @@ fn yank_main_selection_to_clipboard(
return Ok(()); return Ok(());
} }
yank_primary_selection_impl(cx.editor, '+'); yank_main_selection_to_register(cx.editor, '+');
Ok(()) Ok(())
} }
@ -966,7 +966,7 @@ fn yank_main_selection_to_primary_clipboard(
return Ok(()); return Ok(());
} }
yank_primary_selection_impl(cx.editor, '*'); yank_main_selection_to_register(cx.editor, '*');
Ok(()) Ok(())
} }
@ -1047,7 +1047,7 @@ fn replace_selections_with_clipboard(
return Ok(()); return Ok(());
} }
replace_with_yanked_impl(cx.editor, '+', 1); replace_selections_with_register(cx.editor, '+', 1);
Ok(()) Ok(())
} }
@ -1060,7 +1060,7 @@ fn replace_selections_with_primary_clipboard(
return Ok(()); return Ok(());
} }
replace_with_yanked_impl(cx.editor, '*', 1); replace_selections_with_register(cx.editor, '*', 1);
Ok(()) Ok(())
} }

View File

@ -1251,8 +1251,10 @@ fn handle_mouse_event(
}; };
if should_yank { if should_yank {
commands::MappableCommand::yank_main_selection_to_primary_clipboard commands::yank_main_selection_to_register(
.execute(cxt); cxt.editor,
config.mouse_yank_register,
);
EventResult::Consumed(None) EventResult::Consumed(None)
} else { } else {
EventResult::Ignored(None) EventResult::Ignored(None)
@ -1292,8 +1294,11 @@ fn handle_mouse_event(
} }
if modifiers == KeyModifiers::ALT { if modifiers == KeyModifiers::ALT {
commands::MappableCommand::replace_selections_with_primary_clipboard commands::replace_selections_with_register(
.execute(cxt); cxt.editor,
config.mouse_yank_register,
cxt.count(),
);
return EventResult::Consumed(None); return EventResult::Consumed(None);
} }
@ -1302,7 +1307,13 @@ fn handle_mouse_event(
let doc = doc_mut!(editor, &view!(editor, view_id).doc); let doc = doc_mut!(editor, &view!(editor, view_id).doc);
doc.set_selection(view_id, Selection::point(pos)); doc.set_selection(view_id, Selection::point(pos));
cxt.editor.focus(view_id); cxt.editor.focus(view_id);
commands::MappableCommand::paste_primary_clipboard_before.execute(cxt);
commands::paste(
cxt.editor,
config.mouse_yank_register,
commands::Paste::Before,
cxt.count(),
);
return EventResult::Consumed(None); return EventResult::Consumed(None);
} }

View File

@ -249,6 +249,8 @@ pub struct Config {
pub scroll_lines: isize, pub scroll_lines: isize,
/// Mouse support. Defaults to true. /// Mouse support. Defaults to true.
pub mouse: bool, pub mouse: bool,
/// Which register to use for mouse yank.
pub mouse_yank_register: char,
/// Shell to use for shell commands. Defaults to ["cmd", "/C"] on Windows and ["sh", "-c"] otherwise. /// Shell to use for shell commands. Defaults to ["cmd", "/C"] on Windows and ["sh", "-c"] otherwise.
pub shell: Vec<String>, pub shell: Vec<String>,
/// Line number mode. /// Line number mode.
@ -932,6 +934,7 @@ fn default() -> Self {
scrolloff: 5, scrolloff: 5,
scroll_lines: 3, scroll_lines: 3,
mouse: true, mouse: true,
mouse_yank_register: '*',
shell: if cfg!(windows) { shell: if cfg!(windows) {
vec!["cmd".to_owned(), "/C".to_owned()] vec!["cmd".to_owned(), "/C".to_owned()]
} else { } else {