Merge pull request #2547 from rtfeldman/simplify-editor

simplify editor
This commit is contained in:
Richard Feldman 2022-02-27 21:43:09 -05:00 committed by GitHub
commit 8ec7b26a1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 353 additions and 918 deletions

View File

@ -154,12 +154,18 @@ fn canonicalize_field<'a>(
let (loc_can_expr, output) =
expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region);
Ok(CanonicalField::LabelAndValue {
label: label.value,
value_expr: loc_can_expr,
value_output: output,
var: field_var,
})
match loc_can_expr {
Expr2::RuntimeError() => Ok(CanonicalField::InvalidLabelOnly {
label: label.value,
var: field_var,
}),
_ => Ok(CanonicalField::LabelAndValue {
label: label.value,
value_expr: loc_can_expr,
value_output: output,
var: field_var,
}),
}
}
OptionalValue(label, _, loc_expr) => Err(CanonicalizeFieldProblem::InvalidOptionalValue {

View File

@ -15,6 +15,24 @@ pub struct AST {
pub def_ids: Vec<DefId>,
}
impl AST {
pub fn insert_def_at_index(&mut self, new_def_id: DefId, index: usize) {
self.def_ids.insert(index, new_def_id);
}
// TODO print in tree shape, similar to linux tree command
pub fn ast_to_string(&self, pool: &Pool) -> String {
let mut full_ast_string = String::new();
for def_id in self.def_ids.iter() {
full_ast_string.push_str(&def2_to_string(*def_id, pool));
full_ast_string.push_str("\n\n");
}
full_ast_string
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ASTNodeId {
ADefId(DefId),

View File

@ -148,6 +148,9 @@ fn expr2_to_string_helper(
&Expr2::Var { .. } => {
out_string.push_str(&format!("{:?}", expr2,));
}
Expr2::RuntimeError { .. } => {
out_string.push_str("RuntimeError\n");
}
other => todo!("Implement for {:?}", other),
}

View File

@ -50,6 +50,7 @@ pub fn expr_to_expr2<'a>(
region: Region,
) -> (Expr2, self::Output) {
use roc_parse::ast::Expr::*;
//dbg!("{:?}", parse_expr);
match parse_expr {
Float(string) => {

View File

@ -27,7 +27,7 @@ pub fn load_module(src_file: &Path) -> LoadedModule {
Ok(x) => x,
Err(roc_load::file::LoadingProblem::FormattedReport(report)) => {
panic!(
"Failed to load module from src_file {:?}. Report: {:?}",
"Failed to load module from src_file {:?}. Report: {}",
src_file, report
);
}

View File

@ -25,7 +25,7 @@ pub fn parse_from_string<'a>(
) -> ASTResult<AST> {
let blank_line_indx = code_str
.find("\n\n")
.expect("I was expecting a double newline to split header and rest of code.");
.expect("I was expecting two newline chars to split header and rest of code.");
let header_str = &code_str[0..blank_line_indx];
let tail_str = &code_str[blank_line_indx..];

View File

@ -64,13 +64,12 @@ pub fn expr2_to_markup<'a>(
Expr2::Str(text) => {
let content = format!("\"{}\"", text.as_str(env.pool));
new_markup_node(
with_indent(indent_level, &content),
ast_node_id,
HighlightStyle::String,
mark_node_pool,
indent_level,
)
string_mark_node(&content, indent_level, ast_node_id, mark_node_pool)
}
Expr2::SmallStr(array_str) => {
let content = format!("\"{}\"", array_str.as_str());
string_mark_node(&content, indent_level, ast_node_id, mark_node_pool)
}
Expr2::GlobalTag { name, .. } => new_markup_node(
with_indent(indent_level, &get_string(env, name)),
@ -387,3 +386,18 @@ fn with_indent(indent_level: usize, some_str: &str) -> String {
full_string
}
fn string_mark_node(
content: &str,
indent_level: usize,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
) -> MarkNodeId {
new_markup_node(
with_indent(indent_level, content),
ast_node_id,
HighlightStyle::String,
mark_node_pool,
indent_level,
)
}

View File

@ -468,3 +468,34 @@ pub fn join_mark_nodes_commas(
mark_nodes.into_iter().interleave(join_nodes).collect()
}
pub fn mark_nodes_to_string(markup_node_ids: &[MarkNodeId], mark_node_pool: &SlowPool) -> String {
let mut all_code_string = String::new();
for mark_node_id in markup_node_ids.iter() {
node_to_string_w_children(*mark_node_id, &mut all_code_string, mark_node_pool)
}
all_code_string
}
pub fn node_to_string_w_children(
node_id: MarkNodeId,
str_buffer: &mut String,
mark_node_pool: &SlowPool,
) {
let node = mark_node_pool.get(node_id);
if node.is_nested() {
for child_id in node.get_children_ids() {
node_to_string_w_children(child_id, str_buffer, mark_node_pool);
}
for _ in 0..node.get_newlines_at_end() {
str_buffer.push('\n')
}
} else {
let node_content_str = node.get_full_content();
str_buffer.push_str(&node_content_str);
}
}

View File

@ -580,6 +580,7 @@ impl IdentIds {
}
// necessary when the name of a value is changed in the editor
// TODO fix when same ident_name is present multiple times, see issue #2548
pub fn update_key(
&mut self,
old_ident_name: &str,

View File

@ -43,7 +43,7 @@ From roc to render:
- `ed_model` also contains an `EdModule`, which holds the parsed abstract syntax tree (AST).
- In the `init_model` function:
+ The AST is converted into a tree of `MarkupNode`. The different types of `MarkupNode` are similar to the elements/nodes in HTML. A line of roc code is represented as a nested `MarkupNode` containing mostly text `MarkupNode`s. The line `foo = "bar"` is represented as
three text `MarkupNode` representing `foo`, ` = ` and `bar`. Multiple lines of roc code are represented as nested `MarkupNode` that contain other nested `MarkupNode`.
three text `MarkupNode`; representing `foo`, ` = ` and `bar`. Multiple lines of roc code are represented as nested `MarkupNode` that contain other nested `MarkupNode`.
+ `CodeLines` holds a `Vec` of `String`, each line of code is a `String`. When saving the file, the content of `CodeLines` is written to disk.
+ `GridNodeMap` maps every position of a char of roc code to a `MarkNodeId`, for easy interaction with the caret.
- Back in `editor/src/editor/main.rs` we convert the `EdModel` to `RenderedWgpu` by calling `model_to_wgpu`.

View File

@ -1,10 +1,7 @@
use crate::ui::text::lines::Lines;
use crate::ui::text::selection::Selection;
use crate::ui::text::text_pos::TextPos;
use crate::ui::ui_error::{LineInsertionFailed, OutOfBounds, UIResult};
use crate::ui::ui_error::UIResult;
use crate::ui::util::slice_get;
use crate::ui::util::slice_get_mut;
use std::cmp::Ordering;
use std::fmt;
#[derive(Debug, Default)]
@ -14,134 +11,11 @@ pub struct CodeLines {
}
impl CodeLines {
pub fn insert_between_line(
&mut self,
line_nr: usize,
index: usize,
new_str: &str,
) -> UIResult<()> {
let nr_of_lines = self.lines.len();
if line_nr < nr_of_lines {
let line_ref = slice_get_mut(line_nr, &mut self.lines)?;
line_ref.insert_str(index, new_str);
} else if line_nr >= self.lines.len() {
for _ in 0..((line_nr - nr_of_lines) + 1) {
self.push_empty_line();
}
self.insert_between_line(line_nr, index, new_str)?;
} else {
LineInsertionFailed {
line_nr,
nr_of_lines,
}
.fail()?;
pub fn from_str(code_str: &str) -> CodeLines {
CodeLines {
lines: code_str.split('\n').map(|s| s.to_owned()).collect(),
nr_of_chars: code_str.len(),
}
self.nr_of_chars += new_str.len();
Ok(())
}
pub fn insert_empty_line(&mut self, line_nr: usize) -> UIResult<()> {
if line_nr <= self.lines.len() {
self.lines.insert(line_nr, String::new());
Ok(())
} else {
OutOfBounds {
index: line_nr,
collection_name: "code_lines.lines".to_owned(),
len: self.lines.len(),
}
.fail()
}
}
pub fn push_empty_line(&mut self) {
self.lines.push(String::new())
}
pub fn break_line(&mut self, line_nr: usize, col_nr: usize) -> UIResult<()> {
// clippy prefers this over if-else
match line_nr.cmp(&self.lines.len()) {
Ordering::Less => {
self.insert_empty_line(line_nr + 1)?;
let line_ref = self.lines.get_mut(line_nr).unwrap(); // safe because we checked line_nr
if col_nr < line_ref.len() {
let next_line_str: String = line_ref.drain(col_nr..).collect();
let next_line_ref = self.lines.get_mut(line_nr + 1).unwrap(); // safe because we just added the line
*next_line_ref = next_line_str;
}
Ok(())
}
Ordering::Equal => self.insert_empty_line(line_nr + 1),
Ordering::Greater => OutOfBounds {
index: line_nr,
collection_name: "code_lines.lines".to_owned(),
len: self.lines.len(),
}
.fail(),
}
}
pub fn clear_line(&mut self, line_nr: usize) -> UIResult<()> {
let line_ref = slice_get_mut(line_nr, &mut self.lines)?;
*line_ref = String::new();
Ok(())
}
pub fn del_line(&mut self, line_nr: usize) -> UIResult<()> {
let line_len = self.line_len(line_nr)?;
self.lines.remove(line_nr);
self.nr_of_chars -= line_len;
Ok(())
}
pub fn del_at_line(&mut self, line_nr: usize, index: usize) -> UIResult<()> {
let line_ref = slice_get_mut(line_nr, &mut self.lines)?;
line_ref.remove(index);
self.nr_of_chars -= 1;
Ok(())
}
pub fn del_range_at_line(
&mut self,
line_nr: usize,
col_range: std::ops::Range<usize>,
) -> UIResult<()> {
let line_ref = slice_get_mut(line_nr, &mut self.lines)?;
line_ref.drain(col_range);
Ok(())
}
pub fn del_selection(&mut self, selection: Selection) -> UIResult<()> {
if selection.is_on_same_line() {
let line_ref = slice_get_mut(selection.start_pos.line, &mut self.lines)?;
line_ref.drain(selection.start_pos.column..selection.end_pos.column);
} else {
// TODO support multiline selections
}
Ok(())
}
// last column of last line

View File

@ -1,6 +1,4 @@
use roc_ast::lang::core::ast::ASTNodeId;
use roc_ast::lang::core::def::def2::Def2;
use roc_code_markup::markup::common_nodes::new_blank_mn_w_nls;
use crate::editor::ed_error::EdResult;
use crate::editor::mvc::app_update::InputOutcome;
@ -30,24 +28,12 @@ pub fn break_line(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
&& ed_model.code_lines.line_len(new_blank_line_nr).unwrap() == 0)
{
// two blank lines between top level definitions
EdModel::insert_empty_line(
caret_line_nr + 1,
&mut ed_model.code_lines,
&mut ed_model.grid_node_map,
)?;
EdModel::insert_empty_line(
caret_line_nr + 2,
&mut ed_model.code_lines,
&mut ed_model.grid_node_map,
)?;
EdModel::insert_empty_line(caret_line_nr + 1, &mut ed_model.grid_node_map)?;
EdModel::insert_empty_line(caret_line_nr + 2, &mut ed_model.grid_node_map)?;
// third "empty" line will be filled by the blank
EdModel::insert_empty_line(
caret_line_nr + 3,
&mut ed_model.code_lines,
&mut ed_model.grid_node_map,
)?;
EdModel::insert_empty_line(caret_line_nr + 3, &mut ed_model.grid_node_map)?;
insert_new_blank(ed_model, caret_pos, caret_pos.line + 3)?;
insert_new_blank(ed_model, caret_pos.line + 3)?;
}
}
}
@ -57,39 +43,25 @@ pub fn break_line(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
Ok(InputOutcome::Accepted)
}
pub fn insert_new_blank(
ed_model: &mut EdModel,
caret_pos: &TextPos,
insert_on_line_nr: usize,
) -> EdResult<()> {
pub fn insert_new_blank(ed_model: &mut EdModel, insert_on_line_nr: usize) -> EdResult<()> {
println!(
"{}",
ed_model.module.ast.ast_to_string(ed_model.module.env.pool)
);
// find position of the previous ASTNode to figure out where to add this new Blank ASTNode
let def_mark_node_id = ed_model
.grid_node_map
.get_def_mark_node_id_before_line(insert_on_line_nr, &ed_model.mark_node_pool)?;
let new_line_blank = Def2::Blank;
let new_line_blank_id = ed_model.module.env.pool.add(new_line_blank);
let prev_def_mn_id = ed_model
.grid_node_map
.get_def_mark_node_id_before_line(caret_pos.line + 1, &ed_model.mark_node_pool)?;
let prev_def_mn_id_indx = index_of(prev_def_mn_id, &ed_model.markup_ids)?;
let insertion_index = index_of(def_mark_node_id, &ed_model.markup_ids)?;
ed_model
.module
.ast
.def_ids
.insert(prev_def_mn_id_indx, new_line_blank_id);
let blank_mn_id = ed_model.add_mark_node(new_blank_mn_w_nls(
ASTNodeId::ADefId(new_line_blank_id),
None,
2,
));
ed_model
.markup_ids
.insert(prev_def_mn_id_indx + 1, blank_mn_id); // + 1 because first markup node is header
ed_model.insert_all_between_line(
insert_on_line_nr, // one blank line between top level definitions
0,
&[blank_mn_id],
)?;
.insert_def_at_index(new_line_blank_id, insertion_index);
Ok(())
}

View File

@ -16,6 +16,7 @@ use roc_ast::lang::env::Env;
use roc_ast::mem_pool::pool_str::PoolStr;
use roc_ast::parse::parse_ast;
use roc_code_markup::markup::convert::from_ast::ast_to_mark_nodes;
use roc_code_markup::markup::nodes;
use roc_code_markup::slow_pool::{MarkNodeId, SlowPool};
use roc_load::file::LoadedModule;
use roc_module::symbol::Interns;
@ -74,7 +75,8 @@ pub fn init_model<'a>(
)?)
}?;
let mut code_lines = CodeLines::default();
let code_lines =
CodeLines::from_str(&nodes::mark_nodes_to_string(&markup_ids, &mark_node_pool));
let mut grid_node_map = GridNodeMap::default();
let mut line_nr = 0;
@ -88,7 +90,6 @@ pub fn init_model<'a>(
&mut col_nr,
*mark_node_id,
&mut grid_node_map,
&mut code_lines,
&mark_node_pool,
)?
}

View File

@ -49,6 +49,7 @@ use roc_ast::mem_pool::pool_str::PoolStr;
use roc_ast::solve_type;
use roc_can::expected::Expected;
use roc_code_markup::markup::attribute::Attributes;
use roc_code_markup::markup::convert::from_ast::ast_to_mark_nodes;
use roc_code_markup::markup::nodes;
use roc_code_markup::markup::nodes::MarkupNode;
use roc_code_markup::markup::nodes::EQUALS;
@ -187,10 +188,8 @@ impl<'a> EdModel<'a> {
new_str: &str,
node_id: MarkNodeId,
grid_node_map: &mut GridNodeMap,
code_lines: &mut CodeLines,
) -> UIResult<()> {
grid_node_map.insert_between_line(line_nr, index, new_str.len(), node_id)?;
code_lines.insert_between_line(line_nr, index, new_str)
grid_node_map.insert_between_line(line_nr, index, new_str.len(), node_id)
}
pub fn insert_all_between_line(
@ -218,9 +217,6 @@ impl<'a> EdModel<'a> {
node_id,
)?;
self.code_lines
.insert_between_line(curr_line_nr, col_nr, line)?;
curr_line_nr += 1;
col_nr = 0;
}
@ -234,9 +230,6 @@ impl<'a> EdModel<'a> {
node_id,
)?;
self.code_lines
.insert_between_line(line_nr, col_nr, &node_content)?;
col_nr += node_content.len();
}
}
@ -249,7 +242,6 @@ impl<'a> EdModel<'a> {
col_nr: &mut usize,
mark_node_id: MarkNodeId,
grid_node_map: &mut GridNodeMap,
code_lines: &mut CodeLines,
mark_node_pool: &SlowPool,
) -> UIResult<()> {
let mark_node = mark_node_pool.get(mark_node_id);
@ -265,7 +257,6 @@ impl<'a> EdModel<'a> {
col_nr,
child_id,
grid_node_map,
code_lines,
mark_node_pool,
)?;
}
@ -278,20 +269,19 @@ impl<'a> EdModel<'a> {
&node_content,
mark_node_id,
grid_node_map,
code_lines,
)?;
*col_nr += node_content.len();
}
if node_newlines > 0 {
EdModel::break_line(*line_nr, *col_nr, code_lines, grid_node_map)?;
EdModel::break_line(*line_nr, *col_nr, grid_node_map)?;
*line_nr += 1;
*col_nr = 0;
for _ in 1..node_newlines {
EdModel::insert_empty_line(*line_nr, code_lines, grid_node_map)?;
EdModel::insert_empty_line(*line_nr, grid_node_map)?;
*line_nr += 1;
*col_nr = 0;
@ -305,40 +295,29 @@ impl<'a> EdModel<'a> {
pub fn break_line(
line_nr: usize,
col_nr: usize,
code_lines: &mut CodeLines,
grid_node_map: &mut GridNodeMap,
) -> UIResult<()> {
code_lines.break_line(line_nr, col_nr)?;
grid_node_map.break_line(line_nr, col_nr)
}
pub fn insert_empty_line(
line_nr: usize,
code_lines: &mut CodeLines,
grid_node_map: &mut GridNodeMap,
) -> UIResult<()> {
code_lines.insert_empty_line(line_nr)?;
pub fn insert_empty_line(line_nr: usize, grid_node_map: &mut GridNodeMap) -> UIResult<()> {
grid_node_map.insert_empty_line(line_nr)
}
pub fn push_empty_line(code_lines: &mut CodeLines, grid_node_map: &mut GridNodeMap) {
code_lines.push_empty_line();
pub fn push_empty_line(grid_node_map: &mut GridNodeMap) {
grid_node_map.push_empty_line();
}
pub fn clear_line(&mut self, line_nr: usize) -> UIResult<()> {
self.grid_node_map.clear_line(line_nr)?;
self.code_lines.clear_line(line_nr)
self.grid_node_map.clear_line(line_nr)
}
pub fn del_line(&mut self, line_nr: usize) -> UIResult<()> {
self.grid_node_map.del_line(line_nr);
self.code_lines.del_line(line_nr)
pub fn del_line(&mut self, line_nr: usize) {
self.grid_node_map.del_line(line_nr)
}
pub fn del_at_line(&mut self, line_nr: usize, index: usize) -> UIResult<()> {
self.grid_node_map.del_at_line(line_nr, index)?;
self.code_lines.del_at_line(line_nr, index)
self.grid_node_map.del_at_line(line_nr, index)
}
// updates grid_node_map and code_lines but nothing else.
@ -347,9 +326,7 @@ impl<'a> EdModel<'a> {
line_nr: usize,
col_range: std::ops::Range<usize>,
) -> UIResult<()> {
self.grid_node_map
.del_range_at_line(line_nr, col_range.clone())?;
self.code_lines.del_range_at_line(line_nr, col_range)
self.grid_node_map.del_range_at_line(line_nr, col_range)
}
pub fn del_blank_expr_node(&mut self, txt_pos: TextPos) -> UIResult<()> {
@ -602,7 +579,6 @@ impl<'a> EdModel<'a> {
let active_selection = self.get_selection().context(MissingSelection {})?;
self.code_lines.del_selection(active_selection)?;
self.grid_node_map.del_selection(active_selection)?;
match sel_block.ast_node_id {
@ -624,7 +600,6 @@ impl<'a> EdModel<'a> {
nodes::BLANK_PLACEHOLDER,
expr_mark_node_id,
&mut self.grid_node_map,
&mut self.code_lines,
)?;
self.set_sel_none();
@ -678,6 +653,41 @@ impl<'a> EdModel<'a> {
Ok(())
}
/// update MarkupNode's, grid_node_map, code_lines after the AST has been updated
fn post_process_ast_update(&mut self) -> EdResult<()> {
//dbg!("{}",self.module.ast.ast_to_string(self.module.env.pool));
self.markup_ids = ast_to_mark_nodes(
&mut self.module.env,
&self.module.ast,
&mut self.mark_node_pool,
&self.loaded_module.interns,
)?;
self.code_lines = CodeLines::from_str(&nodes::mark_nodes_to_string(
&self.markup_ids,
&self.mark_node_pool,
));
self.grid_node_map = GridNodeMap::default();
let mut line_nr = 0;
let mut col_nr = 0;
for mark_node_id in &self.markup_ids {
// for debugging:
//println!("{}", tree_as_string(*mark_node_id, &mark_node_pool));
EdModel::insert_mark_node_between_line(
&mut line_nr,
&mut col_nr,
*mark_node_id,
&mut self.grid_node_map,
&self.mark_node_pool,
)?
}
Ok(())
}
}
impl<'a> SelectableLines for EdModel<'a> {
@ -1080,6 +1090,7 @@ pub fn handle_new_char_expr(
let (new_child_index, new_ast_child_index) = ed_model.get_curr_child_indices()?;
// insert a Blank first, this results in cleaner code
add_blank_child(new_child_index, new_ast_child_index, ed_model)?;
ed_model.post_process_ast_update()?;
handle_new_char(received_char, ed_model)?
} else {
InputOutcome::Ignored
@ -1162,6 +1173,7 @@ pub fn handle_new_char_diff_mark_nodes_prev_is_expr(
let new_ast_child_index = 0;
// insert a Blank first, this results in cleaner code
add_blank_child(new_child_index, new_ast_child_index, ed_model)?;
ed_model.post_process_ast_update()?;
handle_new_char(received_char, ed_model)?
} else {
InputOutcome::Ignored
@ -1182,6 +1194,8 @@ pub fn handle_new_char_diff_mark_nodes_prev_is_expr(
// updates the ed_model based on the char the user just typed if the result would be syntactically correct.
pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<InputOutcome> {
//dbg!("{}", ed_model.module.ast.ast_to_string(ed_model.module.env.pool));
let input_outcome = match received_char {
'\u{e000}'..='\u{f8ff}' // http://www.unicode.org/faq/private_use.html
| '\u{f0000}'..='\u{ffffd}' // ^
@ -1237,7 +1251,8 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
for caret_pos in ed_model.get_carets() {
if caret_pos.line > 0 {
insert_new_blank(ed_model, &caret_pos, caret_pos.line)?;
insert_new_blank(ed_model, caret_pos.line)?;
ed_model.post_process_ast_update()?;
}
}
handle_new_char(received_char, ed_model)?
@ -1260,6 +1275,7 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
};
if let InputOutcome::Accepted = input_outcome {
ed_model.post_process_ast_update()?;
ed_model.dirty = true;
}
@ -1684,92 +1700,32 @@ pub mod test_ed_update {
fn test_record() -> Result<(), String> {
assert_insert_in_def_nls(ovec!["{ ┃ }"], '{')?;
assert_insert_nls(ovec!["val = { ┃ }"], ovec!["val = { a┃ }"], 'a')?;
assert_insert_nls(
ovec!["val = { a┃ }"],
ovec!["val = { ab┃: RunTimeError }"],
'b',
)?; // TODO: remove RunTimeError, see issue #1649
assert_insert_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a1┃: RunTimeError }"],
'1',
)?;
assert_insert_nls(
ovec!["val = { a1┃ }"],
ovec!["val = { a1z┃: RunTimeError }"],
'z',
)?;
assert_insert_nls(
ovec!["val = { a1┃ }"],
ovec!["val = { a15┃: RunTimeError }"],
'5',
)?;
assert_insert_nls(
ovec!["val = { ab┃ }"],
ovec!["val = { abc┃: RunTimeError }"],
'c',
)?;
assert_insert_nls(
ovec!["val = { ┃abc }"],
ovec!["val = { z┃abc: RunTimeError }"],
'z',
)?;
assert_insert_nls(
ovec!["val = { a┃b }"],
ovec!["val = { az┃b: RunTimeError }"],
'z',
)?;
assert_insert_nls(
ovec!["val = { a┃b }"],
ovec!["val = { a9┃b: RunTimeError }"],
'9',
)?;
assert_insert_nls(ovec!["val = { a┃ }"], ovec!["val = { ab┃ }"], 'b')?;
assert_insert_nls(ovec!["val = { a┃ }"], ovec!["val = { a1┃ }"], '1')?;
assert_insert_nls(ovec!["val = { a1┃ }"], ovec!["val = { a1z┃ }"], 'z')?;
assert_insert_nls(ovec!["val = { a1┃ }"], ovec!["val = { a15┃ }"], '5')?;
assert_insert_nls(ovec!["val = { ab┃ }"], ovec!["val = { abc┃ }"], 'c')?;
assert_insert_nls(ovec!["val = { ┃abc }"], ovec!["val = { z┃abc }"], 'z')?;
assert_insert_nls(ovec!["val = { a┃b }"], ovec!["val = { az┃b }"], 'z')?;
assert_insert_nls(ovec!["val = { a┃b }"], ovec!["val = { a9┃b }"], '9')?;
assert_insert_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a┃: RunTimeError }"],
':',
)?;
assert_insert_nls(
ovec!["val = { abc┃ }"],
ovec!["val = { abc┃: RunTimeError }"],
':',
)?;
assert_insert_nls(
ovec!["val = { aBc┃ }"],
ovec!["val = { aBc┃: RunTimeError }"],
':',
)?;
assert_insert_nls(ovec!["val = { a┃ }"], ovec!["val = { a: ┃ }"], ':')?;
assert_insert_nls(ovec!["val = { abc┃ }"], ovec!["val = { abc: ┃ }"], ':')?;
assert_insert_nls(ovec!["val = { aBc┃ }"], ovec!["val = { aBc: ┃ }"], ':')?;
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a┃: RunTimeError }"],
":\"",
)?;
assert_insert_seq_nls(ovec!["val = { a┃ }"], ovec!["val = { a: \"\" }"], ":\"")?;
assert_insert_seq_nls(
ovec!["val = { abc┃ }"],
ovec!["val = { abc┃: RunTimeError }"],
ovec!["val = { abc: \"\" }"],
":\"",
)?;
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a0┃: RunTimeError }"],
":0",
)?;
assert_insert_seq_nls(ovec!["val = { a┃ }"], ovec!["val = { a: 0┃ }"], ":0")?;
assert_insert_seq_nls(ovec!["val = { abc┃ }"], ovec!["val = { abc: 9┃ }"], ":9")?;
assert_insert_seq_nls(ovec!["val = { a┃ }"], ovec!["val = { a: 1000┃ }"], ":1000")?;
assert_insert_seq_nls(
ovec!["val = { abc┃ }"],
ovec!["val = { abc9┃: RunTimeError }"],
":9",
)?;
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a1000┃: RunTimeError }"],
":1000",
)?;
assert_insert_seq_nls(
ovec!["val = { abc┃ }"],
ovec!["val = { abc98761┃: RunTimeError }"],
ovec!["val = { abc: 98761┃ }"],
":98761",
)?;
@ -1919,19 +1875,11 @@ pub mod test_ed_update {
#[test]
fn test_nested_record() -> Result<(), String> {
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a┃: RunTimeError }"],
":{",
)?;
assert_insert_seq_nls(
ovec!["val = { abc┃ }"],
ovec!["val = { abc┃: RunTimeError }"],
":{",
)?;
assert_insert_seq_nls(ovec!["val = { a┃ }"], ovec!["val = { a: { ┃ } }"], ":{")?;
assert_insert_seq_nls(ovec!["val = { abc┃ }"], ovec!["val = { abc: { ┃ } }"], ":{")?;
assert_insert_seq_nls(
ovec!["val = { camelCase┃ }"],
ovec!["val = { camelCase┃: RunTimeError }"],
ovec!["val = { camelCase: { ┃ } }"],
":{",
)?;
@ -1953,49 +1901,49 @@ pub mod test_ed_update {
assert_insert_seq_nls(
ovec!["val = { a: { zulu┃ } }"],
ovec!["val = { a: { zulu┃: RunTimeError } }"],
ovec!["val = { a: { zulu: ┃ } }"],
":",
)?;
assert_insert_seq_nls(
ovec!["val = { abc: { camelCase┃ } }"],
ovec!["val = { abc: { camelCase┃: RunTimeError } }"],
ovec!["val = { abc: { camelCase: ┃ } }"],
":",
)?;
assert_insert_seq_nls(
ovec!["val = { camelCase: { z┃ } }"],
ovec!["val = { camelCase: { z┃: RunTimeError } }"],
ovec!["val = { camelCase: { z: ┃ } }"],
":",
)?;
assert_insert_seq_nls(
ovec!["val = { a┃: { zulu } }"],
ovec!["val = { a0┃: { zulu: RunTimeError } }"],
ovec!["val = { a0┃: { zulu } }"],
"0",
)?;
assert_insert_seq_nls(
ovec!["val = { ab┃c: { camelCase } }"],
ovec!["val = { abz┃c: { camelCase: RunTimeError } }"],
ovec!["val = { abz┃c: { camelCase } }"],
"z",
)?;
assert_insert_seq_nls(
ovec!["val = { ┃camelCase: { z } }"],
ovec!["val = { x┃camelCase: { z: RunTimeError } }"],
ovec!["val = { x┃camelCase: { z } }"],
"x",
)?;
assert_insert_seq_nls(
ovec!["val = { a: { zulu┃ } }"],
ovec!["val = { a: { zulu┃: RunTimeError } }"],
ovec!["val = { a: { zulu: \"\" } }"],
":\"",
)?;
assert_insert_seq_nls(
ovec!["val = { abc: { camelCase┃ } }"],
ovec!["val = { abc: { camelCase┃: RunTimeError } }"],
ovec!["val = { abc: { camelCase: \"\" } }"],
":\"",
)?;
assert_insert_seq_nls(
ovec!["val = { camelCase: { z┃ } }"],
ovec!["val = { camelCase: { z┃: RunTimeError } }"],
ovec!["val = { camelCase: { z: \"\" } }"],
":\"",
)?;
@ -2012,17 +1960,17 @@ pub mod test_ed_update {
assert_insert_seq_nls(
ovec!["val = { a: { zulu┃ } }"],
ovec!["val = { a: { zulu1┃: RunTimeError } }"],
ovec!["val = { a: { zulu: 1┃ } }"],
":1",
)?;
assert_insert_seq_nls(
ovec!["val = { abc: { camelCase┃ } }"],
ovec!["val = { abc: { camelCase0┃: RunTimeError } }"],
ovec!["val = { abc: { camelCase: 0┃ } }"],
":0",
)?;
assert_insert_seq_nls(
ovec!["val = { camelCase: { z┃ } }"],
ovec!["val = { camelCase: { z45┃: RunTimeError } }"],
ovec!["val = { camelCase: { z: 45┃ } }"],
":45",
)?;
@ -2039,17 +1987,17 @@ pub mod test_ed_update {
assert_insert_seq_nls(
ovec!["val = { a: { zulu┃ } }"],
ovec!["val = { a: { zulu┃: RunTimeError } }"],
ovec!["val = { a: { zulu: { ┃ } } }"],
":{",
)?;
assert_insert_seq_nls(
ovec!["val = { abc: { camelCase┃ } }"],
ovec!["val = { abc: { camelCase┃: RunTimeError } }"],
ovec!["val = { abc: { camelCase: { ┃ } } }"],
":{",
)?;
assert_insert_seq_nls(
ovec!["val = { camelCase: { z┃ } }"],
ovec!["val = { camelCase: { z┃: RunTimeError } }"],
ovec!["val = { camelCase: { z: { ┃ } } }"],
":{",
)?;
@ -2076,17 +2024,17 @@ pub mod test_ed_update {
assert_insert_seq_nls(
ovec!["val = { a┃: { bcD: { eFgHij: { k15 } } } }"],
ovec!["val = { a4┃: { bcD: { eFgHij: { k15: RunTimeError } } } }"],
ovec!["val = { a4┃: { bcD: { eFgHij: { k15 } } } }"],
"4",
)?;
assert_insert_seq_nls(
ovec!["val = { ┃a: { bcD: { eFgHij: { k15 } } } }"],
ovec!["val = { y┃a: { bcD: { eFgHij: { k15: RunTimeError } } } }"],
ovec!["val = { y┃a: { bcD: { eFgHij: { k15 } } } }"],
"y",
)?;
assert_insert_seq_nls(
ovec!["val = { a: { bcD: { eF┃gHij: { k15 } } } }"],
ovec!["val = { a: { bcD: { eFxyz┃gHij: { k15: RunTimeError } } } }"],
ovec!["val = { a: { bcD: { eFxyz┃gHij: { k15 } } } }"],
"xyz",
)?;
@ -2099,6 +2047,14 @@ pub mod test_ed_update {
Ok(())
}
fn concat_strings(str_a: &str, str_b: &str) -> String {
let mut string_a = str_a.to_owned();
string_a.push_str(str_b);
string_a
}
#[test]
fn test_ignore_record() -> Result<(), String> {
assert_insert_seq_ignore_nls(ovec!["val = ┃{ }"], IGNORE_CHARS)?;
@ -2107,23 +2063,37 @@ pub mod test_ed_update {
assert_insert_seq_ignore_nls(ovec!["val = { ┃}"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃ }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃a: RunTimeError }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃abc: RunTimeError }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃a }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃abc }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { a: ┃RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ a: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { a:┃ RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a }"], IGNORE_CHARS)?;
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a:┃ }"],
&concat_strings(":🡰", IGNORE_CHARS),
)?;
assert_insert_seq_nls(
ovec!["val = { a┃ }"],
ovec!["val = { a: ┃ }"],
&concat_strings(":🡲", IGNORE_CHARS),
)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ a }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a15: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { a15: ┃RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ a15: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { a15:┃ RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a15 }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ a15 }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ camelCase: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCase: ┃RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ camelCase: RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCase:┃ RunTimeError }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ camelCase }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ camelCase }"], IGNORE_CHARS)?;
assert_insert_seq_nls(
ovec!["val = { camelCase┃ }"],
ovec!["val = { camelCase:┃ }"],
&concat_strings(":🡰", IGNORE_CHARS),
)?;
assert_insert_seq_nls(
ovec!["val = { camelCase┃ }"],
ovec!["val = { camelCase: ┃ }"],
&concat_strings(":🡲", IGNORE_CHARS),
)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a: \"\" }"], IGNORE_CHARS)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ a: \"\" }"], IGNORE_CHARS)?;
@ -2198,44 +2168,23 @@ pub mod test_ed_update {
assert_insert_seq_ignore_nls(ovec!["val = ┃{ a: { } }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃a: { } }"], "1")?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: { z15a:┃ RunTimeError } }"],
IGNORE_NO_LTR,
assert_insert_seq_ignore_nls(ovec!["val = { camelCaseB1: {┃ z15a } }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCaseB1: ┃{ z15a } }"], IGNORE_NO_LTR)?;
assert_insert_seq_nls(
ovec!["val = { camelCaseB1: { z15a┃ } }"],
ovec!["val = { camelCaseB1: { z15a:┃ } }"],
&concat_strings(":🡰", IGNORE_CHARS),
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: {┃ z15a: RunTimeError } }"],
IGNORE_NO_LTR,
assert_insert_seq_nls(
ovec!["val = { camelCaseB1: { z15a┃ } }"],
ovec!["val = { camelCaseB1: { z15a: ┃ } }"],
&concat_strings(":🡲", IGNORE_CHARS),
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: ┃{ z15a: RunTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: { z15a: ┃RunTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: { z15a: R┃unTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: { z15a: Ru┃nTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1:┃ { z15a: RunTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = {┃ camelCaseB1: { z15a: RunTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = ┃{ camelCaseB1: { z15a: RunTimeError } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃camelCaseB1: { z15a: RunTimeError } }"], "1")?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCaseB1: { ┃z15a: RunTimeError } }"], "1")?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCaseB1:┃ { z15a } }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = {┃ camelCaseB1: { z15a } }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = ┃{ camelCaseB1: { z15a } }"], IGNORE_NO_LTR)?;
assert_insert_seq_ignore_nls(ovec!["val = { ┃camelCaseB1: { z15a } }"], "1")?;
assert_insert_seq_ignore_nls(ovec!["val = { camelCaseB1: { ┃z15a } }"], "1")?;
assert_insert_seq_ignore_nls(
ovec!["val = { camelCaseB1: { z15a: \"\"┃ } }"],
@ -2376,39 +2325,27 @@ pub mod test_ed_update {
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase:┃ RunTimeError } } } } } } } }"],
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase: R┃unTimeError } } } } } } } }"],
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeError } } } } } } } }"],
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeEr┃ror } } } } } } } }"],
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeError } } } } } } } }"],
ovec!["val = { g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { g: { oi: { ng: { d: { e: { e:┃ { p: { camelCase: RunTimeError } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = {┃ g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeError } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = ┃{ g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeError } } } } } } } }"],
IGNORE_NO_LTR,
)?;
assert_insert_seq_ignore_nls(
ovec!["val = { ┃g: { oi: { ng: { d: { e: { e: { p: { camelCase: RunTimeError } } } } } } } }"],
ovec!["val = { ┃g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
"2",
)?;
Ok(())
@ -2619,7 +2556,8 @@ pub mod test_ed_update {
assert_insert_nls(ovec![""], ovec!["z┃ = "], 'z')?;
assert_insert_seq_nls(ovec![""], ovec!["ab┃ = "], "ab")?;
assert_insert_seq_nls(ovec![""], ovec!["mainVal┃ = "], "mainVal")?;
// TODO see issue #2548
//assert_insert_seq_nls(ovec!["┃"], ovec!["mainVal┃ = "], "mainVal")?;
assert_insert_seq_nls(ovec![""], ovec!["camelCase123┃ = "], "camelCase123")?;
assert_insert_seq_nls(ovec![""], ovec!["c137┃ = "], "c137")?;
assert_insert_seq_nls(ovec![""], ovec!["c137Bb┃ = "], "c137Bb")?;

View File

@ -2,10 +2,7 @@ use roc_ast::lang::core::expr::expr2::Expr2::SmallInt;
use roc_ast::lang::core::expr::expr2::IntStyle;
use roc_ast::lang::core::expr::expr2::IntVal;
use roc_ast::mem_pool::pool_str::PoolStr;
use roc_code_markup::markup::attribute::Attributes;
use roc_code_markup::markup::nodes::MarkupNode;
use roc_code_markup::slow_pool::MarkNodeId;
use roc_code_markup::syntax_highlight::HighlightStyle;
use crate::editor::ed_error::EdResult;
use crate::editor::ed_error::StringParseError;
@ -18,15 +15,14 @@ use crate::ui::text::lines::SelectableLines;
// digit_char should be verified to be a digit before calling this function
pub fn start_new_int(ed_model: &mut EdModel, digit_char: &char) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node,
parent_id_opt,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
let is_blank_node = curr_mark_node.is_blank();
let curr_mark_node_nls = curr_mark_node.get_newlines_at_end();
let int_var = ed_model.module.env.var_store.fresh();
@ -45,36 +41,10 @@ pub fn start_new_int(ed_model: &mut EdModel, digit_char: &char) -> EdResult<Inpu
.pool
.set(ast_node_id.to_expr_id()?, expr2_node);
let int_node = MarkupNode::Text {
content: digit_string,
ast_node_id,
syn_high_style: HighlightStyle::Number,
attributes: Attributes::default(),
parent_id_opt,
newlines_at_end: curr_mark_node_nls,
};
if is_blank_node {
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, int_node);
// remove data corresponding to Blank node
ed_model.del_at_line(old_caret_pos.line, old_caret_pos.column)?;
let char_len = 1;
ed_model.simple_move_carets_right(char_len);
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
&digit_char.to_string(),
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)
@ -109,16 +79,6 @@ pub fn update_int(
let content_str = int_mark_node.get_content();
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
&ch.to_string(),
int_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
// update ast
let new_pool_str = PoolStr::new(&content_str, ed_model.module.env.pool);
let int_ast_node = ed_model

View File

@ -1,12 +1,6 @@
use roc_ast::lang::core::ast::ASTNodeId;
use roc_ast::lang::core::expr::expr2::Expr2;
use roc_ast::lang::core::pattern::Pattern2;
use roc_ast::lang::core::val_def::ValueDef;
use roc_code_markup::markup::attribute::Attributes;
use roc_code_markup::markup::common_nodes::new_blank_mn_w_nls;
use roc_code_markup::markup::common_nodes::new_equals_mn;
use roc_code_markup::markup::nodes::MarkupNode;
use roc_code_markup::syntax_highlight::HighlightStyle;
use roc_module::symbol::Symbol;
use crate::editor::ed_error::EdResult;
@ -17,26 +11,21 @@ use crate::editor::mvc::ed_update::NodeContext;
pub fn start_new_let_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node,
parent_id_opt,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
let is_blank_node = curr_mark_node.is_blank();
let curr_mark_node_nls = curr_mark_node.get_newlines_at_end();
let val_name_string = new_char.to_string();
// safe unwrap because our ArrString has a 30B capacity
let val_expr2_node = Expr2::Blank;
let val_expr_id = ed_model.module.env.pool.add(val_expr2_node);
let ident_id = ed_model
.module
.env
.ident_ids
.add(val_name_string.clone().into());
let ident_id = ed_model.module.env.ident_ids.add(val_name_string.into());
let var_symbol = Symbol::new(ed_model.module.env.home, ident_id);
let body = Expr2::Var(var_symbol);
let body_id = ed_model.module.env.pool.add(body);
@ -63,50 +52,10 @@ pub fn start_new_let_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<
.pool
.set(ast_node_id.to_expr_id()?, expr2_node);
let val_name_mark_node = MarkupNode::Text {
content: val_name_string,
ast_node_id,
syn_high_style: HighlightStyle::Value,
attributes: Attributes::default(),
parent_id_opt: Some(curr_mark_node_id),
newlines_at_end: curr_mark_node_nls,
};
let val_name_mn_id = ed_model.add_mark_node(val_name_mark_node);
let equals_mn_id = ed_model.add_mark_node(new_equals_mn(ast_node_id, Some(curr_mark_node_id)));
let body_mn_id = ed_model.add_mark_node(new_blank_mn_w_nls(
ASTNodeId::AExprId(val_expr_id),
Some(curr_mark_node_id),
1,
));
let val_mark_node = MarkupNode::Nested {
ast_node_id,
children_ids: vec![val_name_mn_id, equals_mn_id, body_mn_id],
parent_id_opt,
newlines_at_end: 1,
};
if is_blank_node {
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, val_mark_node);
// remove data corresponding to Blank node
ed_model.del_blank_expr_node(old_caret_pos)?;
let char_len = 1;
ed_model.simple_move_carets_right(char_len);
// update GridNodeMap and CodeLines
ed_model.insert_all_between_line(
old_caret_pos.line,
old_caret_pos.column,
&[val_name_mn_id, equals_mn_id, body_mn_id],
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)

View File

@ -1,10 +1,7 @@
use roc_ast::lang::core::ast::{ast_node_to_string, ASTNodeId};
use roc_ast::lang::core::ast::ast_node_to_string;
use roc_ast::lang::core::expr::expr2::{Expr2, ExprId};
use roc_ast::mem_pool::pool_vec::PoolVec;
use roc_code_markup::markup::common_nodes::{
new_blank_mn, new_comma_mn, new_left_square_mn, new_right_square_mn,
};
use roc_code_markup::markup::nodes::{self, MarkupNode};
use roc_code_markup::markup::nodes::{self};
use roc_code_markup::slow_pool::MarkNodeId;
use crate::editor::ed_error::EdResult;
@ -13,19 +10,17 @@ use crate::editor::mvc::app_update::InputOutcome;
use crate::editor::mvc::ed_model::EdModel;
use crate::editor::mvc::ed_update::get_node_context;
use crate::editor::mvc::ed_update::NodeContext;
use crate::ui::text::text_pos::TextPos;
pub fn start_new_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node,
parent_id_opt,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
let is_blank_node = curr_mark_node.is_blank();
let curr_mark_node_nls = curr_mark_node.get_newlines_at_end();
let expr2_node = Expr2::List {
elem_var: ed_model.module.env.var_store.fresh(),
@ -38,51 +33,9 @@ pub fn start_new_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
.pool
.set(ast_node_id.to_expr_id()?, expr2_node);
let left_bracket_node_id = ed_model.add_mark_node(new_left_square_mn(
ast_node_id.to_expr_id()?,
Some(curr_mark_node_id),
));
let right_bracket_node_id = ed_model.add_mark_node(new_right_square_mn(
ast_node_id.to_expr_id()?,
Some(curr_mark_node_id),
));
let nested_node = MarkupNode::Nested {
ast_node_id,
children_ids: vec![left_bracket_node_id, right_bracket_node_id],
parent_id_opt,
newlines_at_end: curr_mark_node_nls,
};
if is_blank_node {
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, nested_node);
ed_model.del_blank_expr_node(old_caret_pos)?;
ed_model.simple_move_carets_right(nodes::LEFT_SQUARE_BR.len());
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
nodes::LEFT_SQUARE_BR,
left_bracket_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column + nodes::LEFT_SQUARE_BR.len(),
nodes::RIGHT_SQUARE_BR,
right_bracket_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)
@ -96,7 +49,7 @@ pub fn add_blank_child(
ed_model: &mut EdModel,
) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
old_caret_pos: _,
curr_mark_node_id,
curr_mark_node: _,
parent_id_opt,
@ -133,7 +86,7 @@ pub fn add_blank_child(
.fail()
};
let (blank_elt_id, list_ast_node_id, parent_id) = trip_result?;
let (blank_elt_id, list_ast_node_id, _parent_id) = trip_result?;
let list_ast_node = ed_model.module.env.pool.get(list_ast_node_id);
@ -164,75 +117,9 @@ pub fn add_blank_child(
.fail(),
}?;
let new_mark_children = update_mark_children(
new_child_index,
blank_elt_id,
list_ast_node_id,
old_caret_pos,
parent_id_opt,
ed_model,
)?;
let parent = ed_model.mark_node_pool.get_mut(parent_id);
for (indx, child) in new_mark_children.iter().enumerate() {
parent.add_child_at_index(new_child_index + indx, *child)?;
if new_child_index > 1 {
ed_model.simple_move_carets_right(nodes::COMMA.len());
}
Ok(InputOutcome::Accepted)
}
// add a Blank child to the Nested mark node and update the caret
pub fn update_mark_children(
new_child_index: usize,
blank_elt_id: ExprId,
list_ast_node_id: ExprId,
old_caret_pos: TextPos,
parent_id_opt: Option<MarkNodeId>,
ed_model: &mut EdModel,
) -> EdResult<Vec<MarkNodeId>> {
let blank_mark_node_id = ed_model.add_mark_node(new_blank_mn(
ASTNodeId::AExprId(blank_elt_id),
parent_id_opt,
));
let mut children: Vec<MarkNodeId> = vec![];
if new_child_index > 1 {
let comma_mark_node_id =
ed_model.add_mark_node(new_comma_mn(list_ast_node_id, parent_id_opt));
ed_model.simple_move_carets_right(nodes::COMMA.len());
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
nodes::COMMA,
comma_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
children.push(comma_mark_node_id);
}
children.push(blank_mark_node_id);
let comma_shift = if new_child_index == 1 {
0
} else {
nodes::COMMA.len()
};
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column + comma_shift,
nodes::BLANK_PLACEHOLDER,
blank_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
Ok(children)
}

View File

@ -15,7 +15,6 @@ pub fn update_invalid_lookup(
ed_model: &mut EdModel,
) -> EdResult<InputOutcome> {
if input_str.chars().all(|ch| ch.is_ascii_alphanumeric()) {
let old_caret_pos = ed_model.get_caret();
let mut new_lookup_str = String::new();
new_lookup_str.push_str(old_pool_str.as_str(ed_model.module.env.pool));
@ -35,24 +34,9 @@ pub fn update_invalid_lookup(
.pool
.set(expr_id, Expr2::InvalidLookup(new_pool_str));
// update MarkupNode
let curr_mark_node_mut = ed_model.mark_node_pool.get_mut(curr_mark_node_id);
let content_str_mut = curr_mark_node_mut.get_content_mut()?;
content_str_mut.insert_str(caret_offset, input_str);
// update caret
ed_model.simple_move_carets_right(input_str.len());
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
input_str,
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)

View File

@ -14,65 +14,32 @@ use roc_ast::lang::core::expr::record_field::RecordField;
use roc_ast::mem_pool::pool_str::PoolStr;
use roc_ast::mem_pool::pool_vec::PoolVec;
use roc_code_markup::markup::attribute::Attributes;
use roc_code_markup::markup::common_nodes::new_blank_mn;
use roc_code_markup::markup::common_nodes::new_left_accolade_mn;
use roc_code_markup::markup::common_nodes::new_right_accolade_mn;
use roc_code_markup::markup::nodes;
use roc_code_markup::markup::nodes::MarkupNode;
use roc_code_markup::markup::nodes::COLON;
use roc_code_markup::slow_pool::MarkNodeId;
use roc_code_markup::syntax_highlight::HighlightStyle;
use snafu::OptionExt;
pub fn start_new_record(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node,
parent_id_opt,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
let is_blank_node = curr_mark_node.is_blank();
let curr_mark_node_nls = curr_mark_node.get_newlines_at_end();
let ast_pool = &mut ed_model.module.env.pool;
let expr2_node = Expr2::EmptyRecord;
ast_pool.set(ast_node_id.to_expr_id()?, expr2_node);
let left_bracket_node_id = ed_model.add_mark_node(new_left_accolade_mn(
ast_node_id.to_expr_id()?,
Some(curr_mark_node_id),
));
let right_bracket_node_id = ed_model.add_mark_node(new_right_accolade_mn(
ast_node_id.to_expr_id()?,
Some(curr_mark_node_id),
));
let nested_node = MarkupNode::Nested {
ast_node_id,
children_ids: vec![left_bracket_node_id, right_bracket_node_id],
parent_id_opt,
newlines_at_end: curr_mark_node_nls,
};
if is_blank_node {
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, nested_node);
ed_model.del_blank_expr_node(old_caret_pos)?;
ed_model.simple_move_carets_right(nodes::LEFT_ACCOLADE.len());
// update GridNodeMap and CodeLines
ed_model.insert_all_between_line(
old_caret_pos.line,
old_caret_pos.column,
&[left_bracket_node_id, right_bracket_node_id],
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)
@ -156,7 +123,6 @@ pub fn update_empty_record(
new_input,
record_field_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
Ok(InputOutcome::Accepted)
@ -174,129 +140,74 @@ pub fn update_record_colon(
) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
curr_mark_node,
parent_id_opt,
curr_mark_node_id: _,
curr_mark_node: _,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
if let Some(parent_id) = parent_id_opt {
let curr_ast_node = ed_model.module.env.pool.get(ast_node_id.to_expr_id()?);
let curr_ast_node = ed_model.module.env.pool.get(ast_node_id.to_expr_id()?);
let prev_mark_node_id_opt = ed_model.get_prev_mark_node_id()?;
if let Some(prev_mark_node_id) = prev_mark_node_id_opt {
let prev_mark_node = ed_model.mark_node_pool.get(prev_mark_node_id);
let prev_mark_node_id_opt = ed_model.get_prev_mark_node_id()?;
if let Some(prev_mark_node_id) = prev_mark_node_id_opt {
let prev_mark_node = ed_model.mark_node_pool.get(prev_mark_node_id);
match prev_mark_node.get_ast_node_id() {
ASTNodeId::ADefId(_) => Ok(InputOutcome::Ignored),
ASTNodeId::AExprId(prev_expr_id) => {
let prev_expr = ed_model.module.env.pool.get(prev_expr_id);
match prev_mark_node.get_ast_node_id() {
ASTNodeId::ADefId(_) => Ok(InputOutcome::Ignored),
ASTNodeId::AExprId(prev_expr_id) => {
let prev_expr = ed_model.module.env.pool.get(prev_expr_id);
// current and prev node should always point to record when in valid position to add ':'
if matches!(prev_expr, Expr2::Record { .. })
&& matches!(curr_ast_node, Expr2::Record { .. })
{
let sibling_ids = curr_mark_node.get_sibling_ids(&ed_model.mark_node_pool);
// current and prev node should always point to record when in valid position to add ':'
if matches!(prev_expr, Expr2::Record { .. })
&& matches!(curr_ast_node, Expr2::Record { .. })
{
let ast_node_ref = ed_model.module.env.pool.get(record_ast_node_id);
let new_child_index = index_of(curr_mark_node_id, &sibling_ids)?;
match ast_node_ref {
Expr2::Record {
record_var: _,
fields,
} => {
if ed_model.node_exists_at_caret() {
let next_mark_node_id =
ed_model.grid_node_map.get_id_at_row_col(old_caret_pos)?;
let next_mark_node = ed_model.mark_node_pool.get(next_mark_node_id);
if next_mark_node.get_content() == nodes::RIGHT_ACCOLADE {
// update AST node
let new_field_val = Expr2::Blank;
let new_field_val_id =
ed_model.module.env.pool.add(new_field_val);
let ast_node_ref = ed_model.module.env.pool.get(record_ast_node_id);
let first_field_mut = fields
.iter_mut(ed_model.module.env.pool)
.next()
.with_context(|| RecordWithoutFields {})?;
match ast_node_ref {
Expr2::Record {
record_var: _,
fields,
} => {
if ed_model.node_exists_at_caret() {
let next_mark_node_id =
ed_model.grid_node_map.get_id_at_row_col(old_caret_pos)?;
let next_mark_node =
ed_model.mark_node_pool.get(next_mark_node_id);
if next_mark_node.get_content() == nodes::RIGHT_ACCOLADE {
// update AST node
let new_field_val = Expr2::Blank;
let new_field_val_id =
ed_model.module.env.pool.add(new_field_val);
*first_field_mut = RecordField::LabeledValue(
*first_field_mut.get_record_field_pool_str(),
*first_field_mut.get_record_field_var(),
new_field_val_id,
);
let first_field_mut = fields
.iter_mut(ed_model.module.env.pool)
.next()
.with_context(|| RecordWithoutFields {})?;
// update caret
ed_model.simple_move_carets_right(COLON.len());
*first_field_mut = RecordField::LabeledValue(
*first_field_mut.get_record_field_pool_str(),
*first_field_mut.get_record_field_var(),
new_field_val_id,
);
// update Markup
let record_colon = nodes::COLON;
let record_colon_node = MarkupNode::Text {
content: record_colon.to_owned(),
ast_node_id: ASTNodeId::AExprId(record_ast_node_id),
syn_high_style: HighlightStyle::Operator,
attributes: Attributes::default(),
parent_id_opt: Some(parent_id),
newlines_at_end: 0,
};
let record_colon_node_id =
ed_model.add_mark_node(record_colon_node);
ed_model
.mark_node_pool
.get_mut(parent_id)
.add_child_at_index(
new_child_index,
record_colon_node_id,
)?;
let record_blank_node_id =
ed_model.add_mark_node(new_blank_mn(
ASTNodeId::AExprId(new_field_val_id),
Some(parent_id),
));
ed_model
.mark_node_pool
.get_mut(parent_id)
.add_child_at_index(
new_child_index + 1,
record_blank_node_id,
)?;
// update caret
ed_model.simple_move_carets_right(record_colon.len());
// update GridNodeMap and CodeLines
ed_model.insert_all_between_line(
old_caret_pos.line,
old_caret_pos.column,
&[record_colon_node_id, record_blank_node_id],
)?;
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)
}
Ok(InputOutcome::Accepted)
} else {
Ok(InputOutcome::Ignored)
}
} else {
Ok(InputOutcome::Ignored)
}
_ => Ok(InputOutcome::Ignored),
}
} else {
Ok(InputOutcome::Ignored)
_ => Ok(InputOutcome::Ignored),
}
} else {
Ok(InputOutcome::Ignored)
}
}
} else {
Ok(InputOutcome::Ignored)
}
} else {
MissingParent {
node_id: curr_mark_node_id,
}
.fail()
Ok(InputOutcome::Ignored)
}
}
@ -329,16 +240,6 @@ pub fn update_record_field(
// update caret
ed_model.simple_move_carets_right(new_input.len());
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
new_input,
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
// update AST Node
let first_field = record_fields
.iter(ed_model.module.env.pool)

View File

@ -2,10 +2,6 @@ use roc_ast::lang::core::expr::expr2::ArrString;
use roc_ast::lang::core::expr::expr2::Expr2;
use roc_ast::lang::core::str::update_str_expr;
use roc_ast::mem_pool::pool_str::PoolStr;
use roc_code_markup::markup::attribute::Attributes;
use roc_code_markup::markup::nodes;
use roc_code_markup::markup::nodes::MarkupNode;
use roc_code_markup::syntax_highlight::HighlightStyle;
use crate::editor::ed_error::EdResult;
use crate::editor::mvc::app_update::InputOutcome;
@ -21,21 +17,19 @@ pub fn update_small_string(
let NodeContext {
old_caret_pos,
curr_mark_node_id,
curr_mark_node: _,
curr_mark_node,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
let new_input = &new_char.to_string();
// update markup
let curr_mark_node_mut = ed_model.mark_node_pool.get_mut(curr_mark_node_id);
let content_str_mut = curr_mark_node_mut.get_content_mut()?;
let content_str = curr_mark_node.get_content();
let node_caret_offset = ed_model
.grid_node_map
.get_offset_to_node_id(old_caret_pos, curr_mark_node_id)?;
if node_caret_offset != 0 && node_caret_offset < content_str_mut.len() {
if node_caret_offset != 0 && node_caret_offset < content_str.len() {
if old_array_str.len() < old_array_str.capacity() {
if let Expr2::SmallStr(ref mut mut_array_str) =
ed_model.module.env.pool.get_mut(ast_node_id.to_expr_id()?)
@ -58,18 +52,6 @@ pub fn update_small_string(
.set(ast_node_id.to_expr_id()?, new_ast_node);
}
content_str_mut.insert_str(node_caret_offset, new_input);
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
new_input,
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
// update caret
ed_model.simple_move_carets_right(new_input.len());
@ -83,31 +65,17 @@ pub fn update_string(new_char: char, ed_model: &mut EdModel) -> EdResult<InputOu
let NodeContext {
old_caret_pos,
curr_mark_node_id,
curr_mark_node: _,
curr_mark_node,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
// update markup
let curr_mark_node_mut = ed_model.mark_node_pool.get_mut(curr_mark_node_id);
let content_str_mut = curr_mark_node_mut.get_content_mut()?;
let content_str = curr_mark_node.get_content();
let node_caret_offset = ed_model
.grid_node_map
.get_offset_to_node_id(old_caret_pos, curr_mark_node_id)?;
if node_caret_offset != 0 && node_caret_offset < content_str_mut.len() {
content_str_mut.insert(node_caret_offset, new_char);
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
&new_char.to_string(),
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
if node_caret_offset != 0 && node_caret_offset < content_str.len() {
// update ast
update_str_expr(
ast_node_id.to_expr_id()?,
@ -127,16 +95,15 @@ pub fn update_string(new_char: char, ed_model: &mut EdModel) -> EdResult<InputOu
pub fn start_new_string(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node,
parent_id_opt,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
if curr_mark_node.is_blank() {
let new_expr2_node = Expr2::SmallStr(arrayvec::ArrayString::new());
let curr_mark_node_nls = curr_mark_node.get_newlines_at_end();
ed_model
.module
@ -144,32 +111,6 @@ pub fn start_new_string(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
.pool
.set(ast_node_id.to_expr_id()?, new_expr2_node);
let new_string_node = MarkupNode::Text {
content: nodes::STRING_QUOTES.to_owned(),
ast_node_id,
syn_high_style: HighlightStyle::String,
attributes: Attributes::default(),
parent_id_opt,
newlines_at_end: curr_mark_node_nls,
};
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, new_string_node);
// remove data corresponding to Blank node
ed_model.del_blank_expr_node(old_caret_pos)?;
// update GridNodeMap and CodeLines
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
nodes::STRING_QUOTES,
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
ed_model.simple_move_carets_right(1);
Ok(InputOutcome::Accepted)

View File

@ -1,10 +1,5 @@
use roc_ast::lang::core::{ast::ASTNodeId, def::def2::Def2, expr::expr2::Expr2};
use roc_code_markup::{
markup::{
common_nodes::new_blank_mn_w_nls, nodes::set_parent_for_all, top_level_def::tld_mark_node,
},
slow_pool::MarkNodeId,
};
use roc_ast::lang::core::{def::def2::Def2, expr::expr2::Expr2};
use roc_code_markup::slow_pool::MarkNodeId;
use crate::{
editor::ed_error::{EdResult, FailedToUpdateIdentIdName, KeyNotFound},
@ -20,19 +15,17 @@ use super::{
// Top Level Defined Value. example: `main = "Hello, World!"`
pub fn start_new_tld_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
old_caret_pos: _,
curr_mark_node_id: _,
curr_mark_node: _,
parent_id_opt: _,
ast_node_id,
} = get_node_context(ed_model)?;
// create new blank >> m = Blank
let val_expr_node = Expr2::Blank;
let val_expr_id = ed_model.module.env.pool.add(val_expr_node);
let val_expr_mn = new_blank_mn_w_nls(ASTNodeId::AExprId(val_expr_id), None, 0);
let val_expr_mn_id = ed_model.mark_node_pool.add(val_expr_mn);
let val_name_string = new_char.to_string();
let ident_id = ed_model
@ -57,14 +50,6 @@ pub fn start_new_tld_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<
.fail()?
}
let tld_mark_node = tld_mark_node(
ident_id,
val_expr_mn_id,
ast_node_id,
&mut ed_model.mark_node_pool,
&ed_model.module.env,
)?;
let new_ast_node = Def2::ValueDef {
identifier_id: ident_id,
expr_id: val_expr_id,
@ -76,31 +61,9 @@ pub fn start_new_tld_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<
.pool
.set(ast_node_id.to_def_id()?, new_ast_node);
ed_model
.mark_node_pool
.replace_node(curr_mark_node_id, tld_mark_node);
set_parent_for_all(curr_mark_node_id, &mut ed_model.mark_node_pool);
// remove data corresponding to old Blank node
ed_model.del_line(old_caret_pos.line + 1)?;
ed_model.del_line(old_caret_pos.line)?;
let char_len = 1;
ed_model.simple_move_carets_right(char_len);
let mut curr_line = old_caret_pos.line;
let mut curr_column = old_caret_pos.column;
EdModel::insert_mark_node_between_line(
&mut curr_line,
&mut curr_column,
curr_mark_node_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
&ed_model.mark_node_pool,
)?;
Ok(InputOutcome::Accepted)
}
@ -112,37 +75,28 @@ pub fn update_tld_val_name(
) -> EdResult<InputOutcome> {
if new_char.is_ascii_alphanumeric() {
// update markup
let val_name_mn_mut = ed_model.mark_node_pool.get_mut(val_name_mn_id);
let content_str_mut = val_name_mn_mut.get_content_mut()?;
let val_name_mn = ed_model.mark_node_pool.get(val_name_mn_id);
let mut val_name_str = val_name_mn.get_content();
let old_val_name = content_str_mut.clone();
let old_val_name = val_name_str.clone();
let node_caret_offset = ed_model
.grid_node_map
.get_offset_to_node_id(old_caret_pos, val_name_mn_id)?;
if node_caret_offset <= content_str_mut.len() {
content_str_mut.insert(node_caret_offset, *new_char);
if node_caret_offset <= val_name_str.len() {
val_name_str.insert(node_caret_offset, *new_char);
let update_val_name_res = ed_model
.module
.env
.ident_ids
.update_key(&old_val_name, content_str_mut);
.update_key(&old_val_name, &val_name_str);
if let Err(err_str) = update_val_name_res {
FailedToUpdateIdentIdName { err_str }.fail()?;
}
EdModel::insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
&new_char.to_string(),
val_name_mn_id,
&mut ed_model.grid_node_map,
&mut ed_model.code_lines,
)?;
ed_model.simple_move_caret_right(old_caret_pos, 1);
Ok(InputOutcome::Accepted)