mirror of https://github.com/helix-editor/helix
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 contentspull/315/head
parent
a2b8cfca34
commit
f50261c944
|
@ -222,9 +222,14 @@ impl Command {
|
||||||
undo,
|
undo,
|
||||||
redo,
|
redo,
|
||||||
yank,
|
yank,
|
||||||
|
yank_joined_to_clipboard,
|
||||||
|
yank_main_selection_to_clipboard,
|
||||||
replace_with_yanked,
|
replace_with_yanked,
|
||||||
|
replace_selections_with_clipboard,
|
||||||
paste_after,
|
paste_after,
|
||||||
paste_before,
|
paste_before,
|
||||||
|
paste_clipboard_after,
|
||||||
|
paste_clipboard_before,
|
||||||
indent,
|
indent,
|
||||||
unindent,
|
unindent,
|
||||||
format_selections,
|
format_selections,
|
||||||
|
@ -1280,74 +1285,24 @@ mod cmd {
|
||||||
editor.set_theme_from_name(theme);
|
editor.set_theme_from_name(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn yank_main_selection_to_clipboard(editor: &mut Editor, args: &[&str], event: PromptEvent) {
|
fn yank_main_selection_to_clipboard(editor: &mut Editor, _: &[&str], _: PromptEvent) {
|
||||||
let (view, doc) = current!(editor);
|
yank_main_selection_to_clipboard_impl(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], _: PromptEvent) {
|
||||||
}
|
let separator = args.first().copied().unwrap_or("\n");
|
||||||
|
yank_joined_to_clipboard_impl(editor, separator);
|
||||||
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) {
|
fn paste_clipboard_after(editor: &mut Editor, _: &[&str], _: PromptEvent) {
|
||||||
paste_clipboard_impl(editor, Paste::After);
|
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);
|
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);
|
let (view, doc) = current!(editor);
|
||||||
|
|
||||||
match editor.clipboard_provider.get_contents() {
|
match editor.clipboard_provider.get_contents() {
|
||||||
|
@ -1500,7 +1455,7 @@ mod cmd {
|
||||||
TypableCommand {
|
TypableCommand {
|
||||||
name: "clipboard-yank-join",
|
name: "clipboard-yank-join",
|
||||||
alias: None,
|
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,
|
fun: yank_joined_to_clipboard,
|
||||||
completer: None,
|
completer: None,
|
||||||
},
|
},
|
||||||
|
@ -2525,6 +2480,52 @@ fn yank(cx: &mut Context) {
|
||||||
cx.editor.set_status(msg)
|
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)]
|
#[derive(Copy, Clone)]
|
||||||
enum Paste {
|
enum Paste {
|
||||||
Before,
|
Before,
|
||||||
|
@ -2568,6 +2569,31 @@ fn paste_impl(
|
||||||
Some(transaction)
|
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) {
|
fn replace_with_yanked(cx: &mut Context) {
|
||||||
let reg_name = cx.selected_register.name();
|
let reg_name = cx.selected_register.name();
|
||||||
let (view, doc) = current!(cx.editor);
|
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 after selected text
|
||||||
// alt-P => paste every yanked selection before selected text
|
// alt-P => paste every yanked selection before selected text
|
||||||
// R => replace selected text with yanked text
|
// R => replace selected text with yanked text
|
||||||
|
@ -3108,6 +3157,11 @@ fn space_mode(cx: &mut Context) {
|
||||||
'b' => buffer_picker(cx),
|
'b' => buffer_picker(cx),
|
||||||
's' => symbol_picker(cx),
|
's' => symbol_picker(cx),
|
||||||
'w' => window_mode(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),
|
// ' ' => toggle_alternate_buffer(cx),
|
||||||
// TODO: temporary since space mode took its old key
|
// TODO: temporary since space mode took its old key
|
||||||
' ' => keep_primary_selection(cx),
|
' ' => keep_primary_selection(cx),
|
||||||
|
|
Loading…
Reference in New Issue