aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davis2023-07-11 15:23:49 +0000
committerBlaž Hrastnik2023-07-31 06:05:38 +0000
commit4555a6b4332b48384d4bccfef527d26060c34037 (patch)
treebaab80c83c6e4abe9bf9035794045d6ba575bb1f
parent2d838d729cca26a718e3536e8d75c60396420dbd (diff)
Reimplement clipboard commands in terms of special regs
Since the clipboard provider now lives on the Registers type, we want to eliminate it from the Editor. We can do that and clean up the commands that interact with the clipboard by calling regular yank, paste and replace impls on the clipboard special registers. Eventually the clipboard commands could be removed once macro keybinding is supported.
-rw-r--r--helix-term/src/commands.rs227
-rw-r--r--helix-term/src/commands/typed.rs55
-rw-r--r--helix-view/src/editor.rs4
-rw-r--r--helix-view/src/register.rs4
4 files changed, 89 insertions, 201 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 6f10848a..21e2933f 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -32,7 +32,6 @@ use helix_core::{
RopeReader, RopeSlice, Selection, SmallVec, Tendril, Transaction,
};
use helix_view::{
- clipboard::ClipboardType,
document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
editor::{Action, CompleteAction},
info::Info,
@@ -3759,7 +3758,12 @@ fn commit_undo_checkpoint(cx: &mut Context) {
// Yank / Paste
fn yank(cx: &mut Context) {
- let (view, doc) = current!(cx.editor);
+ yank_impl(cx.editor, cx.register.unwrap_or('"'));
+ exit_select_mode(cx);
+}
+
+fn yank_impl(editor: &mut Editor, register: char) {
+ let (view, doc) = current!(editor);
let text = doc.text().slice(..);
let values: Vec<String> = doc
@@ -3768,16 +3772,14 @@ fn yank(cx: &mut Context) {
.map(Cow::into_owned)
.collect();
let selections = values.len();
- let register = cx.register.unwrap_or('"');
- match cx.editor.registers.write(register, values) {
- Ok(_) => cx.editor.set_status(format!(
- "yanked {selections} selection(s) to register {register}",
+ match editor.registers.write(register, values) {
+ Ok(_) => editor.set_status(format!(
+ "yanked {selections} selection{} to register {register}",
+ if selections == 1 { "" } else { "s" }
)),
- Err(err) => cx.editor.set_error(err.to_string()),
+ Err(err) => editor.set_error(err.to_string()),
}
-
- exit_select_mode(cx);
}
fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
@@ -3798,100 +3800,50 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
match editor.registers.write(register, vec![joined]) {
Ok(_) => editor.set_status(format!(
- "joined and yanked {selections} selection(s) to register {register}",
+ "joined and yanked {selections} selection{} to register {register}",
+ if selections == 1 { "" } else { "s" }
)),
Err(err) => editor.set_error(err.to_string()),
}
}
fn yank_joined(cx: &mut Context) {
- let line_ending = doc!(cx.editor).line_ending;
- let register = cx.register.unwrap_or('"');
- yank_joined_impl(cx.editor, line_ending.as_str(), register);
+ let separator = doc!(cx.editor).line_ending.as_str();
+ yank_joined_impl(cx.editor, separator, cx.register.unwrap_or('"'));
exit_select_mode(cx);
}
-fn yank_joined_to_clipboard_impl(
- editor: &mut Editor,
- separator: &str,
- clipboard_type: ClipboardType,
-) -> anyhow::Result<()> {
- let (view, doc) = current!(editor);
- let text = doc.text().slice(..);
-
- let values: Vec<String> = doc
- .selection(view.id)
- .fragments(text)
- .map(Cow::into_owned)
- .collect();
-
- let clipboard_text = match clipboard_type {
- ClipboardType::Clipboard => "system clipboard",
- ClipboardType::Selection => "primary clipboard",
- };
-
- let msg = format!(
- "joined and yanked {} selection(s) to {}",
- values.len(),
- clipboard_text,
- );
-
- let joined = values.join(separator);
-
- editor
- .clipboard_provider
- .set_contents(joined, clipboard_type)
- .context("Couldn't set system clipboard content")?;
-
- editor.set_status(msg);
-
- Ok(())
+fn yank_joined_to_clipboard(cx: &mut Context) {
+ let line_ending = doc!(cx.editor).line_ending;
+ yank_joined_impl(cx.editor, line_ending.as_str(), '*');
+ exit_select_mode(cx);
}
-fn yank_joined_to_clipboard(cx: &mut Context) {
+fn yank_joined_to_primary_clipboard(cx: &mut Context) {
let line_ending = doc!(cx.editor).line_ending;
- let _ =
- yank_joined_to_clipboard_impl(cx.editor, line_ending.as_str(), ClipboardType::Clipboard);
+ yank_joined_impl(cx.editor, line_ending.as_str(), '+');
exit_select_mode(cx);
}
-fn yank_main_selection_to_clipboard_impl(
- editor: &mut Editor,
- clipboard_type: ClipboardType,
-) -> anyhow::Result<()> {
+fn yank_primary_selection_impl(editor: &mut Editor, register: char) {
let (view, doc) = current!(editor);
let text = doc.text().slice(..);
- let message_text = match clipboard_type {
- ClipboardType::Clipboard => "yanked main selection to system clipboard",
- ClipboardType::Selection => "yanked main selection to primary clipboard",
- };
-
- let value = doc.selection(view.id).primary().fragment(text);
+ let selection = doc.selection(view.id).primary().fragment(text).to_string();
- if let Err(e) = editor
- .clipboard_provider
- .set_contents(value.into_owned(), clipboard_type)
- {
- bail!("Couldn't set system clipboard content: {}", e);
+ match editor.registers.write(register, vec![selection]) {
+ Ok(_) => editor.set_status(format!("yanked primary selection to register {register}",)),
+ Err(err) => editor.set_error(err.to_string()),
}
-
- editor.set_status(message_text);
- Ok(())
}
fn yank_main_selection_to_clipboard(cx: &mut Context) {
- let _ = yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Clipboard);
-}
-
-fn yank_joined_to_primary_clipboard(cx: &mut Context) {
- let line_ending = doc!(cx.editor).line_ending;
- let _ =
- yank_joined_to_clipboard_impl(cx.editor, line_ending.as_str(), ClipboardType::Selection);
+ yank_primary_selection_impl(cx.editor, '*');
+ exit_select_mode(cx);
}
fn yank_main_selection_to_primary_clipboard(cx: &mut Context) {
- let _ = yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Selection);
+ yank_primary_selection_impl(cx.editor, '+');
exit_select_mode(cx);
}
@@ -3991,68 +3943,34 @@ pub(crate) fn paste_bracketed_value(cx: &mut Context, contents: String) {
paste_impl(&[contents], doc, view, paste, count, cx.editor.mode);
}
-fn paste_clipboard_impl(
- editor: &mut Editor,
- action: Paste,
- clipboard_type: ClipboardType,
- count: usize,
-) -> anyhow::Result<()> {
- let (view, doc) = current!(editor);
- match editor.clipboard_provider.get_contents(clipboard_type) {
- Ok(contents) => {
- paste_impl(&[contents], doc, view, action, count, editor.mode);
- Ok(())
- }
- Err(e) => Err(e.context("Couldn't get system clipboard contents")),
- }
-}
-
fn paste_clipboard_after(cx: &mut Context) {
- let _ = paste_clipboard_impl(
- cx.editor,
- Paste::After,
- ClipboardType::Clipboard,
- cx.count(),
- );
+ paste(cx.editor, '*', Paste::After, cx.count());
}
fn paste_clipboard_before(cx: &mut Context) {
- let _ = paste_clipboard_impl(
- cx.editor,
- Paste::Before,
- ClipboardType::Clipboard,
- cx.count(),
- );
+ paste(cx.editor, '*', Paste::Before, cx.count());
}
fn paste_primary_clipboard_after(cx: &mut Context) {
- let _ = paste_clipboard_impl(
- cx.editor,
- Paste::After,
- ClipboardType::Selection,
- cx.count(),
- );
+ paste(cx.editor, '+', Paste::After, cx.count());
}
fn paste_primary_clipboard_before(cx: &mut Context) {
- let _ = paste_clipboard_impl(
- cx.editor,
- Paste::Before,
- ClipboardType::Selection,
- cx.count(),
- );
+ paste(cx.editor, '+', Paste::Before, cx.count());
}
fn replace_with_yanked(cx: &mut Context) {
- let count = cx.count();
- let reg_name = cx.register.unwrap_or('"');
+ replace_with_yanked_impl(cx.editor, cx.register.unwrap_or('"'), cx.count());
+ exit_select_mode(cx);
+}
- let Some(values) = cx.editor.registers
- .read(reg_name, cx.editor)
+fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) {
+ let Some(values) = editor.registers
+ .read(register, editor)
.filter(|values| values.len() > 0) else { return };
let values: Vec<_> = values.map(|value| value.to_string()).collect();
- let (view, doc) = current!(cx.editor);
+ let (view, doc) = current!(editor);
let repeat = std::iter::repeat(
values
.last()
@@ -4073,62 +3991,40 @@ fn replace_with_yanked(cx: &mut Context) {
});
doc.apply(&transaction, view.id);
- exit_select_mode(cx);
-}
-
-fn replace_selections_with_clipboard_impl(
- cx: &mut Context,
- clipboard_type: ClipboardType,
-) -> anyhow::Result<()> {
- let count = cx.count();
- let (view, doc) = current!(cx.editor);
-
- match cx.editor.clipboard_provider.get_contents(clipboard_type) {
- Ok(contents) => {
- let selection = doc.selection(view.id);
- let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
- (
- range.from(),
- range.to(),
- Some(contents.repeat(count).as_str().into()),
- )
- });
-
- doc.apply(&transaction, view.id);
- doc.append_changes_to_history(view);
- }
- Err(e) => return Err(e.context("Couldn't get system clipboard contents")),
- }
-
- exit_select_mode(cx);
- Ok(())
}
fn replace_selections_with_clipboard(cx: &mut Context) {
- let _ = replace_selections_with_clipboard_impl(cx, ClipboardType::Clipboard);
+ replace_with_yanked_impl(cx.editor, '*', cx.count());
}
fn replace_selections_with_primary_clipboard(cx: &mut Context) {
- let _ = replace_selections_with_clipboard_impl(cx, ClipboardType::Selection);
+ replace_with_yanked_impl(cx.editor, '+', cx.count());
}
-fn paste(cx: &mut Context, pos: Paste) {
- let count = cx.count();
- let reg_name = cx.register.unwrap_or('"');
-
- let Some(values) = cx.editor.registers.read(reg_name, cx.editor) else { return };
+fn paste(editor: &mut Editor, register: char, pos: Paste, count: usize) {
+ let Some(values) = editor.registers.read(register, editor) else { return };
let values: Vec<_> = values.map(|value| value.to_string()).collect();
- let (view, doc) = current!(cx.editor);
- paste_impl(&values, doc, view, pos, count, cx.editor.mode);
+ let (view, doc) = current!(editor);
+ paste_impl(&values, doc, view, pos, count, editor.mode);
}
fn paste_after(cx: &mut Context) {
- paste(cx, Paste::After)
+ paste(
+ cx.editor,
+ cx.register.unwrap_or('"'),
+ Paste::After,
+ cx.count(),
+ );
}
fn paste_before(cx: &mut Context) {
- paste(cx, Paste::Before)
+ paste(
+ cx.editor,
+ cx.register.unwrap_or('"'),
+ Paste::Before,
+ cx.count(),
+ );
}
fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
@@ -4885,7 +4781,12 @@ fn insert_register(cx: &mut Context) {
if let Some(ch) = event.char() {
cx.editor.autoinfo = None;
cx.register = Some(ch);
- paste(cx, Paste::Cursor);
+ paste(
+ cx.editor,
+ cx.register.unwrap_or('"'),
+ Paste::Cursor,
+ cx.count(),
+ );
}
})
}
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 28759b3f..67640f79 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -904,7 +904,8 @@ fn yank_main_selection_to_clipboard(
return Ok(());
}
- yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Clipboard)
+ yank_primary_selection_impl(cx.editor, '*');
+ Ok(())
}
fn yank_joined(
@@ -938,7 +939,8 @@ fn yank_joined_to_clipboard(
let doc = doc!(cx.editor);
let default_sep = Cow::Borrowed(doc.line_ending.as_str());
let separator = args.first().unwrap_or(&default_sep);
- yank_joined_to_clipboard_impl(cx.editor, separator, ClipboardType::Clipboard)
+ yank_joined_impl(cx.editor, separator, '*');
+ Ok(())
}
fn yank_main_selection_to_primary_clipboard(
@@ -950,7 +952,8 @@ fn yank_main_selection_to_primary_clipboard(
return Ok(());
}
- yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Selection)
+ yank_primary_selection_impl(cx.editor, '+');
+ Ok(())
}
fn yank_joined_to_primary_clipboard(
@@ -965,7 +968,8 @@ fn yank_joined_to_primary_clipboard(
let doc = doc!(cx.editor);
let default_sep = Cow::Borrowed(doc.line_ending.as_str());
let separator = args.first().unwrap_or(&default_sep);
- yank_joined_to_clipboard_impl(cx.editor, separator, ClipboardType::Selection)
+ yank_joined_impl(cx.editor, separator, '+');
+ Ok(())
}
fn paste_clipboard_after(
@@ -977,7 +981,8 @@ fn paste_clipboard_after(
return Ok(());
}
- paste_clipboard_impl(cx.editor, Paste::After, ClipboardType::Clipboard, 1)
+ paste(cx.editor, '*', Paste::After, 1);
+ Ok(())
}
fn paste_clipboard_before(
@@ -989,7 +994,8 @@ fn paste_clipboard_before(
return Ok(());
}
- paste_clipboard_impl(cx.editor, Paste::Before, ClipboardType::Clipboard, 1)
+ paste(cx.editor, '*', Paste::Before, 1);
+ Ok(())
}
fn paste_primary_clipboard_after(
@@ -1001,7 +1007,8 @@ fn paste_primary_clipboard_after(
return Ok(());
}
- paste_clipboard_impl(cx.editor, Paste::After, ClipboardType::Selection, 1)
+ paste(cx.editor, '+', Paste::After, 1);
+ Ok(())
}
fn paste_primary_clipboard_before(
@@ -1013,30 +1020,8 @@ fn paste_primary_clipboard_before(
return Ok(());
}
- paste_clipboard_impl(cx.editor, Paste::Before, ClipboardType::Selection, 1)
-}
-
-fn replace_selections_with_clipboard_impl(
- cx: &mut compositor::Context,
- clipboard_type: ClipboardType,
-) -> anyhow::Result<()> {
- let scrolloff = cx.editor.config().scrolloff;
- let (view, doc) = current!(cx.editor);
-
- match cx.editor.clipboard_provider.get_contents(clipboard_type) {
- Ok(contents) => {
- let selection = doc.selection(view.id);
- let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
- (range.from(), range.to(), Some(contents.as_str().into()))
- });
-
- doc.apply(&transaction, view.id);
- doc.append_changes_to_history(view);
- view.ensure_cursor_in_view(doc, scrolloff);
- Ok(())
- }
- Err(e) => Err(e.context("Couldn't get system clipboard contents")),
- }
+ paste(cx.editor, '+', Paste::Before, 1);
+ Ok(())
}
fn replace_selections_with_clipboard(
@@ -1048,7 +1033,8 @@ fn replace_selections_with_clipboard(
return Ok(());
}
- replace_selections_with_clipboard_impl(cx, ClipboardType::Clipboard)
+ replace_with_yanked_impl(cx.editor, '*', 1);
+ Ok(())
}
fn replace_selections_with_primary_clipboard(
@@ -1060,7 +1046,8 @@ fn replace_selections_with_primary_clipboard(
return Ok(());
}
- replace_selections_with_clipboard_impl(cx, ClipboardType::Selection)
+ replace_with_yanked_impl(cx.editor, '+', 1);
+ Ok(())
}
fn show_clipboard_provider(
@@ -1073,7 +1060,7 @@ fn show_clipboard_provider(
}
cx.editor
- .set_status(cx.editor.clipboard_provider.name().to_string());
+ .set_status(cx.editor.registers.clipboard_provider_name().to_string());
Ok(())
}
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 1824ebf7..4ea1c49f 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -1,6 +1,5 @@
use crate::{
align_view,
- clipboard::{get_clipboard_provider, ClipboardProvider},
document::{DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint},
graphics::{CursorKind, Rect},
info::Info,
@@ -875,8 +874,6 @@ pub struct Editor {
pub debugger_events: SelectAll<UnboundedReceiverStream<dap::Payload>>,
pub breakpoints: HashMap<PathBuf, Vec<Breakpoint>>,
- pub clipboard_provider: Box<dyn ClipboardProvider>,
-
pub syn_loader: Arc<syntax::Loader>,
pub theme_loader: Arc<theme::Loader>,
/// last_theme is used for theme previews. We store the current theme here,
@@ -1023,7 +1020,6 @@ impl Editor {
last_theme: None,
last_selection: None,
registers: Registers::default(),
- clipboard_provider: get_clipboard_provider(),
status_msg: None,
autoinfo: None,
idle_timer: Box::pin(sleep(conf.idle_timeout)),
diff --git a/helix-view/src/register.rs b/helix-view/src/register.rs
index 61912378..3d1849a6 100644
--- a/helix-view/src/register.rs
+++ b/helix-view/src/register.rs
@@ -215,6 +215,10 @@ impl Registers {
)
}
}
+
+ pub fn clipboard_provider_name(&self) -> Cow<str> {
+ self.clipboard_provider.name()
+ }
}
fn read_from_clipboard<'a>(