From 1acbe42962292b83c95bbbc635604e8e88fca58b Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 2 Jan 2021 19:33:26 +0100 Subject: [PATCH 01/13] implemented selection test DSL, added caret tests for move right --- Cargo.lock | 2 + editor/Cargo.toml | 2 + editor/editor-ideas.md | 4 +- editor/src/lib.rs | 5 + editor/src/selection.rs | 221 +++++++++++++++++++++++++++++++++++- editor/src/tea/model.rs | 1 - editor/src/util.rs | 2 +- editor/src/vec_result.rs | 1 + editor/tests/selection.pest | 11 ++ 9 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 editor/tests/selection.pest diff --git a/Cargo.lock b/Cargo.lock index f493e55a6b..0af4e03703 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2672,6 +2672,8 @@ dependencies = [ "log", "maplit", "page_size", + "pest", + "pest_derive", "pretty_assertions", "quickcheck", "quickcheck_macros", diff --git a/editor/Cargo.toml b/editor/Cargo.toml index fd0b8f6d6e..fcfda19a8a 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -66,6 +66,8 @@ cgmath = "0.17.0" itertools = "0.9.0" snafu = { version = "0.6", features = ["backtraces"] } colored = "2" +pest = "2.1" +pest_derive = "2.1" [dependencies.bytemuck] diff --git a/editor/editor-ideas.md b/editor/editor-ideas.md index ab10bb43d1..55e00d488a 100644 --- a/editor/editor-ideas.md +++ b/editor/editor-ideas.md @@ -55,8 +55,8 @@ These are potentially inspirational resources for the editor's design. ### Productivity features * When refactoring; - - cutting and pasting code to a new file should automatically add imports to the new file and delete them from the old file. - - When renaming a function for example, references in comments should be brought to the user's attention. + - Cutting and pasting code to a new file should automatically add imports to the new file and delete them from the old file. + - Ability to link e.g. variable name in comments to actual variable name. Comment is automatically updated when variable name is changed. * Automatically create all "arms" when pattern matching after entering `when var is` based on the type. - All `when ... is` should be updated if the type is changed, e.g. adding Indigo to the Color type should add an arm everywhere where `when color is` is used. diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 8835f556bc..3ecfb28da8 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -8,6 +8,11 @@ // See this link to learn wgpu: https://sotrh.github.io/learn-wgpu/ +extern crate pest; +#[cfg(test)] +#[macro_use] +extern crate pest_derive; + use crate::error::print_err; use crate::graphics::lowlevel::buffer::create_rect_buffers; use crate::graphics::lowlevel::ortho::{init_ortho, update_ortho_buffer, OrthoResources}; diff --git a/editor/src/selection.rs b/editor/src/selection.rs index bd5228d3e4..a03219bd9e 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -2,7 +2,7 @@ use crate::error::{EdResult, InvalidSelection}; use crate::graphics::colors; use crate::graphics::primitives::rect::Rect; use crate::tea::model::RawSelection; -use crate::vec_result::get_res; +use crate::vec_result::{get_res}; use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; use snafu::ensure; @@ -150,3 +150,222 @@ pub fn create_selection_rects<'a>( Ok(all_rects) } } + +#[cfg(test)] +mod test_parse { + use crate::tea::update::{move_caret_left, move_caret_right, move_caret_down, move_caret_up}; + use crate::tea::model::{RawSelection, Position}; + use crate::error::{EdResult, OutOfBounds}; + use crate::vec_result::{get_res}; + use snafu::OptionExt; + use std::slice::SliceIndex; + use pest::Parser; + + #[derive(Parser)] + #[grammar = "../tests/selection.pest"] + pub struct LineParser; + + fn convert_selection_to_dsl(raw_sel_opt: Option, caret_pos: Position, lines: &mut [String]) -> EdResult<&[String]> { + if let Some(raw_sel) = raw_sel_opt { + let mut to_insert = vec![(raw_sel.start_pos, '['), (raw_sel.end_pos, ']'), (caret_pos, '|')]; + to_insert.sort(); + + for i in 0..to_insert.len() { + let (pos, insert_char) = *get_res(i, &to_insert)?; + + insert_at_pos(lines, pos, insert_char)?; + + for j in i..to_insert.len() { + let (old_pos, _) = get_mut_res(j, &mut to_insert)?; + + if old_pos.line == pos.line { + old_pos.column += 1; + } + } + } + + } else { + insert_at_pos(lines, caret_pos, '|')?; + } + + Ok(lines) + } + + fn insert_at_pos(lines: &mut [String], pos: Position, insert_char: char) -> EdResult<()> { + let line = get_mut_res(pos.line, lines)?; + line.insert(pos.column, insert_char); + + Ok(()) + } + + fn get_mut_res(index: usize, vec: & mut [T]) -> EdResult<& mut >::Output> { + let vec_len = vec.len(); + + let elt_ref = vec.get_mut(index).context(OutOfBounds { + index, + vec_len, + })?; + + Ok(elt_ref) + } + + fn convert_dsl_to_selection(lines: &[String]) -> Result<(Option, Position), String> { + let lines_str: String = lines.join(""); + + let parsed = LineParser::parse(Rule::linesWithSelect, &lines_str).expect("Selection test DSL parsing failed"); + + let mut caret_opt: Option<(usize, usize)> = None; + let mut sel_start_opt: Option<(usize, usize)> = None; + let mut sel_end_opt: Option<(usize, usize)> = None; + let mut line_nr = 0; + let mut col_nr = 0; + + for line in parsed { + + for elt in line.into_inner() { + match elt.as_rule() { + Rule::optCaret => { + if elt.as_span().as_str() == "|" { + if caret_opt.is_some() { + return Err("Multiple carets found, there should be only one".to_owned()) + } else { + caret_opt = Some((line_nr, col_nr)); + col_nr += elt.as_span().as_str().len(); + } + } + }, + Rule::optSelStart => { + if sel_start_opt.is_some() { + if elt.as_span().as_str() == "[" { + return Err("Found start of selection more than once, there should be only one".to_owned()) + } + } else if elt.as_span().as_str() == "[" { + sel_start_opt = Some((line_nr, col_nr)); + col_nr += elt.as_span().as_str().len(); + } + }, + Rule::optSelEnd => { + if sel_end_opt.is_some() { + if elt.as_span().as_str() == "]" { + return Err("Found end of selection more than once, there should be only one".to_owned()) + } + } else if elt.as_span().as_str() == "]" { + sel_end_opt = Some((line_nr, col_nr)); + col_nr += elt.as_span().as_str().len(); + } + }, + Rule::text => { + let split_str = elt.as_span().as_str().split('\n').into_iter().collect::>(); + + if split_str.len() > 1 { + line_nr += split_str.len() - 1; + col_nr = 0 + } + if let Some(last_str) = split_str.last() { + col_nr += last_str.len() + } + + } + _ => {} + } + } + } + + if let Some((line, column)) = caret_opt { + let caret_pos = + Position { + line, + column + }; + if sel_start_opt.is_none() && sel_end_opt.is_none() { + Ok (( + None, + caret_pos + )) + } else if let Some((start_line, start_column)) = sel_start_opt { + if let Some((end_line, end_column)) = sel_end_opt { + Ok (( + Some ( + RawSelection { + start_pos : + Position { + line: start_line, + column: start_column + }, + end_pos : + Position { + line: end_line, + column: end_column + } + } + ), + caret_pos + )) + } else { + Err("Selection end ']' was not found, but selection start '[' was. Bad input string.".to_owned()) + } + } else { + Err("Selection start '[' was not found, but selection end ']' was. Bad input string.".to_owned()) + } + } else { + Err("No caret was found in lines.".to_owned()) + } + + } + + fn assert_move( + pre_lines_str: &[&str], + expected_post_lines_str: &[&str], + shift_pressed: bool, + move_fun: + fn(Position, Option, bool, &[String]) -> (Position, Option) + ) -> Result<(), String> { + let pre_lines: Vec = pre_lines_str.iter().map(|l| l.to_string()).collect(); + let expected_post_lines: Vec = expected_post_lines_str.iter().map(|l| l.to_string()).collect(); + + let (sel_opt, caret_pos) = convert_dsl_to_selection(&pre_lines)?; + + let mut clean_lines = + pre_lines.into_iter() + .map(|line| { + line.replace(&['[', ']', '|'][..], "") + }) + .collect::>(); + + let (new_caret_pos, new_sel_opt) = move_fun(caret_pos, sel_opt, shift_pressed, &clean_lines); + + let post_lines_res = + convert_selection_to_dsl(new_sel_opt, new_caret_pos, &mut clean_lines); + + match post_lines_res { + Ok(post_lines) => { + assert_eq!(expected_post_lines, post_lines); + Ok(()) + }, + Err(e) => Err(format!("{:?}", e)) + } + } + + #[test] + fn move_right() -> Result<(), String> { + assert_move(&["|"], &["|"], false, move_caret_right)?; + assert_move(&["a|"], &["a|"], false, move_caret_right)?; + assert_move(&["|A"], &["A|"], false, move_caret_right)?; + assert_move(&["|abc"], &["a|bc"], false, move_caret_right)?; + assert_move(&["a|bc"], &["ab|c"], false, move_caret_right)?; + assert_move(&["abc|"], &["abc|"], false, move_caret_right)?; + assert_move(&["| abc"], &[" |abc"], false, move_caret_right)?; + assert_move(&["abc| "], &["abc |"], false, move_caret_right)?; + assert_move(&["abc|\n","d"], &["abc\n","|d"], false, move_caret_right)?; + assert_move(&["abc|\n",""], &["abc\n","|"], false, move_caret_right)?; + assert_move(&["abc\n","|def"], &["abc\n","d|ef"], false, move_caret_right)?; + assert_move(&["abc\n","def| "], &["abc\n","def |"], false, move_caret_right)?; + assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_right)?; + assert_move(&["abc\n","def|\n",""], &["abc\n","def\n", "|"], false, move_caret_right)?; + assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "ghi\n", "|jkl"], false, move_caret_right)?; + assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def\n", "g|hi\n", "jkl"], false, move_caret_right)?; + assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "gh|i\n", "jkl"], false, move_caret_right)?; + + Ok(()) + } +} diff --git a/editor/src/tea/model.rs b/editor/src/tea/model.rs index d7a314c03a..60219986f5 100644 --- a/editor/src/tea/model.rs +++ b/editor/src/tea/model.rs @@ -15,7 +15,6 @@ pub fn init_model() -> Model { } } -//Is model.rs the right place for these structs? #[derive(Debug, Copy, Clone)] pub struct Position { pub line: usize, diff --git a/editor/src/util.rs b/editor/src/util.rs index 3f49f32c79..8fba081a08 100644 --- a/editor/src/util.rs +++ b/editor/src/util.rs @@ -1,5 +1,5 @@ pub fn is_newline(char_ref: &char) -> bool { - let newline_codes = vec!['\u{d}']; + let newline_codes = vec!['\u{d}', '\n']; newline_codes.contains(char_ref) } diff --git a/editor/src/vec_result.rs b/editor/src/vec_result.rs index 202af28a96..0d8eb67c8a 100644 --- a/editor/src/vec_result.rs +++ b/editor/src/vec_result.rs @@ -13,3 +13,4 @@ pub fn get_res(index: usize, vec: &[T]) -> EdResult<& Date: Mon, 4 Jan 2021 14:42:24 +0100 Subject: [PATCH 02/13] tests for all caret movement, moving caret up now goes to beginning of line for first line --- editor/src/selection.rs | 113 ++++++++++++++++++++++++++++++++++++++- editor/src/tea/update.rs | 10 ++-- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index a03219bd9e..ac41c5a6bf 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -368,4 +368,115 @@ mod test_parse { Ok(()) } -} + + #[test] + fn move_left() -> Result<(), String> { + assert_move(&["|"], &["|"], false, move_caret_left)?; + assert_move(&["|a"], &["|a"], false, move_caret_left)?; + assert_move(&["|A"], &["|A"], false, move_caret_left)?; + assert_move(&["a|bc"], &["|abc"], false, move_caret_left)?; + assert_move(&["ab|c"], &["a|bc"], false, move_caret_left)?; + assert_move(&["abc|"], &["ab|c"], false, move_caret_left)?; + assert_move(&[" |abc"], &["| abc"], false, move_caret_left)?; + assert_move(&["abc |"], &["abc| "], false, move_caret_left)?; + assert_move(&["abc\n","|d"], &["abc|\n","d"], false, move_caret_left)?; + assert_move(&["abc\n","|"], &["abc|\n",""], false, move_caret_left)?; + assert_move(&["abc\n","d|ef"], &["abc\n","|def"], false, move_caret_left)?; + assert_move(&["abc\n","def |"], &["abc\n","def| "], false, move_caret_left)?; + assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","def |\n", "ghi"], false, move_caret_left)?; + assert_move(&["abc\n","def\n","|"], &["abc\n","def|\n", ""], false, move_caret_left)?; + assert_move(&["abc\n","def\n", "ghi\n","|jkl"], &["abc\n","def\n", "ghi|\n", "jkl"], false, move_caret_left)?; + assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "|ghi\n", "jkl"], false, move_caret_left)?; + assert_move(&["abc\n","def\n", "gh|i\n","jkl"], &["abc\n","def\n", "g|hi\n", "jkl"], false, move_caret_left)?; + + Ok(()) + } + + #[test] + fn move_up() -> Result<(), String> { + assert_move(&["|"], &["|"], false, move_caret_up)?; + assert_move(&["|a"], &["|a"], false, move_caret_up)?; + assert_move(&["A|"], &["|A"], false, move_caret_up)?; + assert_move(&["a|bc"], &["|abc"], false, move_caret_up)?; + assert_move(&["ab|c"], &["|abc"], false, move_caret_up)?; + assert_move(&["abc|"], &["|abc"], false, move_caret_up)?; + assert_move(&["|abc\n","def"], &["|abc\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","|def"], &["|abc\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","d|ef"], &["a|bc\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","de|f"], &["ab|c\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","def|"], &["abc|\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","|def \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","def \n", "g|hi"], &["abc\n","d|ef \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","def \n", "gh|i"], &["abc\n","de|f \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","def \n", "ghi|"], &["abc\n","def| \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","de\n", "ghi|"], &["abc\n","de|\n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","de|"], &["ab|c\n","de"], false, move_caret_up)?; + assert_move(&["abc\n","d|e"], &["a|bc\n","de"], false, move_caret_up)?; + assert_move(&["abc\n","|de"], &["|abc\n","de"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], &[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cde|f\n", "ghijkl\n","mnopqrst"], &["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","st|"], &["abcdefgh\n","ijklmn\n", "op|qr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijkl|mn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdef|gh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefg|h\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["a|bcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["|abcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abc def gh |"], &["|abc def gh "], false, move_caret_up)?; + assert_move(&["abc de|f gh "], &["|abc def gh "], false, move_caret_up)?; + assert_move(&["ab|c def gh "], &["|abc def gh "], false, move_caret_up)?; + assert_move(&["a|bc def gh "], &["|abc def gh "], false, move_caret_up)?; + + Ok(()) + } + + #[test] + fn move_down() -> Result<(), String> { + assert_move(&["|"], &["|"], false, move_caret_down)?; + assert_move(&["|a"], &["a|"], false, move_caret_down)?; + assert_move(&["A|"], &["A|"], false, move_caret_down)?; + assert_move(&["a|bc"], &["abc|"], false, move_caret_down)?; + assert_move(&["ab|c"], &["abc|"], false, move_caret_down)?; + assert_move(&["abc|"], &["abc|"], false, move_caret_down)?; + assert_move(&["abc| "], &["abc |"], false, move_caret_down)?; + assert_move(&["abc\n","|def"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","d|ef"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","de|f"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","def|"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["|abc\n","def"], &["abc\n","|def"], false, move_caret_down)?; + assert_move(&["a|bc\n","def"], &["abc\n","d|ef"], false, move_caret_down)?; + assert_move(&["ab|c\n","def"], &["abc\n","de|f"], false, move_caret_down)?; + assert_move(&["abc|\n","def"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","|def \n", "ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_down)?; + assert_move(&["abc\n","d|ef \n", "ghi"], &["abc\n","def \n", "g|hi"], false, move_caret_down)?; + assert_move(&["abc\n","de|f \n", "ghi"], &["abc\n","def \n", "gh|i"], false, move_caret_down)?; + assert_move(&["abc\n","def| \n", "ghi"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; + assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; + assert_move(&["abc\n","de|\n", "ghi"], &["abc\n","de\n", "gh|i"], false, move_caret_down)?; + assert_move(&["abc|\n","de"], &["abc\n","de|"], false, move_caret_down)?; + assert_move(&["ab|c\n","de"], &["abc\n","de|"], false, move_caret_down)?; + assert_move(&["a|bc\n","de"], &["abc\n","d|e"], false, move_caret_down)?; + assert_move(&["|abc\n","de"], &["abc\n","|de"], false, move_caret_down)?; + assert_move(&["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","cd|ef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "ghij|kl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], false, move_caret_down)?; + assert_move(&[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], &[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], false, move_caret_down)?; + assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","|st"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; + assert_move(&["abc def gh |"], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["abc de|f gh "], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["ab|c def gh "], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["a|bc def gh "], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["|abc def gh "], &["abc def gh |"], false, move_caret_down)?; + + Ok(()) + } +} \ No newline at end of file diff --git a/editor/src/tea/update.rs b/editor/src/tea/update.rs index f542bfdf50..baeaa7939e 100644 --- a/editor/src/tea/update.rs +++ b/editor/src/tea/update.rs @@ -132,9 +132,9 @@ pub fn move_caret_up( let old_col_nr = old_caret_pos.column; let (line_nr, col_nr) = if old_line_nr == 0 { - (old_line_nr, old_col_nr) + (old_line_nr, 0) } else if let Some(prev_line) = lines.get(old_line_nr - 1) { - if prev_line.len() < old_col_nr { + if prev_line.len() <= old_col_nr { (old_line_nr - 1, prev_line.len() - 1) } else { (old_line_nr - 1, old_col_nr) @@ -179,7 +179,11 @@ pub fn move_caret_down( let old_col_nr = old_caret_pos.column; let (line_nr, col_nr) = if old_line_nr + 1 >= lines.len() { - (old_line_nr, old_col_nr) + if let Some(curr_line) = lines.get(old_line_nr) { + (old_line_nr, curr_line.len()) + } else { + unreachable!() + } } else if let Some(next_line) = lines.get(old_line_nr + 1) { if next_line.len() < old_col_nr { if let Some(last_char) = next_line.chars().last() { From 45296ba2e584a0a61024bb57e7f6328168dd34f1 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 4 Jan 2021 16:45:55 +0100 Subject: [PATCH 03/13] start selection tests --- editor/src/selection.rs | 153 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index ac41c5a6bf..ae5118111f 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -159,8 +159,11 @@ mod test_parse { use crate::vec_result::{get_res}; use snafu::OptionExt; use std::slice::SliceIndex; + use std::collections::HashMap; + use core::cmp::Ordering; use pest::Parser; + #[derive(Parser)] #[grammar = "../tests/selection.pest"] pub struct LineParser; @@ -168,7 +171,18 @@ mod test_parse { fn convert_selection_to_dsl(raw_sel_opt: Option, caret_pos: Position, lines: &mut [String]) -> EdResult<&[String]> { if let Some(raw_sel) = raw_sel_opt { let mut to_insert = vec![(raw_sel.start_pos, '['), (raw_sel.end_pos, ']'), (caret_pos, '|')]; - to_insert.sort(); + let symbol_map: HashMap = [('[', 2), (']', 0), ('|', 1)].iter().cloned().collect(); + + to_insert.sort_by( + |a, b| { + let pos_cmp = a.0.cmp(&b.0); + if pos_cmp == Ordering::Equal { + symbol_map.get(&a.1).cmp(&symbol_map.get(&b.1)) + } else { + pos_cmp + } + } + ); for i in 0..to_insert.len() { let (pos, insert_char) = *get_res(i, &to_insert)?; @@ -479,4 +493,141 @@ mod test_parse { Ok(()) } + + #[test] + fn start_selection_right() -> Result<(), String> { + assert_move(&["|"], &["|"], true, move_caret_right)?; + assert_move(&["a|"], &["a|"], true, move_caret_right)?; + assert_move(&["|A"], &["[A]|"], true, move_caret_right)?; + assert_move(&["|abc"], &["[a]|bc"], true, move_caret_right)?; + assert_move(&["a|bc"], &["a[b]|c"], true, move_caret_right)?; + assert_move(&["abc|"], &["abc|"], true, move_caret_right)?; + assert_move(&["| abc"], &["[ ]|abc"], true, move_caret_right)?; + assert_move(&["abc| "], &["abc[ ]|"], true, move_caret_right)?; + assert_move(&["abc|\n","d"], &["abc[\n","]|d"], true, move_caret_right)?; + assert_move(&["abc|\n",""], &["abc[\n","]|"], true, move_caret_right)?; + assert_move(&["abc\n","|def"], &["abc\n","[d]|ef"], true, move_caret_right)?; + assert_move(&["abc\n","def| "], &["abc\n","def[ ]|"], true, move_caret_right)?; + assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def [\n", "]|ghi"], true, move_caret_right)?; + assert_move(&["abc\n","def|\n",""], &["abc\n","def[\n", "]|"], true, move_caret_right)?; + assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "ghi[\n", "]|jkl"], true, move_caret_right)?; + assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def\n", "[g]|hi\n", "jkl"], true, move_caret_right)?; + assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "g[h]|i\n", "jkl"], true, move_caret_right)?; + + Ok(()) + } + + #[test] + fn start_selection_left() -> Result<(), String> { + assert_move(&["|"], &["|"], true, move_caret_left)?; + assert_move(&["a|"], &["|[a]"], true, move_caret_left)?; + assert_move(&["|A"], &["|A"], true, move_caret_left)?; + assert_move(&["|abc"], &["|abc"], true, move_caret_left)?; + assert_move(&["a|bc"], &["|[a]bc"], true, move_caret_left)?; + assert_move(&["abc|"], &["ab|[c]"], true, move_caret_left)?; + assert_move(&[" |abc"], &["|[ ]abc"], true, move_caret_left)?; + assert_move(&["abc |"], &["abc|[ ]"], true, move_caret_left)?; + assert_move(&["abc|\n","d"], &["ab|[c]\n","d"], true, move_caret_left)?; + assert_move(&["abc\n","|d"], &["abc|[\n","]d"], true, move_caret_left)?; + assert_move(&["abc\n","|"], &["abc|[\n","]"], true, move_caret_left)?; + assert_move(&["abc\n"," |def"], &["abc\n","|[ ]def"], true, move_caret_left)?; + assert_move(&["abc\n","d|ef"], &["abc\n","|[d]ef"], true, move_caret_left)?; + assert_move(&["abc\n","de|f "], &["abc\n","d|[e]f "], true, move_caret_left)?; + assert_move(&["abc\n","def\n","|"], &["abc\n","def|[\n", "]"], true, move_caret_left)?; + assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def|[\n", "]ghi\n", "jkl"], true, move_caret_left)?; + assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "|[g]hi\n", "jkl"], true, move_caret_left)?; + assert_move(&["abc\n","def\n", "gh|i\n","jkl"], &["abc\n","def\n", "g|[h]i\n", "jkl"], true, move_caret_left)?; + assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "gh|[i]\n", "jkl"], true, move_caret_left)?; + + Ok(()) + } + + #[test] + fn start_selection_down() -> Result<(), String> { + assert_move(&["|"], &["|"], true, move_caret_down)?; + assert_move(&["|a"], &["[a]|"], true, move_caret_down)?; + assert_move(&["A|"], &["A|"], true, move_caret_down)?; + assert_move(&["a|bc"], &["a[bc]|"], true, move_caret_down)?; + assert_move(&["ab|c"], &["ab[c]|"], true, move_caret_down)?; + assert_move(&["abc|"], &["abc|"], true, move_caret_down)?; + assert_move(&["abc| "], &["abc[ ]|"], true, move_caret_down)?; + assert_move(&["abc\n","|def"], &["abc\n","[def]|"], true, move_caret_down)?; + assert_move(&["abc\n","d|ef"], &["abc\n","d[ef]|"], true, move_caret_down)?; + assert_move(&["abc\n","de|f"], &["abc\n","de[f]|"], true, move_caret_down)?; + assert_move(&["abc\n","def|"], &["abc\n","def|"], true, move_caret_down)?; + assert_move(&["|abc\n","def"], &["[abc\n","]|def"], true, move_caret_down)?; + assert_move(&["a|bc\n","def"], &["a[bc\n","d]|ef"], true, move_caret_down)?; + assert_move(&["ab|c\n","def"], &["ab[c\n","de]|f"], true, move_caret_down)?; + assert_move(&["abc|\n","def"], &["abc[\n","def]|"], true, move_caret_down)?; + assert_move(&["abc\n","|def \n", "ghi"], &["abc\n","[def \n", "]|ghi"], true, move_caret_down)?; + assert_move(&["abc\n","d|ef \n", "ghi"], &["abc\n","d[ef \n", "g]|hi"], true, move_caret_down)?; + assert_move(&["abc\n","de|f \n", "ghi"], &["abc\n","de[f \n", "gh]|i"], true, move_caret_down)?; + assert_move(&["abc\n","def| \n", "ghi"], &["abc\n","def[ \n", "ghi]|"], true, move_caret_down)?; + assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def [\n", "ghi]|"], true, move_caret_down)?; + assert_move(&["abc\n","de|\n", "ghi"], &["abc\n","de[\n", "gh]|i"], true, move_caret_down)?; + assert_move(&["abc|\n","de"], &["abc[\n","de]|"], true, move_caret_down)?; + assert_move(&["ab|c\n","de"], &["ab[c\n","de]|"], true, move_caret_down)?; + assert_move(&["a|bc\n","de"], &["a[bc\n","d]|e"], true, move_caret_down)?; + assert_move(&["|abc\n","de"], &["[abc\n","]|de"], true, move_caret_down)?; + assert_move(&["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], &["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], true, move_caret_down)?; + assert_move(&["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef[\n", "ghij]|kl\n","mnopqrst"], true, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], true, move_caret_down)?; + assert_move(&[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], &[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], true, move_caret_down)?; + assert_move(&["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","[cdef\n", "]|ghijkl\n","mnopqrst"], true, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], true, move_caret_down)?; + assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], true, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], true, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], true, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","|st"], &["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], true, move_caret_down)?; + assert_move(&["abc def gh |"], &["abc def gh |"], true, move_caret_down)?; + assert_move(&["abc de|f gh "], &["abc de[f gh ]|"], true, move_caret_down)?; + assert_move(&["ab|c def gh "], &["ab[c def gh ]|"], true, move_caret_down)?; + assert_move(&["a|bc def gh "], &["a[bc def gh ]|"], true, move_caret_down)?; + assert_move(&["|abc def gh "], &["[abc def gh ]|"], true, move_caret_down)?; + + Ok(()) + } + + #[test] + fn start_selection_up() -> Result<(), String> { + assert_move(&["|"], &["|"], true, move_caret_up)?; + assert_move(&["|a"], &["|a"], true, move_caret_up)?; + assert_move(&["A|"], &["|[A]"], true, move_caret_up)?; + assert_move(&["a|bc"], &["|[a]bc"], true, move_caret_up)?; + assert_move(&["ab|c"], &["|[ab]c"], true, move_caret_up)?; + assert_move(&["abc|"], &["|[abc]"], true, move_caret_up)?; + assert_move(&["|abc\n","def"], &["|abc\n","def"], true, move_caret_up)?; + assert_move(&["abc\n","|def"], &["|[abc\n","]def"], true, move_caret_up)?; + assert_move(&["abc\n","d|ef"], &["a|[bc\n","d]ef"], true, move_caret_up)?; + assert_move(&["abc\n","de|f"], &["ab|[c\n","de]f"], true, move_caret_up)?; + assert_move(&["abc\n","def|"], &["abc|[\n","def]"], true, move_caret_up)?; + assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","|[def \n", "]ghi"], true, move_caret_up)?; + assert_move(&["abc\n","def \n", "g|hi"], &["abc\n","d|[ef \n", "g]hi"], true, move_caret_up)?; + assert_move(&["abc\n","def \n", "gh|i"], &["abc\n","de|[f \n", "gh]i"], true, move_caret_up)?; + assert_move(&["abc\n","def \n", "ghi|"], &["abc\n","def|[ \n", "ghi]"], true, move_caret_up)?; + assert_move(&["abc\n","de\n", "ghi|"], &["abc\n","de|[\n", "ghi]"], true, move_caret_up)?; + assert_move(&["abc\n","de|"], &["ab|[c\n","de]"], true, move_caret_up)?; + assert_move(&["abc\n","d|e"], &["a|[bc\n","d]e"], true, move_caret_up)?; + assert_move(&["abc\n","|de"], &["|[abc\n","]de"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], &["ab\n","cdef\n", "ghijkl|[\n","mnopqrst]"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef|[\n", "ghijkl]\n","mnopqrst"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], &["ab\n","cdef\n", "|[ghijkl\n","]mnopqrst"], true, move_caret_up)?; + assert_move(&[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], &[" |[ab\n"," ]cdef\n", "ghijkl\n","mnopqrst"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], &["ab\n","cdef\n", "ghijkl|[\n","mnopqr]st"], true, move_caret_up)?; + assert_move(&["ab\n","cde|f\n", "ghijkl\n","mnopqrst"], &["ab|[\n","cde]f\n", "ghijkl\n","mnopqrst"], true, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","st|"], &["abcdefgh\n","ijklmn\n", "op|[qr\n","st]"], true, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijkl|[mn\n", "opqr]\n","st"], true, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdef|[gh\n","ijklmn]\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["|[abcdefgh]\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["abcdefg|h\n","ijklmn\n", "opqr\n","st"], &["|[abcdefg]h\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["a|bcdefgh\n","ijklmn\n", "opqr\n","st"], &["|[a]bcdefgh\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["|abcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["abc def gh |"], &["|[abc def gh ]"], true, move_caret_up)?; + assert_move(&["abc de|f gh "], &["|[abc de]f gh "], true, move_caret_up)?; + assert_move(&["ab|c def gh "], &["|[ab]c def gh "], true, move_caret_up)?; + assert_move(&["a|bc def gh "], &["|[a]bc def gh "], true, move_caret_up)?; + + Ok(()) + } + } \ No newline at end of file From 85553987eccc2c06afc29101eda6aa3bced6dc8a Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 4 Jan 2021 20:06:32 +0100 Subject: [PATCH 04/13] end selection tests --- editor/src/selection.rs | 147 ++++++++++++++++++++++++++++++++++++++- editor/src/tea/update.rs | 92 +++++++++++++++--------- 2 files changed, 202 insertions(+), 37 deletions(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index ae5118111f..72d8df2ead 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -244,7 +244,6 @@ mod test_parse { return Err("Multiple carets found, there should be only one".to_owned()) } else { caret_opt = Some((line_nr, col_nr)); - col_nr += elt.as_span().as_str().len(); } } }, @@ -255,7 +254,6 @@ mod test_parse { } } else if elt.as_span().as_str() == "[" { sel_start_opt = Some((line_nr, col_nr)); - col_nr += elt.as_span().as_str().len(); } }, Rule::optSelEnd => { @@ -265,7 +263,6 @@ mod test_parse { } } else if elt.as_span().as_str() == "]" { sel_end_opt = Some((line_nr, col_nr)); - col_nr += elt.as_span().as_str().len(); } }, Rule::text => { @@ -630,4 +627,148 @@ mod test_parse { Ok(()) } + #[test] + fn end_selection_right() -> Result<(), String> { + assert_move(&["[A]|"], &["A|"], false, move_caret_right)?; + assert_move(&["[a]|bc"], &["a|bc"], false, move_caret_right)?; + assert_move(&["a[b]|c"], &["ab|c"], false, move_caret_right)?; + assert_move(&["ab[c]|"], &["abc|"], false, move_caret_right)?; + assert_move(&["[ ]|abc"], &[" |abc"], false, move_caret_right)?; + assert_move(&["|[ ]abc"], &[" |abc"], false, move_caret_right)?; + assert_move(&["a|[b]c"], &["ab|c"], false, move_caret_right)?; + assert_move(&["abc[\n","]|d"], &["abc\n","|d"], false, move_caret_right)?; + assert_move(&["abc|[\n","]d"], &["abc\n","|d"], false, move_caret_right)?; + assert_move(&["abc|[\n","]"], &["abc\n","|"], false, move_caret_right)?; + assert_move(&["abc\n","[d]|ef"], &["abc\n","d|ef"], false, move_caret_right)?; + assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi\n", "|jkl"], false, move_caret_right)?; + assert_move(&["[ab]|c"], &["ab|c"], false, move_caret_right)?; + assert_move(&["[abc]|"], &["abc|"], false, move_caret_right)?; + assert_move(&["ab|[c\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; + assert_move(&["ab[c\n","]|def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; + assert_move(&["a|[bc\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; + assert_move(&["|[abc\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; + assert_move(&["a|[bc\n","d]ef\n","ghi"], &["abc\n","d|ef\n","ghi"], false, move_caret_right)?; + assert_move(&["|[abc\n","def]\n","ghi"], &["abc\n","def|\n","ghi"], false, move_caret_right)?; + assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], false, move_caret_right)?; + assert_move(&["|[ab\n","cdef\n", "ghijkl\n","mnopqrst]"], &["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], false, move_caret_right)?; + assert_move(&["ab\n","c[def\n", "ghijkl\n","mno]|pqrst"], &["ab\n","cdef\n", "ghijkl\n","mno|pqrst"], false, move_caret_right)?; + assert_move(&["ab\n","c|[def\n", "ghijkl\n","mno]pqrst"], &["ab\n","cdef\n", "ghijkl\n","mno|pqrst"], false, move_caret_right)?; + + Ok(()) + } + + #[test] + fn end_selection_left() -> Result<(), String> { + assert_move(&["[A]|"], &["|A"], false, move_caret_left)?; + assert_move(&["[a]|bc"], &["|abc"], false, move_caret_left)?; + assert_move(&["a[b]|c"], &["a|bc"], false, move_caret_left)?; + assert_move(&["ab[c]|"], &["ab|c"], false, move_caret_left)?; + assert_move(&["[ ]|abc"], &["| abc"], false, move_caret_left)?; + assert_move(&["|[ ]abc"], &["| abc"], false, move_caret_left)?; + assert_move(&["a|[b]c"], &["a|bc"], false, move_caret_left)?; + assert_move(&["abc[\n","]|d"], &["abc|\n","d"], false, move_caret_left)?; + assert_move(&["abc|[\n","]d"], &["abc|\n","d"], false, move_caret_left)?; + assert_move(&["abc|[\n","]"], &["abc|\n",""], false, move_caret_left)?; + assert_move(&["abc\n","[d]|ef"], &["abc\n","|def"], false, move_caret_left)?; + assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi|\n", "jkl"], false, move_caret_left)?; + assert_move(&["[ab]|c"], &["|abc"], false, move_caret_left)?; + assert_move(&["[abc]|"], &["|abc"], false, move_caret_left)?; + assert_move(&["ab|[c\n","]def\n","ghi"], &["ab|c\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["ab[c\n","]|def\n","ghi"], &["ab|c\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["a|[bc\n","]def\n","ghi"], &["a|bc\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["|[abc\n","]def\n","ghi"], &["|abc\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["a|[bc\n","d]ef\n","ghi"], &["a|bc\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["|[abc\n","def]\n","ghi"], &["|abc\n","def\n","ghi"], false, move_caret_left)?; + assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["|ab\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; + assert_move(&["|[ab\n","cdef\n", "ghijkl\n","mnopqrst]"], &["|ab\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; + assert_move(&["ab\n","c[def\n", "ghijkl\n","mno]|pqrst"], &["ab\n","c|def\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; + assert_move(&["ab\n","c|[def\n", "ghijkl\n","mno]pqrst"], &["ab\n","c|def\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; + + Ok(()) + } + + #[test] + fn end_selection_down() -> Result<(), String> { + assert_move(&["[a]|"], &["a|"], false, move_caret_down)?; + assert_move(&["|[a]"], &["a|"], false, move_caret_down)?; + assert_move(&["a|[bc]"], &["abc|"], false, move_caret_down)?; + assert_move(&["ab[c]|"], &["abc|"], false, move_caret_down)?; + assert_move(&["abc|[ ]"], &["abc |"], false, move_caret_down)?; + assert_move(&["abc\n","|[def]"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","d|[ef]"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","de|[f]"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["[abc\n","]|def"], &["abc\n","|def"], false, move_caret_down)?; + assert_move(&["a[bc\n","d]|ef"], &["abc\n","d|ef"], false, move_caret_down)?; + assert_move(&["ab|[c\n","de]f"], &["abc\n","de|f"], false, move_caret_down)?; + assert_move(&["abc[\n","def]|"], &["abc\n","def|"], false, move_caret_down)?; + assert_move(&["abc\n","|[def \n", "]ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_down)?; + assert_move(&["abc\n","d[ef \n", "g]|hi"], &["abc\n","def \n", "g|hi"], false, move_caret_down)?; + assert_move(&["abc\n","de[f \n", "gh]|i"], &["abc\n","def \n", "gh|i"], false, move_caret_down)?; + assert_move(&["abc\n","def[ \n", "ghi]|"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; + assert_move(&["abc\n","def [\n", "ghi]|"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; + assert_move(&["abc\n","de[\n", "gh]|i"], &["abc\n","de\n", "gh|i"], false, move_caret_down)?; + assert_move(&["abc|[\n","de]"], &["abc\n","de|"], false, move_caret_down)?; + assert_move(&["ab[c\n","de]|"], &["abc\n","de|"], false, move_caret_down)?; + assert_move(&["a|[bc\n","d]e"], &["abc\n","d|e"], false, move_caret_down)?; + assert_move(&["[abc\n","]|de"], &["abc\n","|de"], false, move_caret_down)?; + assert_move(&["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], &["ab\n","cd|ef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef|[\n", "ghij]kl\n","mnopqrst"], &["ab\n","cdef\n", "ghij|kl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], &["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], false, move_caret_down)?; + assert_move(&[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], &[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","|[cdef\n", "]ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], false, move_caret_down)?; + assert_move(&["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; + assert_move(&["abc de[f gh ]|"], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["ab|[c def gh ]"], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["a[bc def gh ]|"], &["abc def gh |"], false, move_caret_down)?; + assert_move(&["[abc def gh ]|"], &["abc def gh |"], false, move_caret_down)?; + + Ok(()) + } + + #[test] + fn end_selection_up() -> Result<(), String> { + assert_move(&["[a]|"], &["|a"], false, move_caret_up)?; + assert_move(&["|[a]"], &["|a"], false, move_caret_up)?; + assert_move(&["a|[bc]"], &["a|bc"], false, move_caret_up)?; + assert_move(&["ab[c]|"], &["ab|c"], false, move_caret_up)?; + assert_move(&["abc|[ ]"], &["abc| "], false, move_caret_up)?; + assert_move(&["abc\n","|[def]"], &["abc\n","|def"], false, move_caret_up)?; + assert_move(&["abc\n","d|[ef]"], &["abc\n","d|ef"], false, move_caret_up)?; + assert_move(&["abc\n","de|[f]"], &["abc\n","de|f"], false, move_caret_up)?; + assert_move(&["[abc\n","]|def"], &["|abc\n","def"], false, move_caret_up)?; + assert_move(&["a[bc\n","d]|ef"], &["a|bc\n","def"], false, move_caret_up)?; + assert_move(&["ab|[c\n","de]f"], &["ab|c\n","def"], false, move_caret_up)?; + assert_move(&["abc[\n","def]|"], &["abc|\n","def"], false, move_caret_up)?; + assert_move(&["abc\n","|[def \n", "]ghi"], &["abc\n","|def \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","d[ef \n", "g]|hi"], &["abc\n","d|ef \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","de|[f \n", "gh]i"], &["abc\n","de|f \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","def[ \n", "ghi]|"], &["abc\n","def| \n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","def [\n", "ghi]|"], &["abc\n","def |\n", "ghi"], false, move_caret_up)?; + assert_move(&["abc\n","de[\n", "gh]|i"], &["abc\n","de|\n", "ghi"], false, move_caret_up)?; + assert_move(&["abc|[\n","de]"], &["abc|\n","de"], false, move_caret_up)?; + assert_move(&["ab[c\n","de]|"], &["ab|c\n","de"], false, move_caret_up)?; + assert_move(&["a|[bc\n","d]e"], &["a|bc\n","de"], false, move_caret_up)?; + assert_move(&["[abc\n","]|de"], &["|abc\n","de"], false, move_caret_up)?; + assert_move(&["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], &["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef|[\n", "ghij]kl\n","mnopqrst"], &["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; + assert_move(&[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], &[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","|[cdef\n", "]ghijkl\n","mnopqrst"], &["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_up)?; + assert_move(&["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], &["abcdefgh|\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","|st"], false, move_caret_up)?; + assert_move(&["abc de[f gh ]|"], &["abc de|f gh "], false, move_caret_up)?; + assert_move(&["ab|[c def gh ]"], &["ab|c def gh "], false, move_caret_up)?; + assert_move(&["a[bc def gh ]|"], &["a|bc def gh "], false, move_caret_up)?; + assert_move(&["[abc def gh ]|"], &["|abc def gh "], false, move_caret_up)?; + + Ok(()) + } + } \ No newline at end of file diff --git a/editor/src/tea/update.rs b/editor/src/tea/update.rs index baeaa7939e..9d01694d61 100644 --- a/editor/src/tea/update.rs +++ b/editor/src/tea/update.rs @@ -11,17 +11,23 @@ pub fn move_caret_left( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = if old_col_nr == 0 { - if old_line_nr == 0 { - (0, 0) - } else if let Some(curr_line) = lines.get(old_line_nr - 1) { - (old_line_nr - 1, curr_line.len() - 1) + let (line_nr, col_nr) = + if old_selection_opt.is_some() && !shift_pressed{ + match old_selection_opt { + Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), + None => unreachable!(), + } + } else if old_col_nr == 0 { + if old_line_nr == 0 { + (0, 0) + } else if let Some(curr_line) = lines.get(old_line_nr - 1) { + (old_line_nr - 1, curr_line.len() - 1) + } else { + unreachable!() + } } else { - unreachable!() - } - } else { - (old_line_nr, old_col_nr - 1) - }; + (old_line_nr, old_col_nr - 1) + }; let new_caret_pos = Position { line: line_nr, @@ -67,25 +73,31 @@ pub fn move_caret_right( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = if let Some(curr_line) = lines.get(old_line_nr) { - if let Some(last_char) = curr_line.chars().last() { - if is_newline(&last_char) { - if old_col_nr + 1 > curr_line.len() - 1 { - (old_line_nr + 1, 0) - } else { + let (line_nr, col_nr) = + if old_selection_opt.is_some() && !shift_pressed{ + match old_selection_opt { + Some(old_selection) => (old_selection.end_pos.line, old_selection.end_pos.column), + None => unreachable!(), + } + } else if let Some(curr_line) = lines.get(old_line_nr) { + if let Some(last_char) = curr_line.chars().last() { + if is_newline(&last_char) { + if old_col_nr + 1 > curr_line.len() - 1 { + (old_line_nr + 1, 0) + } else { + (old_line_nr, old_col_nr + 1) + } + } else if old_col_nr < curr_line.len() { (old_line_nr, old_col_nr + 1) + } else { + (old_line_nr, old_col_nr) } - } else if old_col_nr < curr_line.len() { - (old_line_nr, old_col_nr + 1) } else { (old_line_nr, old_col_nr) } } else { - (old_line_nr, old_col_nr) - } - } else { - unreachable!() - }; + unreachable!() + }; let new_caret_pos = Position { line: line_nr, @@ -131,17 +143,23 @@ pub fn move_caret_up( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = if old_line_nr == 0 { - (old_line_nr, 0) - } else if let Some(prev_line) = lines.get(old_line_nr - 1) { - if prev_line.len() <= old_col_nr { - (old_line_nr - 1, prev_line.len() - 1) + let (line_nr, col_nr) = + if old_selection_opt.is_some() && !shift_pressed{ + match old_selection_opt { + Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), + None => unreachable!(), + } + } else if old_line_nr == 0 { + (old_line_nr, 0) + } else if let Some(prev_line) = lines.get(old_line_nr - 1) { + if prev_line.len() <= old_col_nr { + (old_line_nr - 1, prev_line.len() - 1) + } else { + (old_line_nr - 1, old_col_nr) + } } else { - (old_line_nr - 1, old_col_nr) - } - } else { - unreachable!() - }; + unreachable!() + }; let new_caret_pos = Position { line: line_nr, @@ -178,7 +196,13 @@ pub fn move_caret_down( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = if old_line_nr + 1 >= lines.len() { + let (line_nr, col_nr) = + if old_selection_opt.is_some() && !shift_pressed{ + match old_selection_opt { + Some(old_selection) => (old_selection.end_pos.line, old_selection.end_pos.column), + None => unreachable!(), + } + } else if old_line_nr + 1 >= lines.len() { if let Some(curr_line) = lines.get(old_line_nr) { (old_line_nr, curr_line.len()) } else { From bed9166fcb30e00f6e6f0073db34869634c90c52 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 5 Jan 2021 17:56:28 +0100 Subject: [PATCH 05/13] selection extension test, selection extension fixes --- editor/src/selection.rs | 81 ++++++++++++++++++++++++++++++++++++++++ editor/src/tea/update.rs | 38 +++++++++++++++---- 2 files changed, 111 insertions(+), 8 deletions(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index 72d8df2ead..4dfa0bd719 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -771,4 +771,85 @@ mod test_parse { Ok(()) } + #[test] + fn extend_selection_right() -> Result<(), String> { + assert_move(&["[a]|bc"], &["[ab]|c"], true, move_caret_right)?; + assert_move(&["a[b]|c"], &["a[bc]|"], true, move_caret_right)?; + assert_move(&["[ab]|c"], &["[abc]|"], true, move_caret_right)?; + assert_move(&["[ ]|abc"], &["[ a]|bc"], true, move_caret_right)?; + assert_move(&["[abc]|"], &["[abc]|"], true, move_caret_right)?; + assert_move(&["a[bc]|"], &["a[bc]|"], true, move_caret_right)?; + assert_move(&["ab[c]|"], &["ab[c]|"], true, move_caret_right)?; + assert_move(&["abc[\n","]|d"], &["abc[\n","d]|"], true, move_caret_right)?; + assert_move(&["ab[c]|\n",""], &["ab[c\n","]|"], true, move_caret_right)?; + assert_move(&["ab[c]|\n","d"], &["ab[c\n","]|d"], true, move_caret_right)?; + assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi[\n", "j]|kl"], true, move_caret_right)?; + assert_move(&["ab[c\n","def\n", "ghi\n","]|jkl"], &["ab[c\n","def\n", "ghi\n", "j]|kl"], true, move_caret_right)?; + assert_move(&["ab[c\n","def\n", "]|ghi\n","jkl"], &["ab[c\n","def\n", "g]|hi\n", "jkl"], true, move_caret_right)?; + assert_move(&["[abc\n","def\n", "ghi\n","jk]|l"], &["[abc\n","def\n", "ghi\n", "jkl]|"], true, move_caret_right)?; + assert_move(&["[abc\n","def\n", "ghi\n", "jkl]|"], &["[abc\n","def\n", "ghi\n", "jkl]|"], true, move_caret_right)?; + + Ok(()) + } + + #[test] + fn extend_selection_left() -> Result<(), String> { + assert_move(&["ab|[c]"], &["a|[bc]"], true, move_caret_left)?; + assert_move(&["a|[bc]"], &["|[abc]"], true, move_caret_left)?; + assert_move(&["|[abc]"], &["|[abc]"], true, move_caret_left)?; + assert_move(&["|[ab]c"], &["|[ab]c"], true, move_caret_left)?; + assert_move(&["|[a]bc"], &["|[a]bc"], true, move_caret_left)?; + assert_move(&[" |[a]bc"], &["|[ a]bc"], true, move_caret_left)?; + assert_move(&["abc|[\n","]d"], &["ab|[c\n","]d"], true, move_caret_left)?; + assert_move(&["abc\n","|[d]"], &["abc|[\n","d]"], true, move_caret_left)?; + assert_move(&["ab|[c\n","]"], &["a|[bc\n","]"], true, move_caret_left)?; + assert_move(&["abc\n","def|[\n", "ghi\n","j]kl"], &["abc\n","de|[f\n", "ghi\n", "j]kl"], true, move_caret_left)?; + assert_move(&["a|[bc\n","def\n", "ghi\n","jkl]"], &["|[abc\n","def\n", "ghi\n", "jkl]"], true, move_caret_left)?; + assert_move(&["abc\n","def\n", "ghi\n", "|[jkl]"], &["abc\n","def\n", "ghi|[\n", "jkl]"], true, move_caret_left)?; + + Ok(()) + } + + #[test] + fn extend_selection_up() -> Result<(), String> { + assert_move(&["ab|[c]"], &["|[abc]"], true, move_caret_up)?; + assert_move(&["a|[bc]"], &["|[abc]"], true, move_caret_up)?; + assert_move(&["|[abc]"], &["|[abc]"], true, move_caret_up)?; + assert_move(&["|[ab]c"], &["|[ab]c"], true, move_caret_up)?; + assert_move(&["|[a]bc"], &["|[a]bc"], true, move_caret_up)?; + assert_move(&[" |[a]bc"], &["|[ a]bc"], true, move_caret_up)?; + assert_move(&["ab[c]|"], &["|[ab]c"], true, move_caret_up)?; + assert_move(&["[a]|"], &["|a"], true, move_caret_up)?; + assert_move(&["[a]|bc"], &["|abc"], true, move_caret_up)?; + assert_move(&["[a]|bc\n","d"], &["|abc\n","d"], true, move_caret_up)?; + assert_move(&["abc\n","de[f]|"], &["abc|[\n","de]f"], true, move_caret_up)?; + assert_move(&["abc\n","de|[f]"], &["ab|[c\n","def]"], true, move_caret_up)?; + assert_move(&["ab|[c\n","def]"], &["|[abc\n","def]"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqr]|st"], &["ab\n","cdef\n", "ghijkl|[\n","]mnopqrst"], true, move_caret_up)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqrs]|t"], &["ab\n","cdef\n", "ghijkl|[\n","]mnopqrst"], true, move_caret_up)?; + assert_move(&["abcdefgh\n","ijklmn\n", "|[o]pqr\n","st"], &["abcdefgh\n","|[ijklmn\n", "o]pqr\n","st"], true, move_caret_up)?; + + Ok(()) + } + + #[test] + fn extend_selection_down() -> Result<(), String> { + assert_move(&["[ab]|c"], &["[abc]|"], true, move_caret_down)?; + assert_move(&["[a]|bc"], &["[abc]|"], true, move_caret_down)?; + assert_move(&["[abc]|"], &["[abc]|"], true, move_caret_down)?; + assert_move(&["|[ab]c"], &["ab[c]|"], true, move_caret_down)?; + assert_move(&["|[a]bc"], &["a[bc]|"], true, move_caret_down)?; + assert_move(&["[a]|bc\n","d"], &["[abc\n","d]|"], true, move_caret_down)?; + assert_move(&["[a]|bc\n","de"], &["[abc\n","d]|e"], true, move_caret_down)?; + assert_move(&["[abc\n","d]|e"], &["[abc\n","de]|"], true, move_caret_down)?; + assert_move(&["[a]|bc\n",""], &["[abc\n","]|"], true, move_caret_down)?; + assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqr]|st"], &["ab\n","cdef\n", "ghijkl\n","[mnopqrst]|"], true, move_caret_down)?; + assert_move(&["a[b\n","cdef\n", "ghijkl\n","mnopqr]|st"], &["a[b\n","cdef\n", "ghijkl\n","mnopqrst]|"], true, move_caret_down)?; + assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], true, move_caret_down)?; + assert_move(&["abcd[efgh]|\n","ijklmn\n", "opqr\n","st"], &["abcd[efgh\n","ijklmn]|\n", "opqr\n","st"], true, move_caret_down)?; + assert_move(&["abcd[e]|fgh\n","ijklmn\n", "opqr\n","st"], &["abcd[efgh\n","ijklm]|n\n", "opqr\n","st"], true, move_caret_down)?; + + Ok(()) + } + } \ No newline at end of file diff --git a/editor/src/tea/update.rs b/editor/src/tea/update.rs index 9d01694d61..8808dc6994 100644 --- a/editor/src/tea/update.rs +++ b/editor/src/tea/update.rs @@ -168,10 +168,21 @@ pub fn move_caret_up( let new_selection_opt = if shift_pressed { if let Some(old_selection) = old_selection_opt { - Some(RawSelection { - start_pos: new_caret_pos, - end_pos: old_selection.end_pos, - }) + if old_selection.end_pos <= old_caret_pos { + if new_caret_pos == old_selection.start_pos { + None + } else { + Some(RawSelection { + start_pos: new_caret_pos, + end_pos: old_selection.start_pos, + }) + } + } else { + Some(RawSelection { + start_pos: new_caret_pos, + end_pos: old_selection.end_pos, + }) + } } else if !(old_line_nr == line_nr && old_col_nr == col_nr) { Some(RawSelection { start_pos: min(old_caret_pos, new_caret_pos), @@ -233,10 +244,21 @@ pub fn move_caret_down( let new_selection_opt = if shift_pressed { if let Some(old_selection) = old_selection_opt { - Some(RawSelection { - start_pos: old_selection.start_pos, - end_pos: new_caret_pos, - }) + if old_caret_pos <= old_selection.start_pos { + if new_caret_pos == old_selection.end_pos { + None + } else { + Some(RawSelection { + start_pos: old_selection.end_pos, + end_pos: new_caret_pos, + }) + } + } else { + Some(RawSelection { + start_pos: old_selection.start_pos, + end_pos: new_caret_pos, + }) + } } else if !(old_line_nr == line_nr && old_col_nr == col_nr) { Some(RawSelection { start_pos: min(old_caret_pos, new_caret_pos), From 4e99f7ca6ac7aec9d9f2d7c13dd938d727bcf2e1 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 5 Jan 2021 20:08:19 +0100 Subject: [PATCH 06/13] selection shrink tests, selection shrink fixes --- editor/src/selection.rs | 56 +++++++++++++++++++++++++++++++++++++ editor/src/tea/update.rs | 60 +++++++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index 4dfa0bd719..1025e46a8f 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -852,4 +852,60 @@ mod test_parse { Ok(()) } + #[test] + fn shrink_selection_right() -> Result<(), String> { + assert_move(&["ab|[c]"], &["abc|"], true, move_caret_right)?; + assert_move(&["a|[bc]"], &["ab|[c]"], true, move_caret_right)?; + assert_move(&["|[abc]"], &["a|[bc]"], true, move_caret_right)?; + assert_move(&["|[abc\n","def\n", "ghi\n","jkl]"], &["a|[bc\n","def\n", "ghi\n", "jkl]"], true, move_caret_right)?; + assert_move(&["abc\n","d|[ef\n", "]ghi\n","jkl"], &["abc\n","de|[f\n", "]ghi\n", "jkl"], true, move_caret_right)?; + assert_move(&["abc\n","de|[f]\n", "ghi\n","jkl"], &["abc\n","def|\n", "ghi\n", "jkl"], true, move_caret_right)?; + + Ok(()) + } + + #[test] + fn shrink_selection_left() -> Result<(), String> { + assert_move(&["ab[c]|"], &["ab|c"], true, move_caret_left)?; + assert_move(&["a[bc]|"], &["a[b]|c"], true, move_caret_left)?; + assert_move(&["[abc]|"], &["[ab]|c"], true, move_caret_left)?; + assert_move(&["[abc\n","def\n", "ghi\n","jkl]|"], &["[abc\n","def\n", "ghi\n", "jk]|l"], true, move_caret_left)?; + assert_move(&["|[abc\n","def\n", "ghi\n","jkl]"], &["|[abc\n","def\n", "ghi\n", "jkl]"], true, move_caret_left)?; + assert_move(&["abc\n","def[\n", "]|ghi\n","jkl"], &["abc\n","def|\n", "ghi\n", "jkl"], true, move_caret_left)?; + assert_move(&["abc\n","d[ef\n", "gh]|i\n","jkl"], &["abc\n","d[ef\n", "g]|hi\n", "jkl"], true, move_caret_left)?; + + Ok(()) + } + + #[test] + fn shrink_selection_up() -> Result<(), String> { + assert_move(&["[abc]|"], &["|abc"], true, move_caret_up)?; + assert_move(&["[ab]|c"], &["|abc"], true, move_caret_up)?; + assert_move(&["[a]|bc"], &["|abc"], true, move_caret_up)?; + assert_move(&["|abc"], &["|abc"], true, move_caret_up)?; + assert_move(&["[abc\n","def]|"], &["[abc]|\n","def"], true, move_caret_up)?; + assert_move(&["[abc\n","de]|f"], &["[ab]|c\n","def"], true, move_caret_up)?; + assert_move(&["[abc\n","def\n", "ghi\n","jkl]|"], &["[abc\n","def\n", "ghi]|\n", "jkl"], true, move_caret_up)?; + assert_move(&["abc\n","def\n", "ghi[\n","jkl]|"], &["abc\n","def\n", "ghi|\n", "jkl"], true, move_caret_up)?; + assert_move(&["abc\n","d[ef\n", "ghi\n","jk]|l"], &["abc\n","d[ef\n", "gh]|i\n", "jkl"], true, move_caret_up)?; + assert_move(&["[abc\n","d]|ef\n", "ghi\n","jkl"], &["[a]|bc\n","def\n", "ghi\n", "jkl"], true, move_caret_up)?; + + Ok(()) + } + + #[test] + fn shrink_selection_down() -> Result<(), String> { + assert_move(&["|[abc]"], &["abc|"], true, move_caret_down)?; + assert_move(&["|[abc\n","def]"], &["abc\n","|[def]"], true, move_caret_down)?; + assert_move(&["a|[bc\n","def]"], &["abc\n","d|[ef]"], true, move_caret_down)?; + assert_move(&["|[abc\n","def\n", "ghi]"], &["abc\n","|[def\n", "ghi]"], true, move_caret_down)?; + assert_move(&["ab|[c\n","def\n", "ghi]"], &["abc\n","de|[f\n", "ghi]"], true, move_caret_down)?; + assert_move(&["abc\n","de|[f\n", "ghi]"], &["abc\n","def\n", "gh|[i]"], true, move_caret_down)?; + assert_move(&["abcdef|[\n","ghij\n", "kl]"], &["abcdef\n","ghij|[\n", "kl]"], true, move_caret_down)?; + assert_move(&["abcde|[f\n","ghij\n", "kl]"], &["abcdef\n","ghij|[\n", "kl]"], true, move_caret_down)?; + assert_move(&["ab|[cdef\n","ghij\n", "kl]"], &["abcdef\n","gh|[ij\n", "kl]"], true, move_caret_down)?; + + Ok(()) + } + } \ No newline at end of file diff --git a/editor/src/tea/update.rs b/editor/src/tea/update.rs index 8808dc6994..3a08600282 100644 --- a/editor/src/tea/update.rs +++ b/editor/src/tea/update.rs @@ -36,13 +36,24 @@ pub fn move_caret_left( let new_selection_opt = if shift_pressed { if let Some(old_selection) = old_selection_opt { - Some(RawSelection { - start_pos: Position { - line: line_nr, - column: col_nr, - }, - end_pos: old_selection.end_pos, - }) + if old_caret_pos >= old_selection.end_pos { + if new_caret_pos == old_selection.start_pos { + None + } else { + Some(RawSelection { + start_pos: old_selection.start_pos, + end_pos: new_caret_pos, + }) + } + } else { + Some(RawSelection { + start_pos: Position { + line: line_nr, + column: col_nr, + }, + end_pos: old_selection.end_pos, + }) + } } else if !(old_line_nr == line_nr && old_col_nr == col_nr) { Some(RawSelection { start_pos: Position { @@ -106,13 +117,24 @@ pub fn move_caret_right( let new_selection_opt = if shift_pressed { if let Some(old_selection) = old_selection_opt { - Some(RawSelection { - start_pos: old_selection.start_pos, - end_pos: Position { - line: line_nr, - column: col_nr, - }, - }) + if old_caret_pos <= old_selection.start_pos { + if new_caret_pos == old_selection.end_pos { + None + } else { + Some(RawSelection { + start_pos: new_caret_pos, + end_pos: old_selection.end_pos, + }) + } + } else { + Some(RawSelection { + start_pos: old_selection.start_pos, + end_pos: Position { + line: line_nr, + column: col_nr, + }, + }) + } } else if !(old_line_nr == line_nr && old_col_nr == col_nr) { Some(RawSelection { start_pos: Position { @@ -173,8 +195,8 @@ pub fn move_caret_up( None } else { Some(RawSelection { - start_pos: new_caret_pos, - end_pos: old_selection.start_pos, + start_pos: min(old_selection.start_pos, new_caret_pos), + end_pos: max(old_selection.start_pos, new_caret_pos), }) } } else { @@ -220,7 +242,7 @@ pub fn move_caret_down( unreachable!() } } else if let Some(next_line) = lines.get(old_line_nr + 1) { - if next_line.len() < old_col_nr { + if next_line.len() <= old_col_nr { if let Some(last_char) = next_line.chars().last() { if is_newline(&last_char) { (old_line_nr + 1, next_line.len() - 1) @@ -249,8 +271,8 @@ pub fn move_caret_down( None } else { Some(RawSelection { - start_pos: old_selection.end_pos, - end_pos: new_caret_pos, + start_pos: min(old_selection.end_pos, new_caret_pos), + end_pos: max(old_selection.end_pos, new_caret_pos), }) } } else { From e19969ac6957e88bd2264bdecb24a5f0c121eaca Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 6 Jan 2021 10:38:31 +0100 Subject: [PATCH 07/13] clippy, fmt, comments --- editor/src/selection.rs | 2039 +++++++++++++++++++++++++++++++------- editor/src/tea/update.rs | 102 +- editor/src/vec_result.rs | 1 - 3 files changed, 1704 insertions(+), 438 deletions(-) diff --git a/editor/src/selection.rs b/editor/src/selection.rs index 1025e46a8f..310846cbf4 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -2,7 +2,7 @@ use crate::error::{EdResult, InvalidSelection}; use crate::graphics::colors; use crate::graphics::primitives::rect::Rect; use crate::tea::model::RawSelection; -use crate::vec_result::{get_res}; +use crate::vec_result::get_res; use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; use snafu::ensure; @@ -153,51 +153,60 @@ pub fn create_selection_rects<'a>( #[cfg(test)] mod test_parse { - use crate::tea::update::{move_caret_left, move_caret_right, move_caret_down, move_caret_up}; - use crate::tea::model::{RawSelection, Position}; use crate::error::{EdResult, OutOfBounds}; - use crate::vec_result::{get_res}; - use snafu::OptionExt; - use std::slice::SliceIndex; - use std::collections::HashMap; + use crate::tea::model::{Position, RawSelection}; + use crate::tea::update::{move_caret_down, move_caret_left, move_caret_right, move_caret_up}; + use crate::vec_result::get_res; use core::cmp::Ordering; use pest::Parser; - + use snafu::OptionExt; + use std::collections::HashMap; + use std::slice::SliceIndex; #[derive(Parser)] #[grammar = "../tests/selection.pest"] pub struct LineParser; - fn convert_selection_to_dsl(raw_sel_opt: Option, caret_pos: Position, lines: &mut [String]) -> EdResult<&[String]> { + // show selection and caret position as symbols in lines for easy testing + fn convert_selection_to_dsl( + raw_sel_opt: Option, + caret_pos: Position, + lines: &mut [String], + ) -> EdResult<&[String]> { if let Some(raw_sel) = raw_sel_opt { - let mut to_insert = vec![(raw_sel.start_pos, '['), (raw_sel.end_pos, ']'), (caret_pos, '|')]; - let symbol_map: HashMap = [('[', 2), (']', 0), ('|', 1)].iter().cloned().collect(); + let mut to_insert = vec![ + (raw_sel.start_pos, '['), + (raw_sel.end_pos, ']'), + (caret_pos, '|'), + ]; + let symbol_map: HashMap = + [('[', 2), (']', 0), ('|', 1)].iter().cloned().collect(); - to_insert.sort_by( - |a, b| { - let pos_cmp = a.0.cmp(&b.0); - if pos_cmp == Ordering::Equal { - symbol_map.get(&a.1).cmp(&symbol_map.get(&b.1)) - } else { - pos_cmp - } + // sort for nice printing + to_insert.sort_by(|a, b| { + let pos_cmp = a.0.cmp(&b.0); + if pos_cmp == Ordering::Equal { + symbol_map.get(&a.1).cmp(&symbol_map.get(&b.1)) + } else { + pos_cmp } - ); + }); + // insert symbols into text lines for i in 0..to_insert.len() { let (pos, insert_char) = *get_res(i, &to_insert)?; insert_at_pos(lines, pos, insert_char)?; + // shift position of following symbols now that symbol is inserted for j in i..to_insert.len() { let (old_pos, _) = get_mut_res(j, &mut to_insert)?; - + if old_pos.line == pos.line { old_pos.column += 1; } } } - } else { insert_at_pos(lines, caret_pos, '|')?; } @@ -212,21 +221,26 @@ mod test_parse { Ok(()) } - fn get_mut_res(index: usize, vec: & mut [T]) -> EdResult<& mut >::Output> { + // It's much nicer to have get_mut return a Result with clear error than an Option + fn get_mut_res( + index: usize, + vec: &mut [T], + ) -> EdResult<&mut >::Output> { let vec_len = vec.len(); - - let elt_ref = vec.get_mut(index).context(OutOfBounds { - index, - vec_len, - })?; - + + let elt_ref = vec.get_mut(index).context(OutOfBounds { index, vec_len })?; + Ok(elt_ref) } - fn convert_dsl_to_selection(lines: &[String]) -> Result<(Option, Position), String> { + // Retrieve selection and position from formatted string + fn convert_dsl_to_selection( + lines: &[String], + ) -> Result<(Option, Position), String> { let lines_str: String = lines.join(""); - let parsed = LineParser::parse(Rule::linesWithSelect, &lines_str).expect("Selection test DSL parsing failed"); + let parsed = LineParser::parse(Rule::linesWithSelect, &lines_str) + .expect("Selection test DSL parsing failed"); let mut caret_opt: Option<(usize, usize)> = None; let mut sel_start_opt: Option<(usize, usize)> = None; @@ -235,38 +249,44 @@ mod test_parse { let mut col_nr = 0; for line in parsed { - for elt in line.into_inner() { match elt.as_rule() { Rule::optCaret => { if elt.as_span().as_str() == "|" { if caret_opt.is_some() { - return Err("Multiple carets found, there should be only one".to_owned()) + return Err( + "Multiple carets found, there should be only one".to_owned() + ); } else { caret_opt = Some((line_nr, col_nr)); } } - }, + } Rule::optSelStart => { if sel_start_opt.is_some() { if elt.as_span().as_str() == "[" { - return Err("Found start of selection more than once, there should be only one".to_owned()) + return Err("Found start of selection more than once, there should be only one".to_owned()); } - } else if elt.as_span().as_str() == "[" { + } else if elt.as_span().as_str() == "[" { sel_start_opt = Some((line_nr, col_nr)); } - }, + } Rule::optSelEnd => { if sel_end_opt.is_some() { if elt.as_span().as_str() == "]" { - return Err("Found end of selection more than once, there should be only one".to_owned()) - } + return Err("Found end of selection more than once, there should be only one".to_owned()); + } } else if elt.as_span().as_str() == "]" { - sel_end_opt = Some((line_nr, col_nr)); + sel_end_opt = Some((line_nr, col_nr)); } - }, + } Rule::text => { - let split_str = elt.as_span().as_str().split('\n').into_iter().collect::>(); + let split_str = elt + .as_span() + .as_str() + .split('\n') + .into_iter() + .collect::>(); if split_str.len() > 1 { line_nr += split_str.len() - 1; @@ -275,85 +295,77 @@ mod test_parse { if let Some(last_str) = split_str.last() { col_nr += last_str.len() } - } _ => {} } } } - + + // Make sure return makes sense if let Some((line, column)) = caret_opt { - let caret_pos = - Position { - line, - column - }; + let caret_pos = Position { line, column }; if sel_start_opt.is_none() && sel_end_opt.is_none() { - Ok (( - None, - caret_pos - )) + Ok((None, caret_pos)) } else if let Some((start_line, start_column)) = sel_start_opt { - if let Some((end_line, end_column)) = sel_end_opt { - Ok (( - Some ( - RawSelection { - start_pos : - Position { - line: start_line, - column: start_column - }, - end_pos : - Position { - line: end_line, - column: end_column - } - } - ), - caret_pos - )) - } else { - Err("Selection end ']' was not found, but selection start '[' was. Bad input string.".to_owned()) - } + if let Some((end_line, end_column)) = sel_end_opt { + Ok(( + Some(RawSelection { + start_pos: Position { + line: start_line, + column: start_column, + }, + end_pos: Position { + line: end_line, + column: end_column, + }, + }), + caret_pos, + )) + } else { + Err("Selection end ']' was not found, but selection start '[' was. Bad input string.".to_owned()) + } } else { Err("Selection start '[' was not found, but selection end ']' was. Bad input string.".to_owned()) } } else { Err("No caret was found in lines.".to_owned()) } - } + pub type MoveCaretFun = + fn(Position, Option, bool, &[String]) -> (Position, Option); + + // Convert nice string representations and compare results fn assert_move( pre_lines_str: &[&str], expected_post_lines_str: &[&str], shift_pressed: bool, - move_fun: - fn(Position, Option, bool, &[String]) -> (Position, Option) + move_fun: MoveCaretFun, ) -> Result<(), String> { let pre_lines: Vec = pre_lines_str.iter().map(|l| l.to_string()).collect(); - let expected_post_lines: Vec = expected_post_lines_str.iter().map(|l| l.to_string()).collect(); + let expected_post_lines: Vec = expected_post_lines_str + .iter() + .map(|l| l.to_string()) + .collect(); let (sel_opt, caret_pos) = convert_dsl_to_selection(&pre_lines)?; - let mut clean_lines = - pre_lines.into_iter() - .map(|line| { - line.replace(&['[', ']', '|'][..], "") - }) + let mut clean_lines = pre_lines + .into_iter() + .map(|line| line.replace(&['[', ']', '|'][..], "")) .collect::>(); - let (new_caret_pos, new_sel_opt) = move_fun(caret_pos, sel_opt, shift_pressed, &clean_lines); + let (new_caret_pos, new_sel_opt) = + move_fun(caret_pos, sel_opt, shift_pressed, &clean_lines); - let post_lines_res = - convert_selection_to_dsl(new_sel_opt, new_caret_pos, &mut clean_lines); + let post_lines_res = convert_selection_to_dsl(new_sel_opt, new_caret_pos, &mut clean_lines); match post_lines_res { Ok(post_lines) => { assert_eq!(expected_post_lines, post_lines); Ok(()) - }, - Err(e) => Err(format!("{:?}", e)) + } + Err(e) => Err(format!("{:?}", e)), } } @@ -367,16 +379,51 @@ mod test_parse { assert_move(&["abc|"], &["abc|"], false, move_caret_right)?; assert_move(&["| abc"], &[" |abc"], false, move_caret_right)?; assert_move(&["abc| "], &["abc |"], false, move_caret_right)?; - assert_move(&["abc|\n","d"], &["abc\n","|d"], false, move_caret_right)?; - assert_move(&["abc|\n",""], &["abc\n","|"], false, move_caret_right)?; - assert_move(&["abc\n","|def"], &["abc\n","d|ef"], false, move_caret_right)?; - assert_move(&["abc\n","def| "], &["abc\n","def |"], false, move_caret_right)?; - assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_right)?; - assert_move(&["abc\n","def|\n",""], &["abc\n","def\n", "|"], false, move_caret_right)?; - assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "ghi\n", "|jkl"], false, move_caret_right)?; - assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def\n", "g|hi\n", "jkl"], false, move_caret_right)?; - assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "gh|i\n", "jkl"], false, move_caret_right)?; - + assert_move(&["abc|\n", "d"], &["abc\n", "|d"], false, move_caret_right)?; + assert_move(&["abc|\n", ""], &["abc\n", "|"], false, move_caret_right)?; + assert_move( + &["abc\n", "|def"], + &["abc\n", "d|ef"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def| "], + &["abc\n", "def |"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def |\n", "ghi"], + &["abc\n", "def \n", "|ghi"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def|\n", ""], + &["abc\n", "def\n", "|"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "ghi|\n", "jkl"], + &["abc\n", "def\n", "ghi\n", "|jkl"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "|ghi\n", "jkl"], + &["abc\n", "def\n", "g|hi\n", "jkl"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "g|hi\n", "jkl"], + &["abc\n", "def\n", "gh|i\n", "jkl"], + false, + move_caret_right, + )?; + Ok(()) } @@ -390,16 +437,51 @@ mod test_parse { assert_move(&["abc|"], &["ab|c"], false, move_caret_left)?; assert_move(&[" |abc"], &["| abc"], false, move_caret_left)?; assert_move(&["abc |"], &["abc| "], false, move_caret_left)?; - assert_move(&["abc\n","|d"], &["abc|\n","d"], false, move_caret_left)?; - assert_move(&["abc\n","|"], &["abc|\n",""], false, move_caret_left)?; - assert_move(&["abc\n","d|ef"], &["abc\n","|def"], false, move_caret_left)?; - assert_move(&["abc\n","def |"], &["abc\n","def| "], false, move_caret_left)?; - assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","def |\n", "ghi"], false, move_caret_left)?; - assert_move(&["abc\n","def\n","|"], &["abc\n","def|\n", ""], false, move_caret_left)?; - assert_move(&["abc\n","def\n", "ghi\n","|jkl"], &["abc\n","def\n", "ghi|\n", "jkl"], false, move_caret_left)?; - assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "|ghi\n", "jkl"], false, move_caret_left)?; - assert_move(&["abc\n","def\n", "gh|i\n","jkl"], &["abc\n","def\n", "g|hi\n", "jkl"], false, move_caret_left)?; - + assert_move(&["abc\n", "|d"], &["abc|\n", "d"], false, move_caret_left)?; + assert_move(&["abc\n", "|"], &["abc|\n", ""], false, move_caret_left)?; + assert_move( + &["abc\n", "d|ef"], + &["abc\n", "|def"], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def |"], + &["abc\n", "def| "], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def \n", "|ghi"], + &["abc\n", "def |\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "|"], + &["abc\n", "def|\n", ""], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "ghi\n", "|jkl"], + &["abc\n", "def\n", "ghi|\n", "jkl"], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "g|hi\n", "jkl"], + &["abc\n", "def\n", "|ghi\n", "jkl"], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "gh|i\n", "jkl"], + &["abc\n", "def\n", "g|hi\n", "jkl"], + false, + move_caret_left, + )?; + Ok(()) } @@ -411,32 +493,122 @@ mod test_parse { assert_move(&["a|bc"], &["|abc"], false, move_caret_up)?; assert_move(&["ab|c"], &["|abc"], false, move_caret_up)?; assert_move(&["abc|"], &["|abc"], false, move_caret_up)?; - assert_move(&["|abc\n","def"], &["|abc\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","|def"], &["|abc\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","d|ef"], &["a|bc\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","de|f"], &["ab|c\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","def|"], &["abc|\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","|def \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","def \n", "g|hi"], &["abc\n","d|ef \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","def \n", "gh|i"], &["abc\n","de|f \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","def \n", "ghi|"], &["abc\n","def| \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","de\n", "ghi|"], &["abc\n","de|\n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","de|"], &["ab|c\n","de"], false, move_caret_up)?; - assert_move(&["abc\n","d|e"], &["a|bc\n","de"], false, move_caret_up)?; - assert_move(&["abc\n","|de"], &["|abc\n","de"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], &[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cde|f\n", "ghijkl\n","mnopqrst"], &["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","st|"], &["abcdefgh\n","ijklmn\n", "op|qr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijkl|mn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdef|gh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefg|h\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["a|bcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["|abcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; + assert_move(&["|abc\n", "def"], &["|abc\n", "def"], false, move_caret_up)?; + assert_move(&["abc\n", "|def"], &["|abc\n", "def"], false, move_caret_up)?; + assert_move(&["abc\n", "d|ef"], &["a|bc\n", "def"], false, move_caret_up)?; + assert_move(&["abc\n", "de|f"], &["ab|c\n", "def"], false, move_caret_up)?; + assert_move(&["abc\n", "def|"], &["abc|\n", "def"], false, move_caret_up)?; + assert_move( + &["abc\n", "def \n", "|ghi"], + &["abc\n", "|def \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "g|hi"], + &["abc\n", "d|ef \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "gh|i"], + &["abc\n", "de|f \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "ghi|"], + &["abc\n", "def| \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "de\n", "ghi|"], + &["abc\n", "de|\n", "ghi"], + false, + move_caret_up, + )?; + assert_move(&["abc\n", "de|"], &["ab|c\n", "de"], false, move_caret_up)?; + assert_move(&["abc\n", "d|e"], &["a|bc\n", "de"], false, move_caret_up)?; + assert_move(&["abc\n", "|de"], &["|abc\n", "de"], false, move_caret_up)?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "mnopqrst|"], + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + &["ab\n", "cdef|\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "|mnopqrst"], + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &[" ab\n", " |cdef\n", "ghijkl\n", "mnopqrst"], + &[" |ab\n", " cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "mnopqr|st"], + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cde|f\n", "ghijkl\n", "mnopqrst"], + &["ab|\n", "cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + &["abcdefgh\n", "ijklmn\n", "op|qr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + &["abcdefgh\n", "ijkl|mn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + &["abcdef|gh\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh|\n", "ijklmn\n", "opqr\n", "st"], + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefg|h\n", "ijklmn\n", "opqr\n", "st"], + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["a|bcdefgh\n", "ijklmn\n", "opqr\n", "st"], + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; assert_move(&["abc def gh |"], &["|abc def gh "], false, move_caret_up)?; assert_move(&["abc de|f gh "], &["|abc def gh "], false, move_caret_up)?; assert_move(&["ab|c def gh "], &["|abc def gh "], false, move_caret_up)?; @@ -454,34 +626,154 @@ mod test_parse { assert_move(&["ab|c"], &["abc|"], false, move_caret_down)?; assert_move(&["abc|"], &["abc|"], false, move_caret_down)?; assert_move(&["abc| "], &["abc |"], false, move_caret_down)?; - assert_move(&["abc\n","|def"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","d|ef"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","de|f"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","def|"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["|abc\n","def"], &["abc\n","|def"], false, move_caret_down)?; - assert_move(&["a|bc\n","def"], &["abc\n","d|ef"], false, move_caret_down)?; - assert_move(&["ab|c\n","def"], &["abc\n","de|f"], false, move_caret_down)?; - assert_move(&["abc|\n","def"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","|def \n", "ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_down)?; - assert_move(&["abc\n","d|ef \n", "ghi"], &["abc\n","def \n", "g|hi"], false, move_caret_down)?; - assert_move(&["abc\n","de|f \n", "ghi"], &["abc\n","def \n", "gh|i"], false, move_caret_down)?; - assert_move(&["abc\n","def| \n", "ghi"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; - assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; - assert_move(&["abc\n","de|\n", "ghi"], &["abc\n","de\n", "gh|i"], false, move_caret_down)?; - assert_move(&["abc|\n","de"], &["abc\n","de|"], false, move_caret_down)?; - assert_move(&["ab|c\n","de"], &["abc\n","de|"], false, move_caret_down)?; - assert_move(&["a|bc\n","de"], &["abc\n","d|e"], false, move_caret_down)?; - assert_move(&["|abc\n","de"], &["abc\n","|de"], false, move_caret_down)?; - assert_move(&["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","cd|ef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "ghij|kl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], false, move_caret_down)?; - assert_move(&[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], &[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], false, move_caret_down)?; - assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","|st"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; + assert_move( + &["abc\n", "|def"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "d|ef"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|f"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "def|"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["|abc\n", "def"], + &["abc\n", "|def"], + false, + move_caret_down, + )?; + assert_move( + &["a|bc\n", "def"], + &["abc\n", "d|ef"], + false, + move_caret_down, + )?; + assert_move( + &["ab|c\n", "def"], + &["abc\n", "de|f"], + false, + move_caret_down, + )?; + assert_move( + &["abc|\n", "def"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "|def \n", "ghi"], + &["abc\n", "def \n", "|ghi"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "d|ef \n", "ghi"], + &["abc\n", "def \n", "g|hi"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|f \n", "ghi"], + &["abc\n", "def \n", "gh|i"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "def| \n", "ghi"], + &["abc\n", "def \n", "ghi|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "def |\n", "ghi"], + &["abc\n", "def \n", "ghi|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|\n", "ghi"], + &["abc\n", "de\n", "gh|i"], + false, + move_caret_down, + )?; + assert_move(&["abc|\n", "de"], &["abc\n", "de|"], false, move_caret_down)?; + assert_move(&["ab|c\n", "de"], &["abc\n", "de|"], false, move_caret_down)?; + assert_move(&["a|bc\n", "de"], &["abc\n", "d|e"], false, move_caret_down)?; + assert_move(&["|abc\n", "de"], &["abc\n", "|de"], false, move_caret_down)?; + assert_move( + &["ab|\n", "cdef\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "cd|ef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef|\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "cdef\n", "ghij|kl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + &["ab\n", "cdef\n", "ghijkl\n", "mnopqr|st"], + false, + move_caret_down, + )?; + assert_move( + &[" |ab\n", " cdef\n", "ghijkl\n", "mnopqrst"], + &[" ab\n", " |cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "|cdef\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + &["ab\n", "cdef\n", "ghijkl\n", "|mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh|\n", "ijklmn\n", "opqr\n", "st"], + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "|st"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + false, + move_caret_down, + )?; assert_move(&["abc def gh |"], &["abc def gh |"], false, move_caret_down)?; assert_move(&["abc de|f gh "], &["abc def gh |"], false, move_caret_down)?; assert_move(&["ab|c def gh "], &["abc def gh |"], false, move_caret_down)?; @@ -501,16 +793,51 @@ mod test_parse { assert_move(&["abc|"], &["abc|"], true, move_caret_right)?; assert_move(&["| abc"], &["[ ]|abc"], true, move_caret_right)?; assert_move(&["abc| "], &["abc[ ]|"], true, move_caret_right)?; - assert_move(&["abc|\n","d"], &["abc[\n","]|d"], true, move_caret_right)?; - assert_move(&["abc|\n",""], &["abc[\n","]|"], true, move_caret_right)?; - assert_move(&["abc\n","|def"], &["abc\n","[d]|ef"], true, move_caret_right)?; - assert_move(&["abc\n","def| "], &["abc\n","def[ ]|"], true, move_caret_right)?; - assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def [\n", "]|ghi"], true, move_caret_right)?; - assert_move(&["abc\n","def|\n",""], &["abc\n","def[\n", "]|"], true, move_caret_right)?; - assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "ghi[\n", "]|jkl"], true, move_caret_right)?; - assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def\n", "[g]|hi\n", "jkl"], true, move_caret_right)?; - assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "g[h]|i\n", "jkl"], true, move_caret_right)?; - + assert_move(&["abc|\n", "d"], &["abc[\n", "]|d"], true, move_caret_right)?; + assert_move(&["abc|\n", ""], &["abc[\n", "]|"], true, move_caret_right)?; + assert_move( + &["abc\n", "|def"], + &["abc\n", "[d]|ef"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def| "], + &["abc\n", "def[ ]|"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def |\n", "ghi"], + &["abc\n", "def [\n", "]|ghi"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def|\n", ""], + &["abc\n", "def[\n", "]|"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "ghi|\n", "jkl"], + &["abc\n", "def\n", "ghi[\n", "]|jkl"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "|ghi\n", "jkl"], + &["abc\n", "def\n", "[g]|hi\n", "jkl"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "g|hi\n", "jkl"], + &["abc\n", "def\n", "g[h]|i\n", "jkl"], + true, + move_caret_right, + )?; + Ok(()) } @@ -524,18 +851,58 @@ mod test_parse { assert_move(&["abc|"], &["ab|[c]"], true, move_caret_left)?; assert_move(&[" |abc"], &["|[ ]abc"], true, move_caret_left)?; assert_move(&["abc |"], &["abc|[ ]"], true, move_caret_left)?; - assert_move(&["abc|\n","d"], &["ab|[c]\n","d"], true, move_caret_left)?; - assert_move(&["abc\n","|d"], &["abc|[\n","]d"], true, move_caret_left)?; - assert_move(&["abc\n","|"], &["abc|[\n","]"], true, move_caret_left)?; - assert_move(&["abc\n"," |def"], &["abc\n","|[ ]def"], true, move_caret_left)?; - assert_move(&["abc\n","d|ef"], &["abc\n","|[d]ef"], true, move_caret_left)?; - assert_move(&["abc\n","de|f "], &["abc\n","d|[e]f "], true, move_caret_left)?; - assert_move(&["abc\n","def\n","|"], &["abc\n","def|[\n", "]"], true, move_caret_left)?; - assert_move(&["abc\n","def\n", "|ghi\n","jkl"], &["abc\n","def|[\n", "]ghi\n", "jkl"], true, move_caret_left)?; - assert_move(&["abc\n","def\n", "g|hi\n","jkl"], &["abc\n","def\n", "|[g]hi\n", "jkl"], true, move_caret_left)?; - assert_move(&["abc\n","def\n", "gh|i\n","jkl"], &["abc\n","def\n", "g|[h]i\n", "jkl"], true, move_caret_left)?; - assert_move(&["abc\n","def\n", "ghi|\n","jkl"], &["abc\n","def\n", "gh|[i]\n", "jkl"], true, move_caret_left)?; - + assert_move(&["abc|\n", "d"], &["ab|[c]\n", "d"], true, move_caret_left)?; + assert_move(&["abc\n", "|d"], &["abc|[\n", "]d"], true, move_caret_left)?; + assert_move(&["abc\n", "|"], &["abc|[\n", "]"], true, move_caret_left)?; + assert_move( + &["abc\n", " |def"], + &["abc\n", "|[ ]def"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "d|ef"], + &["abc\n", "|[d]ef"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "de|f "], + &["abc\n", "d|[e]f "], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "|"], + &["abc\n", "def|[\n", "]"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "|ghi\n", "jkl"], + &["abc\n", "def|[\n", "]ghi\n", "jkl"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "g|hi\n", "jkl"], + &["abc\n", "def\n", "|[g]hi\n", "jkl"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "gh|i\n", "jkl"], + &["abc\n", "def\n", "g|[h]i\n", "jkl"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "ghi|\n", "jkl"], + &["abc\n", "def\n", "gh|[i]\n", "jkl"], + true, + move_caret_left, + )?; + Ok(()) } @@ -548,39 +915,199 @@ mod test_parse { assert_move(&["ab|c"], &["ab[c]|"], true, move_caret_down)?; assert_move(&["abc|"], &["abc|"], true, move_caret_down)?; assert_move(&["abc| "], &["abc[ ]|"], true, move_caret_down)?; - assert_move(&["abc\n","|def"], &["abc\n","[def]|"], true, move_caret_down)?; - assert_move(&["abc\n","d|ef"], &["abc\n","d[ef]|"], true, move_caret_down)?; - assert_move(&["abc\n","de|f"], &["abc\n","de[f]|"], true, move_caret_down)?; - assert_move(&["abc\n","def|"], &["abc\n","def|"], true, move_caret_down)?; - assert_move(&["|abc\n","def"], &["[abc\n","]|def"], true, move_caret_down)?; - assert_move(&["a|bc\n","def"], &["a[bc\n","d]|ef"], true, move_caret_down)?; - assert_move(&["ab|c\n","def"], &["ab[c\n","de]|f"], true, move_caret_down)?; - assert_move(&["abc|\n","def"], &["abc[\n","def]|"], true, move_caret_down)?; - assert_move(&["abc\n","|def \n", "ghi"], &["abc\n","[def \n", "]|ghi"], true, move_caret_down)?; - assert_move(&["abc\n","d|ef \n", "ghi"], &["abc\n","d[ef \n", "g]|hi"], true, move_caret_down)?; - assert_move(&["abc\n","de|f \n", "ghi"], &["abc\n","de[f \n", "gh]|i"], true, move_caret_down)?; - assert_move(&["abc\n","def| \n", "ghi"], &["abc\n","def[ \n", "ghi]|"], true, move_caret_down)?; - assert_move(&["abc\n","def |\n", "ghi"], &["abc\n","def [\n", "ghi]|"], true, move_caret_down)?; - assert_move(&["abc\n","de|\n", "ghi"], &["abc\n","de[\n", "gh]|i"], true, move_caret_down)?; - assert_move(&["abc|\n","de"], &["abc[\n","de]|"], true, move_caret_down)?; - assert_move(&["ab|c\n","de"], &["ab[c\n","de]|"], true, move_caret_down)?; - assert_move(&["a|bc\n","de"], &["a[bc\n","d]|e"], true, move_caret_down)?; - assert_move(&["|abc\n","de"], &["[abc\n","]|de"], true, move_caret_down)?; - assert_move(&["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], &["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], true, move_caret_down)?; - assert_move(&["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], &["ab\n","cdef[\n", "ghij]|kl\n","mnopqrst"], true, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], true, move_caret_down)?; - assert_move(&[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], &[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], true, move_caret_down)?; - assert_move(&["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], &["ab\n","[cdef\n", "]|ghijkl\n","mnopqrst"], true, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], true, move_caret_down)?; - assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], true, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], true, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], true, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","|st"], &["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], true, move_caret_down)?; + assert_move( + &["abc\n", "|def"], + &["abc\n", "[def]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "d|ef"], + &["abc\n", "d[ef]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|f"], + &["abc\n", "de[f]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "def|"], + &["abc\n", "def|"], + true, + move_caret_down, + )?; + assert_move( + &["|abc\n", "def"], + &["[abc\n", "]|def"], + true, + move_caret_down, + )?; + assert_move( + &["a|bc\n", "def"], + &["a[bc\n", "d]|ef"], + true, + move_caret_down, + )?; + assert_move( + &["ab|c\n", "def"], + &["ab[c\n", "de]|f"], + true, + move_caret_down, + )?; + assert_move( + &["abc|\n", "def"], + &["abc[\n", "def]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "|def \n", "ghi"], + &["abc\n", "[def \n", "]|ghi"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "d|ef \n", "ghi"], + &["abc\n", "d[ef \n", "g]|hi"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|f \n", "ghi"], + &["abc\n", "de[f \n", "gh]|i"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "def| \n", "ghi"], + &["abc\n", "def[ \n", "ghi]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "def |\n", "ghi"], + &["abc\n", "def [\n", "ghi]|"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|\n", "ghi"], + &["abc\n", "de[\n", "gh]|i"], + true, + move_caret_down, + )?; + assert_move( + &["abc|\n", "de"], + &["abc[\n", "de]|"], + true, + move_caret_down, + )?; + assert_move( + &["ab|c\n", "de"], + &["ab[c\n", "de]|"], + true, + move_caret_down, + )?; + assert_move( + &["a|bc\n", "de"], + &["a[bc\n", "d]|e"], + true, + move_caret_down, + )?; + assert_move( + &["|abc\n", "de"], + &["[abc\n", "]|de"], + true, + move_caret_down, + )?; + assert_move( + &["ab|\n", "cdef\n", "ghijkl\n", "mnopqrst"], + &["ab[\n", "cd]|ef\n", "ghijkl\n", "mnopqrst"], + true, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef|\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "cdef[\n", "ghij]|kl\n", "mnopqrst"], + true, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + &["ab\n", "cdef\n", "ghijkl[\n", "mnopqr]|st"], + true, + move_caret_down, + )?; + assert_move( + &[" |ab\n", " cdef\n", "ghijkl\n", "mnopqrst"], + &[" [ab\n", " ]|cdef\n", "ghijkl\n", "mnopqrst"], + true, + move_caret_down, + )?; + assert_move( + &["ab\n", "|cdef\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "[cdef\n", "]|ghijkl\n", "mnopqrst"], + true, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + &["ab\n", "cdef\n", "[ghijkl\n", "]|mnopqrst"], + true, + move_caret_down, + )?; + assert_move( + &["abcdefgh|\n", "ijklmn\n", "opqr\n", "st"], + &["abcdefgh[\n", "ijklmn]|\n", "opqr\n", "st"], + true, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + &["abcdefgh\n", "ijklmn[\n", "opqr]|\n", "st"], + true, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + &["abcdefgh\n", "ijklmn\n", "opqr[\n", "st]|"], + true, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "|st"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "[st]|"], + true, + move_caret_down, + )?; assert_move(&["abc def gh |"], &["abc def gh |"], true, move_caret_down)?; - assert_move(&["abc de|f gh "], &["abc de[f gh ]|"], true, move_caret_down)?; - assert_move(&["ab|c def gh "], &["ab[c def gh ]|"], true, move_caret_down)?; - assert_move(&["a|bc def gh "], &["a[bc def gh ]|"], true, move_caret_down)?; - assert_move(&["|abc def gh "], &["[abc def gh ]|"], true, move_caret_down)?; + assert_move( + &["abc de|f gh "], + &["abc de[f gh ]|"], + true, + move_caret_down, + )?; + assert_move( + &["ab|c def gh "], + &["ab[c def gh ]|"], + true, + move_caret_down, + )?; + assert_move( + &["a|bc def gh "], + &["a[bc def gh ]|"], + true, + move_caret_down, + )?; + assert_move( + &["|abc def gh "], + &["[abc def gh ]|"], + true, + move_caret_down, + )?; Ok(()) } @@ -593,32 +1120,142 @@ mod test_parse { assert_move(&["a|bc"], &["|[a]bc"], true, move_caret_up)?; assert_move(&["ab|c"], &["|[ab]c"], true, move_caret_up)?; assert_move(&["abc|"], &["|[abc]"], true, move_caret_up)?; - assert_move(&["|abc\n","def"], &["|abc\n","def"], true, move_caret_up)?; - assert_move(&["abc\n","|def"], &["|[abc\n","]def"], true, move_caret_up)?; - assert_move(&["abc\n","d|ef"], &["a|[bc\n","d]ef"], true, move_caret_up)?; - assert_move(&["abc\n","de|f"], &["ab|[c\n","de]f"], true, move_caret_up)?; - assert_move(&["abc\n","def|"], &["abc|[\n","def]"], true, move_caret_up)?; - assert_move(&["abc\n","def \n", "|ghi"], &["abc\n","|[def \n", "]ghi"], true, move_caret_up)?; - assert_move(&["abc\n","def \n", "g|hi"], &["abc\n","d|[ef \n", "g]hi"], true, move_caret_up)?; - assert_move(&["abc\n","def \n", "gh|i"], &["abc\n","de|[f \n", "gh]i"], true, move_caret_up)?; - assert_move(&["abc\n","def \n", "ghi|"], &["abc\n","def|[ \n", "ghi]"], true, move_caret_up)?; - assert_move(&["abc\n","de\n", "ghi|"], &["abc\n","de|[\n", "ghi]"], true, move_caret_up)?; - assert_move(&["abc\n","de|"], &["ab|[c\n","de]"], true, move_caret_up)?; - assert_move(&["abc\n","d|e"], &["a|[bc\n","d]e"], true, move_caret_up)?; - assert_move(&["abc\n","|de"], &["|[abc\n","]de"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], &["ab\n","cdef\n", "ghijkl|[\n","mnopqrst]"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], &["ab\n","cdef|[\n", "ghijkl]\n","mnopqrst"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], &["ab\n","cdef\n", "|[ghijkl\n","]mnopqrst"], true, move_caret_up)?; - assert_move(&[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], &[" |[ab\n"," ]cdef\n", "ghijkl\n","mnopqrst"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], &["ab\n","cdef\n", "ghijkl|[\n","mnopqr]st"], true, move_caret_up)?; - assert_move(&["ab\n","cde|f\n", "ghijkl\n","mnopqrst"], &["ab|[\n","cde]f\n", "ghijkl\n","mnopqrst"], true, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","st|"], &["abcdefgh\n","ijklmn\n", "op|[qr\n","st]"], true, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr|\n","st"], &["abcdefgh\n","ijkl|[mn\n", "opqr]\n","st"], true, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn|\n", "opqr\n","st"], &["abcdef|[gh\n","ijklmn]\n", "opqr\n","st"], true, move_caret_up)?; - assert_move(&["abcdefgh|\n","ijklmn\n", "opqr\n","st"], &["|[abcdefgh]\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; - assert_move(&["abcdefg|h\n","ijklmn\n", "opqr\n","st"], &["|[abcdefg]h\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; - assert_move(&["a|bcdefgh\n","ijklmn\n", "opqr\n","st"], &["|[a]bcdefgh\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; - assert_move(&["|abcdefgh\n","ijklmn\n", "opqr\n","st"], &["|abcdefgh\n","ijklmn\n", "opqr\n","st"], true, move_caret_up)?; + assert_move(&["|abc\n", "def"], &["|abc\n", "def"], true, move_caret_up)?; + assert_move( + &["abc\n", "|def"], + &["|[abc\n", "]def"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "d|ef"], + &["a|[bc\n", "d]ef"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "de|f"], + &["ab|[c\n", "de]f"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def|"], + &["abc|[\n", "def]"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "|ghi"], + &["abc\n", "|[def \n", "]ghi"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "g|hi"], + &["abc\n", "d|[ef \n", "g]hi"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "gh|i"], + &["abc\n", "de|[f \n", "gh]i"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def \n", "ghi|"], + &["abc\n", "def|[ \n", "ghi]"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "de\n", "ghi|"], + &["abc\n", "de|[\n", "ghi]"], + true, + move_caret_up, + )?; + assert_move(&["abc\n", "de|"], &["ab|[c\n", "de]"], true, move_caret_up)?; + assert_move(&["abc\n", "d|e"], &["a|[bc\n", "d]e"], true, move_caret_up)?; + assert_move(&["abc\n", "|de"], &["|[abc\n", "]de"], true, move_caret_up)?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "mnopqrst|"], + &["ab\n", "cdef\n", "ghijkl|[\n", "mnopqrst]"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + &["ab\n", "cdef|[\n", "ghijkl]\n", "mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "|mnopqrst"], + &["ab\n", "cdef\n", "|[ghijkl\n", "]mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &[" ab\n", " |cdef\n", "ghijkl\n", "mnopqrst"], + &[" |[ab\n", " ]cdef\n", "ghijkl\n", "mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "mnopqr|st"], + &["ab\n", "cdef\n", "ghijkl|[\n", "mnopqr]st"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cde|f\n", "ghijkl\n", "mnopqrst"], + &["ab|[\n", "cde]f\n", "ghijkl\n", "mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + &["abcdefgh\n", "ijklmn\n", "op|[qr\n", "st]"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + &["abcdefgh\n", "ijkl|[mn\n", "opqr]\n", "st"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + &["abcdef|[gh\n", "ijklmn]\n", "opqr\n", "st"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefgh|\n", "ijklmn\n", "opqr\n", "st"], + &["|[abcdefgh]\n", "ijklmn\n", "opqr\n", "st"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefg|h\n", "ijklmn\n", "opqr\n", "st"], + &["|[abcdefg]h\n", "ijklmn\n", "opqr\n", "st"], + true, + move_caret_up, + )?; + assert_move( + &["a|bcdefgh\n", "ijklmn\n", "opqr\n", "st"], + &["|[a]bcdefgh\n", "ijklmn\n", "opqr\n", "st"], + true, + move_caret_up, + )?; + assert_move( + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + &["|abcdefgh\n", "ijklmn\n", "opqr\n", "st"], + true, + move_caret_up, + )?; assert_move(&["abc def gh |"], &["|[abc def gh ]"], true, move_caret_up)?; assert_move(&["abc de|f gh "], &["|[abc de]f gh "], true, move_caret_up)?; assert_move(&["ab|c def gh "], &["|[ab]c def gh "], true, move_caret_up)?; @@ -636,23 +1273,93 @@ mod test_parse { assert_move(&["[ ]|abc"], &[" |abc"], false, move_caret_right)?; assert_move(&["|[ ]abc"], &[" |abc"], false, move_caret_right)?; assert_move(&["a|[b]c"], &["ab|c"], false, move_caret_right)?; - assert_move(&["abc[\n","]|d"], &["abc\n","|d"], false, move_caret_right)?; - assert_move(&["abc|[\n","]d"], &["abc\n","|d"], false, move_caret_right)?; - assert_move(&["abc|[\n","]"], &["abc\n","|"], false, move_caret_right)?; - assert_move(&["abc\n","[d]|ef"], &["abc\n","d|ef"], false, move_caret_right)?; - assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi\n", "|jkl"], false, move_caret_right)?; + assert_move( + &["abc[\n", "]|d"], + &["abc\n", "|d"], + false, + move_caret_right, + )?; + assert_move( + &["abc|[\n", "]d"], + &["abc\n", "|d"], + false, + move_caret_right, + )?; + assert_move(&["abc|[\n", "]"], &["abc\n", "|"], false, move_caret_right)?; + assert_move( + &["abc\n", "[d]|ef"], + &["abc\n", "d|ef"], + false, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "ghi[\n", "]|jkl"], + &["abc\n", "def\n", "ghi\n", "|jkl"], + false, + move_caret_right, + )?; assert_move(&["[ab]|c"], &["ab|c"], false, move_caret_right)?; assert_move(&["[abc]|"], &["abc|"], false, move_caret_right)?; - assert_move(&["ab|[c\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; - assert_move(&["ab[c\n","]|def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; - assert_move(&["a|[bc\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; - assert_move(&["|[abc\n","]def\n","ghi"], &["abc\n","|def\n","ghi"], false, move_caret_right)?; - assert_move(&["a|[bc\n","d]ef\n","ghi"], &["abc\n","d|ef\n","ghi"], false, move_caret_right)?; - assert_move(&["|[abc\n","def]\n","ghi"], &["abc\n","def|\n","ghi"], false, move_caret_right)?; - assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], false, move_caret_right)?; - assert_move(&["|[ab\n","cdef\n", "ghijkl\n","mnopqrst]"], &["ab\n","cdef\n", "ghijkl\n","mnopqrst|"], false, move_caret_right)?; - assert_move(&["ab\n","c[def\n", "ghijkl\n","mno]|pqrst"], &["ab\n","cdef\n", "ghijkl\n","mno|pqrst"], false, move_caret_right)?; - assert_move(&["ab\n","c|[def\n", "ghijkl\n","mno]pqrst"], &["ab\n","cdef\n", "ghijkl\n","mno|pqrst"], false, move_caret_right)?; + assert_move( + &["ab|[c\n", "]def\n", "ghi"], + &["abc\n", "|def\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["ab[c\n", "]|def\n", "ghi"], + &["abc\n", "|def\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["a|[bc\n", "]def\n", "ghi"], + &["abc\n", "|def\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["|[abc\n", "]def\n", "ghi"], + &["abc\n", "|def\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["a|[bc\n", "d]ef\n", "ghi"], + &["abc\n", "d|ef\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["|[abc\n", "def]\n", "ghi"], + &["abc\n", "def|\n", "ghi"], + false, + move_caret_right, + )?; + assert_move( + &["[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]|"], + &["ab\n", "cdef\n", "ghijkl\n", "mnopqrst|"], + false, + move_caret_right, + )?; + assert_move( + &["|[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]"], + &["ab\n", "cdef\n", "ghijkl\n", "mnopqrst|"], + false, + move_caret_right, + )?; + assert_move( + &["ab\n", "c[def\n", "ghijkl\n", "mno]|pqrst"], + &["ab\n", "cdef\n", "ghijkl\n", "mno|pqrst"], + false, + move_caret_right, + )?; + assert_move( + &["ab\n", "c|[def\n", "ghijkl\n", "mno]pqrst"], + &["ab\n", "cdef\n", "ghijkl\n", "mno|pqrst"], + false, + move_caret_right, + )?; Ok(()) } @@ -663,26 +1370,86 @@ mod test_parse { assert_move(&["[a]|bc"], &["|abc"], false, move_caret_left)?; assert_move(&["a[b]|c"], &["a|bc"], false, move_caret_left)?; assert_move(&["ab[c]|"], &["ab|c"], false, move_caret_left)?; - assert_move(&["[ ]|abc"], &["| abc"], false, move_caret_left)?; + assert_move(&["[ ]|abc"], &["| abc"], false, move_caret_left)?; assert_move(&["|[ ]abc"], &["| abc"], false, move_caret_left)?; assert_move(&["a|[b]c"], &["a|bc"], false, move_caret_left)?; - assert_move(&["abc[\n","]|d"], &["abc|\n","d"], false, move_caret_left)?; - assert_move(&["abc|[\n","]d"], &["abc|\n","d"], false, move_caret_left)?; - assert_move(&["abc|[\n","]"], &["abc|\n",""], false, move_caret_left)?; - assert_move(&["abc\n","[d]|ef"], &["abc\n","|def"], false, move_caret_left)?; - assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi|\n", "jkl"], false, move_caret_left)?; + assert_move(&["abc[\n", "]|d"], &["abc|\n", "d"], false, move_caret_left)?; + assert_move(&["abc|[\n", "]d"], &["abc|\n", "d"], false, move_caret_left)?; + assert_move(&["abc|[\n", "]"], &["abc|\n", ""], false, move_caret_left)?; + assert_move( + &["abc\n", "[d]|ef"], + &["abc\n", "|def"], + false, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "ghi[\n", "]|jkl"], + &["abc\n", "def\n", "ghi|\n", "jkl"], + false, + move_caret_left, + )?; assert_move(&["[ab]|c"], &["|abc"], false, move_caret_left)?; assert_move(&["[abc]|"], &["|abc"], false, move_caret_left)?; - assert_move(&["ab|[c\n","]def\n","ghi"], &["ab|c\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["ab[c\n","]|def\n","ghi"], &["ab|c\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["a|[bc\n","]def\n","ghi"], &["a|bc\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["|[abc\n","]def\n","ghi"], &["|abc\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["a|[bc\n","d]ef\n","ghi"], &["a|bc\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["|[abc\n","def]\n","ghi"], &["|abc\n","def\n","ghi"], false, move_caret_left)?; - assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["|ab\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; - assert_move(&["|[ab\n","cdef\n", "ghijkl\n","mnopqrst]"], &["|ab\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; - assert_move(&["ab\n","c[def\n", "ghijkl\n","mno]|pqrst"], &["ab\n","c|def\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; - assert_move(&["ab\n","c|[def\n", "ghijkl\n","mno]pqrst"], &["ab\n","c|def\n", "ghijkl\n","mnopqrst"], false, move_caret_left)?; + assert_move( + &["ab|[c\n", "]def\n", "ghi"], + &["ab|c\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["ab[c\n", "]|def\n", "ghi"], + &["ab|c\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["a|[bc\n", "]def\n", "ghi"], + &["a|bc\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["|[abc\n", "]def\n", "ghi"], + &["|abc\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["a|[bc\n", "d]ef\n", "ghi"], + &["a|bc\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["|[abc\n", "def]\n", "ghi"], + &["|abc\n", "def\n", "ghi"], + false, + move_caret_left, + )?; + assert_move( + &["[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]|"], + &["|ab\n", "cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_left, + )?; + assert_move( + &["|[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]"], + &["|ab\n", "cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_left, + )?; + assert_move( + &["ab\n", "c[def\n", "ghijkl\n", "mno]|pqrst"], + &["ab\n", "c|def\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_left, + )?; + assert_move( + &["ab\n", "c|[def\n", "ghijkl\n", "mno]pqrst"], + &["ab\n", "c|def\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_left, + )?; Ok(()) } @@ -694,37 +1461,192 @@ mod test_parse { assert_move(&["a|[bc]"], &["abc|"], false, move_caret_down)?; assert_move(&["ab[c]|"], &["abc|"], false, move_caret_down)?; assert_move(&["abc|[ ]"], &["abc |"], false, move_caret_down)?; - assert_move(&["abc\n","|[def]"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","d|[ef]"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","de|[f]"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["[abc\n","]|def"], &["abc\n","|def"], false, move_caret_down)?; - assert_move(&["a[bc\n","d]|ef"], &["abc\n","d|ef"], false, move_caret_down)?; - assert_move(&["ab|[c\n","de]f"], &["abc\n","de|f"], false, move_caret_down)?; - assert_move(&["abc[\n","def]|"], &["abc\n","def|"], false, move_caret_down)?; - assert_move(&["abc\n","|[def \n", "]ghi"], &["abc\n","def \n", "|ghi"], false, move_caret_down)?; - assert_move(&["abc\n","d[ef \n", "g]|hi"], &["abc\n","def \n", "g|hi"], false, move_caret_down)?; - assert_move(&["abc\n","de[f \n", "gh]|i"], &["abc\n","def \n", "gh|i"], false, move_caret_down)?; - assert_move(&["abc\n","def[ \n", "ghi]|"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; - assert_move(&["abc\n","def [\n", "ghi]|"], &["abc\n","def \n", "ghi|"], false, move_caret_down)?; - assert_move(&["abc\n","de[\n", "gh]|i"], &["abc\n","de\n", "gh|i"], false, move_caret_down)?; - assert_move(&["abc|[\n","de]"], &["abc\n","de|"], false, move_caret_down)?; - assert_move(&["ab[c\n","de]|"], &["abc\n","de|"], false, move_caret_down)?; - assert_move(&["a|[bc\n","d]e"], &["abc\n","d|e"], false, move_caret_down)?; - assert_move(&["[abc\n","]|de"], &["abc\n","|de"], false, move_caret_down)?; - assert_move(&["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], &["ab\n","cd|ef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef|[\n", "ghij]kl\n","mnopqrst"], &["ab\n","cdef\n", "ghij|kl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], &["ab\n","cdef\n", "ghijkl\n","mnopqr|st"], false, move_caret_down)?; - assert_move(&[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], &[" ab\n"," |cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","|[cdef\n", "]ghijkl\n","mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], &["ab\n","cdef\n", "ghijkl\n","|mnopqrst"], false, move_caret_down)?; - assert_move(&["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","st|"], false, move_caret_down)?; - assert_move(&["abc de[f gh ]|"], &["abc def gh |"], false, move_caret_down)?; - assert_move(&["ab|[c def gh ]"], &["abc def gh |"], false, move_caret_down)?; - assert_move(&["a[bc def gh ]|"], &["abc def gh |"], false, move_caret_down)?; - assert_move(&["[abc def gh ]|"], &["abc def gh |"], false, move_caret_down)?; + assert_move( + &["abc\n", "|[def]"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "d|[ef]"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|[f]"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["[abc\n", "]|def"], + &["abc\n", "|def"], + false, + move_caret_down, + )?; + assert_move( + &["a[bc\n", "d]|ef"], + &["abc\n", "d|ef"], + false, + move_caret_down, + )?; + assert_move( + &["ab|[c\n", "de]f"], + &["abc\n", "de|f"], + false, + move_caret_down, + )?; + assert_move( + &["abc[\n", "def]|"], + &["abc\n", "def|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "|[def \n", "]ghi"], + &["abc\n", "def \n", "|ghi"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "d[ef \n", "g]|hi"], + &["abc\n", "def \n", "g|hi"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de[f \n", "gh]|i"], + &["abc\n", "def \n", "gh|i"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "def[ \n", "ghi]|"], + &["abc\n", "def \n", "ghi|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "def [\n", "ghi]|"], + &["abc\n", "def \n", "ghi|"], + false, + move_caret_down, + )?; + assert_move( + &["abc\n", "de[\n", "gh]|i"], + &["abc\n", "de\n", "gh|i"], + false, + move_caret_down, + )?; + assert_move( + &["abc|[\n", "de]"], + &["abc\n", "de|"], + false, + move_caret_down, + )?; + assert_move( + &["ab[c\n", "de]|"], + &["abc\n", "de|"], + false, + move_caret_down, + )?; + assert_move( + &["a|[bc\n", "d]e"], + &["abc\n", "d|e"], + false, + move_caret_down, + )?; + assert_move( + &["[abc\n", "]|de"], + &["abc\n", "|de"], + false, + move_caret_down, + )?; + assert_move( + &["ab[\n", "cd]|ef\n", "ghijkl\n", "mnopqrst"], + &["ab\n", "cd|ef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef|[\n", "ghij]kl\n", "mnopqrst"], + &["ab\n", "cdef\n", "ghij|kl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl[\n", "mnopqr]|st"], + &["ab\n", "cdef\n", "ghijkl\n", "mnopqr|st"], + false, + move_caret_down, + )?; + assert_move( + &[" [ab\n", " ]|cdef\n", "ghijkl\n", "mnopqrst"], + &[" ab\n", " |cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "|[cdef\n", "]ghijkl\n", "mnopqrst"], + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["ab\n", "cdef\n", "[ghijkl\n", "]|mnopqrst"], + &["ab\n", "cdef\n", "ghijkl\n", "|mnopqrst"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh[\n", "ijklmn]|\n", "opqr\n", "st"], + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn[\n", "opqr]|\n", "st"], + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr[\n", "st]|"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + false, + move_caret_down, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "[st]|"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "st|"], + false, + move_caret_down, + )?; + assert_move( + &["abc de[f gh ]|"], + &["abc def gh |"], + false, + move_caret_down, + )?; + assert_move( + &["ab|[c def gh ]"], + &["abc def gh |"], + false, + move_caret_down, + )?; + assert_move( + &["a[bc def gh ]|"], + &["abc def gh |"], + false, + move_caret_down, + )?; + assert_move( + &["[abc def gh ]|"], + &["abc def gh |"], + false, + move_caret_down, + )?; Ok(()) } @@ -736,33 +1658,148 @@ mod test_parse { assert_move(&["a|[bc]"], &["a|bc"], false, move_caret_up)?; assert_move(&["ab[c]|"], &["ab|c"], false, move_caret_up)?; assert_move(&["abc|[ ]"], &["abc| "], false, move_caret_up)?; - assert_move(&["abc\n","|[def]"], &["abc\n","|def"], false, move_caret_up)?; - assert_move(&["abc\n","d|[ef]"], &["abc\n","d|ef"], false, move_caret_up)?; - assert_move(&["abc\n","de|[f]"], &["abc\n","de|f"], false, move_caret_up)?; - assert_move(&["[abc\n","]|def"], &["|abc\n","def"], false, move_caret_up)?; - assert_move(&["a[bc\n","d]|ef"], &["a|bc\n","def"], false, move_caret_up)?; - assert_move(&["ab|[c\n","de]f"], &["ab|c\n","def"], false, move_caret_up)?; - assert_move(&["abc[\n","def]|"], &["abc|\n","def"], false, move_caret_up)?; - assert_move(&["abc\n","|[def \n", "]ghi"], &["abc\n","|def \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","d[ef \n", "g]|hi"], &["abc\n","d|ef \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","de|[f \n", "gh]i"], &["abc\n","de|f \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","def[ \n", "ghi]|"], &["abc\n","def| \n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","def [\n", "ghi]|"], &["abc\n","def |\n", "ghi"], false, move_caret_up)?; - assert_move(&["abc\n","de[\n", "gh]|i"], &["abc\n","de|\n", "ghi"], false, move_caret_up)?; - assert_move(&["abc|[\n","de]"], &["abc|\n","de"], false, move_caret_up)?; - assert_move(&["ab[c\n","de]|"], &["ab|c\n","de"], false, move_caret_up)?; - assert_move(&["a|[bc\n","d]e"], &["a|bc\n","de"], false, move_caret_up)?; - assert_move(&["[abc\n","]|de"], &["|abc\n","de"], false, move_caret_up)?; - assert_move(&["ab[\n","cd]|ef\n", "ghijkl\n","mnopqrst"], &["ab|\n","cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef|[\n", "ghij]kl\n","mnopqrst"], &["ab\n","cdef|\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl[\n","mnopqr]|st"], &["ab\n","cdef\n", "ghijkl|\n","mnopqrst"], false, move_caret_up)?; - assert_move(&[" [ab\n"," ]|cdef\n", "ghijkl\n","mnopqrst"], &[" |ab\n"," cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","|[cdef\n", "]ghijkl\n","mnopqrst"], &["ab\n","|cdef\n", "ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "[ghijkl\n","]|mnopqrst"], &["ab\n","cdef\n", "|ghijkl\n","mnopqrst"], false, move_caret_up)?; - assert_move(&["abcdefgh[\n","ijklmn]|\n", "opqr\n","st"], &["abcdefgh|\n","ijklmn\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn[\n", "opqr]|\n","st"], &["abcdefgh\n","ijklmn|\n", "opqr\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr[\n","st]|"], &["abcdefgh\n","ijklmn\n", "opqr|\n","st"], false, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "opqr\n","[st]|"], &["abcdefgh\n","ijklmn\n", "opqr\n","|st"], false, move_caret_up)?; + assert_move( + &["abc\n", "|[def]"], + &["abc\n", "|def"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "d|[ef]"], + &["abc\n", "d|ef"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "de|[f]"], + &["abc\n", "de|f"], + false, + move_caret_up, + )?; + assert_move( + &["[abc\n", "]|def"], + &["|abc\n", "def"], + false, + move_caret_up, + )?; + assert_move( + &["a[bc\n", "d]|ef"], + &["a|bc\n", "def"], + false, + move_caret_up, + )?; + assert_move( + &["ab|[c\n", "de]f"], + &["ab|c\n", "def"], + false, + move_caret_up, + )?; + assert_move( + &["abc[\n", "def]|"], + &["abc|\n", "def"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "|[def \n", "]ghi"], + &["abc\n", "|def \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "d[ef \n", "g]|hi"], + &["abc\n", "d|ef \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "de|[f \n", "gh]i"], + &["abc\n", "de|f \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "def[ \n", "ghi]|"], + &["abc\n", "def| \n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "def [\n", "ghi]|"], + &["abc\n", "def |\n", "ghi"], + false, + move_caret_up, + )?; + assert_move( + &["abc\n", "de[\n", "gh]|i"], + &["abc\n", "de|\n", "ghi"], + false, + move_caret_up, + )?; + assert_move(&["abc|[\n", "de]"], &["abc|\n", "de"], false, move_caret_up)?; + assert_move(&["ab[c\n", "de]|"], &["ab|c\n", "de"], false, move_caret_up)?; + assert_move(&["a|[bc\n", "d]e"], &["a|bc\n", "de"], false, move_caret_up)?; + assert_move(&["[abc\n", "]|de"], &["|abc\n", "de"], false, move_caret_up)?; + assert_move( + &["ab[\n", "cd]|ef\n", "ghijkl\n", "mnopqrst"], + &["ab|\n", "cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef|[\n", "ghij]kl\n", "mnopqrst"], + &["ab\n", "cdef|\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl[\n", "mnopqr]|st"], + &["ab\n", "cdef\n", "ghijkl|\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &[" [ab\n", " ]|cdef\n", "ghijkl\n", "mnopqrst"], + &[" |ab\n", " cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "|[cdef\n", "]ghijkl\n", "mnopqrst"], + &["ab\n", "|cdef\n", "ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "[ghijkl\n", "]|mnopqrst"], + &["ab\n", "cdef\n", "|ghijkl\n", "mnopqrst"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh[\n", "ijklmn]|\n", "opqr\n", "st"], + &["abcdefgh|\n", "ijklmn\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn[\n", "opqr]|\n", "st"], + &["abcdefgh\n", "ijklmn|\n", "opqr\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr[\n", "st]|"], + &["abcdefgh\n", "ijklmn\n", "opqr|\n", "st"], + false, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "opqr\n", "[st]|"], + &["abcdefgh\n", "ijklmn\n", "opqr\n", "|st"], + false, + move_caret_up, + )?; assert_move(&["abc de[f gh ]|"], &["abc de|f gh "], false, move_caret_up)?; assert_move(&["ab|[c def gh ]"], &["ab|c def gh "], false, move_caret_up)?; assert_move(&["a[bc def gh ]|"], &["a|bc def gh "], false, move_caret_up)?; @@ -780,14 +1817,49 @@ mod test_parse { assert_move(&["[abc]|"], &["[abc]|"], true, move_caret_right)?; assert_move(&["a[bc]|"], &["a[bc]|"], true, move_caret_right)?; assert_move(&["ab[c]|"], &["ab[c]|"], true, move_caret_right)?; - assert_move(&["abc[\n","]|d"], &["abc[\n","d]|"], true, move_caret_right)?; - assert_move(&["ab[c]|\n",""], &["ab[c\n","]|"], true, move_caret_right)?; - assert_move(&["ab[c]|\n","d"], &["ab[c\n","]|d"], true, move_caret_right)?; - assert_move(&["abc\n","def\n", "ghi[\n","]|jkl"], &["abc\n","def\n", "ghi[\n", "j]|kl"], true, move_caret_right)?; - assert_move(&["ab[c\n","def\n", "ghi\n","]|jkl"], &["ab[c\n","def\n", "ghi\n", "j]|kl"], true, move_caret_right)?; - assert_move(&["ab[c\n","def\n", "]|ghi\n","jkl"], &["ab[c\n","def\n", "g]|hi\n", "jkl"], true, move_caret_right)?; - assert_move(&["[abc\n","def\n", "ghi\n","jk]|l"], &["[abc\n","def\n", "ghi\n", "jkl]|"], true, move_caret_right)?; - assert_move(&["[abc\n","def\n", "ghi\n", "jkl]|"], &["[abc\n","def\n", "ghi\n", "jkl]|"], true, move_caret_right)?; + assert_move( + &["abc[\n", "]|d"], + &["abc[\n", "d]|"], + true, + move_caret_right, + )?; + assert_move(&["ab[c]|\n", ""], &["ab[c\n", "]|"], true, move_caret_right)?; + assert_move( + &["ab[c]|\n", "d"], + &["ab[c\n", "]|d"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "def\n", "ghi[\n", "]|jkl"], + &["abc\n", "def\n", "ghi[\n", "j]|kl"], + true, + move_caret_right, + )?; + assert_move( + &["ab[c\n", "def\n", "ghi\n", "]|jkl"], + &["ab[c\n", "def\n", "ghi\n", "j]|kl"], + true, + move_caret_right, + )?; + assert_move( + &["ab[c\n", "def\n", "]|ghi\n", "jkl"], + &["ab[c\n", "def\n", "g]|hi\n", "jkl"], + true, + move_caret_right, + )?; + assert_move( + &["[abc\n", "def\n", "ghi\n", "jk]|l"], + &["[abc\n", "def\n", "ghi\n", "jkl]|"], + true, + move_caret_right, + )?; + assert_move( + &["[abc\n", "def\n", "ghi\n", "jkl]|"], + &["[abc\n", "def\n", "ghi\n", "jkl]|"], + true, + move_caret_right, + )?; Ok(()) } @@ -800,12 +1872,37 @@ mod test_parse { assert_move(&["|[ab]c"], &["|[ab]c"], true, move_caret_left)?; assert_move(&["|[a]bc"], &["|[a]bc"], true, move_caret_left)?; assert_move(&[" |[a]bc"], &["|[ a]bc"], true, move_caret_left)?; - assert_move(&["abc|[\n","]d"], &["ab|[c\n","]d"], true, move_caret_left)?; - assert_move(&["abc\n","|[d]"], &["abc|[\n","d]"], true, move_caret_left)?; - assert_move(&["ab|[c\n","]"], &["a|[bc\n","]"], true, move_caret_left)?; - assert_move(&["abc\n","def|[\n", "ghi\n","j]kl"], &["abc\n","de|[f\n", "ghi\n", "j]kl"], true, move_caret_left)?; - assert_move(&["a|[bc\n","def\n", "ghi\n","jkl]"], &["|[abc\n","def\n", "ghi\n", "jkl]"], true, move_caret_left)?; - assert_move(&["abc\n","def\n", "ghi\n", "|[jkl]"], &["abc\n","def\n", "ghi|[\n", "jkl]"], true, move_caret_left)?; + assert_move( + &["abc|[\n", "]d"], + &["ab|[c\n", "]d"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "|[d]"], + &["abc|[\n", "d]"], + true, + move_caret_left, + )?; + assert_move(&["ab|[c\n", "]"], &["a|[bc\n", "]"], true, move_caret_left)?; + assert_move( + &["abc\n", "def|[\n", "ghi\n", "j]kl"], + &["abc\n", "de|[f\n", "ghi\n", "j]kl"], + true, + move_caret_left, + )?; + assert_move( + &["a|[bc\n", "def\n", "ghi\n", "jkl]"], + &["|[abc\n", "def\n", "ghi\n", "jkl]"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def\n", "ghi\n", "|[jkl]"], + &["abc\n", "def\n", "ghi|[\n", "jkl]"], + true, + move_caret_left, + )?; Ok(()) } @@ -821,13 +1918,43 @@ mod test_parse { assert_move(&["ab[c]|"], &["|[ab]c"], true, move_caret_up)?; assert_move(&["[a]|"], &["|a"], true, move_caret_up)?; assert_move(&["[a]|bc"], &["|abc"], true, move_caret_up)?; - assert_move(&["[a]|bc\n","d"], &["|abc\n","d"], true, move_caret_up)?; - assert_move(&["abc\n","de[f]|"], &["abc|[\n","de]f"], true, move_caret_up)?; - assert_move(&["abc\n","de|[f]"], &["ab|[c\n","def]"], true, move_caret_up)?; - assert_move(&["ab|[c\n","def]"], &["|[abc\n","def]"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqr]|st"], &["ab\n","cdef\n", "ghijkl|[\n","]mnopqrst"], true, move_caret_up)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqrs]|t"], &["ab\n","cdef\n", "ghijkl|[\n","]mnopqrst"], true, move_caret_up)?; - assert_move(&["abcdefgh\n","ijklmn\n", "|[o]pqr\n","st"], &["abcdefgh\n","|[ijklmn\n", "o]pqr\n","st"], true, move_caret_up)?; + assert_move(&["[a]|bc\n", "d"], &["|abc\n", "d"], true, move_caret_up)?; + assert_move( + &["abc\n", "de[f]|"], + &["abc|[\n", "de]f"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "de|[f]"], + &["ab|[c\n", "def]"], + true, + move_caret_up, + )?; + assert_move( + &["ab|[c\n", "def]"], + &["|[abc\n", "def]"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "[mnopqr]|st"], + &["ab\n", "cdef\n", "ghijkl|[\n", "]mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "[mnopqrs]|t"], + &["ab\n", "cdef\n", "ghijkl|[\n", "]mnopqrst"], + true, + move_caret_up, + )?; + assert_move( + &["abcdefgh\n", "ijklmn\n", "|[o]pqr\n", "st"], + &["abcdefgh\n", "|[ijklmn\n", "o]pqr\n", "st"], + true, + move_caret_up, + )?; Ok(()) } @@ -839,15 +1966,55 @@ mod test_parse { assert_move(&["[abc]|"], &["[abc]|"], true, move_caret_down)?; assert_move(&["|[ab]c"], &["ab[c]|"], true, move_caret_down)?; assert_move(&["|[a]bc"], &["a[bc]|"], true, move_caret_down)?; - assert_move(&["[a]|bc\n","d"], &["[abc\n","d]|"], true, move_caret_down)?; - assert_move(&["[a]|bc\n","de"], &["[abc\n","d]|e"], true, move_caret_down)?; - assert_move(&["[abc\n","d]|e"], &["[abc\n","de]|"], true, move_caret_down)?; - assert_move(&["[a]|bc\n",""], &["[abc\n","]|"], true, move_caret_down)?; - assert_move(&["ab\n","cdef\n", "ghijkl\n","[mnopqr]|st"], &["ab\n","cdef\n", "ghijkl\n","[mnopqrst]|"], true, move_caret_down)?; - assert_move(&["a[b\n","cdef\n", "ghijkl\n","mnopqr]|st"], &["a[b\n","cdef\n", "ghijkl\n","mnopqrst]|"], true, move_caret_down)?; - assert_move(&["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], &["[ab\n","cdef\n", "ghijkl\n","mnopqrst]|"], true, move_caret_down)?; - assert_move(&["abcd[efgh]|\n","ijklmn\n", "opqr\n","st"], &["abcd[efgh\n","ijklmn]|\n", "opqr\n","st"], true, move_caret_down)?; - assert_move(&["abcd[e]|fgh\n","ijklmn\n", "opqr\n","st"], &["abcd[efgh\n","ijklm]|n\n", "opqr\n","st"], true, move_caret_down)?; + assert_move( + &["[a]|bc\n", "d"], + &["[abc\n", "d]|"], + true, + move_caret_down, + )?; + assert_move( + &["[a]|bc\n", "de"], + &["[abc\n", "d]|e"], + true, + move_caret_down, + )?; + assert_move( + &["[abc\n", "d]|e"], + &["[abc\n", "de]|"], + true, + move_caret_down, + )?; + assert_move(&["[a]|bc\n", ""], &["[abc\n", "]|"], true, move_caret_down)?; + assert_move( + &["ab\n", "cdef\n", "ghijkl\n", "[mnopqr]|st"], + &["ab\n", "cdef\n", "ghijkl\n", "[mnopqrst]|"], + true, + move_caret_down, + )?; + assert_move( + &["a[b\n", "cdef\n", "ghijkl\n", "mnopqr]|st"], + &["a[b\n", "cdef\n", "ghijkl\n", "mnopqrst]|"], + true, + move_caret_down, + )?; + assert_move( + &["[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]|"], + &["[ab\n", "cdef\n", "ghijkl\n", "mnopqrst]|"], + true, + move_caret_down, + )?; + assert_move( + &["abcd[efgh]|\n", "ijklmn\n", "opqr\n", "st"], + &["abcd[efgh\n", "ijklmn]|\n", "opqr\n", "st"], + true, + move_caret_down, + )?; + assert_move( + &["abcd[e]|fgh\n", "ijklmn\n", "opqr\n", "st"], + &["abcd[efgh\n", "ijklm]|n\n", "opqr\n", "st"], + true, + move_caret_down, + )?; Ok(()) } @@ -857,9 +2024,24 @@ mod test_parse { assert_move(&["ab|[c]"], &["abc|"], true, move_caret_right)?; assert_move(&["a|[bc]"], &["ab|[c]"], true, move_caret_right)?; assert_move(&["|[abc]"], &["a|[bc]"], true, move_caret_right)?; - assert_move(&["|[abc\n","def\n", "ghi\n","jkl]"], &["a|[bc\n","def\n", "ghi\n", "jkl]"], true, move_caret_right)?; - assert_move(&["abc\n","d|[ef\n", "]ghi\n","jkl"], &["abc\n","de|[f\n", "]ghi\n", "jkl"], true, move_caret_right)?; - assert_move(&["abc\n","de|[f]\n", "ghi\n","jkl"], &["abc\n","def|\n", "ghi\n", "jkl"], true, move_caret_right)?; + assert_move( + &["|[abc\n", "def\n", "ghi\n", "jkl]"], + &["a|[bc\n", "def\n", "ghi\n", "jkl]"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "d|[ef\n", "]ghi\n", "jkl"], + &["abc\n", "de|[f\n", "]ghi\n", "jkl"], + true, + move_caret_right, + )?; + assert_move( + &["abc\n", "de|[f]\n", "ghi\n", "jkl"], + &["abc\n", "def|\n", "ghi\n", "jkl"], + true, + move_caret_right, + )?; Ok(()) } @@ -869,10 +2051,30 @@ mod test_parse { assert_move(&["ab[c]|"], &["ab|c"], true, move_caret_left)?; assert_move(&["a[bc]|"], &["a[b]|c"], true, move_caret_left)?; assert_move(&["[abc]|"], &["[ab]|c"], true, move_caret_left)?; - assert_move(&["[abc\n","def\n", "ghi\n","jkl]|"], &["[abc\n","def\n", "ghi\n", "jk]|l"], true, move_caret_left)?; - assert_move(&["|[abc\n","def\n", "ghi\n","jkl]"], &["|[abc\n","def\n", "ghi\n", "jkl]"], true, move_caret_left)?; - assert_move(&["abc\n","def[\n", "]|ghi\n","jkl"], &["abc\n","def|\n", "ghi\n", "jkl"], true, move_caret_left)?; - assert_move(&["abc\n","d[ef\n", "gh]|i\n","jkl"], &["abc\n","d[ef\n", "g]|hi\n", "jkl"], true, move_caret_left)?; + assert_move( + &["[abc\n", "def\n", "ghi\n", "jkl]|"], + &["[abc\n", "def\n", "ghi\n", "jk]|l"], + true, + move_caret_left, + )?; + assert_move( + &["|[abc\n", "def\n", "ghi\n", "jkl]"], + &["|[abc\n", "def\n", "ghi\n", "jkl]"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "def[\n", "]|ghi\n", "jkl"], + &["abc\n", "def|\n", "ghi\n", "jkl"], + true, + move_caret_left, + )?; + assert_move( + &["abc\n", "d[ef\n", "gh]|i\n", "jkl"], + &["abc\n", "d[ef\n", "g]|hi\n", "jkl"], + true, + move_caret_left, + )?; Ok(()) } @@ -883,12 +2085,42 @@ mod test_parse { assert_move(&["[ab]|c"], &["|abc"], true, move_caret_up)?; assert_move(&["[a]|bc"], &["|abc"], true, move_caret_up)?; assert_move(&["|abc"], &["|abc"], true, move_caret_up)?; - assert_move(&["[abc\n","def]|"], &["[abc]|\n","def"], true, move_caret_up)?; - assert_move(&["[abc\n","de]|f"], &["[ab]|c\n","def"], true, move_caret_up)?; - assert_move(&["[abc\n","def\n", "ghi\n","jkl]|"], &["[abc\n","def\n", "ghi]|\n", "jkl"], true, move_caret_up)?; - assert_move(&["abc\n","def\n", "ghi[\n","jkl]|"], &["abc\n","def\n", "ghi|\n", "jkl"], true, move_caret_up)?; - assert_move(&["abc\n","d[ef\n", "ghi\n","jk]|l"], &["abc\n","d[ef\n", "gh]|i\n", "jkl"], true, move_caret_up)?; - assert_move(&["[abc\n","d]|ef\n", "ghi\n","jkl"], &["[a]|bc\n","def\n", "ghi\n", "jkl"], true, move_caret_up)?; + assert_move( + &["[abc\n", "def]|"], + &["[abc]|\n", "def"], + true, + move_caret_up, + )?; + assert_move( + &["[abc\n", "de]|f"], + &["[ab]|c\n", "def"], + true, + move_caret_up, + )?; + assert_move( + &["[abc\n", "def\n", "ghi\n", "jkl]|"], + &["[abc\n", "def\n", "ghi]|\n", "jkl"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "def\n", "ghi[\n", "jkl]|"], + &["abc\n", "def\n", "ghi|\n", "jkl"], + true, + move_caret_up, + )?; + assert_move( + &["abc\n", "d[ef\n", "ghi\n", "jk]|l"], + &["abc\n", "d[ef\n", "gh]|i\n", "jkl"], + true, + move_caret_up, + )?; + assert_move( + &["[abc\n", "d]|ef\n", "ghi\n", "jkl"], + &["[a]|bc\n", "def\n", "ghi\n", "jkl"], + true, + move_caret_up, + )?; Ok(()) } @@ -896,16 +2128,55 @@ mod test_parse { #[test] fn shrink_selection_down() -> Result<(), String> { assert_move(&["|[abc]"], &["abc|"], true, move_caret_down)?; - assert_move(&["|[abc\n","def]"], &["abc\n","|[def]"], true, move_caret_down)?; - assert_move(&["a|[bc\n","def]"], &["abc\n","d|[ef]"], true, move_caret_down)?; - assert_move(&["|[abc\n","def\n", "ghi]"], &["abc\n","|[def\n", "ghi]"], true, move_caret_down)?; - assert_move(&["ab|[c\n","def\n", "ghi]"], &["abc\n","de|[f\n", "ghi]"], true, move_caret_down)?; - assert_move(&["abc\n","de|[f\n", "ghi]"], &["abc\n","def\n", "gh|[i]"], true, move_caret_down)?; - assert_move(&["abcdef|[\n","ghij\n", "kl]"], &["abcdef\n","ghij|[\n", "kl]"], true, move_caret_down)?; - assert_move(&["abcde|[f\n","ghij\n", "kl]"], &["abcdef\n","ghij|[\n", "kl]"], true, move_caret_down)?; - assert_move(&["ab|[cdef\n","ghij\n", "kl]"], &["abcdef\n","gh|[ij\n", "kl]"], true, move_caret_down)?; + assert_move( + &["|[abc\n", "def]"], + &["abc\n", "|[def]"], + true, + move_caret_down, + )?; + assert_move( + &["a|[bc\n", "def]"], + &["abc\n", "d|[ef]"], + true, + move_caret_down, + )?; + assert_move( + &["|[abc\n", "def\n", "ghi]"], + &["abc\n", "|[def\n", "ghi]"], + true, + move_caret_down, + )?; + assert_move( + &["ab|[c\n", "def\n", "ghi]"], + &["abc\n", "de|[f\n", "ghi]"], + true, + move_caret_down, + )?; + assert_move( + &["abc\n", "de|[f\n", "ghi]"], + &["abc\n", "def\n", "gh|[i]"], + true, + move_caret_down, + )?; + assert_move( + &["abcdef|[\n", "ghij\n", "kl]"], + &["abcdef\n", "ghij|[\n", "kl]"], + true, + move_caret_down, + )?; + assert_move( + &["abcde|[f\n", "ghij\n", "kl]"], + &["abcdef\n", "ghij|[\n", "kl]"], + true, + move_caret_down, + )?; + assert_move( + &["ab|[cdef\n", "ghij\n", "kl]"], + &["abcdef\n", "gh|[ij\n", "kl]"], + true, + move_caret_down, + )?; Ok(()) } - -} \ No newline at end of file +} diff --git a/editor/src/tea/update.rs b/editor/src/tea/update.rs index 3a08600282..3e08a3cb21 100644 --- a/editor/src/tea/update.rs +++ b/editor/src/tea/update.rs @@ -11,23 +11,22 @@ pub fn move_caret_left( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = - if old_selection_opt.is_some() && !shift_pressed{ - match old_selection_opt { - Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), - None => unreachable!(), - } - } else if old_col_nr == 0 { - if old_line_nr == 0 { - (0, 0) - } else if let Some(curr_line) = lines.get(old_line_nr - 1) { - (old_line_nr - 1, curr_line.len() - 1) - } else { - unreachable!() - } + let (line_nr, col_nr) = if old_selection_opt.is_some() && !shift_pressed { + match old_selection_opt { + Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), + None => unreachable!(), + } + } else if old_col_nr == 0 { + if old_line_nr == 0 { + (0, 0) + } else if let Some(curr_line) = lines.get(old_line_nr - 1) { + (old_line_nr - 1, curr_line.len() - 1) } else { - (old_line_nr, old_col_nr - 1) - }; + unreachable!() + } + } else { + (old_line_nr, old_col_nr - 1) + }; let new_caret_pos = Position { line: line_nr, @@ -84,31 +83,30 @@ pub fn move_caret_right( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = - if old_selection_opt.is_some() && !shift_pressed{ - match old_selection_opt { - Some(old_selection) => (old_selection.end_pos.line, old_selection.end_pos.column), - None => unreachable!(), - } - } else if let Some(curr_line) = lines.get(old_line_nr) { - if let Some(last_char) = curr_line.chars().last() { - if is_newline(&last_char) { - if old_col_nr + 1 > curr_line.len() - 1 { - (old_line_nr + 1, 0) - } else { - (old_line_nr, old_col_nr + 1) - } - } else if old_col_nr < curr_line.len() { - (old_line_nr, old_col_nr + 1) + let (line_nr, col_nr) = if old_selection_opt.is_some() && !shift_pressed { + match old_selection_opt { + Some(old_selection) => (old_selection.end_pos.line, old_selection.end_pos.column), + None => unreachable!(), + } + } else if let Some(curr_line) = lines.get(old_line_nr) { + if let Some(last_char) = curr_line.chars().last() { + if is_newline(&last_char) { + if old_col_nr + 1 > curr_line.len() - 1 { + (old_line_nr + 1, 0) } else { - (old_line_nr, old_col_nr) + (old_line_nr, old_col_nr + 1) } + } else if old_col_nr < curr_line.len() { + (old_line_nr, old_col_nr + 1) } else { (old_line_nr, old_col_nr) } } else { - unreachable!() - }; + (old_line_nr, old_col_nr) + } + } else { + unreachable!() + }; let new_caret_pos = Position { line: line_nr, @@ -165,23 +163,22 @@ pub fn move_caret_up( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = - if old_selection_opt.is_some() && !shift_pressed{ - match old_selection_opt { - Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), - None => unreachable!(), - } - } else if old_line_nr == 0 { - (old_line_nr, 0) - } else if let Some(prev_line) = lines.get(old_line_nr - 1) { - if prev_line.len() <= old_col_nr { - (old_line_nr - 1, prev_line.len() - 1) - } else { - (old_line_nr - 1, old_col_nr) - } + let (line_nr, col_nr) = if old_selection_opt.is_some() && !shift_pressed { + match old_selection_opt { + Some(old_selection) => (old_selection.start_pos.line, old_selection.start_pos.column), + None => unreachable!(), + } + } else if old_line_nr == 0 { + (old_line_nr, 0) + } else if let Some(prev_line) = lines.get(old_line_nr - 1) { + if prev_line.len() <= old_col_nr { + (old_line_nr - 1, prev_line.len() - 1) } else { - unreachable!() - }; + (old_line_nr - 1, old_col_nr) + } + } else { + unreachable!() + }; let new_caret_pos = Position { line: line_nr, @@ -229,8 +226,7 @@ pub fn move_caret_down( let old_line_nr = old_caret_pos.line; let old_col_nr = old_caret_pos.column; - let (line_nr, col_nr) = - if old_selection_opt.is_some() && !shift_pressed{ + let (line_nr, col_nr) = if old_selection_opt.is_some() && !shift_pressed { match old_selection_opt { Some(old_selection) => (old_selection.end_pos.line, old_selection.end_pos.column), None => unreachable!(), diff --git a/editor/src/vec_result.rs b/editor/src/vec_result.rs index 0d8eb67c8a..202af28a96 100644 --- a/editor/src/vec_result.rs +++ b/editor/src/vec_result.rs @@ -13,4 +13,3 @@ pub fn get_res(index: usize, vec: &[T]) -> EdResult<& Date: Wed, 6 Jan 2021 07:42:01 -0500 Subject: [PATCH 08/13] fix(gen_list): forgot to use Nat in these tests as well --- compiler/gen/tests/gen_list.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/gen/tests/gen_list.rs b/compiler/gen/tests/gen_list.rs index 8916d07586..cbc73b429f 100644 --- a/compiler/gen/tests/gen_list.rs +++ b/compiler/gen/tests/gen_list.rs @@ -1273,7 +1273,7 @@ mod gen_list { app "quicksort" provides [ main ] to "./platform" - swap : Int *, Int *, List a -> List a + swap : Nat, Nat, List a -> List a swap = \i, j, list -> when Pair (List.get list i) (List.get list j) is Pair (Ok atI) (Ok atJ) -> @@ -1396,7 +1396,7 @@ mod gen_list { quicksortHelp list 0 (n - 1) - quicksortHelp : List (Num a), Int *, Int * -> List (Num a) + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) quicksortHelp = \list, low, high -> if low < high then when partition low high list is @@ -1408,7 +1408,7 @@ mod gen_list { list - swap : Int *, Int *, List a -> List a + swap : Nat, Nat, List a -> List a swap = \i, j, list -> when Pair (List.get list i) (List.get list j) is Pair (Ok atI) (Ok atJ) -> @@ -1419,7 +1419,7 @@ mod gen_list { _ -> [] - partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ] + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition = \low, high, initialList -> when List.get initialList high is Ok pivot -> @@ -1431,7 +1431,7 @@ mod gen_list { Pair (low - 1) initialList - partitionHelp : Int *, Int *, List (Num a), Int *, (Num a) -> [ Pair (Int *) (List (Num a)) ] + partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] partitionHelp = \i, j, list, high, pivot -> if j < high then when List.get list j is @@ -1466,7 +1466,7 @@ mod gen_list { quicksortHelp list 0 (List.len list - 1) - quicksortHelp : List (Num a), Int *, Int * -> List (Num a) + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) quicksortHelp = \list, low, high -> if low < high then when partition low high list is @@ -1478,7 +1478,7 @@ mod gen_list { list - swap : Int *, Int *, List a -> List a + swap : Nat, Nat, List a -> List a swap = \i, j, list -> when Pair (List.get list i) (List.get list j) is Pair (Ok atI) (Ok atJ) -> @@ -1489,7 +1489,7 @@ mod gen_list { _ -> [] - partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ] + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition = \low, high, initialList -> when List.get initialList high is Ok pivot -> @@ -1501,7 +1501,7 @@ mod gen_list { Pair (low - 1) initialList - partitionHelp : Int *, Int *, List (Num a), Int *, Num a -> [ Pair (Int *) (List (Num a)) ] + partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] partitionHelp = \i, j, list, high, pivot -> # if j < high then if False then @@ -1539,7 +1539,7 @@ mod gen_list { quicksortHelp list 0 (List.len list - 1) - quicksortHelp : List (Num a), Int *, Int * -> List (Num a) + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) quicksortHelp = \list, low, high -> if low < high then when partition low high list is @@ -1551,7 +1551,7 @@ mod gen_list { list - swap : Int *, Int *, List a -> List a + swap : Nat, Nat, List a -> List a swap = \i, j, list -> when Pair (List.get list i) (List.get list j) is Pair (Ok atI) (Ok atJ) -> @@ -1562,7 +1562,7 @@ mod gen_list { _ -> [] - partition : Int *, Int *, List (Num a) -> [ Pair (Int *) (List (Num a)) ] + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition = \low, high, initialList -> when List.get initialList high is Ok pivot -> @@ -1574,7 +1574,7 @@ mod gen_list { Pair (low - 1) initialList - partitionHelp : Int *, Int *, List (Num a), Int *, Num a -> [ Pair (Int *) (List (Num a)) ] + partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] partitionHelp = \i, j, list, high, pivot -> if j < high then when List.get list j is From b9359ffd71a025a1828648c246bba78ef1e27a24 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 7 Jan 2021 20:12:11 +0100 Subject: [PATCH 09/13] remove variable from mono patterns --- compiler/mono/src/decision_tree.rs | 18 ++++++++++-------- compiler/mono/src/exhaustive.rs | 6 +++--- compiler/mono/src/ir.rs | 30 ++++++++++++++---------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/mono/src/decision_tree.rs b/compiler/mono/src/decision_tree.rs index 6c0015129f..f0107b78ce 100644 --- a/compiler/mono/src/decision_tree.rs +++ b/compiler/mono/src/decision_tree.rs @@ -66,7 +66,7 @@ pub enum Test<'a> { union: crate::exhaustive::Union, arguments: Vec<(Pattern<'a>, Layout<'a>)>, }, - IsInt(i64), + IsInt(i128), // float patterns are stored as u64 so they are comparable/hashable IsFloat(u64), IsStr(Box), @@ -445,10 +445,10 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V num_alts: union.alternatives.len(), }); } - IntLiteral(_, v) => { + IntLiteral(v) => { all_tests.push(guarded(IsInt(*v))); } - FloatLiteral(_, v) => { + FloatLiteral(v) => { all_tests.push(IsFloat(*v)); } StrLiteral(v) => { @@ -636,7 +636,7 @@ fn to_relevant_branch_help<'a>( _ => None, }, - IntLiteral(_, int) => match test { + IntLiteral(int) => match test { IsInt(is_int) if int == *is_int => { start.extend(end); Some(Branch { @@ -647,7 +647,7 @@ fn to_relevant_branch_help<'a>( _ => None, }, - FloatLiteral(_, float) => match test { + FloatLiteral(float) => match test { IsFloat(test_float) if float == *test_float => { start.extend(end); Some(Branch { @@ -740,8 +740,8 @@ fn needs_tests(pattern: &Pattern) -> bool { | AppliedTag { .. } | BitLiteral { .. } | EnumLiteral { .. } - | IntLiteral(_, _) - | FloatLiteral(_, _) + | IntLiteral(_) + | FloatLiteral(_) | StrLiteral(_) => true, } } @@ -1092,7 +1092,9 @@ fn test_to_equality<'a>( ) } Test::IsInt(test_int) => { - let lhs = Expr::Literal(Literal::Int(test_int)); + // TODO don't downcast i128 here + debug_assert!(test_int <= i64::MAX as i128); + let lhs = Expr::Literal(Literal::Int(test_int as i64)); let lhs_symbol = env.unique_symbol(); stores.push((lhs_symbol, Layout::Builtin(Builtin::Int64), lhs)); diff --git a/compiler/mono/src/exhaustive.rs b/compiler/mono/src/exhaustive.rs index 8e6442cf08..f3726960e8 100644 --- a/compiler/mono/src/exhaustive.rs +++ b/compiler/mono/src/exhaustive.rs @@ -37,7 +37,7 @@ pub enum Pattern { #[derive(Clone, Debug, PartialEq)] pub enum Literal { - Int(i64), + Int(i128), Bit(bool), Byte(u8), Float(u64), @@ -48,8 +48,8 @@ fn simplify(pattern: &crate::ir::Pattern) -> Pattern { use crate::ir::Pattern::*; match pattern { - IntLiteral(_, v) => Literal(Literal::Int(*v)), - FloatLiteral(_, v) => Literal(Literal::Float(*v)), + IntLiteral(v) => Literal(Literal::Int(*v)), + FloatLiteral(v) => Literal(Literal::Float(*v)), StrLiteral(v) => Literal(Literal::Str(v.clone())), // To make sure these are exhaustive, we have to "fake" a union here diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 5942e55e2d..8ad8820390 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -4774,8 +4774,8 @@ fn store_pattern<'a>( Underscore => { // do nothing } - IntLiteral(_, _) - | FloatLiteral(_, _) + IntLiteral(_) + | FloatLiteral(_) | EnumLiteral { .. } | BitLiteral { .. } | StrLiteral(_) => {} @@ -4814,8 +4814,8 @@ fn store_pattern<'a>( Underscore => { // ignore } - IntLiteral(_, _) - | FloatLiteral(_, _) + IntLiteral(_) + | FloatLiteral(_) | EnumLiteral { .. } | BitLiteral { .. } | StrLiteral(_) => {} @@ -4909,8 +4909,8 @@ fn store_record_destruct<'a>( // // internally. But `y` is never used, so we must make sure it't not stored/loaded. } - IntLiteral(_, _) - | FloatLiteral(_, _) + IntLiteral(_) + | FloatLiteral(_) | EnumLiteral { .. } | BitLiteral { .. } | StrLiteral(_) => {} @@ -5654,8 +5654,8 @@ fn call_by_name<'a>( pub enum Pattern<'a> { Identifier(Symbol), Underscore, - IntLiteral(Variable, i64), - FloatLiteral(Variable, u64), + IntLiteral(i128), + FloatLiteral(u64), BitLiteral { value: bool, tag_name: TagName, @@ -5728,10 +5728,8 @@ fn from_can_pattern_help<'a>( match can_pattern { Underscore => Ok(Pattern::Underscore), Identifier(symbol) => Ok(Pattern::Identifier(*symbol)), - IntLiteral(precision_var, int) => Ok(Pattern::IntLiteral(*precision_var, *int)), - FloatLiteral(precision_var, float) => { - Ok(Pattern::FloatLiteral(*precision_var, f64::to_bits(*float))) - } + IntLiteral(_, int) => Ok(Pattern::IntLiteral(*int as i128)), + FloatLiteral(_, float) => Ok(Pattern::FloatLiteral(f64::to_bits(*float))), StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())), Shadowed(region, ident) => Err(RuntimeError::Shadowing { original_region: *region, @@ -5744,10 +5742,10 @@ fn from_can_pattern_help<'a>( } NumLiteral(var, num) => { match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) { - IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*var, *num)), - IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*var, *num)), - IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*var, *num as u64)), - IntOrFloat::DecimalFloatType(_) => Ok(Pattern::FloatLiteral(*var, *num as u64)), + IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)), + IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)), + IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*num as u64)), + IntOrFloat::DecimalFloatType(_) => Ok(Pattern::FloatLiteral(*num as u64)), } } From 9dd02ea0908954ab25a807f13d170d7614ffb30f Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 7 Jan 2021 20:15:06 +0100 Subject: [PATCH 10/13] reenable test --- compiler/gen/tests/gen_list.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/gen/tests/gen_list.rs b/compiler/gen/tests/gen_list.rs index cbc73b429f..cb01dc7760 100644 --- a/compiler/gen/tests/gen_list.rs +++ b/compiler/gen/tests/gen_list.rs @@ -1740,6 +1740,7 @@ mod gen_list { assert_evals_to!("[[2]] != [[1]]", true, bool); } + #[test] #[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)] fn cleanup_because_exception() { assert_evals_to!( From e005dbde4c45ccbe305e04503e02e3acb792dc2a Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 7 Jan 2021 20:19:12 +0100 Subject: [PATCH 11/13] rename Unreachable -> Rethrow --- compiler/gen/src/llvm/build.rs | 6 +++--- compiler/mono/src/borrow.rs | 4 ++-- compiler/mono/src/inc_dec.rs | 6 +++--- compiler/mono/src/ir.rs | 15 +++++---------- compiler/mono/src/tail_recursion.rs | 4 ++-- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index ecb40b74ea..a2e2c8f3c6 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1494,9 +1494,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( call, layout, pass, - fail: roc_mono::ir::Stmt::Unreachable, + fail: roc_mono::ir::Stmt::Rethrow, } => { - // when the fail case is just Unreachable, there is no cleanup work to do + // when the fail case is just Rethrow, there is no cleanup work to do // so we can just treat this invoke as a normal call let stmt = roc_mono::ir::Stmt::Let(*symbol, Expr::Call(call.clone()), layout.clone(), pass); @@ -1561,7 +1561,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( } }, - Unreachable => { + Rethrow => { cxa_rethrow_exception(env); // used in exception handling diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index 019a2249c2..8fe05e3e7e 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -170,7 +170,7 @@ impl<'a> ParamMap<'a> { } Inc(_, _) | Dec(_, _) => unreachable!("these have not been introduced yet"), - Ret(_) | Unreachable | Jump(_, _) | RuntimeError(_) => { + Ret(_) | Rethrow | Jump(_, _) | RuntimeError(_) => { // these are terminal, do nothing } } @@ -515,7 +515,7 @@ impl<'a> BorrowInfState<'a> { } Inc(_, _) | Dec(_, _) => unreachable!("these have not been introduced yet"), - Ret(_) | RuntimeError(_) | Unreachable => { + Ret(_) | RuntimeError(_) | Rethrow => { // these are terminal, do nothing } } diff --git a/compiler/mono/src/inc_dec.rs b/compiler/mono/src/inc_dec.rs index 219dba7607..27503a35e1 100644 --- a/compiler/mono/src/inc_dec.rs +++ b/compiler/mono/src/inc_dec.rs @@ -50,7 +50,7 @@ pub fn occuring_variables(stmt: &Stmt<'_>) -> (MutSet, MutSet) { result.insert(*symbol); } - Unreachable => {} + Rethrow => {} Inc(symbol, cont) | Dec(symbol, cont) => { result.insert(*symbol); @@ -792,7 +792,7 @@ impl<'a> Context<'a> { } } - Unreachable => (stmt, MutSet::default()), + Rethrow => (stmt, MutSet::default()), Jump(j, xs) => { let empty = MutSet::default(); @@ -953,7 +953,7 @@ pub fn collect_stmt( vars } - Unreachable => vars, + Rethrow => vars, RuntimeError(_) => vars, } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 8ad8820390..f011c2857e 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -762,7 +762,7 @@ pub enum Stmt<'a> { ret_layout: Layout<'a>, }, Ret(Symbol), - Unreachable, + Rethrow, Inc(Symbol, &'a Stmt<'a>), Dec(Symbol, &'a Stmt<'a>), Join { @@ -911,11 +911,6 @@ pub enum CallType<'a> { }, } -// x = f a b c; S -// -// -// invoke x = f a b c in S else Unreachable - #[derive(Clone, Debug, PartialEq)] pub enum Expr<'a> { Literal(Literal<'a>), @@ -1133,7 +1128,7 @@ impl<'a> Stmt<'a> { symbol, call, pass, - fail: Stmt::Unreachable, + fail: Stmt::Rethrow, .. } => alloc .text("let ") @@ -1166,7 +1161,7 @@ impl<'a> Stmt<'a> { .append(symbol_to_doc(alloc, *symbol)) .append(";"), - Unreachable => alloc.text("unreachable;"), + Rethrow => alloc.text("unreachable;"), Switch { cond_symbol, @@ -4572,7 +4567,7 @@ fn substitute_in_stmt_help<'a>( } } - Unreachable => None, + Rethrow => None, RuntimeError(_) => None, } @@ -5293,7 +5288,7 @@ fn build_call<'a>( hole: &'a Stmt<'a>, ) -> Stmt<'a> { if can_throw_exception(&call) { - let fail = env.arena.alloc(Stmt::Unreachable); + let fail = env.arena.alloc(Stmt::Rethrow); Stmt::Invoke { symbol: assigned, call, diff --git a/compiler/mono/src/tail_recursion.rs b/compiler/mono/src/tail_recursion.rs index 4998c5fd84..87aa45038c 100644 --- a/compiler/mono/src/tail_recursion.rs +++ b/compiler/mono/src/tail_recursion.rs @@ -102,7 +102,7 @@ fn insert_jumps<'a>( pass: Stmt::Ret(rsym), .. } if needle == *fsym && symbol == rsym => { - debug_assert_eq!(fail, &&Stmt::Unreachable); + debug_assert_eq!(fail, &&Stmt::Rethrow); // replace the call and return with a jump @@ -237,7 +237,7 @@ fn insert_jumps<'a>( None => None, }, - Unreachable => None, + Rethrow => None, Ret(_) => None, Jump(_, _) => None, RuntimeError(_) => None, From ecd03186dc79132e71f55e644bbc2c3d1af6dad1 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 7 Jan 2021 20:55:31 +0100 Subject: [PATCH 12/13] fix i128 bug --- compiler/gen/src/llvm/build.rs | 72 ++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index a2e2c8f3c6..884909a0c8 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -484,6 +484,34 @@ fn get_inplace_from_layout(layout: &Layout<'_>) -> InPlace { } } +pub fn int_with_precision<'a, 'ctx, 'env>( + env: &Env<'a, 'ctx, 'env>, + value: i128, + precision: &Builtin, +) -> IntValue<'ctx> { + match precision { + Builtin::Usize => ptr_int(env.context, env.ptr_bytes).const_int(value as u64, false), + Builtin::Int128 => const_i128(env, value), + Builtin::Int64 => env.context.i64_type().const_int(value as u64, false), + Builtin::Int32 => env.context.i32_type().const_int(value as u64, false), + Builtin::Int16 => env.context.i16_type().const_int(value as u64, false), + Builtin::Int8 => env.context.i8_type().const_int(value as u64, false), + _ => panic!("Invalid layout for int literal = {:?}", precision), + } +} + +pub fn float_with_precision<'a, 'ctx, 'env>( + env: &Env<'a, 'ctx, 'env>, + value: f64, + precision: &Builtin, +) -> FloatValue<'ctx> { + match precision { + Builtin::Float64 => env.context.f64_type().const_float(value), + Builtin::Float32 => env.context.f32_type().const_float(value), + _ => panic!("Invalid layout for float literal = {:?}", precision), + } +} + pub fn build_exp_literal<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout: &Layout<'_>, @@ -492,22 +520,16 @@ pub fn build_exp_literal<'a, 'ctx, 'env>( use roc_mono::ir::Literal::*; match literal { - Int(int) => - (match layout { - Layout::Builtin(Builtin::Usize) => ptr_int(env.context, env.ptr_bytes), - Layout::Builtin(Builtin::Int128) => env.context.i128_type(), /* TODO file an issue: you can't currently have an int literal bigger than 64 bits long, and also (as we see here), you can't currently have (at least in Inkwell) a when-branch with an i128 literal in its pattren */ - Layout::Builtin(Builtin::Int64) => env.context.i64_type(), - Layout::Builtin(Builtin::Int32) => env.context.i32_type(), - Layout::Builtin(Builtin::Int16) => env.context.i16_type(), - Layout::Builtin(Builtin::Int8) => env.context.i8_type(), - _ => panic!("Invalid layout for int literal = {:?}", layout), - }).const_int(*int as u64, false).into(), - Float(num) => - (match layout { - Layout::Builtin(Builtin::Float64) => env.context.f64_type(), - Layout::Builtin(Builtin::Float32) => env.context.f32_type(), - _ => panic!("Invalid layout for float literal = {:?}", layout), - }).const_float(*num).into(), + Int(int) => match layout { + Layout::Builtin(builtin) => int_with_precision(env, *int as i128, builtin).into(), + _ => panic!("Invalid layout for int literal = {:?}", layout), + }, + + Float(float) => match layout { + Layout::Builtin(builtin) => float_with_precision(env, *float, builtin).into(), + _ => panic!("Invalid layout for float literal = {:?}", layout), + }, + Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(), Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(), Str(str_literal) => { @@ -1783,6 +1805,22 @@ struct SwitchArgsIr<'a, 'ctx> { pub ret_type: BasicTypeEnum<'ctx>, } +fn const_i128<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, value: i128) -> IntValue<'ctx> { + // TODO verify the order [a, b] is correct for larger numbers when we can parse them + debug_assert!(value <= i64::MAX as i128); + + // truncate the lower 64 bits + let value = value as u128; + let a = value as u64; + + // get the upper 64 bits + let b = (value >> 64) as u64; + + env.context + .i128_type() + .const_int_arbitrary_precision(&[a, b]) +} + fn build_switch_ir<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_ids: &mut LayoutIds<'a>, @@ -1860,7 +1898,7 @@ fn build_switch_ir<'a, 'ctx, 'env>( ptr_int(env.context, env.ptr_bytes).const_int(*int as u64, false) } Layout::Builtin(Builtin::Int64) => context.i64_type().const_int(*int as u64, false), - Layout::Builtin(Builtin::Int128) => context.i128_type().const_int(*int as u64, false), /* TODO file an issue: you can't currently have an int literal bigger than 64 bits long, and also (as we see here), you can't currently have (at least in Inkwell) a when-branch with an i128 literal in its pattren */ + Layout::Builtin(Builtin::Int128) => const_i128(env, *int as i128), Layout::Builtin(Builtin::Int32) => context.i32_type().const_int(*int as u64, false), Layout::Builtin(Builtin::Int16) => context.i16_type().const_int(*int as u64, false), Layout::Builtin(Builtin::Int8) => context.i8_type().const_int(*int as u64, false), From 78f653b85c23d9d1ce24e1e4d1e30642c41bb018 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 7 Jan 2021 23:19:17 +0100 Subject: [PATCH 13/13] fix typo --- compiler/gen_dev/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/gen_dev/src/lib.rs b/compiler/gen_dev/src/lib.rs index 0a5a922a1a..a4df102b59 100644 --- a/compiler/gen_dev/src/lib.rs +++ b/compiler/gen_dev/src/lib.rs @@ -339,7 +339,7 @@ where Stmt::Ret(sym) => { self.set_last_seen(*sym, stmt); } - Stmt::Unreachable => {} + Stmt::Rethrow => {} Stmt::Inc(sym, following) => { self.set_last_seen(*sym, stmt); self.scan_ast(following);