mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
cut text with Ctrl+X
This commit is contained in:
parent
cc81c6e5ba
commit
ae57b87b1e
4 changed files with 89 additions and 19 deletions
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::EdResult;
|
use crate::error::EdResult;
|
||||||
use crate::mvc::app_model::AppModel;
|
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::VirtualKeyCode::*;
|
||||||
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
|
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
|
||||||
|
|
||||||
|
@ -22,11 +22,7 @@ pub fn handle_keydown(
|
||||||
|
|
||||||
Copy => handle_copy(app_model)?,
|
Copy => handle_copy(app_model)?,
|
||||||
Paste => handle_paste(app_model)?,
|
Paste => handle_paste(app_model)?,
|
||||||
Cut => {
|
Cut => handle_cut(app_model)?,
|
||||||
//handle_cut(app_model)?
|
|
||||||
todo!("cut");
|
|
||||||
}
|
|
||||||
|
|
||||||
C => {
|
C => {
|
||||||
if modifiers.ctrl() {
|
if modifiers.ctrl() {
|
||||||
handle_copy(app_model)?
|
handle_copy(app_model)?
|
||||||
|
@ -39,8 +35,7 @@ pub fn handle_keydown(
|
||||||
}
|
}
|
||||||
X => {
|
X => {
|
||||||
if modifiers.ctrl() {
|
if modifiers.ctrl() {
|
||||||
//handle_cut(app_model)?
|
handle_cut(app_model)?
|
||||||
todo!("cut");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -8,7 +8,7 @@ use winit::event::{ModifiersState, VirtualKeyCode};
|
||||||
pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> {
|
pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> {
|
||||||
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
||||||
if ed_model.has_focus {
|
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 {
|
if let Some(selected_str) = selected_str_opt {
|
||||||
app_model::set_clipboard_txt(&mut app_model.clipboard_opt, selected_str)?;
|
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(())
|
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(
|
pub fn pass_keydown_to_focused(
|
||||||
modifiers: &ModifiersState,
|
modifiers: &ModifiersState,
|
||||||
virtual_keycode: VirtualKeyCode,
|
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 {
|
pub mod test_app_update {
|
||||||
use crate::mvc::app_model;
|
use crate::mvc::app_model;
|
||||||
use crate::mvc::app_model::{AppModel, Clipboard};
|
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_model::{EdModel, Position, RawSelection};
|
||||||
use crate::mvc::ed_update::test_ed_update::gen_caret_text_buf;
|
use crate::mvc::ed_update::test_ed_update::gen_caret_text_buf;
|
||||||
use crate::selection::test_selection::{all_lines_vec, convert_selection_to_dsl};
|
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)
|
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]
|
#[test]
|
||||||
#[ignore] // ignored because of clipboard problems on ci
|
#[ignore] // ignored because of clipboard problems on ci
|
||||||
fn copy_paste() -> Result<(), String> {
|
fn copy_paste_cut() -> Result<(), String> {
|
||||||
// can only init clipboard once
|
// can only init clipboard once
|
||||||
let mut clipboard_opt = AppModel::init_clipboard_opt();
|
let mut clipboard_opt = AppModel::init_clipboard_opt();
|
||||||
|
|
||||||
|
// copy
|
||||||
clipboard_opt = assert_copy(&["[a]|"], "a", clipboard_opt)?;
|
clipboard_opt = assert_copy(&["[a]|"], "a", clipboard_opt)?;
|
||||||
clipboard_opt = assert_copy(&["|[b]"], "b", clipboard_opt)?;
|
clipboard_opt = assert_copy(&["|[b]"], "b", clipboard_opt)?;
|
||||||
clipboard_opt = assert_copy(&["a[ ]|"], " ", clipboard_opt)?;
|
clipboard_opt = assert_copy(&["a[ ]|"], " ", clipboard_opt)?;
|
||||||
|
@ -188,6 +234,8 @@ pub mod test_app_update {
|
||||||
"ef\nghi",
|
"ef\nghi",
|
||||||
clipboard_opt,
|
clipboard_opt,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// paste
|
||||||
clipboard_opt = assert_paste(&["|"], "", &["|"], clipboard_opt)?;
|
clipboard_opt = assert_paste(&["|"], "", &["|"], clipboard_opt)?;
|
||||||
clipboard_opt = assert_paste(&["|"], "a", &["a|"], clipboard_opt)?;
|
clipboard_opt = assert_paste(&["|"], "a", &["a|"], clipboard_opt)?;
|
||||||
clipboard_opt = assert_paste(&["a|"], "b", &["ab|"], 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(&["[ab]|"], "d", &["d|"], clipboard_opt)?;
|
||||||
clipboard_opt = assert_paste(&["a[b]|c"], "e", &["ae|c"], 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)?;
|
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"],
|
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"],
|
||||||
"ef\nghi",
|
"ef\nghi",
|
||||||
&["abc\n", "def\n", "ghi|\n", "jkl"],
|
&["abc\n", "def\n", "ghi|\n", "jkl"],
|
||||||
clipboard_opt,
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,27 @@ pub fn init_model(file_path: &Path) -> EdResult<EdModel> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_selected_str(ed_model: &EdModel) -> EdResult<Option<&str>> {
|
impl EdModel {
|
||||||
if let Some(curr_selection) = ed_model.selection_opt {
|
pub fn get_selected_str(&self) -> EdResult<Option<&str>> {
|
||||||
let selected_str = ed_model.text_buf.get_selection(curr_selection)?;
|
if let Some(curr_selection) = self.selection_opt {
|
||||||
|
let selected_str = self.text_buf.get_selection(curr_selection)?;
|
||||||
|
|
||||||
Ok(Some(selected_str))
|
Ok(Some(selected_str))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
|
@ -353,7 +353,7 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
|
||||||
}
|
}
|
||||||
'\u{3}' // Ctrl + C
|
'\u{3}' // Ctrl + C
|
||||||
| '\u{16}' // Ctrl + V
|
| '\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{e000}'..='\u{f8ff}' // http://www.unicode.org/faq/private_use.html
|
||||||
| '\u{f0000}'..='\u{ffffd}' // ^
|
| '\u{f0000}'..='\u{ffffd}' // ^
|
||||||
| '\u{100000}'..='\u{10fffd}' // ^
|
| '\u{100000}'..='\u{10fffd}' // ^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue