Skip to content

Commit

Permalink
Use separate variants to differentiate between local cut buffer and s…
Browse files Browse the repository at this point in the history
…ystem clipboard. Compile out all system clipboard functionality statically if feature is not active.
  • Loading branch information
Tastaturtaste committed Mar 12, 2024
1 parent 50172cb commit 39ba760
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 92 deletions.
82 changes: 25 additions & 57 deletions src/core_editor/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,15 @@ impl Editor {
self.move_left_until_char(*c, true, true, *select)
}
EditCommand::SelectAll => self.select_all(),
EditCommand::CutSelection {
system_clipboard: true,
} => self.cut_selection_to_system(),
EditCommand::CutSelection {
system_clipboard: false,
} => self.cut_selection_to_cut_buffer(),
EditCommand::CopySelection {
system_clipboard: true,
} => self.copy_selection_to_system(),
EditCommand::CopySelection {
system_clipboard: false,
} => self.copy_selection_to_cut_buffer(),
EditCommand::Paste {
system_clipboard: true,
} => self.paste_system_clipboard(),
EditCommand::Paste {
system_clipboard: false,
} => self.paste_cut_buffer(),
EditCommand::CutSelection => self.cut_selection_to_cut_buffer(),
EditCommand::CopySelection => self.copy_selection_to_cut_buffer(),
EditCommand::Paste => self.paste_cut_buffer(),
#[cfg(feature = "system_clipboard")]
EditCommand::CutSelectionSystem => self.cut_selection_to_system(),
#[cfg(feature = "system_clipboard")]
EditCommand::CopySelectionSystem => self.copy_selection_to_system(),
#[cfg(feature = "system_clipboard")]
EditCommand::PasteSystem => self.paste_from_system(),
}
if !matches!(command.edit_type(), EditType::MoveCursor { select: true }) {
self.selection_anchor = None;
Expand Down Expand Up @@ -535,10 +526,8 @@ impl Editor {
self.line_buffer.move_to_end();
}

#[cfg(feature = "system_clipboard")]
fn cut_selection_to_system(&mut self) {
#[cfg(not(feature = "system_clipboard"))]
panic!("The OS clipboard is not enabled. Enable its use with the reedline/system_clipboard feature!");
#[cfg(feature = "system_clipboard")]
if let Some((start, end)) = self.get_selection() {
let cut_slice = &self.line_buffer.get_buffer()[start..end];
self.system_clipboard.set(cut_slice, ClipboardMode::Normal);
Expand All @@ -556,10 +545,8 @@ impl Editor {
}
}

#[cfg(feature = "system_clipboard")]
fn copy_selection_to_system(&mut self) {
#[cfg(not(feature = "system_clipboard"))]
panic!("The OS clipboard is not enabled. Enable its use with the reedline/system_clipboard feature!");
#[cfg(feature = "system_clipboard")]
if let Some((start, end)) = self.get_selection() {
let cut_slice = &self.line_buffer.get_buffer()[start..end];
self.system_clipboard.set(cut_slice, ClipboardMode::Normal);
Expand Down Expand Up @@ -651,17 +638,10 @@ impl Editor {
self.line_buffer.insert_newline();
}

fn paste_system_clipboard(&mut self) {
#[cfg(not(feature = "system_clipboard"))]
panic!("The OS clipboard is not enabled. Enable its use with the reedline/system_clipboard feature!");
#[cfg(feature = "system_clipboard")]
{
self.delete_selection();
insert_clipboard_content_before(
&mut self.line_buffer,
self.system_clipboard.deref_mut(),
);
}
#[cfg(feature = "system_clipboard")]
fn paste_from_system(&mut self) {
self.delete_selection();
insert_clipboard_content_before(&mut self.line_buffer, self.system_clipboard.deref_mut());
}

fn paste_cut_buffer(&mut self) {
Expand Down Expand Up @@ -896,38 +876,26 @@ mod test {
editor.run_edit_command(&EditCommand::Undo);
assert_eq!(editor.get_buffer(), "This \r\n is a test");
}
#[cfg(not(feature = "system_clipboard"))]
#[cfg(feature = "system_clipboard")]
mod without_system_clipboard {
use super::*;
#[test]
#[should_panic]
fn test_cut_selection_panic() {
let mut editor = editor_with("This is a test!");
editor.selection_anchor = Some(editor.line_buffer.len());
editor.line_buffer.set_insertion_point(0);
editor.run_edit_command(&EditCommand::CutSelection {
system_clipboard: true,
});
}
#[test]
#[should_panic]
fn test_copy_selection_panic() {
fn test_cut_selection_system() {
let mut editor = editor_with("This is a test!");
editor.selection_anchor = Some(editor.line_buffer.len());
editor.line_buffer.set_insertion_point(0);
editor.run_edit_command(&EditCommand::CopySelection {
system_clipboard: true,
});
editor.run_edit_command(&EditCommand::CutSelectionSystem);
assert!(editor.line_buffer.get_buffer().is_empty());
}
#[test]
#[should_panic]
fn test_paste_selection_panic() {
let mut editor = editor_with("This is a test!");
fn test_copypaste_selection_system() {
let s = "This is a test!";
let mut editor = editor_with(s);
editor.selection_anchor = Some(editor.line_buffer.len());
editor.line_buffer.set_insertion_point(0);
editor.run_edit_command(&EditCommand::Paste {
system_clipboard: true,
});
editor.run_edit_command(&EditCommand::CopySelectionSystem);
editor.run_edit_command(&EditCommand::PasteSystem);
pretty_assertions::assert_eq!(editor.line_buffer.len(), s.len() * 2);
}
}
}
15 changes: 6 additions & 9 deletions src/edit_mode/keybindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,26 +214,23 @@ pub fn add_common_edit_bindings(kb: &mut Keybindings) {
// Base commands should not affect cut buffer
kb.add_binding(KM::CONTROL, KC::Char('h'), edit_bind(EC::Backspace));
kb.add_binding(KM::CONTROL, KC::Char('w'), edit_bind(EC::BackspaceWord));
#[cfg(feature = "system_clipboard")]
kb.add_binding(
KM::CONTROL | KM::SHIFT,
KC::Char('x'),
edit_bind(EC::CutSelection {
system_clipboard: true,
}),
edit_bind(EC::CutSelectionSystem),
);
#[cfg(feature = "system_clipboard")]
kb.add_binding(
KM::CONTROL | KM::SHIFT,
KC::Char('c'),
edit_bind(EC::CopySelection {
system_clipboard: true,
}),
edit_bind(EC::CopySelectionSystem),
);
#[cfg(feature = "system_clipboard")]
kb.add_binding(
KM::CONTROL | KM::SHIFT,
KC::Char('v'),
edit_bind(EC::Paste {
system_clipboard: true,
}),
edit_bind(EC::PasteSystem),
);
}

Expand Down
62 changes: 36 additions & 26 deletions src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum Signal {
/// Editing actions which can be mapped to key bindings.
///
/// Executed by `Reedline::run_edit_commands()`
#[non_exhaustive]
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, EnumIter)]
pub enum EditCommand {
/// Move to the start of the buffer
Expand Down Expand Up @@ -257,23 +258,26 @@ pub enum EditCommand {
/// Select whole input buffer
SelectAll,

/// Cut selection to local buffer or system clipboard
CutSelection {
/// Should the system clipboard be used as the destination of the content?
system_clipboard: bool,
},
/// Cut selection to local buffer
CutSelection,

/// Copy selection to local buffer or system clipboard
CopySelection {
/// Should the system clipboard be used as the destination of the content?
system_clipboard: bool,
},
/// Copy selection to local buffer
CopySelection,

/// Paste content from local buffer or system clipboard at the current cursor position
Paste {
/// Is the system clipboard the source of the paste operation?
system_clipboard: bool,
},
/// Paste content from local buffer at the current cursor position
Paste,

/// Cut selection to system clipboard
#[cfg(feature = "system_clipboard")]
CutSelectionSystem,

/// Copy selection to system clipboard
#[cfg(feature = "system_clipboard")]
CopySelectionSystem,

/// Paste content from system clipboard at the current cursor position
#[cfg(feature = "system_clipboard")]
PasteSystem,
}

impl Display for EditCommand {
Expand Down Expand Up @@ -358,13 +362,15 @@ impl Display for EditCommand {
EditCommand::CutLeftUntil(_) => write!(f, "CutLeftUntil Value: <char>"),
EditCommand::CutLeftBefore(_) => write!(f, "CutLeftBefore Value: <char>"),
EditCommand::SelectAll => write!(f, "SelectAll"),
EditCommand::CutSelection { .. } => {
write!(f, "CutSelectionToSystem system_clipboard: <bool>")
}
EditCommand::CopySelection { .. } => {
write!(f, "CopySelectionToSystem system_clipboard: <bool>")
}
EditCommand::Paste { .. } => write!(f, "PasteSystemClipboard system_clipboard: <bool>"),
EditCommand::CutSelection => write!(f, "CutSelection"),
EditCommand::CopySelection => write!(f, "CopySelection"),
EditCommand::Paste => write!(f, "Paste"),
#[cfg(feature = "system_clipboard")]
EditCommand::CutSelectionSystem => write!(f, "CutSelectionSystem"),
#[cfg(feature = "system_clipboard")]
EditCommand::CopySelectionSystem => write!(f, "CopySelectionSystem"),
#[cfg(feature = "system_clipboard")]
EditCommand::PasteSystem => write!(f, "PasteSystem"),
}
}
}
Expand Down Expand Up @@ -397,7 +403,6 @@ impl EditCommand {
}

EditCommand::SelectAll => EditType::MoveCursor { select: true },

// Text edits
EditCommand::InsertChar(_)
| EditCommand::Backspace
Expand Down Expand Up @@ -435,12 +440,17 @@ impl EditCommand {
| EditCommand::CutRightBefore(_)
| EditCommand::CutLeftUntil(_)
| EditCommand::CutLeftBefore(_)
| EditCommand::CutSelection { .. }
| EditCommand::Paste { .. } => EditType::EditText,
| EditCommand::CutSelection
| EditCommand::Paste => EditType::EditText,

#[cfg(feature = "system_clipboard")] // Sadly cfg attributes in patterns don't work
EditCommand::CutSelectionSystem | EditCommand::PasteSystem => EditType::EditText,

EditCommand::Undo | EditCommand::Redo => EditType::UndoRedo,

EditCommand::CopySelection { .. } => EditType::NoOp,
EditCommand::CopySelection => EditType::NoOp,
#[cfg(feature = "system_clipboard")]
EditCommand::CopySelectionSystem => EditType::NoOp,
}
}
}
Expand Down

0 comments on commit 39ba760

Please sign in to comment.