cut text with Ctrl+X

This commit is contained in:
Anton-4 2021-02-10 16:44:14 +01:00
parent cc81c6e5ba
commit ae57b87b1e
4 changed files with 89 additions and 19 deletions

View file

@ -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)?
}
}
_ => (),

View file

@ -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<Clipboard>,
) -> Result<Option<Clipboard>, 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(())
}
}

View file

@ -25,13 +25,26 @@ pub fn init_model(file_path: &Path) -> EdResult<EdModel> {
})
}
pub fn get_selected_str(ed_model: &EdModel) -> EdResult<Option<&str>> {
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<Option<&str>> {
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(())
}
}

View file

@ -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}' // ^