diff options
author | Benoît CORTIER | 2021-06-14 21:37:17 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2021-06-20 14:25:53 +0000 |
commit | a2b8cfca34433b1d4595143652e10b58685d0dc0 (patch) | |
tree | 86c3dc49706da2755e8a4e8b0366842379392852 /helix-term/src/commands.rs | |
parent | d59c9f3bafefaa9cf65ca711fc0e2e5cc0d250ab (diff) |
Add system clipboard yank and paste commands
This commit adds six new commands to interact with system clipboard:
- clipboard-yank
- clipboard-yank-join
- clipboard-paste-after
- clipboard-paste-before
- clipboard-paste-replace
- show-clipboard-provider
System clipboard provider is detected by checking a few environment
variables and executables. Currently only built-in detection is
supported.
`clipboard-yank` will only yank the "main" selection, which is currently the first
one. This will need to be revisited later.
Closes https://github.com/helix-editor/helix/issues/76
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r-- | helix-term/src/commands.rs | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 3223b14f..5cfee75d 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1280,6 +1280,96 @@ mod cmd { editor.set_theme_from_name(theme); } + fn yank_main_selection_to_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) { + let (view, doc) = current!(editor); + + // TODO: currently the main selection is the first one. This needs to be revisited later. + let range = doc + .selection(view.id) + .ranges() + .first() + .expect("at least one selection"); + + let value = range.fragment(doc.text().slice(..)); + + if let Err(e) = editor.clipboard_provider.set_contents(value.into_owned()) { + log::error!("Couldn't set system clipboard content: {:?}", e); + } + + editor.set_status("yanked main selection to system clipboard".to_owned()); + } + + fn yank_joined_to_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) { + let (view, doc) = current!(editor); + + let values: Vec<String> = doc + .selection(view.id) + .fragments(doc.text().slice(..)) + .map(Cow::into_owned) + .collect(); + + let msg = format!( + "joined and yanked {} selection(s) to system clipboard", + values.len(), + ); + + let joined = values.join("\n"); + + if let Err(e) = editor.clipboard_provider.set_contents(joined) { + log::error!("Couldn't set system clipboard content: {:?}", e); + } + + editor.set_status(msg); + } + + fn paste_clipboard_impl(editor: &mut Editor, action: Paste) { + let (view, doc) = current!(editor); + + match editor + .clipboard_provider + .get_contents() + .map(|contents| paste_impl(&[contents], doc, view, action)) + { + Ok(Some(transaction)) => { + doc.apply(&transaction, view.id); + doc.append_changes_to_history(view.id); + } + Ok(None) => {} + Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e), + } + } + + fn paste_clipboard_after(editor: &mut Editor, _: &[&str], _: PromptEvent) { + paste_clipboard_impl(editor, Paste::After); + } + + fn paste_clipboard_before(editor: &mut Editor, args: &[&str], event: PromptEvent) { + paste_clipboard_impl(editor, Paste::After); + } + + fn replace_selections_with_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) { + let (view, doc) = current!(editor); + + match editor.clipboard_provider.get_contents() { + Ok(contents) => { + let transaction = + Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| { + let max_to = doc.text().len_chars().saturating_sub(1); + let to = std::cmp::min(max_to, range.to() + 1); + (range.from(), to, Some(contents.as_str().into())) + }); + + doc.apply(&transaction, view.id); + doc.append_changes_to_history(view.id); + } + Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e), + } + } + + fn show_clipboard_provider(editor: &mut Editor, _: &[&str], _: PromptEvent) { + editor.set_status(editor.clipboard_provider.name().into()); + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -1400,7 +1490,48 @@ mod cmd { fun: theme, completer: Some(completers::theme), }, - + TypableCommand { + name: "clipboard-yank", + alias: None, + doc: "Yank main selection into system clipboard.", + fun: yank_main_selection_to_clipboard, + completer: None, + }, + TypableCommand { + name: "clipboard-yank-join", + alias: None, + doc: "Yank joined selections into system clipboard.", + fun: yank_joined_to_clipboard, + completer: None, + }, + TypableCommand { + name: "clipboard-paste-after", + alias: None, + doc: "Paste system clipboard after selections.", + fun: paste_clipboard_after, + completer: None, + }, + TypableCommand { + name: "clipboard-paste-before", + alias: None, + doc: "Paste system clipboard before selections.", + fun: paste_clipboard_before, + completer: None, + }, + TypableCommand { + name: "clipboard-paste-replace", + alias: None, + doc: "Replace selections with content of system clipboard.", + fun: replace_selections_with_clipboard, + completer: None, + }, + TypableCommand { + name: "show-clipboard-provider", + alias: None, + doc: "Show clipboard provider name in status bar.", + fun: show_clipboard_provider, + completer: None, + }, ]; pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| { |