From a193497c370450fda5e90bd54b803dcfabbd5009 Mon Sep 17 00:00:00 2001 From: thomasschafer Date: Fri, 31 Jan 2025 16:04:30 +0000 Subject: [PATCH 1/2] Add command to swap anchor and cursor --- src/core_editor/editor.rs | 9 +++++++++ src/edit_mode/vi/command.rs | 8 ++++++++ src/enums.rs | 4 ++++ 3 files changed, 21 insertions(+) diff --git a/src/core_editor/editor.rs b/src/core_editor/editor.rs index 68b8bc89..27d33f30 100644 --- a/src/core_editor/editor.rs +++ b/src/core_editor/editor.rs @@ -163,6 +163,7 @@ impl Editor { ); } } + EditCommand::SwapCursorAndAnchor => self.swap_cursor_and_anchor(), #[cfg(feature = "system_clipboard")] EditCommand::CutSelectionSystem => self.cut_selection_to_system(), #[cfg(feature = "system_clipboard")] @@ -194,6 +195,14 @@ impl Editor { self.update_undo_state(new_undo_behavior); } + + fn swap_cursor_and_anchor(&mut self) { + if let Some(anchor) = self.selection_anchor { + self.selection_anchor = Some(self.insertion_point()); + self.line_buffer.set_insertion_point(anchor); + } + } + fn update_selection_anchor(&mut self, select: bool) { self.selection_anchor = if select { self.selection_anchor diff --git a/src/edit_mode/vi/command.rs b/src/edit_mode/vi/command.rs index 2b0a98d6..94871c19 100644 --- a/src/edit_mode/vi/command.rs +++ b/src/edit_mode/vi/command.rs @@ -113,6 +113,10 @@ where let _ = input.next(); Some(Command::RepeatLastAction) } + Some('o') => { + let _ = input.next(); + Some(Command::SwapCursorAndAnchor) + } _ => None, } } @@ -143,6 +147,7 @@ pub enum Command { ChangeInsidePair { left: char, right: char }, DeleteInsidePair { left: char, right: char }, YankInsidePair { left: char, right: char }, + SwapCursorAndAnchor, } impl Command { @@ -222,6 +227,9 @@ impl Command { right: *right, })] } + Self::SwapCursorAndAnchor => { + vec![ReedlineOption::Edit(EditCommand::SwapCursorAndAnchor)] + } } } diff --git a/src/enums.rs b/src/enums.rs index f8e7f5d7..53913db4 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -317,6 +317,8 @@ pub enum EditCommand { /// Copy left before char CopyLeftBefore(char), + /// Swap the positions of the cursor and anchor + SwapCursorAndAnchor, /// Cut selection to system clipboard #[cfg(feature = "system_clipboard")] @@ -448,6 +450,7 @@ impl Display for EditCommand { EditCommand::CopyRightBefore(_) => write!(f, "CopyRightBefore Value: "), EditCommand::CopyLeftUntil(_) => write!(f, "CopyLeftUntil Value: "), EditCommand::CopyLeftBefore(_) => write!(f, "CopyLeftBefore Value: "), + EditCommand::SwapCursorAndAnchor => write!(f, "SwapCursorAndAnchor"), #[cfg(feature = "system_clipboard")] EditCommand::CutSelectionSystem => write!(f, "CutSelectionSystem"), #[cfg(feature = "system_clipboard")] @@ -486,6 +489,7 @@ impl EditCommand { | EditCommand::MoveLeftBefore { select, .. } => { EditType::MoveCursor { select: *select } } + EditCommand::SwapCursorAndAnchor => EditType::MoveCursor { select: true }, EditCommand::SelectAll => EditType::MoveCursor { select: true }, // Text edits From 1df24d5b6712adbe017c73c68ea33b71817fb79a Mon Sep 17 00:00:00 2001 From: thomasschafer Date: Fri, 31 Jan 2025 16:26:33 +0000 Subject: [PATCH 2/2] Add test for swapping anchor and cursor --- src/core_editor/editor.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/core_editor/editor.rs b/src/core_editor/editor.rs index 27d33f30..2ce8e8c9 100644 --- a/src/core_editor/editor.rs +++ b/src/core_editor/editor.rs @@ -1127,6 +1127,31 @@ mod test { editor.run_edit_command(&EditCommand::Undo); assert_eq!(editor.get_buffer(), "This \r\n is a test"); } + + #[test] + fn test_swap_cursor_and_anchor() { + let mut editor = editor_with("This is some test content"); + editor.line_buffer.set_insertion_point(0); + editor.update_selection_anchor(true); + + for _ in 0..3 { + editor.run_edit_command(&EditCommand::MoveRight { select: true }); + } + assert_eq!(editor.selection_anchor, Some(0)); + assert_eq!(editor.insertion_point(), 3); + assert_eq!(editor.get_selection(), Some((0, 4))); + + editor.run_edit_command(&EditCommand::SwapCursorAndAnchor); + assert_eq!(editor.selection_anchor, Some(3)); + assert_eq!(editor.insertion_point(), 0); + assert_eq!(editor.get_selection(), Some((0, 4))); + + editor.run_edit_command(&EditCommand::SwapCursorAndAnchor); + assert_eq!(editor.selection_anchor, Some(0)); + assert_eq!(editor.insertion_point(), 3); + assert_eq!(editor.get_selection(), Some((0, 4))); + } + #[cfg(feature = "system_clipboard")] mod without_system_clipboard { use super::*;