From ae57b87b1eb1430b74be7ebc35106b95f8a82732 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 10 Feb 2021 16:44:14 +0100 Subject: [PATCH] cut text with Ctrl+X --- editor/src/keyboard_input.rs | 11 ++---- editor/src/mvc/app_update.rs | 70 +++++++++++++++++++++++++++++++++--- editor/src/mvc/ed_model.rs | 25 +++++++++---- editor/src/mvc/ed_update.rs | 2 +- 4 files changed, 89 insertions(+), 19 deletions(-) diff --git a/editor/src/keyboard_input.rs b/editor/src/keyboard_input.rs index 3478840a56..0a976a1a0f 100644 --- a/editor/src/keyboard_input.rs +++ b/editor/src/keyboard_input.rs @@ -1,6 +1,6 @@ use crate::error::EdResult; use crate::mvc::app_model::AppModel; -use crate::mvc::app_update::{handle_copy, handle_paste, pass_keydown_to_focused}; +use crate::mvc::app_update::{handle_copy, handle_cut, handle_paste, pass_keydown_to_focused}; use winit::event::VirtualKeyCode::*; use winit::event::{ElementState, ModifiersState, VirtualKeyCode}; @@ -22,11 +22,7 @@ pub fn handle_keydown( Copy => handle_copy(app_model)?, Paste => handle_paste(app_model)?, - Cut => { - //handle_cut(app_model)? - todo!("cut"); - } - + Cut => handle_cut(app_model)?, C => { if modifiers.ctrl() { handle_copy(app_model)? @@ -39,8 +35,7 @@ pub fn handle_keydown( } X => { if modifiers.ctrl() { - //handle_cut(app_model)? - todo!("cut"); + handle_cut(app_model)? } } _ => (), diff --git a/editor/src/mvc/app_update.rs b/editor/src/mvc/app_update.rs index 46a9c84647..ed18811688 100644 --- a/editor/src/mvc/app_update.rs +++ b/editor/src/mvc/app_update.rs @@ -8,7 +8,7 @@ use winit::event::{ModifiersState, VirtualKeyCode}; pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> { if let Some(ref mut ed_model) = app_model.ed_model_opt { if ed_model.has_focus { - let selected_str_opt = super::ed_model::get_selected_str(ed_model)?; + let selected_str_opt = ed_model.get_selected_str()?; if let Some(selected_str) = selected_str_opt { app_model::set_clipboard_txt(&mut app_model.clipboard_opt, selected_str)?; @@ -76,6 +76,22 @@ pub fn handle_paste(app_model: &mut AppModel) -> EdResult<()> { Ok(()) } +pub fn handle_cut(app_model: &mut AppModel) -> EdResult<()> { + if let Some(ref mut ed_model) = app_model.ed_model_opt { + if ed_model.has_focus { + let selected_str_opt = ed_model.get_selected_str()?; + + if let Some(selected_str) = selected_str_opt { + app_model::set_clipboard_txt(&mut app_model.clipboard_opt, selected_str)?; + + ed_model.del_selection()?; + } + } + } + + Ok(()) +} + pub fn pass_keydown_to_focused( modifiers: &ModifiersState, virtual_keycode: VirtualKeyCode, @@ -102,7 +118,7 @@ pub fn handle_new_char(received_char: &char, app_model: &mut AppModel) -> EdResu pub mod test_app_update { use crate::mvc::app_model; use crate::mvc::app_model::{AppModel, Clipboard}; - use crate::mvc::app_update::{handle_copy, handle_paste}; + use crate::mvc::app_update::{handle_copy, handle_cut, handle_paste}; use crate::mvc::ed_model::{EdModel, Position, RawSelection}; use crate::mvc::ed_update::test_ed_update::gen_caret_text_buf; use crate::selection::test_selection::{all_lines_vec, convert_selection_to_dsl}; @@ -171,12 +187,42 @@ pub mod test_app_update { Ok(app_model.clipboard_opt) } + fn assert_cut( + pre_lines_str: &[&str], + expected_clipboard_content: &str, + expected_post_lines_str: &[&str], + clipboard_opt: Option, + ) -> Result, String> { + let (caret_pos, selection_opt, pre_text_buf) = gen_caret_text_buf(pre_lines_str)?; + + let mut app_model = mock_app_model(pre_text_buf, caret_pos, selection_opt, clipboard_opt); + + handle_cut(&mut app_model)?; + + let clipboard_content = app_model::get_clipboard_txt(&mut app_model.clipboard_opt)?; + + assert_eq!(clipboard_content, expected_clipboard_content); + + let ed_model = app_model.ed_model_opt.unwrap(); + let mut text_buf_lines = all_lines_vec(&ed_model.text_buf); + let post_lines_str = convert_selection_to_dsl( + ed_model.selection_opt, + ed_model.caret_pos, + &mut text_buf_lines, + )?; + + assert_eq!(post_lines_str, expected_post_lines_str); + + Ok(app_model.clipboard_opt) + } + #[test] #[ignore] // ignored because of clipboard problems on ci - fn copy_paste() -> Result<(), String> { + fn copy_paste_cut() -> Result<(), String> { // can only init clipboard once let mut clipboard_opt = AppModel::init_clipboard_opt(); + // copy clipboard_opt = assert_copy(&["[a]|"], "a", clipboard_opt)?; clipboard_opt = assert_copy(&["|[b]"], "b", clipboard_opt)?; clipboard_opt = assert_copy(&["a[ ]|"], " ", clipboard_opt)?; @@ -188,6 +234,8 @@ pub mod test_app_update { "ef\nghi", clipboard_opt, )?; + + // paste clipboard_opt = assert_paste(&["|"], "", &["|"], clipboard_opt)?; clipboard_opt = assert_paste(&["|"], "a", &["a|"], clipboard_opt)?; clipboard_opt = assert_paste(&["a|"], "b", &["ab|"], clipboard_opt)?; @@ -196,13 +244,27 @@ pub mod test_app_update { clipboard_opt = assert_paste(&["[ab]|"], "d", &["d|"], clipboard_opt)?; clipboard_opt = assert_paste(&["a[b]|c"], "e", &["ae|c"], clipboard_opt)?; clipboard_opt = assert_paste(&["a\n", "[b\n", "]|"], "f", &["a\n", "f|"], clipboard_opt)?; - assert_paste( + clipboard_opt = assert_paste( &["abc\n", "d[ef\n", "ghi]|\n", "jkl"], "ef\nghi", &["abc\n", "def\n", "ghi|\n", "jkl"], clipboard_opt, )?; + // cut + clipboard_opt = assert_cut(&["[a]|"], "a", &["|"], clipboard_opt)?; + clipboard_opt = assert_cut(&["|[b]"], "b", &["|"], clipboard_opt)?; + clipboard_opt = assert_cut(&["a[ ]|"], " ", &["a|"], clipboard_opt)?; + clipboard_opt = assert_cut(&["[ ]|b"], " ", &["|b"], clipboard_opt)?; + clipboard_opt = assert_cut(&["a\n", "[b\n", "]|"], "b\n", &["a\n", "|"], clipboard_opt)?; + clipboard_opt = assert_cut(&["[a\n", " b\n", "]|"], "a\n b\n", &["|"], clipboard_opt)?; + assert_cut( + &["abc\n", "d[ef\n", "ghi]|\n", "jkl"], + "ef\nghi", + &["abc\n", "d|\n", "jkl"], + clipboard_opt, + )?; + Ok(()) } } diff --git a/editor/src/mvc/ed_model.rs b/editor/src/mvc/ed_model.rs index 5fcb3a080c..a9fa4f9733 100644 --- a/editor/src/mvc/ed_model.rs +++ b/editor/src/mvc/ed_model.rs @@ -25,13 +25,26 @@ pub fn init_model(file_path: &Path) -> EdResult { }) } -pub fn get_selected_str(ed_model: &EdModel) -> EdResult> { - if let Some(curr_selection) = ed_model.selection_opt { - let selected_str = ed_model.text_buf.get_selection(curr_selection)?; +impl EdModel { + pub fn get_selected_str(&self) -> EdResult> { + if let Some(curr_selection) = self.selection_opt { + let selected_str = self.text_buf.get_selection(curr_selection)?; - Ok(Some(selected_str)) - } else { - Ok(None) + Ok(Some(selected_str)) + } else { + Ok(None) + } + } + + pub fn del_selection(&mut self) -> EdResult<()> { + if let Some(selection) = self.selection_opt { + self.text_buf.del_selection(selection)?; + + self.caret_pos = selection.start_pos; + } + self.selection_opt = None; + + Ok(()) } } diff --git a/editor/src/mvc/ed_update.rs b/editor/src/mvc/ed_update.rs index 86fe4652e7..83cb701aec 100644 --- a/editor/src/mvc/ed_update.rs +++ b/editor/src/mvc/ed_update.rs @@ -353,7 +353,7 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult } '\u{3}' // Ctrl + C | '\u{16}' // Ctrl + V - | '\u{30}' // Ctrl + X + | '\u{18}' // Ctrl + X | '\u{e000}'..='\u{f8ff}' // http://www.unicode.org/faq/private_use.html | '\u{f0000}'..='\u{ffffd}' // ^ | '\u{100000}'..='\u{10fffd}' // ^