mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Merge pull request #874 from rtfeldman/selection_tests
Text selection test DSL, many tests
This commit is contained in:
commit
93297c0051
9 changed files with 2151 additions and 34 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2672,6 +2672,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"maplit",
|
"maplit",
|
||||||
"page_size",
|
"page_size",
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"quickcheck",
|
"quickcheck",
|
||||||
"quickcheck_macros",
|
"quickcheck_macros",
|
||||||
|
|
|
@ -66,6 +66,8 @@ cgmath = "0.17.0"
|
||||||
itertools = "0.9.0"
|
itertools = "0.9.0"
|
||||||
snafu = { version = "0.6", features = ["backtraces"] }
|
snafu = { version = "0.6", features = ["backtraces"] }
|
||||||
colored = "2"
|
colored = "2"
|
||||||
|
pest = "2.1"
|
||||||
|
pest_derive = "2.1"
|
||||||
|
|
||||||
|
|
||||||
[dependencies.bytemuck]
|
[dependencies.bytemuck]
|
||||||
|
|
|
@ -55,8 +55,8 @@ These are potentially inspirational resources for the editor's design.
|
||||||
### Productivity features
|
### Productivity features
|
||||||
|
|
||||||
* When refactoring;
|
* 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.
|
- 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.
|
- 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.
|
* 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.
|
- 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.
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
|
|
||||||
// See this link to learn wgpu: https://sotrh.github.io/learn-wgpu/
|
// 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::error::print_err;
|
||||||
use crate::graphics::lowlevel::buffer::create_rect_buffers;
|
use crate::graphics::lowlevel::buffer::create_rect_buffers;
|
||||||
use crate::graphics::lowlevel::ortho::{init_ortho, update_ortho_buffer, OrthoResources};
|
use crate::graphics::lowlevel::ortho::{init_ortho, update_ortho_buffer, OrthoResources};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,6 @@ pub fn init_model() -> Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Is model.rs the right place for these structs?
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub line: usize,
|
pub line: usize,
|
||||||
|
|
|
@ -11,7 +11,12 @@ pub fn move_caret_left(
|
||||||
let old_line_nr = old_caret_pos.line;
|
let old_line_nr = old_caret_pos.line;
|
||||||
let old_col_nr = old_caret_pos.column;
|
let old_col_nr = old_caret_pos.column;
|
||||||
|
|
||||||
let (line_nr, col_nr) = if old_col_nr == 0 {
|
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 {
|
if old_line_nr == 0 {
|
||||||
(0, 0)
|
(0, 0)
|
||||||
} else if let Some(curr_line) = lines.get(old_line_nr - 1) {
|
} else if let Some(curr_line) = lines.get(old_line_nr - 1) {
|
||||||
|
@ -30,6 +35,16 @@ pub fn move_caret_left(
|
||||||
|
|
||||||
let new_selection_opt = if shift_pressed {
|
let new_selection_opt = if shift_pressed {
|
||||||
if let Some(old_selection) = old_selection_opt {
|
if let Some(old_selection) = old_selection_opt {
|
||||||
|
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 {
|
Some(RawSelection {
|
||||||
start_pos: Position {
|
start_pos: Position {
|
||||||
line: line_nr,
|
line: line_nr,
|
||||||
|
@ -37,6 +52,7 @@ pub fn move_caret_left(
|
||||||
},
|
},
|
||||||
end_pos: old_selection.end_pos,
|
end_pos: old_selection.end_pos,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: Position {
|
start_pos: Position {
|
||||||
|
@ -67,7 +83,12 @@ pub fn move_caret_right(
|
||||||
let old_line_nr = old_caret_pos.line;
|
let old_line_nr = old_caret_pos.line;
|
||||||
let old_col_nr = old_caret_pos.column;
|
let old_col_nr = old_caret_pos.column;
|
||||||
|
|
||||||
let (line_nr, col_nr) = if let Some(curr_line) = lines.get(old_line_nr) {
|
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 let Some(last_char) = curr_line.chars().last() {
|
||||||
if is_newline(&last_char) {
|
if is_newline(&last_char) {
|
||||||
if old_col_nr + 1 > curr_line.len() - 1 {
|
if old_col_nr + 1 > curr_line.len() - 1 {
|
||||||
|
@ -94,6 +115,16 @@ pub fn move_caret_right(
|
||||||
|
|
||||||
let new_selection_opt = if shift_pressed {
|
let new_selection_opt = if shift_pressed {
|
||||||
if let Some(old_selection) = old_selection_opt {
|
if let Some(old_selection) = old_selection_opt {
|
||||||
|
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 {
|
Some(RawSelection {
|
||||||
start_pos: old_selection.start_pos,
|
start_pos: old_selection.start_pos,
|
||||||
end_pos: Position {
|
end_pos: Position {
|
||||||
|
@ -101,6 +132,7 @@ pub fn move_caret_right(
|
||||||
column: col_nr,
|
column: col_nr,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: Position {
|
start_pos: Position {
|
||||||
|
@ -131,10 +163,15 @@ pub fn move_caret_up(
|
||||||
let old_line_nr = old_caret_pos.line;
|
let old_line_nr = old_caret_pos.line;
|
||||||
let old_col_nr = old_caret_pos.column;
|
let old_col_nr = old_caret_pos.column;
|
||||||
|
|
||||||
let (line_nr, col_nr) = if old_line_nr == 0 {
|
let (line_nr, col_nr) = if old_selection_opt.is_some() && !shift_pressed {
|
||||||
(old_line_nr, old_col_nr)
|
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) {
|
} 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)
|
(old_line_nr - 1, prev_line.len() - 1)
|
||||||
} else {
|
} else {
|
||||||
(old_line_nr - 1, old_col_nr)
|
(old_line_nr - 1, old_col_nr)
|
||||||
|
@ -150,10 +187,21 @@ pub fn move_caret_up(
|
||||||
|
|
||||||
let new_selection_opt = if shift_pressed {
|
let new_selection_opt = if shift_pressed {
|
||||||
if let Some(old_selection) = old_selection_opt {
|
if let Some(old_selection) = old_selection_opt {
|
||||||
|
if old_selection.end_pos <= old_caret_pos {
|
||||||
|
if new_caret_pos == old_selection.start_pos {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(RawSelection {
|
||||||
|
start_pos: min(old_selection.start_pos, new_caret_pos),
|
||||||
|
end_pos: max(old_selection.start_pos, new_caret_pos),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: new_caret_pos,
|
start_pos: new_caret_pos,
|
||||||
end_pos: old_selection.end_pos,
|
end_pos: old_selection.end_pos,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: min(old_caret_pos, new_caret_pos),
|
start_pos: min(old_caret_pos, new_caret_pos),
|
||||||
|
@ -178,10 +226,19 @@ pub fn move_caret_down(
|
||||||
let old_line_nr = old_caret_pos.line;
|
let old_line_nr = old_caret_pos.line;
|
||||||
let old_col_nr = old_caret_pos.column;
|
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 {
|
||||||
(old_line_nr, old_col_nr)
|
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 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
} else if let Some(next_line) = lines.get(old_line_nr + 1) {
|
} 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 let Some(last_char) = next_line.chars().last() {
|
||||||
if is_newline(&last_char) {
|
if is_newline(&last_char) {
|
||||||
(old_line_nr + 1, next_line.len() - 1)
|
(old_line_nr + 1, next_line.len() - 1)
|
||||||
|
@ -205,10 +262,21 @@ pub fn move_caret_down(
|
||||||
|
|
||||||
let new_selection_opt = if shift_pressed {
|
let new_selection_opt = if shift_pressed {
|
||||||
if let Some(old_selection) = old_selection_opt {
|
if let Some(old_selection) = old_selection_opt {
|
||||||
|
if old_caret_pos <= old_selection.start_pos {
|
||||||
|
if new_caret_pos == old_selection.end_pos {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(RawSelection {
|
||||||
|
start_pos: min(old_selection.end_pos, new_caret_pos),
|
||||||
|
end_pos: max(old_selection.end_pos, new_caret_pos),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: old_selection.start_pos,
|
start_pos: old_selection.start_pos,
|
||||||
end_pos: new_caret_pos,
|
end_pos: new_caret_pos,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
} else if !(old_line_nr == line_nr && old_col_nr == col_nr) {
|
||||||
Some(RawSelection {
|
Some(RawSelection {
|
||||||
start_pos: min(old_caret_pos, new_caret_pos),
|
start_pos: min(old_caret_pos, new_caret_pos),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub fn is_newline(char_ref: &char) -> bool {
|
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)
|
newline_codes.contains(char_ref)
|
||||||
}
|
}
|
||||||
|
|
11
editor/tests/selection.pest
Normal file
11
editor/tests/selection.pest
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
text = { (ASCII_ALPHANUMERIC | " " | "\t" | "\n")* }
|
||||||
|
|
||||||
|
caret = {"|"}
|
||||||
|
|
||||||
|
optSelStart = { "["{0,1} }
|
||||||
|
|
||||||
|
optSelEnd = { "]"{0,1} }
|
||||||
|
|
||||||
|
optCaret = { caret{0,1} }
|
||||||
|
|
||||||
|
linesWithSelect = { SOI ~ text ~ optCaret ~ text ~ optSelStart ~ text ~ optCaret ~ text ~ optCaret ~ text ~ optSelEnd ~ text ~ optCaret ~ text ~ EOI}
|
Loading…
Add table
Add a link
Reference in a new issue