aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoît CORTIER2021-06-19 06:27:43 +0000
committerBlaž Hrastnik2021-06-20 14:25:53 +0000
commitf50261c944d8cfbb5775dc9350f64a6eefde0295 (patch)
tree7611c8824ed961cb7c89f3897a2cedd55377c83d
parenta2b8cfca34433b1d4595143652e10b58685d0dc0 (diff)
Add mappable commands for system clipboard
System clipboard integration exists now in two favors: typable and mappable. Default mappings are: - SPC p: paste clipboard after - SPC P: paste clipboard before - SPC y: join and yank selection to clipboard - SPC Y: yank main selection to clipboard - SPC R: replace selections by clipboard contents
-rw-r--r--helix-term/src/commands.rs170
1 files changed, 112 insertions, 58 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 5cfee75d..8c290979 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -222,9 +222,14 @@ impl Command {
undo,
redo,
yank,
+ yank_joined_to_clipboard,
+ yank_main_selection_to_clipboard,
replace_with_yanked,
+ replace_selections_with_clipboard,
paste_after,
paste_before,
+ paste_clipboard_after,
+ paste_clipboard_before,
indent,
unindent,
format_selections,
@@ -1280,74 +1285,24 @@ 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_main_selection_to_clipboard(editor: &mut Editor, _: &[&str], _: PromptEvent) {
+ yank_main_selection_to_clipboard_impl(editor);
}
- 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 yank_joined_to_clipboard(editor: &mut Editor, args: &[&str], _: PromptEvent) {
+ let separator = args.first().copied().unwrap_or("\n");
+ yank_joined_to_clipboard_impl(editor, separator);
}
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) {
+ fn paste_clipboard_before(editor: &mut Editor, _: &[&str], _: PromptEvent) {
paste_clipboard_impl(editor, Paste::After);
}
- fn replace_selections_with_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) {
+ fn replace_selections_with_clipboard(editor: &mut Editor, _: &[&str], _: PromptEvent) {
let (view, doc) = current!(editor);
match editor.clipboard_provider.get_contents() {
@@ -1500,7 +1455,7 @@ mod cmd {
TypableCommand {
name: "clipboard-yank-join",
alias: None,
- doc: "Yank joined selections into system clipboard.",
+ 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.
fun: yank_joined_to_clipboard,
completer: None,
},
@@ -2525,6 +2480,52 @@ fn yank(cx: &mut Context) {
cx.editor.set_status(msg)
}
+fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) {
+ 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(separator);
+
+ if let Err(e) = editor.clipboard_provider.set_contents(joined) {
+ log::error!("Couldn't set system clipboard content: {:?}", e);
+ }
+
+ editor.set_status(msg);
+}
+
+fn yank_joined_to_clipboard(cx: &mut Context) {
+ yank_joined_to_clipboard_impl(&mut cx.editor, "\n");
+}
+
+fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) {
+ let (view, doc) = current!(editor);
+
+ let value = doc
+ .selection(view.id)
+ .primary()
+ .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_main_selection_to_clipboard(cx: &mut Context) {
+ yank_main_selection_to_clipboard_impl(&mut cx.editor);
+}
+
#[derive(Copy, Clone)]
enum Paste {
Before,
@@ -2568,6 +2569,31 @@ fn paste_impl(
Some(transaction)
}
+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(cx: &mut Context) {
+ paste_clipboard_impl(&mut cx.editor, Paste::After);
+}
+
+fn paste_clipboard_before(cx: &mut Context) {
+ paste_clipboard_impl(&mut cx.editor, Paste::Before);
+}
+
fn replace_with_yanked(cx: &mut Context) {
let reg_name = cx.selected_register.name();
let (view, doc) = current!(cx.editor);
@@ -2588,6 +2614,29 @@ fn replace_with_yanked(cx: &mut Context) {
}
}
+fn replace_selections_with_clipboard_impl(editor: &mut Editor) {
+ 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 replace_selections_with_clipboard(cx: &mut Context) {
+ replace_selections_with_clipboard_impl(&mut cx.editor);
+}
+
// alt-p => paste every yanked selection after selected text
// alt-P => paste every yanked selection before selected text
// R => replace selected text with yanked text
@@ -3108,6 +3157,11 @@ fn space_mode(cx: &mut Context) {
'b' => buffer_picker(cx),
's' => symbol_picker(cx),
'w' => window_mode(cx),
+ 'y' => yank_joined_to_clipboard(cx),
+ 'Y' => yank_main_selection_to_clipboard(cx),
+ 'p' => paste_clipboard_after(cx),
+ 'P' => paste_clipboard_before(cx),
+ 'R' => replace_selections_with_clipboard(cx),
// ' ' => toggle_alternate_buffer(cx),
// TODO: temporary since space mode took its old key
' ' => keep_primary_selection(cx),