show instructions if no file was opened, fmt

This commit is contained in:
Anton-4 2021-01-13 16:48:45 +01:00
parent d6dc6dbf8b
commit 76e2edff97
15 changed files with 229 additions and 282 deletions

View file

@ -3,7 +3,7 @@
Run the following from the roc folder:
```
cargo run edit
cargo run edit examples/hello-world/Hello.roc
```
## Troubleshooting

View file

@ -27,19 +27,15 @@ pub enum EdError {
backtrace: Backtrace,
},
#[snafu(display("MissingGlyphDims: glyph_dim_rect_opt was None for model. It needs to be set using the example_code_glyph_rect function."))]
MissingGlyphDims {
backtrace: Backtrace,
},
#[snafu(display("FileOpenFailed: failed to open file with path {} with the following error: {}.", path_str, err_msg))]
FileOpenFailed {
path_str: String,
err_msg: String,
},
MissingGlyphDims { backtrace: Backtrace },
#[snafu(display(
"FileOpenFailed: failed to open file with path {} with the following error: {}.",
path_str,
err_msg
))]
FileOpenFailed { path_str: String, err_msg: String },
#[snafu(display("TextBufReadFailed: the file {} could be opened but we encountered the following error while trying to read it: {}.", path_str, err_msg))]
TextBufReadFailed {
path_str: String,
err_msg: String
}
TextBufReadFailed { path_str: String, err_msg: String },
}
pub type EdResult<T, E = EdError> = std::result::Result<T, E>;

View file

@ -1,8 +1,8 @@
// Adapted from https://github.com/sotrh/learn-wgpu
// by Benjamin Hansen, licensed under the MIT license
use super::vertex::Vertex;
use crate::graphics::primitives::rect::Rect;
use crate::graphics::colors::to_slice;
use crate::graphics::primitives::rect::Rect;
use bumpalo::collections::Vec as BumpVec;
use wgpu::util::{BufferInitDescriptor, DeviceExt};

View file

@ -1,5 +1,7 @@
use crate::mvc::ed_model::EdModel;
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,
};
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
pub fn handle_keydown(
@ -15,18 +17,10 @@ pub fn handle_keydown(
}
match virtual_keycode {
Left => {
handle_arrow(move_caret_left, &modifiers, ed_model)
}
Up => {
handle_arrow(move_caret_up, &modifiers, ed_model)
}
Right => {
handle_arrow(move_caret_right, &modifiers, ed_model)
}
Down => {
handle_arrow(move_caret_down, &modifiers, ed_model)
}
Left => handle_arrow(move_caret_left, &modifiers, ed_model),
Up => handle_arrow(move_caret_up, &modifiers, ed_model),
Right => handle_arrow(move_caret_right, &modifiers, ed_model),
Down => handle_arrow(move_caret_down, &modifiers, ed_model),
Copy => {
todo!("copy");
}

View file

@ -1,9 +1,9 @@
pub mod ast;
mod def;
mod expr;
pub mod roc_file;
mod module;
mod pattern;
mod pool;
pub mod roc_file;
mod scope;
mod types;

View file

@ -23,9 +23,10 @@ use crate::graphics::primitives::text::{
};
use crate::graphics::style::CODE_FONT_SIZE;
use crate::graphics::style::CODE_TXT_XY;
use crate::mvc::ed_model::EdModel;
use crate::mvc::{ed_model, update, ed_view};
use crate::mvc::app_model::AppModel;
use crate::mvc::ed_model::EdModel;
use crate::mvc::{ed_model, ed_view, update};
use crate::resources::strings::NOTHING_OPENED;
use crate::vec_result::get_res;
use bumpalo::Bump;
use cgmath::Vector2;
@ -45,17 +46,18 @@ pub mod error;
pub mod graphics;
mod keyboard_input;
pub mod lang;
mod selection;
mod mvc;
mod resources;
mod selection;
mod text_buffer;
mod util;
mod vec_result;
mod text_buffer;
/// The editor is actually launched from the CLI if you pass it zero arguments,
/// or if you provide it 1 or more files or directories to open on launch.
pub fn launch(filepaths: &[&Path]) -> io::Result<()> {
//TODO support using multiple filepaths
let first_path_opt = if !filepaths.is_empty(){
let first_path_opt = if !filepaths.is_empty() {
match get_res(0, filepaths) {
Ok(path_ref_ref) => Some(*path_ref_ref),
Err(e) => {
@ -135,18 +137,15 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
let mut glyph_brush = build_glyph_brush(&gpu_device, render_format)?;
let is_animating = true;
let ed_model_opt =
if let Some(file_path) = file_path_opt {
let ed_model_res =
ed_model::init_model(file_path);
let ed_model_opt = if let Some(file_path) = file_path_opt {
let ed_model_res = ed_model::init_model(file_path);
match ed_model_res {
Ok(mut ed_model) => {
ed_model.glyph_dim_rect_opt =
Some(example_code_glyph_rect(&mut glyph_brush));
ed_model.glyph_dim_rect_opt = Some(example_code_glyph_rect(&mut glyph_brush));
Some(ed_model)
},
}
Err(e) => {
print_err(&e);
None
@ -156,9 +155,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
None
};
let mut app_model = AppModel {
ed_model_opt
};
let mut app_model = AppModel { ed_model_opt };
let mut keyboard_modifiers = ModifiersState::empty();
@ -258,14 +255,15 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
if let Some(ed_model) = &app_model.ed_model_opt {
//TODO don't pass invisible lines
//TODO show text if no file was opened
queue_all_text(
queue_editor_text(
&size,
&ed_model.text_buf.all_lines(),
ed_model.caret_pos,
CODE_TXT_XY.into(),
&mut glyph_brush,
);
} else {
queue_no_file_text(&size, NOTHING_OPENED, CODE_TXT_XY.into(), &mut glyph_brush);
}
match draw_all_rects(
@ -365,7 +363,7 @@ fn begin_render_pass<'a>(
}
// returns bounding boxes for every glyph
fn queue_all_text(
fn queue_editor_text(
size: &PhysicalSize<u32>,
editor_lines: &str,
caret_pos: Position,
@ -396,3 +394,23 @@ fn queue_all_text(
queue_text_draw(&code_text, glyph_brush);
}
fn queue_no_file_text(
size: &PhysicalSize<u32>,
text: &str,
text_coords: Vector2<f32>,
glyph_brush: &mut GlyphBrush<()>,
) {
let area_bounds = (size.width as f32, size.height as f32).into();
let code_text = Text {
position: text_coords,
area_bounds,
color: CODE_COLOR.into(),
text: text.to_owned(),
size: CODE_FONT_SIZE,
..Default::default()
};
queue_text_draw(&code_text, glyph_brush);
}

View file

@ -1,7 +1,6 @@
use super::ed_model::EdModel;
#[derive(Debug)]
pub struct AppModel {
pub ed_model_opt: Option<EdModel>
pub ed_model_opt: Option<EdModel>,
}

View file

@ -1,9 +1,9 @@
use crate::error::EdResult;
use crate::graphics::primitives::rect::Rect;
use crate::text_buffer;
use crate::text_buffer::TextBuffer;
use crate::error::EdResult;
use std::path::Path;
use std::cmp::Ordering;
use std::path::Path;
#[derive(Debug)]
pub struct EdModel {
@ -11,7 +11,7 @@ pub struct EdModel {
pub caret_pos: Position,
pub selection_opt: Option<RawSelection>,
pub glyph_dim_rect_opt: Option<Rect>,
pub has_focus: bool
pub has_focus: bool,
}
pub fn init_model(file_path: &Path) -> EdResult<EdModel> {
@ -20,7 +20,7 @@ pub fn init_model(file_path: &Path) -> EdResult<EdModel> {
caret_pos: Position { line: 0, column: 0 },
selection_opt: None,
glyph_dim_rect_opt: None,
has_focus: true
has_focus: true,
})
}

View file

@ -1,19 +1,16 @@
use super::ed_model::{EdModel, Position};
use crate::graphics::primitives::rect::Rect;
use crate::error::{EdResult, MissingGlyphDims};
use crate::graphics::colors::CARET_COLOR;
use crate::graphics::primitives::rect::Rect;
use crate::selection::create_selection_rects;
use crate::graphics::colors::{CARET_COLOR};
use bumpalo::collections::Vec as BumpVec;
use bumpalo::Bump;
use snafu::{ensure};
use snafu::ensure;
//TODO add editor text here as well
pub fn create_ed_rects<'a>(ed_model: &EdModel, arena: &'a Bump) -> EdResult<BumpVec<'a, Rect>> {
ensure!(ed_model.glyph_dim_rect_opt.is_some(),
MissingGlyphDims {}
);
ensure!(ed_model.glyph_dim_rect_opt.is_some(), MissingGlyphDims {});
let glyph_rect = ed_model.glyph_dim_rect_opt.unwrap();

View file

@ -1,4 +1,4 @@
pub mod app_model;
pub mod ed_model;
pub mod ed_view;
pub mod app_model;
pub mod update;

View file

@ -1,9 +1,9 @@
use super::ed_model::{Position, RawSelection};
use crate::text_buffer::TextBuffer;
use crate::util::is_newline;
use super::app_model::AppModel;
use super::ed_model::EdModel;
use super::ed_model::{Position, RawSelection};
use crate::error::EdResult;
use crate::text_buffer::TextBuffer;
use crate::util::is_newline;
use std::cmp::{max, min};
pub type MoveCaretFun =
@ -343,12 +343,16 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu
_ => {
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
.text_buf
.insert_char(ed_model.caret_pos, received_char)?;
ed_model.caret_pos =
move_caret_right(ed_model.caret_pos, None, false, &ed_model.text_buf).0;
} else {
ed_model.text_buf.insert_char(old_caret_pos, received_char)?;
ed_model
.text_buf
.insert_char(old_caret_pos, received_char)?;
ed_model.caret_pos = Position {
line: old_caret_pos.line,
@ -364,16 +368,19 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu
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::mvc::ed_model::{EdModel, Position, RawSelection};
use crate::mvc::update::handle_new_char;
use crate::selection::test_selection::{
all_lines_vec, convert_dsl_to_selection, convert_selection_to_dsl, text_buffer_from_dsl_str,
};
use crate::text_buffer::TextBuffer;
fn gen_caret_text_buf(lines: &[&str]) -> Result<(Position, Option<RawSelection>, TextBuffer), String> {
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);
@ -381,17 +388,19 @@ mod test_update {
Ok((caret_pos, selection_opt, text_buf))
}
fn mock_app_model(text_buf: TextBuffer, caret_pos: Position, selection_opt: Option<RawSelection>) -> AppModel {
fn mock_app_model(
text_buf: TextBuffer,
caret_pos: Position,
selection_opt: Option<RawSelection>,
) -> AppModel {
AppModel {
ed_model_opt: Some(
EdModel{
ed_model_opt: Some(EdModel {
text_buf,
caret_pos,
selection_opt,
glyph_dim_rect_opt: None,
has_focus: true
}
)
has_focus: true,
}),
}
}
@ -410,7 +419,12 @@ mod test_update {
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();
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.");
@ -421,132 +435,75 @@ mod test_update {
#[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'
)?;
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", " | "], ' '
)?;
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}'
)?;
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(
&["[a]|"], &["|"], '\u{8}'
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"],
&["abc\n", "d|\n", "jkl"],
'\u{8}',
)?;
assert_insert(
&["a[a]|"], &["a|"], '\u{8}'
&["abc\n", "[def\n", "ghi]|\n", "jkl"],
&["abc\n", "|\n", "jkl"],
'\u{8}',
)?;
assert_insert(
&["[aa]|"], &["|"], '\u{8}'
&["abc\n", "\n", "[def\n", "ghi]|\n", "jkl"],
&["abc\n", "\n", "|\n", "jkl"],
'\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}'
&["[abc\n", "\n", "def\n", "ghi\n", "jkl]|"],
&["|"],
'\u{8}',
)?;
Ok(())
@ -554,48 +511,32 @@ mod test_update {
#[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(
&["[a]|"], &["z|"], 'z'
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"],
&["abc\n", "dz|\n", "jkl"],
'z',
)?;
assert_insert(
&["a[a]|"], &["az|"], 'z'
&["abc\n", "[def\n", "ghi]|\n", "jkl"],
&["abc\n", "z|\n", "jkl"],
'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'
&["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(())
}

View file

@ -0,0 +1 @@
pub mod strings;

View file

@ -1 +1 @@
pub const NOTHING_OPENED: &str = "Execute `cargo run edit <filename>` to open a file";
pub const NOTHING_OPENED: &str = "Execute `cargo run edit <filename>` to open a file.";

View file

@ -126,13 +126,15 @@ pub fn create_selection_rects<'a>(
pub mod test_selection {
use crate::error::{EdResult, OutOfBounds};
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::vec_result::get_res;
use crate::mvc::update::{
move_caret_down, move_caret_left, move_caret_right, move_caret_up, MoveCaretFun,
};
use crate::text_buffer::TextBuffer;
use crate::vec_result::get_res;
use core::cmp::Ordering;
use pest::Parser;
use snafu::OptionExt;
use ropey::Rope;
use snafu::OptionExt;
use std::collections::HashMap;
use std::slice::SliceIndex;
@ -204,7 +206,7 @@ pub mod test_selection {
let elt_ref = vec.get_mut(index).context(OutOfBounds {
index,
collection_name: "Slice",
len: vec_len
len: vec_len,
})?;
Ok(elt_ref)
@ -223,7 +225,7 @@ pub mod test_selection {
.iter()
.map(|line| line.replace(&['[', ']', '|'][..], ""))
.collect::<Vec<String>>()
.join("")
.join(""),
)
}
@ -358,8 +360,7 @@ pub mod test_selection {
let (sel_opt, caret_pos) = convert_dsl_to_selection(&pre_lines)?;
let clean_text_buf =
text_buffer_from_dsl_str(&pre_lines);
let clean_text_buf = text_buffer_from_dsl_str(&pre_lines);
let (new_caret_pos, new_sel_opt) =
move_fun(caret_pos, sel_opt, shift_pressed, &clean_text_buf);

View file

@ -1,17 +1,15 @@
// Adapted from https://github.com/cessen/ropey by Nathan Vegdahl, licensed under the MIT license
use crate::error::EdError::{FileOpenFailed, TextBufReadFailed};
use crate::error::EdResult;
use crate::error::OutOfBounds;
use crate::error::EdError::{TextBufReadFailed, FileOpenFailed};
use crate::mvc::ed_model::{Position, RawSelection};
use crate::selection::{validate_selection};
use crate::selection::validate_selection;
use ropey::Rope;
use snafu::{ensure, OptionExt};
use std::fs::File;
use std::io;
use std::path::Path;
use ropey::{Rope};
use snafu::{ensure, OptionExt};
#[derive(Debug)]
pub struct TextBuffer {
@ -23,11 +21,14 @@ impl TextBuffer {
pub fn insert_char(&mut self, caret_pos: Position, new_char: &char) -> EdResult<()> {
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,
collection_name: "Rope",
len: self.text_rope.len_chars()
});
}
);
self.text_rope.insert(char_indx, &new_char.to_string());
@ -45,11 +46,14 @@ impl TextBuffer {
pub fn del_selection(&mut self, raw_sel: RawSelection) -> EdResult<()> {
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,
collection_name: "Rope",
len: self.text_rope.len_chars()
});
}
);
self.text_rope.remove(start_char_indx..end_char_indx);
@ -76,7 +80,7 @@ impl TextBuffer {
self.line_len(line_nr).context(OutOfBounds {
index: line_nr,
collection_name: "Rope",
len: self.text_rope.len_lines()
len: self.text_rope.len_lines(),
})
}
@ -132,20 +136,16 @@ fn rope_from_path(path: &Path) -> EdResult<Rope> {
Ok(file) => {
let buf_reader = &mut io::BufReader::new(file);
match Rope::from_reader(buf_reader) {
Ok(rope) =>
Ok(rope),
Err(e) =>
Err(TextBufReadFailed {
Ok(rope) => Ok(rope),
Err(e) => Err(TextBufReadFailed {
path_str: path_to_string(path),
err_msg: e.to_string()
})
err_msg: e.to_string(),
}),
}
}
Err(e) => {
Err(FileOpenFailed {
Err(e) => Err(FileOpenFailed {
path_str: path_to_string(path),
err_msg: e.to_string()
})
}
err_msg: e.to_string(),
}),
}
}