create ast+markup from roc file, editor idea

This commit is contained in:
Anton-4 2021-03-15 13:16:12 +01:00
parent a0c417c3fa
commit 2cb7341888
6 changed files with 72 additions and 30 deletions

View File

@ -39,6 +39,8 @@ Nice collection of research on innovative editors, [link](https://futureofcoding
* [godbolt.org Compiler Explorer](https://godbolt.org/)
* Say you have a failing test that used to work, it would be very valuable to see all code that was changed that was used only by that test.
e.g. you have a test `calculate_sum_test` that only uses the function `add`, when the test fails you should be able to see a diff showing only what changed for the function `add`. It would also be great to have a diff of [expression values](https://homepages.cwi.nl/~storm/livelit/images/bret.png) Bret Victor style. An ambitious project would be to suggest or automatically try fixes based on these diffs.
+ [whitebox debug visualization](https://vimeo.com/483795097)
### Structured Editing

View File

@ -57,13 +57,13 @@ pub fn print_err(err: &EdError) {
}
}
// pub fn print_ui_err(err: &UIError) {
// eprintln!("{}", format!("{}", err).truecolor(255, 0, 0));
pub fn print_ui_err(err: &UIError) {
eprintln!("{}", format!("{}", err).truecolor(255, 0, 0));
// if let Some(backtrace) = ErrorCompat::backtrace(err) {
// eprintln!("{}", color_backtrace(backtrace));
// }
// }
if let Some(backtrace) = ErrorCompat::backtrace(err) {
eprintln!("{}", color_backtrace(backtrace));
}
}
fn color_backtrace(backtrace: &snafu::Backtrace) -> String {
let backtrace_str = format!("{}", backtrace);

View File

@ -1,6 +1,7 @@
use super::keyboard_input;
use super::style::CODE_TXT_XY;
use super::util::slice_get;
use crate::editor::ed_error::print_ui_err;
use crate::editor::resources::strings::NOTHING_OPENED;
use crate::editor::{
config::Config,
@ -18,6 +19,8 @@ use crate::graphics::{
};
use crate::lang::expr::Env;
use crate::lang::pool::Pool;
use crate::ui::ui_error::UIError::FileOpenFailed;
use bumpalo::collections::String as BumpString;
use bumpalo::Bump;
use cgmath::Vector2;
use pipelines::RectResources;
@ -127,7 +130,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
let mut env_pool = Pool::with_capacity(1024);
let env_arena = Bump::new();
let ast_arena = Bump::new();
let code_arena = Bump::new();
let mut var_store = VarStore::default();
let dep_idents = IdentIds::exposed_builtins(8);
@ -146,8 +149,23 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
exposed_ident_ids,
);
let ed_model_opt = if let Some(file_path) = file_path_opt {
let ed_model_res = ed_model::init_model(file_path, env, &ast_arena);
let mut code_str = BumpString::from_str_in("", &code_arena);
if let Some(file_path) = file_path_opt {
match std::fs::read_to_string(file_path) {
Ok(file_as_str) => {
code_str = BumpString::from_str_in(&file_as_str, &code_arena);
}
Err(e) => print_ui_err(&FileOpenFailed {
path_str: file_path.to_string_lossy().to_string(),
err_msg: e.to_string(),
}),
}
}
let ed_model_opt = {
let ed_model_res = ed_model::init_model(&code_str, env, &code_arena);
match ed_model_res {
Ok(mut ed_model) => {
@ -160,8 +178,6 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
None
}
}
} else {
None
};
let mut app_model = AppModel::init(ed_model_opt);

View File

@ -46,7 +46,6 @@ fn get_string<'a>(env: &Env<'a>, pool_str: &PoolStr) -> String {
}
fn new_markup(text: String, node_id: NodeId<Expr2>, highlight_style: HighlightStyle) -> MarkupNode {
// TODO use real NodeId
MarkupNode::Text {
content: text,
ast_node_id: node_id,
@ -172,3 +171,25 @@ pub fn expr2_to_markup<'a, 'b>(arena: &'a Bump, env: &mut Env<'b>, expr2: &Expr2
rest => todo!("implement expr2_to_markup for {:?}", rest),
}
}
pub fn set_caret_at_start(markup_node: &mut MarkupNode) {
match markup_node {
MarkupNode::Nested {
ast_node_id: _,
children,
} => {
if let Some(child) = children.first_mut() { set_caret_at_start(child) }
}
MarkupNode::Text {
content: _,
ast_node_id: _,
syn_high_style: _,
attributes,
} => attributes.push(Attribute::Caret { offset_col: 0 }),
MarkupNode::Hole {
ast_node_id: _,
attributes,
syn_high_style: _,
} => attributes.push(Attribute::Caret { offset_col: 0 }),
};
}

View File

@ -1,16 +1,17 @@
use crate::editor::ed_error::EdError::ParseError;
use crate::editor::ed_error::EdResult;
use crate::editor::markup::{Attribute, MarkupNode};
use crate::editor::markup::{expr2_to_markup, set_caret_at_start, Attribute, MarkupNode};
use crate::editor::syntax_highlight::HighlightStyle;
use crate::graphics::primitives::rect::Rect;
use crate::lang::ast::Expr2;
use crate::lang::expr::{str_to_expr2, Env};
use bumpalo::collections::String as BumpString;
use bumpalo::Bump;
use std::path::Path;
#[derive(Debug)]
pub struct EdModel<'a> {
pub module: EdModule<'a>,
pub code_as_str: &'a str,
pub markup_root: MarkupNode,
pub glyph_dim_rect_opt: Option<Rect>,
pub has_focus: bool,
@ -18,21 +19,29 @@ pub struct EdModel<'a> {
}
pub fn init_model<'a>(
_file_path: &Path,
code_str: &'a BumpString,
env: Env<'a>,
ast_arena: &'a Bump,
code_arena: &'a Bump,
) -> EdResult<EdModel<'a>> {
let module = EdModule::new(None, env, ast_arena)?;
let mut module = EdModule::new(&code_str, env, code_arena)?;
// TODO fix moving issue and insert module.ast_root into pool
let ast_root_id = module.env.pool.add(Expr2::Hole);
let markup_root = MarkupNode::Hole {
ast_node_id: ast_root_id,
attributes: vec![Attribute::Caret { offset_col: 0 }],
syn_high_style: HighlightStyle::Hole,
let markup_root = if code_str.is_empty() {
MarkupNode::Hole {
ast_node_id: ast_root_id,
attributes: vec![Attribute::Caret { offset_col: 0 }],
syn_high_style: HighlightStyle::Hole,
}
} else {
let mut temp_markup_root = expr2_to_markup(code_arena, &mut module.env, &module.ast_root);
set_caret_at_start(&mut temp_markup_root);
temp_markup_root
};
Ok(EdModel {
module,
code_as_str: code_str,
markup_root,
glyph_dim_rect_opt: None,
has_focus: true,
@ -47,13 +56,9 @@ pub struct EdModule<'a> {
}
impl<'a> EdModule<'a> {
pub fn new(
code_str_opt: Option<&'a str>,
mut env: Env<'a>,
ast_arena: &'a Bump,
) -> EdResult<EdModule<'a>> {
if let Some(code_str) = code_str_opt {
let expr2_result = str_to_expr2(&ast_arena, code_str, &mut env);
pub fn new(code_str: &'a str, mut env: Env<'a>, ast_arena: &'a Bump) -> EdResult<EdModule<'a>> {
if !code_str.is_empty() {
let expr2_result = str_to_expr2(&ast_arena, &code_str, &mut env);
match expr2_result {
Ok((expr2, _output)) => Ok(EdModule {

View File

@ -41,7 +41,6 @@ struct CodeStyle<'a> {
glyph_dim_rect: Rect,
}
// TODO return Rectangles for Box, caret, selection here as well
fn markup_to_wgpu<'a>(
markup_node: &'a MarkupNode,
code_style: &CodeStyle,
@ -94,7 +93,6 @@ fn draw_attributes(
}
// TODO use text_row
// TODO use attributes to render caret
fn markup_to_wgpu_helper<'a>(
markup_node: &'a MarkupNode,
wgpu_texts: &mut Vec<wgpu_glyph::Text<'a>>,