Merge branch 'trunk' into valgrind_ci

This commit is contained in:
Richard Feldman 2021-02-12 19:21:46 -05:00 committed by GitHub
commit c7a61f55d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 2 deletions

View file

@ -38,6 +38,9 @@ pub fn handle_keydown(
handle_cut(app_model)? handle_cut(app_model)?
} }
} }
A => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model),
_ => (), _ => (),
} }

View file

@ -318,6 +318,20 @@ fn del_selection(selection: RawSelection, ed_model: &mut EdModel) -> EdResult<()
Ok(()) Ok(())
} }
// TODO move this to impl EdModel
pub fn handle_select_all(ed_model: &mut EdModel) {
if ed_model.text_buf.nr_of_chars() > 0 {
let last_pos = ed_model.text_buf.last_position();
ed_model.selection_opt = Some(RawSelection {
start_pos: Position { line: 0, column: 0 },
end_pos: last_pos,
});
ed_model.caret_pos = last_pos;
}
}
pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<()> { pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<()> {
let old_caret_pos = ed_model.caret_pos; let old_caret_pos = ed_model.caret_pos;
@ -351,7 +365,8 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
ed_model.selection_opt = None; ed_model.selection_opt = None;
} }
'\u{3}' // Ctrl + C '\u{1}' // Ctrl + A
| '\u{3}' // Ctrl + C
| '\u{16}' // Ctrl + V | '\u{16}' // Ctrl + V
| '\u{18}' // 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
@ -397,6 +412,12 @@ pub fn handle_key_down(
Up => handle_arrow(move_caret_up, modifiers, ed_model), Up => handle_arrow(move_caret_up, modifiers, ed_model),
Right => handle_arrow(move_caret_right, modifiers, ed_model), Right => handle_arrow(move_caret_right, modifiers, ed_model),
Down => handle_arrow(move_caret_down, modifiers, ed_model), Down => handle_arrow(move_caret_down, modifiers, ed_model),
A => {
if modifiers.ctrl() {
handle_select_all(ed_model)
}
}
_ => {} _ => {}
} }
} }
@ -405,7 +426,7 @@ pub fn handle_key_down(
pub mod test_ed_update { pub mod test_ed_update {
use crate::mvc::app_update::test_app_update::mock_app_model; use crate::mvc::app_update::test_app_update::mock_app_model;
use crate::mvc::ed_model::{Position, RawSelection}; use crate::mvc::ed_model::{Position, RawSelection};
use crate::mvc::ed_update::handle_new_char; use crate::mvc::ed_update::{handle_new_char, handle_select_all};
use crate::selection::test_selection::{ use crate::selection::test_selection::{
all_lines_vec, convert_dsl_to_selection, convert_selection_to_dsl, text_buffer_from_dsl_str, all_lines_vec, convert_dsl_to_selection, convert_selection_to_dsl, text_buffer_from_dsl_str,
}; };
@ -554,4 +575,51 @@ pub mod test_ed_update {
Ok(()) Ok(())
} }
fn assert_select_all(
pre_lines_str: &[&str],
expected_post_lines_str: &[&str],
) -> Result<(), String> {
let (caret_pos, selection_opt, pre_text_buf) = gen_caret_text_buf(pre_lines_str)?;
let app_model = mock_app_model(pre_text_buf, caret_pos, selection_opt, None);
let mut ed_model = app_model.ed_model_opt.unwrap();
handle_select_all(&mut ed_model);
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(())
}
#[test]
fn select_all() -> Result<(), String> {
assert_select_all(&["|"], &["|"])?;
assert_select_all(&["|a"], &["[a]|"])?;
assert_select_all(&["a|"], &["[a]|"])?;
assert_select_all(&["abc d|ef ghi"], &["[abc def ghi]|"])?;
assert_select_all(&["[a]|"], &["[a]|"])?;
assert_select_all(&["|[a]"], &["[a]|"])?;
assert_select_all(&["|[abc def ghi]"], &["[abc def ghi]|"])?;
assert_select_all(&["a\n", "[b\n", "]|"], &["[a\n", "b\n", "]|"])?;
assert_select_all(&["a\n", "[b]|\n", ""], &["[a\n", "b\n", "]|"])?;
assert_select_all(&["a\n", "|[b\n", "]"], &["[a\n", "b\n", "]|"])?;
assert_select_all(
&["abc\n", "def\n", "gh|i\n", "jkl"],
&["[abc\n", "def\n", "ghi\n", "jkl]|"],
)?;
assert_select_all(
&["|[abc\n", "def\n", "ghi\n", "jkl]"],
&["[abc\n", "def\n", "ghi\n", "jkl]|"],
)?;
Ok(())
}
} }

View file

@ -116,6 +116,10 @@ impl TextBuffer {
self.text_rope.len_lines() self.text_rope.len_lines()
} }
pub fn nr_of_chars(&self) -> usize {
self.text_rope.len_chars()
}
// expensive function, don't use it if it can be done with a specialized, more efficient function // expensive function, don't use it if it can be done with a specialized, more efficient function
// TODO use pool allocation here // TODO use pool allocation here
pub fn all_lines<'a>(&self, arena: &'a Bump) -> BumpString<'a> { pub fn all_lines<'a>(&self, arena: &'a Bump) -> BumpString<'a> {
@ -132,6 +136,16 @@ impl TextBuffer {
self.text_rope.line_to_char(pos.line) + pos.column self.text_rope.line_to_char(pos.line) + pos.column
} }
fn char_indx_to_pos(&self, char_indx: usize) -> Position {
let line = self.text_rope.char_to_line(char_indx);
let char_idx_line_start = self.pos_to_char_indx(Position { line, column: 0 });
let column = char_indx - char_idx_line_start;
Position { line, column }
}
fn sel_to_tup(&self, raw_sel: RawSelection) -> EdResult<(usize, usize)> { fn sel_to_tup(&self, raw_sel: RawSelection) -> EdResult<(usize, usize)> {
let valid_sel = validate_selection(raw_sel)?; let valid_sel = validate_selection(raw_sel)?;
let start_char_indx = self.pos_to_char_indx(valid_sel.selection.start_pos); let start_char_indx = self.pos_to_char_indx(valid_sel.selection.start_pos);
@ -139,6 +153,10 @@ impl TextBuffer {
Ok((start_char_indx, end_char_indx)) Ok((start_char_indx, end_char_indx))
} }
pub fn last_position(&self) -> Position {
self.char_indx_to_pos(self.nr_of_chars())
}
} }
pub fn from_path(path: &Path) -> EdResult<TextBuffer> { pub fn from_path(path: &Path) -> EdResult<TextBuffer> {