mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
handle_new_char tests, bug fixes for #869
This commit is contained in:
parent
29e9cf3a6f
commit
d6dc6dbf8b
4 changed files with 295 additions and 34 deletions
|
@ -79,7 +79,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
|
||||||
let event_loop = winit::event_loop::EventLoop::new();
|
let event_loop = winit::event_loop::EventLoop::new();
|
||||||
|
|
||||||
let window = winit::window::WindowBuilder::new()
|
let window = winit::window::WindowBuilder::new()
|
||||||
.with_inner_size(PhysicalSize::new(1000.0, 800.0))
|
.with_inner_size(PhysicalSize::new(1200.0, 1000.0))
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -384,11 +384,11 @@ fn queue_all_text(
|
||||||
};
|
};
|
||||||
|
|
||||||
let caret_pos_label = Text {
|
let caret_pos_label = Text {
|
||||||
position: (30.0, (size.height as f32) - 45.0).into(),
|
position: ((size.width as f32) - 150.0, (size.height as f32) - 40.0).into(),
|
||||||
area_bounds,
|
area_bounds,
|
||||||
color: TXT_COLOR.into(),
|
color: TXT_COLOR.into(),
|
||||||
text: format!("Ln {}, Col {}", caret_pos.line, caret_pos.column),
|
text: format!("Ln {}, Col {}", caret_pos.line, caret_pos.column),
|
||||||
size: 30.0,
|
size: 25.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use super::ed_model::{Position, RawSelection};
|
||||||
use crate::text_buffer::TextBuffer;
|
use crate::text_buffer::TextBuffer;
|
||||||
use crate::util::is_newline;
|
use crate::util::is_newline;
|
||||||
use super::app_model::AppModel;
|
use super::app_model::AppModel;
|
||||||
|
use super::ed_model::EdModel;
|
||||||
use crate::error::EdResult;
|
use crate::error::EdResult;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
|
@ -298,9 +299,15 @@ pub fn move_caret_down(
|
||||||
(new_caret_pos, new_selection_opt)
|
(new_caret_pos, new_selection_opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn del_selection(selection: RawSelection, ed_model: &mut EdModel) -> EdResult<()> {
|
||||||
|
ed_model.text_buf.del_selection(selection)?;
|
||||||
|
ed_model.caret_pos = selection.start_pos;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResult<()> {
|
pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResult<()> {
|
||||||
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
||||||
ed_model.selection_opt = None;
|
|
||||||
let old_caret_pos = ed_model.caret_pos;
|
let old_caret_pos = ed_model.caret_pos;
|
||||||
|
|
||||||
match received_char {
|
match received_char {
|
||||||
|
@ -308,34 +315,46 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu
|
||||||
// On Linux, '\u{8}' is backspace,
|
// On Linux, '\u{8}' is backspace,
|
||||||
// on macOS '\u{7f}'.
|
// on macOS '\u{7f}'.
|
||||||
if let Some(selection) = ed_model.selection_opt {
|
if let Some(selection) = ed_model.selection_opt {
|
||||||
ed_model.text_buf.del_selection(selection)?;
|
del_selection(selection, ed_model)?;
|
||||||
ed_model.caret_pos = selection.start_pos;
|
|
||||||
} else {
|
} else {
|
||||||
ed_model.text_buf.pop_char(old_caret_pos);
|
|
||||||
|
|
||||||
ed_model.caret_pos =
|
ed_model.caret_pos =
|
||||||
move_caret_left(old_caret_pos, None, false, &ed_model.text_buf).0;
|
move_caret_left(old_caret_pos, None, false, &ed_model.text_buf).0;
|
||||||
|
|
||||||
|
ed_model.text_buf.pop_char(old_caret_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ch if is_newline(ch) => {
|
ch if is_newline(ch) => {
|
||||||
ed_model.text_buf.insert_char(old_caret_pos, ch)?;
|
if let Some(selection) = ed_model.selection_opt {
|
||||||
ed_model.caret_pos = Position {
|
del_selection(selection, ed_model)?;
|
||||||
line: old_caret_pos.line + 1,
|
ed_model.text_buf.insert_char(ed_model.caret_pos, &'\n')?;
|
||||||
column: 0,
|
} else {
|
||||||
};
|
ed_model.text_buf.insert_char(old_caret_pos, &'\n')?;
|
||||||
|
|
||||||
|
ed_model.caret_pos = Position {
|
||||||
|
line: old_caret_pos.line + 1,
|
||||||
|
column: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
'\u{e000}'..='\u{f8ff}' | '\u{f0000}'..='\u{ffffd}' | '\u{100000}'..='\u{10fffd}' => {
|
'\u{e000}'..='\u{f8ff}' | '\u{f0000}'..='\u{ffffd}' | '\u{100000}'..='\u{10fffd}' => {
|
||||||
// These are private use characters; ignore them.
|
// These are private use characters; ignore them.
|
||||||
// See http://www.unicode.org/faq/private_use.html
|
// See http://www.unicode.org/faq/private_use.html
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
ed_model.text_buf.insert_char(old_caret_pos, received_char)?;
|
if let Some(selection) = ed_model.selection_opt {
|
||||||
|
del_selection(selection, ed_model)?;
|
||||||
|
ed_model.text_buf.insert_char(ed_model.caret_pos, received_char)?;
|
||||||
|
|
||||||
ed_model.caret_pos = Position {
|
ed_model.caret_pos =
|
||||||
line: old_caret_pos.line,
|
move_caret_right(ed_model.caret_pos, None, false, &ed_model.text_buf).0;
|
||||||
column: old_caret_pos.column + 1,
|
} else {
|
||||||
};
|
ed_model.text_buf.insert_char(old_caret_pos, received_char)?;
|
||||||
|
|
||||||
|
ed_model.caret_pos = Position {
|
||||||
|
line: old_caret_pos.line,
|
||||||
|
column: old_caret_pos.column + 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,3 +363,240 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_update {
|
||||||
|
use crate::selection::test_selection::{convert_dsl_to_selection, convert_selection_to_dsl, text_buffer_from_dsl_str, all_lines_vec};
|
||||||
|
use crate::mvc::ed_model::{Position, EdModel, RawSelection};
|
||||||
|
use crate::mvc::app_model::AppModel;
|
||||||
|
use crate::mvc::update::{handle_new_char};
|
||||||
|
use crate::text_buffer::TextBuffer;
|
||||||
|
|
||||||
|
fn gen_caret_text_buf(lines: &[&str]) -> Result<(Position, Option<RawSelection>, TextBuffer), String> {
|
||||||
|
let lines_string_slice: Vec<String> = lines.iter().map(|l| l.to_string()).collect();
|
||||||
|
let (selection_opt, caret_pos) = convert_dsl_to_selection(&lines_string_slice)?;
|
||||||
|
let text_buf = text_buffer_from_dsl_str(&lines_string_slice);
|
||||||
|
|
||||||
|
Ok((caret_pos, selection_opt, text_buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mock_app_model(text_buf: TextBuffer, caret_pos: Position, selection_opt: Option<RawSelection>) -> AppModel {
|
||||||
|
AppModel {
|
||||||
|
ed_model_opt: Some(
|
||||||
|
EdModel{
|
||||||
|
text_buf,
|
||||||
|
caret_pos,
|
||||||
|
selection_opt,
|
||||||
|
glyph_dim_rect_opt: None,
|
||||||
|
has_focus: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_insert(
|
||||||
|
pre_lines_str: &[&str],
|
||||||
|
expected_post_lines_str: &[&str],
|
||||||
|
new_char: char,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let (caret_pos, selection_opt, pre_text_buf) = gen_caret_text_buf(pre_lines_str)?;
|
||||||
|
|
||||||
|
let mut app_model = mock_app_model(pre_text_buf, caret_pos, selection_opt);
|
||||||
|
|
||||||
|
if let Err(e) = handle_new_char(&mut app_model, &new_char) {
|
||||||
|
return Err(e.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ed_model) = app_model.ed_model_opt {
|
||||||
|
let mut actual_lines = all_lines_vec(&ed_model.text_buf);
|
||||||
|
let dsl_slice = convert_selection_to_dsl(ed_model.selection_opt, ed_model.caret_pos, &mut actual_lines).unwrap();
|
||||||
|
assert_eq!(dsl_slice, expected_post_lines_str);
|
||||||
|
} else {
|
||||||
|
panic!("Mock AppModel did not have an EdModel.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_new_char_simple() -> Result<(), String> {
|
||||||
|
assert_insert(
|
||||||
|
&["|"], &["a|"], 'a'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["|"], &[" |"], ' '
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|"], &["aa|"], 'a'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|"], &["a |"], ' '
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|\n", ""], &["ab|\n", ""], 'b'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|\n", ""], &["ab|\n", ""], 'b'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "|"], &["a\n", "b|"], 'b'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "b\n", "c|"], &["a\n", "b\n", "cd|"], 'd'
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_new_char_mid() -> Result<(), String> {
|
||||||
|
assert_insert(
|
||||||
|
&["ab|d"], &["abc|d"], 'c'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|cd"], &["ab|cd"], 'b'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "|e"], &["abc\n", "d|e"], 'd'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "def\n", "| "], &["abc\n", "def\n", "g| "], 'g'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "def\n", "| "], &["abc\n", "def\n", " | "], ' '
|
||||||
|
)?;
|
||||||
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_backspace() -> Result<(), String> {
|
||||||
|
assert_insert(
|
||||||
|
&["|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&[" |"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["ab|"], &["a|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a|\n", ""], &["|\n", ""], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["ab|\n", ""], &["a|\n", ""], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "|"], &["a|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "b\n", "c|"], &["a\n", "b\n", "|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "b\n", "|"], &["a\n", "b|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn selection_backspace() -> Result<(), String> {
|
||||||
|
assert_insert(
|
||||||
|
&["[a]|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[a]|"], &["a|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[aa]|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[b c]|"], &["a|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[abc]|\n", ""], &["|\n", ""], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "[abc]|"], &["a\n","|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[a\n", "abc]|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[b\n", "cdef ghij]|"], &["a|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[a\n", "b\n", "c]|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "[b\n", "]|"], &["a\n", "|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"], &["abc\n", "d|\n", "jkl"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "[def\n", "ghi]|\n", "jkl"], &["abc\n", "|\n", "jkl"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "\n", "[def\n", "ghi]|\n", "jkl"], &["abc\n", "\n", "|\n", "jkl"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[abc\n", "\n", "def\n", "ghi\n", "jkl]|"], &["|"], '\u{8}'
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_with_selection() -> Result<(), String> {
|
||||||
|
assert_insert(
|
||||||
|
&["[a]|"], &["z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[a]|"], &["az|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[aa]|"], &["z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[b c]|"], &["az|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[abc]|\n", ""], &["z|\n", ""], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "[abc]|"], &["a\n","z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[a\n", "abc]|"], &["z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a[b\n", "cdef ghij]|"], &["az|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[a\n", "b\n", "c]|"], &["z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["a\n", "[b\n", "]|"], &["a\n", "z|"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"], &["abc\n", "dz|\n", "jkl"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "[def\n", "ghi]|\n", "jkl"], &["abc\n", "z|\n", "jkl"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["abc\n", "\n", "[def\n", "ghi]|\n", "jkl"], &["abc\n", "\n", "z|\n", "jkl"], 'z'
|
||||||
|
)?;
|
||||||
|
assert_insert(
|
||||||
|
&["[abc\n", "\n", "def\n", "ghi\n", "jkl]|"], &["z|"], 'z'
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub fn create_selection_rects<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_parse {
|
pub mod test_selection {
|
||||||
use crate::error::{EdResult, OutOfBounds};
|
use crate::error::{EdResult, OutOfBounds};
|
||||||
use crate::mvc::ed_model::{Position, RawSelection};
|
use crate::mvc::ed_model::{Position, RawSelection};
|
||||||
use crate::mvc::update::{move_caret_down, move_caret_left, move_caret_right, move_caret_up, MoveCaretFun};
|
use crate::mvc::update::{move_caret_down, move_caret_left, move_caret_right, move_caret_up, MoveCaretFun};
|
||||||
|
@ -141,7 +141,7 @@ mod test_parse {
|
||||||
pub struct LineParser;
|
pub struct LineParser;
|
||||||
|
|
||||||
// show selection and caret position as symbols in lines for easy testing
|
// show selection and caret position as symbols in lines for easy testing
|
||||||
fn convert_selection_to_dsl(
|
pub fn convert_selection_to_dsl(
|
||||||
raw_sel_opt: Option<RawSelection>,
|
raw_sel_opt: Option<RawSelection>,
|
||||||
caret_pos: Position,
|
caret_pos: Position,
|
||||||
lines: &mut [String],
|
lines: &mut [String],
|
||||||
|
@ -217,6 +217,16 @@ mod test_parse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text_buffer_from_dsl_str(lines: &[String]) -> TextBuffer {
|
||||||
|
text_buffer_from_str(
|
||||||
|
&lines
|
||||||
|
.iter()
|
||||||
|
.map(|line| line.replace(&['[', ']', '|'][..], ""))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn all_lines_vec(text_buf: &TextBuffer) -> Vec<String> {
|
pub fn all_lines_vec(text_buf: &TextBuffer) -> Vec<String> {
|
||||||
let mut lines: Vec<String> = Vec::new();
|
let mut lines: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
@ -235,7 +245,7 @@ mod test_parse {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve selection and position from formatted string
|
// Retrieve selection and position from formatted string
|
||||||
fn convert_dsl_to_selection(
|
pub fn convert_dsl_to_selection(
|
||||||
lines: &[String],
|
lines: &[String],
|
||||||
) -> Result<(Option<RawSelection>, Position), String> {
|
) -> Result<(Option<RawSelection>, Position), String> {
|
||||||
let lines_str: String = lines.join("");
|
let lines_str: String = lines.join("");
|
||||||
|
@ -349,13 +359,7 @@ mod test_parse {
|
||||||
let (sel_opt, caret_pos) = convert_dsl_to_selection(&pre_lines)?;
|
let (sel_opt, caret_pos) = convert_dsl_to_selection(&pre_lines)?;
|
||||||
|
|
||||||
let clean_text_buf =
|
let clean_text_buf =
|
||||||
text_buffer_from_str(
|
text_buffer_from_dsl_str(&pre_lines);
|
||||||
&pre_lines
|
|
||||||
.into_iter()
|
|
||||||
.map(|line| line.replace(&['[', ']', '|'][..], ""))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("")
|
|
||||||
);
|
|
||||||
|
|
||||||
let (new_caret_pos, new_sel_opt) =
|
let (new_caret_pos, new_sel_opt) =
|
||||||
move_fun(caret_pos, sel_opt, shift_pressed, &clean_text_buf);
|
move_fun(caret_pos, sel_opt, shift_pressed, &clean_text_buf);
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl TextBuffer {
|
||||||
pub fn insert_char(&mut self, caret_pos: Position, new_char: &char) -> EdResult<()> {
|
pub fn insert_char(&mut self, caret_pos: Position, new_char: &char) -> EdResult<()> {
|
||||||
let char_indx = self.pos_to_char_indx(caret_pos);
|
let char_indx = self.pos_to_char_indx(caret_pos);
|
||||||
|
|
||||||
ensure!(char_indx > self.text_rope.len_chars(), OutOfBounds{
|
ensure!(char_indx <= self.text_rope.len_chars(), OutOfBounds{
|
||||||
index: char_indx,
|
index: char_indx,
|
||||||
collection_name: "Rope",
|
collection_name: "Rope",
|
||||||
len: self.text_rope.len_chars()
|
len: self.text_rope.len_chars()
|
||||||
|
@ -35,16 +35,17 @@ impl TextBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_char(&mut self, caret_pos: Position) {
|
pub fn pop_char(&mut self, caret_pos: Position) {
|
||||||
let char_indx = self.pos_to_char_indx(caret_pos) - 1;
|
let char_indx = self.pos_to_char_indx(caret_pos);
|
||||||
if char_indx < self.text_rope.len_chars() {
|
|
||||||
self.text_rope.remove(char_indx..char_indx);
|
if (char_indx > 0) && char_indx <= self.text_rope.len_chars() {
|
||||||
|
self.text_rope.remove((char_indx - 1)..char_indx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn del_selection(&mut self, raw_sel: RawSelection) -> EdResult<()> {
|
pub fn del_selection(&mut self, raw_sel: RawSelection) -> EdResult<()> {
|
||||||
let (start_char_indx, end_char_indx) = self.sel_to_tup(raw_sel)?;
|
let (start_char_indx, end_char_indx) = self.sel_to_tup(raw_sel)?;
|
||||||
|
|
||||||
ensure!(end_char_indx < self.text_rope.len_chars(), OutOfBounds{
|
ensure!(end_char_indx <= self.text_rope.len_chars(), OutOfBounds{
|
||||||
index: end_char_indx,
|
index: end_char_indx,
|
||||||
collection_name: "Rope",
|
collection_name: "Rope",
|
||||||
len: self.text_rope.len_chars()
|
len: self.text_rope.len_chars()
|
||||||
|
@ -102,7 +103,7 @@ impl TextBuffer {
|
||||||
fn sel_to_tup(&self, raw_sel: RawSelection) -> EdResult<(usize, usize)> {
|
fn sel_to_tup(&self, raw_sel: RawSelection) -> EdResult<(usize, usize)> {
|
||||||
let valid_sel = validate_selection(raw_sel)?;
|
let valid_sel = validate_selection(raw_sel)?;
|
||||||
let start_char_indx = self.pos_to_char_indx(valid_sel.selection.start_pos);
|
let start_char_indx = self.pos_to_char_indx(valid_sel.selection.start_pos);
|
||||||
let end_char_indx = self.pos_to_char_indx(valid_sel.selection.start_pos);
|
let end_char_indx = self.pos_to_char_indx(valid_sel.selection.end_pos);
|
||||||
|
|
||||||
Ok((start_char_indx, end_char_indx))
|
Ok((start_char_indx, end_char_indx))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue