From 68147e770330c34de2018349c6be6ecfb7e68b07 Mon Sep 17 00:00:00 2001 From: Chadtech Date: Mon, 9 Aug 2021 20:21:03 -0400 Subject: [PATCH 1/9] docs Syntax highlight function set up, and test set up for syntax highlighting --- docs/src/lib.rs | 49 +++++++++++- docs/tests/insert_syntax_highlighting.rs | 97 ++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 docs/tests/insert_syntax_highlighting.rs diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 6ed02513c0..5d50d11476 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -14,6 +14,7 @@ use roc_collections::all::MutMap; use roc_load::docs::DocEntry::DocDef; use roc_region::all::Region; use std::path::{Path, PathBuf}; +use std::str::Split; pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { let files_docs = files_to_documentations(filenames, std_lib); @@ -75,7 +76,7 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { fs::create_dir_all(&module_dir) .expect("TODO gracefully handle not being able to create the module dir"); - let rendered_module = template_html + let mut rendered_module = template_html .replace( "", render_name_and_version(package.name.as_str(), package.version.as_str()) @@ -86,14 +87,56 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { render_main_content(&loaded_module.interns, &exports, module).as_str(), ); - fs::write(module_dir.join("index.html"), rendered_module) - .expect("TODO gracefully handle failing to write html"); + fs::write( + module_dir.join("index.html"), + syntax_highlight_code(rendered_module), + ) + .expect("TODO gracefully handle failing to write html"); } } println!("🎉 Docs generated in {}", build_dir.display()); } +pub fn syntax_highlight_code(mut html: String) -> String { + let mut result = html.clone(); + + if let Some(start_index) = html.find("") { + let (before_open_tag, after_open_tag_str) = html.split_at(start_index); + + let mut after_open_tag = after_open_tag_str.to_string(); + drop_letters(&mut after_open_tag, 6); + + if let Some(end_index) = after_open_tag.find("") { + let (code_str, after_close_tag_str) = after_open_tag.split_at(end_index); + + // TODO change code html + let new_code_string = code_str.to_string(); + + result = [ + before_open_tag, + "", + new_code_string.as_str(), + after_close_tag_str, + ] + .concat() + } + } + + result +} + +fn drop_letters(s: &mut String, pos: usize) { + match s.char_indices().nth(pos) { + Some((pos, _)) => { + s.drain(..pos); + } + None => { + s.clear(); + } + } +} + fn render_main_content( interns: &Interns, exposed_values: &[String], diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs new file mode 100644 index 0000000000..c4e95b4744 --- /dev/null +++ b/docs/tests/insert_syntax_highlighting.rs @@ -0,0 +1,97 @@ +#[macro_use] +extern crate pretty_assertions; + +#[cfg(test)] +mod insert_doc_syntax_highlighting { + use roc_can::env::Env; + use roc_can::scope::Scope; + use roc_collections::all::MutMap; + use roc_docs::{insert_doc_links, syntax_highlight_code}; + use roc_module::symbol::{IdentIds, Interns, ModuleIds}; + use roc_types::subs::VarStore; + + #[test] + fn simple_code_block() { + // let home = ModuleIds::default().get_or_insert(&"Test".into()); + // + // let module_ids = ModuleIds::default(); + // + // let dep_idents = IdentIds::exposed_builtins(0); + // + // let env = Env::new(home, dep_idents, &module_ids, IdentIds::default()); + // + // let all_ident_ids = MutMap::default(); + // + // let interns = Interns { + // module_ids: env.module_ids.clone(), + // all_ident_ids, + // }; + // + // let var_store = &mut VarStore::default(); + // let scope = &mut Scope::new(home, var_store); + // + // let markdown = r#" + // # Hello + // Hello thanks for using my package + // "#; + + let html = r#" + + + x : Nat + x = + 4 + + + "# + .to_string(); + + let expectation = r#" + + + x : Nat + x = + 4 + + + "# + .to_string(); + + assert_eq!(syntax_highlight_code(html.clone()), expectation); + } + + #[test] + fn no_code_blocks() { + // let home = ModuleIds::default().get_or_insert(&"Test".into()); + // + // let module_ids = ModuleIds::default(); + // + // let dep_idents = IdentIds::exposed_builtins(0); + // + // let env = Env::new(home, dep_idents, &module_ids, IdentIds::default()); + // + // let all_ident_ids = MutMap::default(); + // + // let interns = Interns { + // module_ids: env.module_ids.clone(), + // all_ident_ids, + // }; + // + // let var_store = &mut VarStore::default(); + // let scope = &mut Scope::new(home, var_store); + // + // let markdown = r#" + // # Hello + // Hello thanks for using my package + // "#; + + let html = r#" + +

Hello

+ + "# + .to_string(); + + assert_eq!(html, syntax_highlight_code(html.clone()),); + } +} From 9e12f6d3ec6849967630d321014e5f5387b1412b Mon Sep 17 00:00:00 2001 From: Chadtech Date: Sun, 22 Aug 2021 15:53:26 -0400 Subject: [PATCH 2/9] ToHtml trait for docs and some rudimentary syntax highlighting that is definitely a work in progress --- Cargo.lock | 1 + docs/Cargo.toml | 1 + docs/src/comment_or_new_line.rs | 29 +++++ docs/src/def.rs | 57 ++++++++ docs/src/expr.rs | 157 +++++++++++++++++++++++ docs/src/html.rs | 43 +++++++ docs/src/lib.rs | 99 ++++++++------ docs/src/pattern.rs | 52 ++++++++ docs/src/static/styles.css | 25 +++- docs/tests/insert_syntax_highlighting.rs | 133 ++++++++----------- www/public/styles.css | 9 +- 11 files changed, 472 insertions(+), 134 deletions(-) create mode 100644 docs/src/comment_or_new_line.rs create mode 100644 docs/src/def.rs create mode 100644 docs/src/expr.rs create mode 100644 docs/src/html.rs create mode 100644 docs/src/pattern.rs diff --git a/Cargo.lock b/Cargo.lock index 4c7a553e59..a9967b45c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3146,6 +3146,7 @@ dependencies = [ "roc_builtins", "roc_can", "roc_collections", + "roc_fmt", "roc_load", "roc_module", "roc_parse", diff --git a/docs/Cargo.toml b/docs/Cargo.toml index 7cb857b8f3..c0f7416516 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -12,6 +12,7 @@ pulldown-cmark = { version = "0.8", default-features = false } roc_load = { path = "../compiler/load" } roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } +roc_fmt = { path = "../compiler/fmt" } roc_module = { path = "../compiler/module" } roc_region = { path = "../compiler/region" } roc_types = { path = "../compiler/types" } diff --git a/docs/src/comment_or_new_line.rs b/docs/src/comment_or_new_line.rs new file mode 100644 index 0000000000..811a879fb2 --- /dev/null +++ b/docs/src/comment_or_new_line.rs @@ -0,0 +1,29 @@ +use crate::html::ToHtml; +use roc_parse::ast::CommentOrNewline; + +impl<'a> ToHtml<'a> for CommentOrNewline<'a> { + fn css_class(&self) -> Option<&'a str> { + match self { + CommentOrNewline::Newline => None, + CommentOrNewline::LineComment(_) => Some("comment"), + CommentOrNewline::DocComment(_) => Some("comment"), + } + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + match self { + CommentOrNewline::Newline => { + buf.push('\n'); + } + CommentOrNewline::LineComment(comment) => { + buf.push('#'); + buf.push_str(comment); + buf.push('\n'); + } + CommentOrNewline::DocComment(comment) => { + buf.push_str("##"); + buf.push_str(comment); + buf.push('\n'); + } + } + } +} diff --git a/docs/src/def.rs b/docs/src/def.rs new file mode 100644 index 0000000000..6b9a0cee11 --- /dev/null +++ b/docs/src/def.rs @@ -0,0 +1,57 @@ +use crate::html::ToHtml; +use roc_parse::ast::Def; + +impl<'a> ToHtml<'a> for Def<'a> { + fn css_class(&self) -> Option<&'a str> { + match self { + // Def::Annotation(_, _) => {} + // Def::Alias { .. } => {} + Def::Body(_, _) => None, + // Def::AnnotatedBody { .. } => {} + // Def::Expect(_) => {} + Def::SpaceBefore(_, _) => None, + Def::SpaceAfter(_, _) => None, + // Def::NotYetImplemented(_) => {} + _ => None, + } + } + + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + match self { + // Def::Annotation(_, _) => {} + // Def::Alias { .. } => {} + Def::Body(pattern, expr) => { + pattern.html(buf); + EqualSign.html(buf); + expr.html(buf); + } + // Def::AnnotatedBody { .. } => {} + // Def::Expect(_) => {} + Def::SpaceBefore(sub_def, spaces) => { + for space in spaces.iter() { + space.html(buf); + } + sub_def.html(buf); + } + Def::SpaceAfter(sub_def, spaces) => { + sub_def.html(buf); + for space in spaces.iter() { + space.html(buf); + } + } + // Def::NotYetImplemented(_) => {} + _ => {} + } + } +} + +struct EqualSign; + +impl<'a> ToHtml<'a> for EqualSign { + fn css_class(&self) -> Option<&'a str> { + Some("operator") + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + buf.push_str(" = ") + } +} diff --git a/docs/src/expr.rs b/docs/src/expr.rs new file mode 100644 index 0000000000..bcb7832cb9 --- /dev/null +++ b/docs/src/expr.rs @@ -0,0 +1,157 @@ +use crate::html::ToHtml; +use roc_parse::ast::{CommentOrNewline, Expr, StrLiteral, StrSegment}; +use roc_region::all::Located; + +impl<'a> ToHtml<'a> for Expr<'a> { + fn css_class(&self) -> Option<&'a str> { + match self { + Expr::Float(_) | Expr::Num(_) | Expr::NonBase10Int { .. } => Some("num"), + Expr::Str(_) => Some("str"), + // Expr::Access(_, _) => {} + // Expr::AccessorFunction(_) => {} + // Expr::List { .. } => {} + // Expr::RecordUpdate { .. } => {} + // Expr::Record { .. } => {} + Expr::Var { .. } => None, + // Expr::Underscore(_) => {} + // Expr::GlobalTag(_) => {} + // Expr::PrivateTag(_) => {} + Expr::Closure(_, _) => None, + + // Expr::Defs(_, _) => {} + // Expr::Backpassing(_, _, _) => {} + // Expr::Expect(_, _) => {} + // Expr::Apply(_, _, _) => {} + // Expr::BinOps(_, _) => {} + // Expr::UnaryOp(_, _) => {} + // Expr::If(_, _) => {} + // Expr::When(_, _) => {} + Expr::SpaceBefore(_, _) => None, + Expr::SpaceAfter(_, _) => None, + // Expr::ParensAround(_) => {} + // Expr::MalformedIdent(_, _) => {} + // Expr::MalformedClosure => {} + // Expr::PrecedenceConflict(_) => {} + _ => None, + } + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + match self { + Expr::Float(str) => { + buf.push_str(str); + } + Expr::Num(str) => { + buf.push_str(str); + } + Expr::NonBase10Int { string, .. } => { + buf.push_str(string); + } + Expr::Str(str_literal) => match str_literal { + StrLiteral::PlainLine(str) => { + buf.push('"'); + buf.push_str(str); + buf.push('"'); + } + StrLiteral::Line(line) => { + panic!("TODO str segments"); + } + StrLiteral::Block(str) => { + panic!("TODO str segments"); + } + }, + // Expr::Access(_, _) => {} + // Expr::AccessorFunction(_) => {} + // Expr::List { .. } => {} + // Expr::RecordUpdate { .. } => {} + // Expr::Record { .. } => {} + Expr::Var { ident, module_name } => { + if !module_name.is_empty() { + buf.push_str(module_name); + buf.push('.'); + } + buf.push_str(ident); + } + // Expr::Underscore(_) => {} + // Expr::GlobalTag(_) => {} + // Expr::PrivateTag(_) => {} + Expr::Closure(patterns, loc_sub_expr) => { + ClosureDash.html(buf); + + let mut patterns_iter = patterns.iter().peekable(); + + while let Some(pattern) = patterns_iter.next() { + pattern.value.html(buf); + if let Some(_) = patterns_iter.peek() { + ParamComma.html(buf); + } + } + + ClosureArrow.html(buf); + loc_sub_expr.html(buf); + } + Expr::Defs(defs, sub_expr) => { + for def_loc in defs.iter() { + def_loc.html(buf); + } + sub_expr.html(buf) + } + // Expr::Backpassing(_, _, _) => {} + // Expr::Expect(_, _) => {} + // Expr::Apply(_, _, _) => {} + // Expr::BinOps(_, _) => {} + // Expr::UnaryOp(_, _) => {} + // Expr::If(_, _) => {} + // Expr::When(_, _) => {} + Expr::SpaceBefore(sub_expr, spaces) => { + for space in spaces.iter() { + space.html(buf); + } + sub_expr.html(buf); + } + Expr::SpaceAfter(sub_expr, spaces) => { + sub_expr.html(buf); + for space in spaces.iter() { + space.html(buf); + } + } + // Expr::ParensAround(_) => {} + // Expr::MalformedIdent(_, _) => {} + // Expr::MalformedClosure => {} + // Expr::PrecedenceConflict(_) => {} + _ => {} + } + } +} + +struct ClosureDash; + +impl<'a> ToHtml<'a> for ClosureDash { + fn css_class(&self) -> Option<&'a str> { + Some("closure-dash") + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + buf.push('\\') + } +} + +struct ClosureArrow; + +impl<'a> ToHtml<'a> for ClosureArrow { + fn css_class(&self) -> Option<&'a str> { + Some("closure-arrow") + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + buf.push_str(" ->") + } +} + +struct ParamComma; + +impl<'a> ToHtml<'a> for ParamComma { + fn css_class(&self) -> Option<&'a str> { + Some("param-comma") + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + buf.push_str(", ") + } +} diff --git a/docs/src/html.rs b/docs/src/html.rs new file mode 100644 index 0000000000..57061f2203 --- /dev/null +++ b/docs/src/html.rs @@ -0,0 +1,43 @@ +use roc_region::all::Located; + +pub trait ToHtml<'a> { + fn css_class(&self) -> Option<&'a str>; + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>); + fn html(&self, buf: &mut bumpalo::collections::String<'a>) { + let maybe_css_class = self.css_class(); + + if let Some(css_class) = maybe_css_class { + let opening_tag: String = [""].concat(); + + buf.push_str(opening_tag.as_str()); + } + + self.html_body(buf); + + if let Some(_) = maybe_css_class { + buf.push_str(""); + } + } +} + +impl<'a, T> ToHtml<'a> for Located +where + T: ToHtml<'a>, +{ + fn css_class(&self) -> Option<&'a str> { + None + } + + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + let start_col = self.region.start_col as usize; + + let last_newline_to_end = buf.len() - buf.rfind("\n").unwrap_or_else(|| buf.len()); + + if start_col > last_newline_to_end { + let new_spaces = start_col - last_newline_to_end; + buf.push_str((0..new_spaces).map(|_| " ").collect::().as_str()); + }; + + self.value.html(buf); + } +} diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 45a4d319f5..eb2c44379c 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -1,5 +1,6 @@ extern crate pulldown_cmark; extern crate roc_load; +use crate::html::ToHtml; use bumpalo::Bump; use roc_builtins::std::StdLib; use roc_can::builtins::builtin_defs_map; @@ -11,11 +12,16 @@ use roc_load::docs::{ModuleDocumentation, RecordField}; use roc_load::file::{LoadedModule, LoadingProblem}; use roc_module::symbol::{IdentIds, Interns, ModuleId}; use roc_parse::ident::{parse_ident, Ident}; -use roc_parse::parser::State; +use roc_parse::parser::{State, SyntaxError}; use roc_region::all::Region; use std::fs; use std::path::{Path, PathBuf}; -use std::str::Split; + +mod comment_or_new_line; +mod def; +mod expr; +mod html; +mod pattern; pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { let files_docs = files_to_documentations(filenames, std_lib); @@ -96,7 +102,7 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { fs::create_dir_all(&module_dir) .expect("TODO gracefully handle not being able to create the module dir"); - let mut rendered_module = template_html + let rendered_module = template_html .replace( "", render_name_and_version(package.name.as_str(), package.version.as_str()) @@ -114,54 +120,34 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { .as_str(), ); - fs::write( - module_dir.join("index.html"), - syntax_highlight_code(rendered_module), - ) - .expect("TODO gracefully handle failing to write html"); + fs::write(module_dir.join("index.html"), rendered_module) + .expect("TODO gracefully handle failing to write html"); } } println!("🎉 Docs generated in {}", build_dir.display()); } -pub fn syntax_highlight_code(mut html: String) -> String { - let mut result = html.clone(); +pub fn syntax_highlight_code<'a>( + arena: &'a Bump, + buf: &mut bumpalo::collections::String<'a>, + code_str: &'a str, +) -> Result> { + let trimmed_code_str = code_str.trim_end().trim(); + let state = State::new(trimmed_code_str.as_bytes()); - if let Some(start_index) = html.find("") { - let (before_open_tag, after_open_tag_str) = html.split_at(start_index); - - let mut after_open_tag = after_open_tag_str.to_string(); - drop_letters(&mut after_open_tag, 6); - - if let Some(end_index) = after_open_tag.find("") { - let (code_str, after_close_tag_str) = after_open_tag.split_at(end_index); - - // TODO change code html - let new_code_string = code_str.to_string(); - - result = [ - before_open_tag, - "", - new_code_string.as_str(), - after_close_tag_str, - ] - .concat() - } - } - - result -} - -fn drop_letters(s: &mut String, pos: usize) { - match s.char_indices().nth(pos) { - Some((pos, _)) => { - s.drain(..pos); - } - None => { - s.clear(); + match roc_parse::expr::test_parse_expr(0, arena, state) { + Ok(loc_expr) => { + loc_expr.value.html(buf); + Ok(buf.to_string()) } + Err(fail) => Err(SyntaxError::Expr(fail)), } + // roc_parse::test_helpers::parse_expr_with(&arena, trimmed_code_str).map(|expr| { + // expr.html(buf); + // + // buf.to_string() + // }) } fn render_main_content( @@ -886,6 +872,9 @@ fn markdown_to_html( }; let markdown_options = pulldown_cmark::Options::empty(); + + let mut expecting_code_block = false; + let mut docs_parser = vec![]; let (_, _) = pulldown_cmark::Parser::new_with_broken_link_callback( &markdown, @@ -893,6 +882,7 @@ fn markdown_to_html( Some(&mut broken_link_callback), ) .fold((0, 0), |(start_quote_count, end_quote_count), event| { + match &event { // Replace this sequence (`>>>` syntax): // Start(BlockQuote) @@ -958,6 +948,31 @@ fn markdown_to_html( (start_quote_count, end_quote_count) } + Event::Start(CodeBlock(CodeBlockKind::Fenced(_))) => { + expecting_code_block = true; + docs_parser.push(event); + (0, 0) + } + Event::End(CodeBlock(_)) => { + expecting_code_block = false; + docs_parser.push(event); + (0, 0) + } + Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => { + let code_block_arena = Bump::new(); + + let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena); + match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) { + Ok(highlighted_code_str) => { + docs_parser.push(Event::Html(CowStr::from(highlighted_code_str))); + } + Err(syntax_error) => { + panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) + } + }; + + (0, 0) + } _ => { docs_parser.push(event); (0, 0) diff --git a/docs/src/pattern.rs b/docs/src/pattern.rs new file mode 100644 index 0000000000..094aee8f8c --- /dev/null +++ b/docs/src/pattern.rs @@ -0,0 +1,52 @@ +use crate::html::ToHtml; +use roc_parse::ast::Pattern; + +impl<'a> ToHtml<'a> for Pattern<'a> { + fn css_class(&self) -> Option<&'a str> { + match self { + // Pattern::Identifier(_) => {} + // Pattern::GlobalTag(_) => {} + // Pattern::PrivateTag(_) => {} + // Pattern::Apply(_, _) => {} + // Pattern::RecordDestructure(_) => {} + // Pattern::RequiredField(_, _) => {} + // Pattern::OptionalField(_, _) => {} + // Pattern::NumLiteral(_) => {} + // Pattern::NonBase10Literal { .. } => {} + // Pattern::FloatLiteral(_) => {} + // Pattern::StrLiteral(_) => {} + // Pattern::Underscore(_) => {} + // Pattern::SpaceBefore(_, _) => {} + // Pattern::SpaceAfter(_, _) => {} + // Pattern::Malformed(_) => {} + // Pattern::MalformedIdent(_, _) => {} + // Pattern::QualifiedIdentifier { .. } => {} + _ => None, + } + } + + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + match self { + Pattern::Identifier(str) => { + buf.push_str(str); + } + // Pattern::GlobalTag(_) => {} + // Pattern::PrivateTag(_) => {} + // Pattern::Apply(_, _) => {} + // Pattern::RecordDestructure(_) => {} + // Pattern::RequiredField(_, _) => {} + // Pattern::OptionalField(_, _) => {} + // Pattern::NumLiteral(_) => {} + // Pattern::NonBase10Literal { .. } => {} + // Pattern::FloatLiteral(_) => {} + // Pattern::StrLiteral(_) => {} + // Pattern::Underscore(_) => {} + // Pattern::SpaceBefore(_, _) => {} + // Pattern::SpaceAfter(_, _) => {} + // Pattern::Malformed(_) => {} + // Pattern::MalformedIdent(_, _) => {} + // Pattern::QualifiedIdentifier { .. } => {} + _ => {} + } + } +} diff --git a/docs/src/static/styles.css b/docs/src/static/styles.css index e78db71ea6..94dc026ca1 100644 --- a/docs/src/static/styles.css +++ b/docs/src/static/styles.css @@ -283,7 +283,6 @@ code { font-family: var(--font-mono); color: var(--code-color); background-color: var(--code-bg-color); - padding: 2px 8px; display: inline-block; } @@ -306,15 +305,31 @@ pre { overflow-x: auto; } -pre code { - padding: 6px 8px; -} - .hidden { /* Use !important to win all specificity fights. */ display: none !important; } +.syntax-num { + color: #8080ff; +} + +.syntax-closure-dash, +.syntax-closure-arrow, +.syntax-operator , +.syntax-param-comma +{ + color: #ff0000; +} + +.syntax-str { + color:#ffff00; +} + +.syntax-comment { + color: #ff0000; +} + #module-search:placeholder-shown { padding: 0; opacity: 0; diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs index c4e95b4744..a9a5e6cabb 100644 --- a/docs/tests/insert_syntax_highlighting.rs +++ b/docs/tests/insert_syntax_highlighting.rs @@ -3,95 +3,64 @@ extern crate pretty_assertions; #[cfg(test)] mod insert_doc_syntax_highlighting { + use bumpalo::Bump; use roc_can::env::Env; use roc_can::scope::Scope; use roc_collections::all::MutMap; - use roc_docs::{insert_doc_links, syntax_highlight_code}; + use roc_docs::syntax_highlight_code; use roc_module::symbol::{IdentIds, Interns, ModuleIds}; use roc_types::subs::VarStore; + fn expect_html(code_str: &str, want: &str) { + let code_block_arena = Bump::new(); + + let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena); + match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) { + Ok(highlighted_code_str) => { + assert_eq!(highlighted_code_str, want); + } + Err(syntax_error) => { + panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) + } + }; + } + #[test] fn simple_code_block() { - // let home = ModuleIds::default().get_or_insert(&"Test".into()); - // - // let module_ids = ModuleIds::default(); - // - // let dep_idents = IdentIds::exposed_builtins(0); - // - // let env = Env::new(home, dep_idents, &module_ids, IdentIds::default()); - // - // let all_ident_ids = MutMap::default(); - // - // let interns = Interns { - // module_ids: env.module_ids.clone(), - // all_ident_ids, - // }; - // - // let var_store = &mut VarStore::default(); - // let scope = &mut Scope::new(home, var_store); - // - // let markdown = r#" - // # Hello - // Hello thanks for using my package - // "#; - - let html = r#" - - - x : Nat - x = - 4 - - - "# - .to_string(); - - let expectation = r#" - - - x : Nat - x = - 4 - - - "# - .to_string(); - - assert_eq!(syntax_highlight_code(html.clone()), expectation); - } - - #[test] - fn no_code_blocks() { - // let home = ModuleIds::default().get_or_insert(&"Test".into()); - // - // let module_ids = ModuleIds::default(); - // - // let dep_idents = IdentIds::exposed_builtins(0); - // - // let env = Env::new(home, dep_idents, &module_ids, IdentIds::default()); - // - // let all_ident_ids = MutMap::default(); - // - // let interns = Interns { - // module_ids: env.module_ids.clone(), - // all_ident_ids, - // }; - // - // let var_store = &mut VarStore::default(); - // let scope = &mut Scope::new(home, var_store); - // - // let markdown = r#" - // # Hello - // Hello thanks for using my package - // "#; - - let html = r#" - -

Hello

- - "# - .to_string(); - - assert_eq!(html, syntax_highlight_code(html.clone()),); + expect_html( + r#" + f = \x, y -> + b = 6 + c + + "string" + "#, + r#" +
x
:
Nat
+
x
=
+
4
+ +
2
+ "#, + ); } + // #[test] + // fn simple_code_block() { + // expect_html( + // r#" + // x : Nat + // x = + // 4 + // + // 2 + // "#, + // r#" + //
x
:
Nat
+ //
x
=
+ //
4
+ // + //
2
+ // "#, + // ); + // } } diff --git a/www/public/styles.css b/www/public/styles.css index b90cfb58a2..3d1a47ec35 100644 --- a/www/public/styles.css +++ b/www/public/styles.css @@ -282,7 +282,6 @@ code { font-family: var(--font-mono); color: var(--code-color); background-color: var(--code-bg-color); - padding: 0 8px; display: inline-block; line-height: 28px; } @@ -303,15 +302,15 @@ pre { overflow-x: auto; } -pre code { - padding: 6px 8px; -} - .hidden { /* Use !important to win all specificity fights. */ display: none !important; } +.syntax-comment { + color: #ff0000; +} + #module-search:placeholder-shown { padding: 0; opacity: 0; From 28cf11a1d90d9fd6ca620de9ea906e368c7d13bc Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 29 Sep 2021 20:05:03 +0200 Subject: [PATCH 3/9] started on docs to markup to html --- Cargo.lock | 2 ++ ast/src/canonicalization/canonicalize.rs | 8 ++--- ast/src/lang/core/def/def.rs | 6 ++-- ast/src/lang/core/def/def_to_def2.rs | 8 ++--- ast/src/lang/core/expr/expr_to_expr2.rs | 24 ++++++------- ast/src/lang/core/expr/mod.rs | 2 +- ast/src/lang/core/str.rs | 4 +-- code_markup/src/markup/nodes.rs | 6 ++-- docs/Cargo.toml | 2 ++ docs/src/def.rs | 43 +++--------------------- docs/src/expr.rs | 40 ++++++++++++++++++++-- 11 files changed, 75 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bc8f34f5d..e3520f0753 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3582,8 +3582,10 @@ dependencies = [ "maplit", "pretty_assertions 0.5.1", "pulldown-cmark", + "roc_ast", "roc_builtins", "roc_can", + "roc_code_markup", "roc_collections", "roc_fmt", "roc_load", diff --git a/ast/src/canonicalization/canonicalize.rs b/ast/src/canonicalization/canonicalize.rs index 211e22cf97..f6a8d00b5c 100644 --- a/ast/src/canonicalization/canonicalize.rs +++ b/ast/src/canonicalization/canonicalize.rs @@ -9,7 +9,7 @@ use crate::{ def::def::References, expr::{ expr2::{Expr2, ExprId, WhenBranch}, - expr_to_expr2::to_expr2, + expr_to_expr2::expr_to_expr2, output::Output, record_field::RecordField, }, @@ -147,7 +147,7 @@ fn canonicalize_field<'a>( // Both a label and a value, e.g. `{ name: "blah" }` RequiredValue(label, _, loc_expr) => { let field_var = env.var_store.fresh(); - let (loc_can_expr, output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region); + let (loc_can_expr, output) = expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); Ok(CanonicalField::LabelAndValue { label: label.value, @@ -211,7 +211,7 @@ pub(crate) fn canonicalize_when_branch<'a>( } let (value, mut branch_output) = - to_expr2(env, &mut scope, &branch.value.value, branch.value.region); + expr_to_expr2(env, &mut scope, &branch.value.value, branch.value.region); let value_id = env.pool.add(value); env.set_region(value_id, branch.value.region); @@ -219,7 +219,7 @@ pub(crate) fn canonicalize_when_branch<'a>( None => None, Some(loc_expr) => { let (can_guard, guard_branch_output) = - to_expr2(env, &mut scope, &loc_expr.value, loc_expr.region); + expr_to_expr2(env, &mut scope, &loc_expr.value, loc_expr.region); let expr_id = env.pool.add(can_guard); env.set_region(expr_id, loc_expr.region); diff --git a/ast/src/lang/core/def/def.rs b/ast/src/lang/core/def/def.rs index c8654b3d73..9584175493 100644 --- a/ast/src/lang/core/def/def.rs +++ b/ast/src/lang/core/def/def.rs @@ -27,7 +27,7 @@ use ven_graph::{strongly_connected_components, topological_sort_into_groups}; use crate::{ lang::{ core::{ - expr::{expr2::Expr2, expr_to_expr2::to_expr2, output::Output}, + expr::{expr2::Expr2, expr_to_expr2::expr_to_expr2, output::Output}, fun_def::FunctionDef, pattern::{self, symbols_from_pattern, to_pattern_id, Pattern2, PatternId}, types::{to_annotation2, Alias, Annotation2, Signature, Type2, TypeId}, @@ -472,7 +472,7 @@ fn canonicalize_pending_def<'a>( }; let (loc_can_expr, can_output) = - to_expr2(env, scope, &loc_expr.value, loc_expr.region); + expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); output.references.union_mut(can_output.references.clone()); @@ -639,7 +639,7 @@ fn canonicalize_pending_def<'a>( env.closure_name_symbol = Some(*defined_symbol); }; - let (loc_can_expr, can_output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region); + let (loc_can_expr, can_output) = expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); output.references.union_mut(can_output.references.clone()); diff --git a/ast/src/lang/core/def/def_to_def2.rs b/ast/src/lang/core/def/def_to_def2.rs index 05cf2747a6..ff659b4310 100644 --- a/ast/src/lang/core/def/def_to_def2.rs +++ b/ast/src/lang/core/def/def_to_def2.rs @@ -20,11 +20,11 @@ pub fn defs_to_defs2<'a>( ) -> Vec { parsed_defs .iter() - .map(|loc| to_def2_from_def(arena, env, scope, &loc.value, region)) + .map(|loc| def_to_def2(arena, env, scope, &loc.value, region)) .collect() } -pub fn to_def2_from_def<'a>( +pub fn def_to_def2<'a>( arena: &'a Bump, env: &mut Env<'a>, scope: &mut Scope, @@ -34,8 +34,8 @@ pub fn to_def2_from_def<'a>( use roc_parse::ast::Def::*; match parsed_def { - SpaceBefore(inner_def, _) => to_def2_from_def(arena, env, scope, inner_def, region), - SpaceAfter(inner_def, _) => to_def2_from_def(arena, env, scope, inner_def, region), + SpaceBefore(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region), + SpaceAfter(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region), Body(&loc_pattern, &loc_expr) => { // TODO loc_pattern use identifier let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0; diff --git a/ast/src/lang/core/expr/expr_to_expr2.rs b/ast/src/lang/core/expr/expr_to_expr2.rs index febad6b13a..9e96fac7e5 100644 --- a/ast/src/lang/core/expr/expr_to_expr2.rs +++ b/ast/src/lang/core/expr/expr_to_expr2.rs @@ -36,12 +36,12 @@ pub fn loc_expr_to_expr2<'a>( ) -> (Expr2, Output) { let desugared_loc_expr = desugar_expr(arena, arena.alloc(loc_expr)); - to_expr2(env, scope, arena.alloc(desugared_loc_expr.value), region) + expr_to_expr2(env, scope, arena.alloc(desugared_loc_expr.value), region) } const ZERO: Region = Region::zero(); -pub fn to_expr2<'a>( +pub fn expr_to_expr2<'a>( env: &mut Env<'a>, scope: &mut Scope, parse_expr: &'a roc_parse::ast::Expr<'a>, @@ -139,7 +139,7 @@ pub fn to_expr2<'a>( let elems: PoolVec = PoolVec::with_capacity(items.len() as u32, env.pool); for (node_id, item) in elems.iter_node_ids().zip(items.iter()) { - let (expr, sub_output) = to_expr2(env, scope, &item.value, item.region); + let (expr, sub_output) = expr_to_expr2(env, scope, &item.value, item.region); output_ref.union(sub_output); @@ -188,7 +188,7 @@ pub fn to_expr2<'a>( final_comments: _, } => { let (can_update, update_out) = - to_expr2(env, scope, &loc_update.value, loc_update.region); + expr_to_expr2(env, scope, &loc_update.value, loc_update.region); if let Expr2::Var(symbol) = &can_update { match canonicalize_fields(env, scope, fields) { @@ -309,10 +309,10 @@ pub fn to_expr2<'a>( let mut output = Output::default(); for (condition, then_branch) in branches.iter() { - let (cond, cond_output) = to_expr2(env, scope, &condition.value, condition.region); + let (cond, cond_output) = expr_to_expr2(env, scope, &condition.value, condition.region); let (then_expr, then_output) = - to_expr2(env, scope, &then_branch.value, then_branch.region); + expr_to_expr2(env, scope, &then_branch.value, then_branch.region); output.references.union_mut(cond_output.references); output.references.union_mut(then_output.references); @@ -321,7 +321,7 @@ pub fn to_expr2<'a>( } let (else_expr, else_output) = - to_expr2(env, scope, &final_else.value, final_else.region); + expr_to_expr2(env, scope, &final_else.value, final_else.region); output.references.union_mut(else_output.references); @@ -338,7 +338,7 @@ pub fn to_expr2<'a>( When(loc_cond, branches) => { // Infer the condition expression's type. let cond_var = env.var_store.fresh(); - let (can_cond, mut output) = to_expr2(env, scope, &loc_cond.value, loc_cond.region); + let (can_cond, mut output) = expr_to_expr2(env, scope, &loc_cond.value, loc_cond.region); // the condition can never be a tail-call output.tail_call = None; @@ -411,7 +411,7 @@ pub fn to_expr2<'a>( } let (body_expr, new_output) = - to_expr2(env, &mut scope, &loc_body_expr.value, loc_body_expr.region); + expr_to_expr2(env, &mut scope, &loc_body_expr.value, loc_body_expr.region); let mut captured_symbols: MutSet = new_output.references.lookups.iter().copied().collect(); @@ -501,7 +501,7 @@ pub fn to_expr2<'a>( let fn_region = loc_fn.region; // Canonicalize the function expression and its arguments - let (fn_expr, mut output) = to_expr2(env, scope, &loc_fn.value, fn_region); + let (fn_expr, mut output) = expr_to_expr2(env, scope, &loc_fn.value, fn_region); // The function's return type let args = PoolVec::with_capacity(loc_args.len() as u32, env.pool); @@ -592,7 +592,7 @@ pub fn to_expr2<'a>( // The def as a whole is a tail call iff its return expression is a tail call. // Use its output as a starting point because its tail_call already has the right answer! - let (ret_expr, mut output) = to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region); + let (ret_expr, mut output) = expr_to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region); output .introduced_variables @@ -704,7 +704,7 @@ pub fn to_expr_id<'a>( parse_expr: &'a roc_parse::ast::Expr<'a>, region: Region, ) -> (ExprId, Output) { - let (expr, output) = to_expr2(env, scope, parse_expr, region); + let (expr, output) = expr_to_expr2(env, scope, parse_expr, region); (env.add(expr, region), output) } diff --git a/ast/src/lang/core/expr/mod.rs b/ast/src/lang/core/expr/mod.rs index 32d768c4c9..bb27a4ad9b 100644 --- a/ast/src/lang/core/expr/mod.rs +++ b/ast/src/lang/core/expr/mod.rs @@ -1,6 +1,6 @@ pub mod expr2; pub mod expr2_to_string; -pub(crate) mod expr_to_expr2; +pub mod expr_to_expr2; mod introduced_vars; pub(crate) mod output; pub mod record_field; diff --git a/ast/src/lang/core/str.rs b/ast/src/lang/core/str.rs index 53b0a999cf..7a939aac33 100644 --- a/ast/src/lang/core/str.rs +++ b/ast/src/lang/core/str.rs @@ -3,7 +3,7 @@ use roc_parse::ast::StrLiteral; use crate::{ ast_error::{ASTResult, UnexpectedASTNode}, - lang::{core::expr::expr_to_expr2::to_expr2, env::Env, scope::Scope}, + lang::{core::expr::expr_to_expr2::expr_to_expr2, env::Env, scope::Scope}, mem_pool::{pool::Pool, pool_str::PoolStr, pool_vec::PoolVec}, }; @@ -94,7 +94,7 @@ fn flatten_str_lines<'a>( } let (loc_expr, new_output) = - to_expr2(env, scope, loc_expr.value, loc_expr.region); + expr_to_expr2(env, scope, loc_expr.value, loc_expr.region); output.union(new_output); diff --git a/code_markup/src/markup/nodes.rs b/code_markup/src/markup/nodes.rs index cea08f288b..385536f7c8 100644 --- a/code_markup/src/markup/nodes.rs +++ b/code_markup/src/markup/nodes.rs @@ -809,11 +809,11 @@ pub fn ast_to_mark_nodes<'a, 'b>( for &def_id in ast.def_ids.iter() { let def2 = env.pool.get(def_id); - let expr2_markup_id = def2_to_markup(arena, env, def2, def_id, mark_node_pool, interns)?; + let def2_markup_id = def2_to_markup(arena, env, def2, def_id, mark_node_pool, interns)?; - set_parent_for_all(expr2_markup_id, mark_node_pool); + set_parent_for_all(def2_markup_id, mark_node_pool); - all_mark_node_ids.push(expr2_markup_id); + all_mark_node_ids.push(def2_markup_id); } Ok(all_mark_node_ids) diff --git a/docs/Cargo.toml b/docs/Cargo.toml index c0f7416516..c311423548 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -9,9 +9,11 @@ edition = "2018" [dependencies] pulldown-cmark = { version = "0.8", default-features = false } +roc_ast = { path = "../ast" } roc_load = { path = "../compiler/load" } roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } +roc_code_markup = { path = "../code_markup"} roc_fmt = { path = "../compiler/fmt" } roc_module = { path = "../compiler/module" } roc_region = { path = "../compiler/region" } diff --git a/docs/src/def.rs b/docs/src/def.rs index 6b9a0cee11..4660d06572 100644 --- a/docs/src/def.rs +++ b/docs/src/def.rs @@ -1,47 +1,12 @@ use crate::html::ToHtml; -use roc_parse::ast::Def; +use roc_code_markup::{markup::nodes::{MarkupNode}}; -impl<'a> ToHtml<'a> for Def<'a> { +impl<'a> ToHtml<'a> for MarkupNode { fn css_class(&self) -> Option<&'a str> { - match self { - // Def::Annotation(_, _) => {} - // Def::Alias { .. } => {} - Def::Body(_, _) => None, - // Def::AnnotatedBody { .. } => {} - // Def::Expect(_) => {} - Def::SpaceBefore(_, _) => None, - Def::SpaceAfter(_, _) => None, - // Def::NotYetImplemented(_) => {} - _ => None, - } + Some("operator") } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - match self { - // Def::Annotation(_, _) => {} - // Def::Alias { .. } => {} - Def::Body(pattern, expr) => { - pattern.html(buf); - EqualSign.html(buf); - expr.html(buf); - } - // Def::AnnotatedBody { .. } => {} - // Def::Expect(_) => {} - Def::SpaceBefore(sub_def, spaces) => { - for space in spaces.iter() { - space.html(buf); - } - sub_def.html(buf); - } - Def::SpaceAfter(sub_def, spaces) => { - sub_def.html(buf); - for space in spaces.iter() { - space.html(buf); - } - } - // Def::NotYetImplemented(_) => {} - _ => {} - } + buf.push_str("MarkupNode") } } diff --git a/docs/src/expr.rs b/docs/src/expr.rs index bcb7832cb9..a37c70d834 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -1,6 +1,10 @@ use crate::html::ToHtml; -use roc_parse::ast::{CommentOrNewline, Expr, StrLiteral, StrSegment}; -use roc_region::all::Located; +use bumpalo::Bump; +use roc_ast::{ast_error::ASTResult, lang::{core::expr::expr_to_expr2::expr_to_expr2, env::Env, scope::Scope}, mem_pool::pool::Pool}; +use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool}; +use roc_module::symbol::Interns; +use roc_parse::ast::{Expr, StrLiteral}; +use roc_region::all::{Located, Region}; impl<'a> ToHtml<'a> for Expr<'a> { fn css_class(&self) -> Option<&'a str> { @@ -155,3 +159,35 @@ impl<'a> ToHtml<'a> for ParamComma { buf.push_str(", ") } } + +fn write_expr_to_bump_str_html<'a>( + arena: &mut Bump, + env: &mut Env<'a>, + scope: &mut Scope, + region: Region, + expr: &'a Expr, + interns: &Interns, + bump_str: &mut bumpalo::collections::String<'a> +) -> ASTResult<()> { + let (expr2, _) = expr_to_expr2(env, scope, expr, region); + + let mut expr2_pool = Pool::with_capacity(1024); + let expr2_id = expr2_pool.add(expr2); + + let mut mark_node_pool = SlowPool::default(); + + let expr2_markup_id = expr2_to_markup( + arena, + env, + &expr2, + expr2_id, + &mut mark_node_pool, + interns, + )?; + + let expr2_markup_node = mark_node_pool.get(expr2_markup_id); + + expr2_markup_node.html(bump_str); + + Ok(()) +} From f63c276a5f38963532dc4823d8178d243e4bc3b6 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 1 Oct 2021 18:22:27 +0200 Subject: [PATCH 4/9] docs flow working with mocked markup to html --- cli/src/lib.rs | 2 +- code_markup/src/markup/nodes.rs | 12 +- compiler/can/src/scope.rs | 2 +- docs/src/def.rs | 10 -- docs/src/expr.rs | 30 ++-- docs/src/html.rs | 2 + docs/src/lib.rs | 199 ++++++++++++++--------- docs/tests/insert_syntax_highlighting.rs | 55 ++++--- editor/src/editor/mvc/ed_model.rs | 1 - 9 files changed, 178 insertions(+), 135 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 618c152f3c..128831bc9f 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -214,7 +214,7 @@ pub fn build_app<'a>() -> App<'a> { } pub fn docs(files: Vec) { - roc_docs::generate( + roc_docs::generate_docs_html( files, roc_builtins::std::standard_stdlib(), Path::new("./generated-docs"), diff --git a/code_markup/src/markup/nodes.rs b/code_markup/src/markup/nodes.rs index 385536f7c8..50e1489150 100644 --- a/code_markup/src/markup/nodes.rs +++ b/code_markup/src/markup/nodes.rs @@ -13,7 +13,6 @@ use super::{ }; use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired}; -use bumpalo::Bump; use roc_ast::{ ast_error::ASTResult, lang::{ @@ -306,7 +305,6 @@ fn new_markup_node( } pub fn def2_to_markup<'a, 'b>( - arena: &'a Bump, env: &mut Env<'b>, def2: &Def2, def2_node_id: DefId, @@ -321,7 +319,6 @@ pub fn def2_to_markup<'a, 'b>( expr_id, } => { let expr_mn_id = expr2_to_markup( - arena, env, env.pool.get(*expr_id), *expr_id, @@ -348,7 +345,6 @@ pub fn def2_to_markup<'a, 'b>( // make Markup Nodes: generate String representation, assign Highlighting Style pub fn expr2_to_markup<'a, 'b>( - arena: &'a Bump, env: &mut Env<'b>, expr2: &Expr2, expr2_node_id: ExprId, @@ -380,7 +376,7 @@ pub fn expr2_to_markup<'a, 'b>( ), Expr2::Call { expr: expr_id, .. } => { let expr = env.pool.get(*expr_id); - expr2_to_markup(arena, env, expr, *expr_id, mark_node_pool, interns)? + expr2_to_markup(env, expr, *expr_id, mark_node_pool, interns)? } Expr2::Var(symbol) => { //TODO make bump_format with arena @@ -398,7 +394,6 @@ pub fn expr2_to_markup<'a, 'b>( let sub_expr2 = env.pool.get(*node_id); children_ids.push(expr2_to_markup( - arena, env, sub_expr2, *node_id, @@ -460,7 +455,6 @@ pub fn expr2_to_markup<'a, 'b>( let sub_expr2 = env.pool.get(*sub_expr2_node_id); children_ids.push(expr2_to_markup( - arena, env, sub_expr2, *sub_expr2_node_id, @@ -520,7 +514,6 @@ pub fn expr2_to_markup<'a, 'b>( expr_var: _, } => { let body_mn_id = expr2_to_markup( - arena, env, env.pool.get(*expr_id), *expr_id, @@ -798,7 +791,6 @@ fn add_header_mn_list( } pub fn ast_to_mark_nodes<'a, 'b>( - arena: &'a Bump, env: &mut Env<'b>, ast: &AST, mark_node_pool: &mut SlowPool, @@ -809,7 +801,7 @@ pub fn ast_to_mark_nodes<'a, 'b>( for &def_id in ast.def_ids.iter() { let def2 = env.pool.get(def_id); - let def2_markup_id = def2_to_markup(arena, env, def2, def_id, mark_node_pool, interns)?; + let def2_markup_id = def2_to_markup(env, def2, def_id, mark_node_pool, interns)?; set_parent_for_all(def2_markup_id, mark_node_pool); diff --git a/compiler/can/src/scope.rs b/compiler/can/src/scope.rs index bde1032119..2a6995d717 100644 --- a/compiler/can/src/scope.rs +++ b/compiler/can/src/scope.rs @@ -83,7 +83,7 @@ impl Scope { self.idents.len() } - pub fn lookup(&mut self, ident: &Ident, region: Region) -> Result { + pub fn lookup(&self, ident: &Ident, region: Region) -> Result { match self.idents.get(ident) { Some((symbol, _)) => Ok(*symbol), None => Err(RuntimeError::LookupNotInScope( diff --git a/docs/src/def.rs b/docs/src/def.rs index 4660d06572..7f86be17f1 100644 --- a/docs/src/def.rs +++ b/docs/src/def.rs @@ -1,14 +1,4 @@ use crate::html::ToHtml; -use roc_code_markup::{markup::nodes::{MarkupNode}}; - -impl<'a> ToHtml<'a> for MarkupNode { - fn css_class(&self) -> Option<&'a str> { - Some("operator") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push_str("MarkupNode") - } -} struct EqualSign; diff --git a/docs/src/expr.rs b/docs/src/expr.rs index a37c70d834..285d8c48cf 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -1,10 +1,19 @@ use crate::html::ToHtml; -use bumpalo::Bump; -use roc_ast::{ast_error::ASTResult, lang::{core::expr::expr_to_expr2::expr_to_expr2, env::Env, scope::Scope}, mem_pool::pool::Pool}; +use roc_ast::{ast_error::ASTResult, lang::{self, core::expr::expr_to_expr2::expr_to_expr2}, mem_pool::pool::Pool}; use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool}; use roc_module::symbol::Interns; use roc_parse::ast::{Expr, StrLiteral}; -use roc_region::all::{Located, Region}; +use roc_region::all::{Region}; +use roc_code_markup::{markup::nodes::{MarkupNode}}; + +impl<'a> ToHtml<'a> for MarkupNode { + fn css_class(&self) -> Option<&'a str> { + Some("operator") + } + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { + buf.push_str("MarkupNode") + } +} impl<'a> ToHtml<'a> for Expr<'a> { fn css_class(&self) -> Option<&'a str> { @@ -95,7 +104,8 @@ impl<'a> ToHtml<'a> for Expr<'a> { } Expr::Defs(defs, sub_expr) => { for def_loc in defs.iter() { - def_loc.html(buf); + unimplemented!(); + //def_loc.html(buf); } sub_expr.html(buf) } @@ -160,14 +170,13 @@ impl<'a> ToHtml<'a> for ParamComma { } } -fn write_expr_to_bump_str_html<'a>( - arena: &mut Bump, - env: &mut Env<'a>, - scope: &mut Scope, +pub fn write_expr_to_bump_str_html<'a, 'b>( + env: &mut lang::env::Env<'a>, + scope: &mut lang::scope::Scope, region: Region, expr: &'a Expr, interns: &Interns, - bump_str: &mut bumpalo::collections::String<'a> + bump_str: &mut bumpalo::collections::String<'b> ) -> ASTResult<()> { let (expr2, _) = expr_to_expr2(env, scope, expr, region); @@ -177,9 +186,8 @@ fn write_expr_to_bump_str_html<'a>( let mut mark_node_pool = SlowPool::default(); let expr2_markup_id = expr2_to_markup( - arena, env, - &expr2, + &expr2_pool.get(expr2_id), expr2_id, &mut mark_node_pool, interns, diff --git a/docs/src/html.rs b/docs/src/html.rs index 57061f2203..e287184c79 100644 --- a/docs/src/html.rs +++ b/docs/src/html.rs @@ -2,7 +2,9 @@ use roc_region::all::Located; pub trait ToHtml<'a> { fn css_class(&self) -> Option<&'a str>; + fn html_body(&self, buf: &mut bumpalo::collections::String<'a>); + fn html(&self, buf: &mut bumpalo::collections::String<'a>) { let maybe_css_class = self.css_class(); diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 76875e9d64..c44aa47fbc 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -1,7 +1,9 @@ extern crate pulldown_cmark; extern crate roc_load; -use crate::html::ToHtml; -use bumpalo::Bump; +use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump}; +use expr::write_expr_to_bump_str_html; +use roc_ast::lang; +use roc_ast::mem_pool::pool::Pool; use roc_builtins::std::StdLib; use roc_can::builtins::builtin_defs_map; use roc_can::scope::Scope; @@ -10,10 +12,12 @@ use roc_load::docs::DocEntry::DocDef; use roc_load::docs::{DocEntry, TypeAnnotation}; use roc_load::docs::{ModuleDocumentation, RecordField}; use roc_load::file::{LoadedModule, LoadingProblem}; -use roc_module::symbol::{IdentIds, Interns, ModuleId}; +use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; +use roc_parse::ast::Expr; use roc_parse::ident::{parse_ident, Ident}; use roc_parse::parser::{State, SyntaxError}; use roc_region::all::Region; +use roc_types::subs::VarStore; use std::fs; use std::path::{Path, PathBuf}; @@ -23,8 +27,8 @@ mod expr; mod html; mod pattern; -pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { - let files_docs = files_to_documentations(filenames, std_lib); +pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: &Path) { + let files_docs = load_modules_for_files(filenames, std_lib); let mut arena = Bump::new(); // @@ -60,11 +64,11 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { .expect("TODO gracefully handle failing to make the favicon"); let template_html = include_str!("./static/index.html") - .replace("", &format!("{}search.js", base_href())) - .replace("", &format!("{}styles.css", base_href())) + .replace("", &format!("{}search.js", base_url())) + .replace("", &format!("{}styles.css", base_url())) .replace( "", - &format!("{}favicon.svg", base_href()), + &format!("{}favicon.svg", base_url()), ) .replace( "", @@ -86,8 +90,8 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { for loaded_module in package.modules.iter_mut() { arena.reset(); - let mut exports: bumpalo::collections::Vec<&str> = - bumpalo::collections::Vec::with_capacity_in(loaded_module.exposed_values.len(), &arena); + let mut exports: BumpVec<&str> = + BumpVec::with_capacity_in(loaded_module.exposed_values.len(), &arena); // TODO should this also include exposed_aliases? for symbol in loaded_module.exposed_values.iter() { @@ -96,8 +100,8 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { let exports = exports.into_bump_slice(); - for module in loaded_module.documentation.values_mut() { - let module_dir = build_dir.join(module.name.replace(".", "/").as_str()); + for module_docs in loaded_module.documentation.values() { + let module_dir = build_dir.join(module_docs.name.replace(".", "/").as_str()); fs::create_dir_all(&module_dir) .expect("TODO gracefully handle not being able to create the module dir"); @@ -111,11 +115,9 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { .replace( "", render_main_content( - loaded_module.module_id, exports, - &loaded_module.dep_idents, - &loaded_module.interns, - module, + module_docs, + &loaded_module ) .as_str(), ); @@ -128,17 +130,56 @@ pub fn generate(filenames: Vec, std_lib: StdLib, build_dir: &Path) { println!("🎉 Docs generated in {}", build_dir.display()); } +// html is written to buf +fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { + + let mut env_pool = Pool::with_capacity(1024); + let mut env_arena = Bump::new(); + + let mut var_store = VarStore::default(); + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); + + let mut env = lang::env::Env::new( + env_module_id, + &mut env_arena, + &mut env_pool, + &mut var_store, + dep_idents, + env_module_ids, + exposed_ident_ids, + ); + + let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); + let region = Region::new(0, 0, 0, 0); + + // TODO remove unwrap + write_expr_to_bump_str_html( + &mut env, + &mut scope, + region, + &expr, + interns, + buf + ).unwrap(); +} + +// converts plain text code to highlighted html pub fn syntax_highlight_code<'a>( arena: &'a Bump, - buf: &mut bumpalo::collections::String<'a>, + buf: &mut BumpString<'a>, code_str: &'a str, + env_module_id: ModuleId, + env_module_ids: &'a ModuleIds, + interns: &Interns ) -> Result> { let trimmed_code_str = code_str.trim_end().trim(); let state = State::new(trimmed_code_str.as_bytes()); match roc_parse::expr::test_parse_expr(0, arena, state) { Ok(loc_expr) => { - loc_expr.value.html(buf); + expr_to_html(buf, loc_expr.value, env_module_id, env_module_ids, interns); + Ok(buf.to_string()) } Err(fail) => Err(SyntaxError::Expr(fail)), @@ -150,20 +191,19 @@ pub fn syntax_highlight_code<'a>( // }) } +// TODO improve name, what is main content? fn render_main_content( - home: ModuleId, exposed_values: &[&str], - dep_idents: &MutMap, - interns: &Interns, - module: &mut ModuleDocumentation, + module: &ModuleDocumentation, + loaded_module: &LoadedModule, ) -> String { let mut buf = String::new(); buf.push_str( - html_node( + html_to_string( "h2", vec![("class", "module-name")], - html_node("a", vec![("href", "/#")], module.name.as_str()).as_str(), + html_to_string("a", vec![("href", "/#")], module.name.as_str()).as_str(), ) .as_str(), ); @@ -187,7 +227,7 @@ fn render_main_content( let mut content = String::new(); - content.push_str(html_node("a", vec![("href", href.as_str())], name).as_str()); + content.push_str(html_to_string("a", vec![("href", href.as_str())], name).as_str()); for type_var in &doc_def.type_vars { content.push(' '); @@ -206,7 +246,7 @@ fn render_main_content( type_annotation_to_html(0, &mut content, type_ann); buf.push_str( - html_node( + html_to_string( "h3", vec![("id", name), ("class", "entry-name")], content.as_str(), @@ -217,12 +257,10 @@ fn render_main_content( if let Some(docs) = &doc_def.docs { buf.push_str( markdown_to_html( - home, exposed_values, - dep_idents, - &mut module.scope, - interns, + &module.scope, docs.to_string(), + loaded_module, ) .as_str(), ); @@ -230,12 +268,10 @@ fn render_main_content( } DocEntry::DetachedDoc(docs) => { let markdown = markdown_to_html( - home, exposed_values, - dep_idents, - &mut module.scope, - interns, + &module.scope, docs.to_string(), + loaded_module, ); buf.push_str(markdown.as_str()); } @@ -246,7 +282,7 @@ fn render_main_content( buf } -fn html_node(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String { +fn html_to_string(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String { let mut buf = String::new(); buf.push('<'); @@ -275,62 +311,62 @@ fn html_node(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String buf } -fn base_href() -> String { +fn base_url() -> String { // e.g. "builtins/" in "https://roc-lang.org/builtins/Str" // // TODO make this a CLI flag to the `docs` subcommand instead of an env var match std::env::var("ROC_DOCS_URL_ROOT") { Ok(root_builtins_path) => { - let mut href = String::with_capacity(root_builtins_path.len() + 64); + let mut url_str = String::with_capacity(root_builtins_path.len() + 64); if !root_builtins_path.starts_with('/') { - href.push('/'); + url_str.push('/'); } - href.push_str(&root_builtins_path); + url_str.push_str(&root_builtins_path); if !root_builtins_path.ends_with('/') { - href.push('/'); + url_str.push('/'); } - href + url_str } _ => { - let mut href = String::with_capacity(64); + let mut url_str = String::with_capacity(64); - href.push('/'); + url_str.push('/'); - href + url_str } } } fn render_name_and_version(name: &str, version: &str) -> String { let mut buf = String::new(); - let mut href = base_href(); + let mut url_str = base_url(); - href.push_str(name); + url_str.push_str(name); buf.push_str( - html_node( + html_to_string( "h1", vec![("class", "pkg-full-name")], - html_node("a", vec![("href", href.as_str())], name).as_str(), + html_to_string("a", vec![("href", url_str.as_str())], name).as_str(), ) .as_str(), ); - let mut versions_href = base_href(); + let mut versions_url_str = base_url(); - versions_href.push('/'); - versions_href.push_str(name); - versions_href.push('/'); - versions_href.push_str(version); + versions_url_str.push('/'); + versions_url_str.push_str(name); + versions_url_str.push('/'); + versions_url_str.push_str(version); buf.push_str( - html_node( + html_to_string( "a", - vec![("class", "version"), ("href", versions_href.as_str())], + vec![("class", "version"), ("href", versions_url_str.as_str())], version, ) .as_str(), @@ -350,13 +386,13 @@ fn render_sidebar<'a, I: Iterator, &'a ModuleDocumentation)> let name = module.name.as_str(); let href = { - let mut href_buf = base_href(); + let mut href_buf = base_url(); href_buf.push_str(name); href_buf }; sidebar_entry_content.push_str( - html_node( + html_to_string( "a", vec![("class", "sidebar-module-link"), ("href", href.as_str())], name, @@ -377,7 +413,7 @@ fn render_sidebar<'a, I: Iterator, &'a ModuleDocumentation)> entry_href.push_str(doc_def.name.as_str()); entries_buf.push_str( - html_node( + html_to_string( "a", vec![("href", entry_href.as_str())], doc_def.name.as_str(), @@ -392,7 +428,7 @@ fn render_sidebar<'a, I: Iterator, &'a ModuleDocumentation)> }; sidebar_entry_content.push_str( - html_node( + html_to_string( "div", vec![("class", "sidebar-sub-entries")], entries.as_str(), @@ -401,7 +437,7 @@ fn render_sidebar<'a, I: Iterator, &'a ModuleDocumentation)> ); buf.push_str( - html_node( + html_to_string( "div", vec![("class", "sidebar-entry")], sidebar_entry_content.as_str(), @@ -413,9 +449,9 @@ fn render_sidebar<'a, I: Iterator, &'a ModuleDocumentation)> buf } -pub fn files_to_documentations(filenames: Vec, std_lib: StdLib) -> Vec { +pub fn load_modules_for_files(filenames: Vec, std_lib: StdLib) -> Vec { let arena = Bump::new(); - let mut files_docs = vec![]; + let mut modules = vec![]; for filename in filenames { let mut src_dir = filename.clone(); @@ -430,7 +466,7 @@ pub fn files_to_documentations(filenames: Vec, std_lib: StdLib) -> Vec< std::mem::size_of::() as u32, // This is just type-checking for docs, so "target" doesn't matter builtin_defs_map, ) { - Ok(loaded) => files_docs.push(loaded), + Ok(loaded) => modules.push(loaded), Err(LoadingProblem::FormattedReport(report)) => { println!("{}", report); panic!(); @@ -439,7 +475,7 @@ pub fn files_to_documentations(filenames: Vec, std_lib: StdLib) -> Vec< } } - files_docs + modules } const INDENT: &str = " "; @@ -454,6 +490,7 @@ fn new_line(buf: &mut String) { buf.push('\n'); } +// html is written to buf fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &TypeAnnotation) { let is_multiline = should_be_multiline(type_ann); match type_ann { @@ -715,7 +752,7 @@ fn doc_url<'a>( home: ModuleId, exposed_values: &[&str], dep_idents: &MutMap, - scope: &mut Scope, + scope: &Scope, interns: &'a Interns, mut module_name: &'a str, ident: &str, @@ -782,7 +819,7 @@ fn doc_url<'a>( } } - let mut url = base_href(); + let mut url = base_url(); // Example: // @@ -798,12 +835,10 @@ fn doc_url<'a>( } fn markdown_to_html( - home: ModuleId, exposed_values: &[&str], - dep_idents: &MutMap, - scope: &mut Scope, - interns: &Interns, + scope: &Scope, markdown: String, + loaded_module: &LoadedModule, ) -> String { use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Tag::*}; @@ -830,11 +865,11 @@ fn markdown_to_html( match iter.next() { Some(symbol_name) if iter.next().is_none() => { let DocUrl { url, title } = doc_url( - home, + loaded_module.module_id, exposed_values, - dep_idents, + &loaded_module.dep_idents, scope, - interns, + &loaded_module.interns, module_name, symbol_name, ); @@ -853,11 +888,11 @@ fn markdown_to_html( // This looks like a global tag name, but it could // be a type alias that's in scope, e.g. [I64] let DocUrl { url, title } = doc_url( - home, + loaded_module.module_id, exposed_values, - dep_idents, + &loaded_module.dep_idents, scope, - interns, + &loaded_module.interns, "", type_name, ); @@ -961,8 +996,16 @@ fn markdown_to_html( Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => { let code_block_arena = Bump::new(); - let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena); - match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) { + let mut code_block_buf = BumpString::new_in(&code_block_arena); + match syntax_highlight_code( + &code_block_arena, + &mut code_block_buf, + code_str, + loaded_module.module_id, + &loaded_module.interns.module_ids, + &loaded_module.interns + ) + { Ok(highlighted_code_str) => { docs_parser.push(Event::Html(CowStr::from(highlighted_code_str))); } diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs index a9a5e6cabb..6ee032d9ce 100644 --- a/docs/tests/insert_syntax_highlighting.rs +++ b/docs/tests/insert_syntax_highlighting.rs @@ -3,7 +3,7 @@ extern crate pretty_assertions; #[cfg(test)] mod insert_doc_syntax_highlighting { - use bumpalo::Bump; + use bumpalo::{collections::String as BumpString, Bump}; use roc_can::env::Env; use roc_can::scope::Scope; use roc_collections::all::MutMap; @@ -14,8 +14,24 @@ mod insert_doc_syntax_highlighting { fn expect_html(code_str: &str, want: &str) { let code_block_arena = Bump::new(); - let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena); - match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) { + + let mut module_ids = ModuleIds::default(); + let mod_id = module_ids.get_or_insert(&"ModId123".into()); + + let interns = Interns { + module_ids: module_ids.clone(), + all_ident_ids: IdentIds::exposed_builtins(8), + }; + let mut code_block_buf = BumpString::new_in(&code_block_arena); + + match syntax_highlight_code( + &code_block_arena, + &mut code_block_buf, + code_str, + mod_id, + &module_ids, + &interns + ) { Ok(highlighted_code_str) => { assert_eq!(highlighted_code_str, want); } @@ -25,7 +41,7 @@ mod insert_doc_syntax_highlighting { }; } - #[test] + /*#[test] fn simple_code_block() { expect_html( r#" @@ -43,24 +59,17 @@ mod insert_doc_syntax_highlighting {
2
"#, ); + }*/ + + #[test] + fn simple_code_block() { + expect_html( + r#" + 2 + "#, + r#" +
2
+ "#, + ); } - // #[test] - // fn simple_code_block() { - // expect_html( - // r#" - // x : Nat - // x = - // 4 - // - // 2 - // "#, - // r#" - //
x
:
Nat
- //
x
=
- //
4
- // - //
2
- // "#, - // ); - // } } diff --git a/editor/src/editor/mvc/ed_model.rs b/editor/src/editor/mvc/ed_model.rs index d255bdbeb5..d22f92d934 100644 --- a/editor/src/editor/mvc/ed_model.rs +++ b/editor/src/editor/mvc/ed_model.rs @@ -63,7 +63,6 @@ pub fn init_model<'a>( EmptyCodeString {}.fail() } else { Ok(ast_to_mark_nodes( - code_arena, &mut module.env, &module.ast, &mut mark_node_pool, From bc50280c0e3ba3aacbaa32a62cbb96b05fdae2fa Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 1 Oct 2021 19:53:51 +0200 Subject: [PATCH 5/9] markup to html progress --- docs/src/expr.rs | 9 ------- docs/src/html.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/docs/src/expr.rs b/docs/src/expr.rs index 285d8c48cf..49a034da70 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -6,15 +6,6 @@ use roc_parse::ast::{Expr, StrLiteral}; use roc_region::all::{Region}; use roc_code_markup::{markup::nodes::{MarkupNode}}; -impl<'a> ToHtml<'a> for MarkupNode { - fn css_class(&self) -> Option<&'a str> { - Some("operator") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push_str("MarkupNode") - } -} - impl<'a> ToHtml<'a> for Expr<'a> { fn css_class(&self) -> Option<&'a str> { match self { diff --git a/docs/src/html.rs b/docs/src/html.rs index e287184c79..7c86d630dd 100644 --- a/docs/src/html.rs +++ b/docs/src/html.rs @@ -1,4 +1,6 @@ +use roc_code_markup::{markup::nodes::MarkupNode, slow_pool::SlowPool}; use roc_region::all::Located; +use bumpalo::{collections::String as BumpString}; pub trait ToHtml<'a> { fn css_class(&self) -> Option<&'a str>; @@ -43,3 +45,63 @@ where self.value.html(buf); } } + + +// determine appropriate css class for MarkupNode +fn mark_node_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &mut bumpalo::collections::String<'a>) { + match mark_node { + MarkupNode::Nested { children_ids, newlines_at_end, .. } => { + for &child_id in children_ids { + mark_node_html( + mark_node_pool.get(child_id), + mark_node_pool, + buf + ) + } + + for _ in 0..*newlines_at_end { + buf.push('\n') + } + } + MarkupNode::Text { syn_high_style, newlines_at_end, .. } => { + use HighlightStyle::*; + + let css_class = match syn_high_style { + Operator => "operator", + String => "string", + FunctionName => "function_name", + Type => "type", + Bracket => "bracket", + Number => "number", + PackageRelated => "package-related", + Variable => "variable", + RecordField => "recordfield", + Import => "import", + Provides => "provides", + Blank => "blank", + }; + } + MarkupNode::Blank { syn_high_style, newlines_at_end, .. } => { + let mut content_str = " ".to_string(); + + for _ in 0..*newlines_at_end { + content_str.push('\n'); + } + + write_html_to_buf(content_str, "blank", buf) + } + } + +} + +fn write_html_to_buf<'a>(content: String, css_class: &'static str, buf: &mut BumpString<'a>) { + + let opening_tag: String = [""].concat(); + + buf.push_str(opening_tag.as_str()); + + buf.push_str(&content); + + buf.push_str(""); +} + From c6066cc629f7dc9f2c16776742986d9b07865cf5 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 2 Oct 2021 19:47:46 +0200 Subject: [PATCH 6/9] expr working, debugging def --- code_markup/src/markup/common_nodes.rs | 2 +- code_markup/src/syntax_highlight.rs | 2 + docs/src/def.rs | 123 ++++++++++++++- docs/src/expr.rs | 192 +++++------------------ docs/src/html.rs | 33 ++-- docs/src/lib.rs | 76 ++++----- docs/src/static/styles.css | 22 +-- docs/tests/insert_syntax_highlighting.rs | 133 ++++++++++------ 8 files changed, 306 insertions(+), 277 deletions(-) diff --git a/code_markup/src/markup/common_nodes.rs b/code_markup/src/markup/common_nodes.rs index 89a8a8c2d9..806d6170cd 100644 --- a/code_markup/src/markup/common_nodes.rs +++ b/code_markup/src/markup/common_nodes.rs @@ -19,7 +19,7 @@ pub fn new_comma_mn(expr_id: ExprId, parent_id_opt: Option) -> Marku MarkupNode::Text { content: nodes::COMMA.to_owned(), ast_node_id: ASTNodeId::AExprId(expr_id), - syn_high_style: HighlightStyle::Blank, + syn_high_style: HighlightStyle::Comma, attributes: Attributes::default(), parent_id_opt, newlines_at_end: 0, diff --git a/code_markup/src/syntax_highlight.rs b/code_markup/src/syntax_highlight.rs index 12c0ef33e1..dfdb32076d 100644 --- a/code_markup/src/syntax_highlight.rs +++ b/code_markup/src/syntax_highlight.rs @@ -6,6 +6,7 @@ use crate::colors::{self, from_hsb, RgbaTup}; #[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Deserialize, Serialize)] pub enum HighlightStyle { Operator, // =+-<>... + Comma, String, FunctionName, Type, @@ -25,6 +26,7 @@ pub fn default_highlight_map() -> HashMap { let mut highlight_map = HashMap::new(); [ (Operator, colors::WHITE), + (Comma, from_hsb(258, 50, 90)), (String, from_hsb(346, 65, 97)), (FunctionName, colors::WHITE), (Type, colors::WHITE), diff --git a/docs/src/def.rs b/docs/src/def.rs index 7f86be17f1..6923b933a0 100644 --- a/docs/src/def.rs +++ b/docs/src/def.rs @@ -1,12 +1,119 @@ -use crate::html::ToHtml; +use roc_ast::{ast_error::ASTResult, lang::{self, core::def::def_to_def2::def_to_def2}, mem_pool::pool::Pool}; +use roc_code_markup::{markup::nodes::def2_to_markup, slow_pool::SlowPool}; +use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; +use roc_region::all::Region; +use bumpalo::{Bump, collections::String as BumpString}; +use roc_types::subs::VarStore; -struct EqualSign; +use crate::html::mark_node_to_html; -impl<'a> ToHtml<'a> for EqualSign { - fn css_class(&self) -> Option<&'a str> { - Some("operator") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push_str(" = ") +// html is written to buf +pub fn defs_to_html<'a>(buf: &mut BumpString<'a>, defs: Vec>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { + + let mut env_pool = Pool::with_capacity(1024); + let mut env_arena = Bump::new(); + + let mut var_store = VarStore::default(); + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); + + let def_arena = Bump::new(); + + let mut env = lang::env::Env::new( + env_module_id, + &mut env_arena, + &mut env_pool, + &mut var_store, + dep_idents, + env_module_ids, + exposed_ident_ids, + ); + + let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); + let region = Region::new(0, 0, 0, 0); + + + + for def in defs.iter() { + // TODO remove unwrap + write_def_to_bump_str_html( + &def_arena, + &mut env, + &mut scope, + region, + &def, + interns, + buf + ).unwrap(); } } + +// html is written to buf +pub fn def_to_html<'a>(buf: &mut BumpString<'a>, def: roc_parse::ast::Def<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { + + let mut env_pool = Pool::with_capacity(1024); + let mut env_arena = Bump::new(); + + let mut var_store = VarStore::default(); + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); + + let def_arena = Bump::new(); + + let mut env = lang::env::Env::new( + env_module_id, + &mut env_arena, + &mut env_pool, + &mut var_store, + dep_idents, + env_module_ids, + exposed_ident_ids, + ); + + let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); + let region = Region::new(0, 0, 0, 0); + + + // TODO remove unwrap + write_def_to_bump_str_html( + &def_arena, + &mut env, + &mut scope, + region, + &def, + interns, + buf + ).unwrap(); +} + +fn write_def_to_bump_str_html<'a, 'b>( + arena: &'a Bump, + env: &mut lang::env::Env<'a>, + scope: &mut lang::scope::Scope, + region: Region, + def: &'a roc_parse::ast::Def<'a>, + interns: &Interns, + buf: &mut BumpString<'b> +) -> ASTResult<()> { + + let def2 = def_to_def2(arena, env, scope, def, region); + + let mut def2_pool = Pool::with_capacity(1024); + let def2_id = def2_pool.add(def2); + + let mut mark_node_pool = SlowPool::default(); + + let def2_markup_id = def2_to_markup( + env, + &def2_pool.get(def2_id), + def2_id, + &mut mark_node_pool, + interns, + )?; + + let def2_markup_node = mark_node_pool.get(def2_markup_id); + + mark_node_to_html(def2_markup_node, &mark_node_pool, buf); + + Ok(()) +} diff --git a/docs/src/expr.rs b/docs/src/expr.rs index 49a034da70..b7e5b9da90 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -1,173 +1,53 @@ -use crate::html::ToHtml; +use crate::html::{mark_node_to_html}; use roc_ast::{ast_error::ASTResult, lang::{self, core::expr::expr_to_expr2::expr_to_expr2}, mem_pool::pool::Pool}; use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool}; -use roc_module::symbol::Interns; -use roc_parse::ast::{Expr, StrLiteral}; +use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; +use roc_parse::ast::{Expr}; use roc_region::all::{Region}; -use roc_code_markup::{markup::nodes::{MarkupNode}}; +use bumpalo::{Bump, collections::String as BumpString}; +use roc_types::subs::VarStore; -impl<'a> ToHtml<'a> for Expr<'a> { - fn css_class(&self) -> Option<&'a str> { - match self { - Expr::Float(_) | Expr::Num(_) | Expr::NonBase10Int { .. } => Some("num"), - Expr::Str(_) => Some("str"), - // Expr::Access(_, _) => {} - // Expr::AccessorFunction(_) => {} - // Expr::List { .. } => {} - // Expr::RecordUpdate { .. } => {} - // Expr::Record { .. } => {} - Expr::Var { .. } => None, - // Expr::Underscore(_) => {} - // Expr::GlobalTag(_) => {} - // Expr::PrivateTag(_) => {} - Expr::Closure(_, _) => None, +// html is written to buf +pub fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { - // Expr::Defs(_, _) => {} - // Expr::Backpassing(_, _, _) => {} - // Expr::Expect(_, _) => {} - // Expr::Apply(_, _, _) => {} - // Expr::BinOps(_, _) => {} - // Expr::UnaryOp(_, _) => {} - // Expr::If(_, _) => {} - // Expr::When(_, _) => {} - Expr::SpaceBefore(_, _) => None, - Expr::SpaceAfter(_, _) => None, - // Expr::ParensAround(_) => {} - // Expr::MalformedIdent(_, _) => {} - // Expr::MalformedClosure => {} - // Expr::PrecedenceConflict(_) => {} - _ => None, - } - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - match self { - Expr::Float(str) => { - buf.push_str(str); - } - Expr::Num(str) => { - buf.push_str(str); - } - Expr::NonBase10Int { string, .. } => { - buf.push_str(string); - } - Expr::Str(str_literal) => match str_literal { - StrLiteral::PlainLine(str) => { - buf.push('"'); - buf.push_str(str); - buf.push('"'); - } - StrLiteral::Line(line) => { - panic!("TODO str segments"); - } - StrLiteral::Block(str) => { - panic!("TODO str segments"); - } - }, - // Expr::Access(_, _) => {} - // Expr::AccessorFunction(_) => {} - // Expr::List { .. } => {} - // Expr::RecordUpdate { .. } => {} - // Expr::Record { .. } => {} - Expr::Var { ident, module_name } => { - if !module_name.is_empty() { - buf.push_str(module_name); - buf.push('.'); - } - buf.push_str(ident); - } - // Expr::Underscore(_) => {} - // Expr::GlobalTag(_) => {} - // Expr::PrivateTag(_) => {} - Expr::Closure(patterns, loc_sub_expr) => { - ClosureDash.html(buf); + let mut env_pool = Pool::with_capacity(1024); + let mut env_arena = Bump::new(); - let mut patterns_iter = patterns.iter().peekable(); + let mut var_store = VarStore::default(); + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); - while let Some(pattern) = patterns_iter.next() { - pattern.value.html(buf); - if let Some(_) = patterns_iter.peek() { - ParamComma.html(buf); - } - } + let mut env = lang::env::Env::new( + env_module_id, + &mut env_arena, + &mut env_pool, + &mut var_store, + dep_idents, + env_module_ids, + exposed_ident_ids, + ); - ClosureArrow.html(buf); - loc_sub_expr.html(buf); - } - Expr::Defs(defs, sub_expr) => { - for def_loc in defs.iter() { - unimplemented!(); - //def_loc.html(buf); - } - sub_expr.html(buf) - } - // Expr::Backpassing(_, _, _) => {} - // Expr::Expect(_, _) => {} - // Expr::Apply(_, _, _) => {} - // Expr::BinOps(_, _) => {} - // Expr::UnaryOp(_, _) => {} - // Expr::If(_, _) => {} - // Expr::When(_, _) => {} - Expr::SpaceBefore(sub_expr, spaces) => { - for space in spaces.iter() { - space.html(buf); - } - sub_expr.html(buf); - } - Expr::SpaceAfter(sub_expr, spaces) => { - sub_expr.html(buf); - for space in spaces.iter() { - space.html(buf); - } - } - // Expr::ParensAround(_) => {} - // Expr::MalformedIdent(_, _) => {} - // Expr::MalformedClosure => {} - // Expr::PrecedenceConflict(_) => {} - _ => {} - } - } + let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); + let region = Region::new(0, 0, 0, 0); + + // TODO remove unwrap + write_expr_to_bump_str_html( + &mut env, + &mut scope, + region, + &expr, + interns, + buf + ).unwrap(); } -struct ClosureDash; - -impl<'a> ToHtml<'a> for ClosureDash { - fn css_class(&self) -> Option<&'a str> { - Some("closure-dash") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push('\\') - } -} - -struct ClosureArrow; - -impl<'a> ToHtml<'a> for ClosureArrow { - fn css_class(&self) -> Option<&'a str> { - Some("closure-arrow") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push_str(" ->") - } -} - -struct ParamComma; - -impl<'a> ToHtml<'a> for ParamComma { - fn css_class(&self) -> Option<&'a str> { - Some("param-comma") - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - buf.push_str(", ") - } -} - -pub fn write_expr_to_bump_str_html<'a, 'b>( +fn write_expr_to_bump_str_html<'a, 'b>( env: &mut lang::env::Env<'a>, scope: &mut lang::scope::Scope, region: Region, expr: &'a Expr, interns: &Interns, - bump_str: &mut bumpalo::collections::String<'b> + buf: &mut BumpString<'b> ) -> ASTResult<()> { let (expr2, _) = expr_to_expr2(env, scope, expr, region); @@ -186,7 +66,7 @@ pub fn write_expr_to_bump_str_html<'a, 'b>( let expr2_markup_node = mark_node_pool.get(expr2_markup_id); - expr2_markup_node.html(bump_str); + mark_node_to_html(expr2_markup_node, &mark_node_pool, buf); Ok(()) } diff --git a/docs/src/html.rs b/docs/src/html.rs index 7c86d630dd..7cdb041a6a 100644 --- a/docs/src/html.rs +++ b/docs/src/html.rs @@ -48,26 +48,27 @@ where // determine appropriate css class for MarkupNode -fn mark_node_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &mut bumpalo::collections::String<'a>) { +pub fn mark_node_to_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &mut BumpString<'a>) { + let additional_newlines:usize; + match mark_node { MarkupNode::Nested { children_ids, newlines_at_end, .. } => { for &child_id in children_ids { - mark_node_html( + mark_node_to_html( mark_node_pool.get(child_id), mark_node_pool, buf ) } - for _ in 0..*newlines_at_end { - buf.push('\n') - } + additional_newlines = *newlines_at_end; } - MarkupNode::Text { syn_high_style, newlines_at_end, .. } => { - use HighlightStyle::*; + MarkupNode::Text { content, syn_high_style, newlines_at_end, .. } => { + use roc_code_markup::syntax_highlight::HighlightStyle::*; let css_class = match syn_high_style { Operator => "operator", + Comma => "comma", String => "string", FunctionName => "function_name", Type => "type", @@ -80,27 +81,37 @@ fn mark_node_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &m Provides => "provides", Blank => "blank", }; + + write_html_to_buf(content, css_class, buf); + + additional_newlines = *newlines_at_end; } - MarkupNode::Blank { syn_high_style, newlines_at_end, .. } => { + MarkupNode::Blank { newlines_at_end, .. } => { let mut content_str = " ".to_string(); for _ in 0..*newlines_at_end { content_str.push('\n'); } - write_html_to_buf(content_str, "blank", buf) + write_html_to_buf(&content_str, "blank", buf); + + additional_newlines = *newlines_at_end; } } + + for _ in 0..additional_newlines { + buf.push('\n') + } } -fn write_html_to_buf<'a>(content: String, css_class: &'static str, buf: &mut BumpString<'a>) { +fn write_html_to_buf<'a>(content: &str, css_class: &'static str, buf: &mut BumpString<'a>) { let opening_tag: String = [""].concat(); buf.push_str(opening_tag.as_str()); - buf.push_str(&content); + buf.push_str(content); buf.push_str(""); } diff --git a/docs/src/lib.rs b/docs/src/lib.rs index c44aa47fbc..3d8d2d09f7 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -1,9 +1,8 @@ extern crate pulldown_cmark; extern crate roc_load; use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump}; -use expr::write_expr_to_bump_str_html; -use roc_ast::lang; -use roc_ast::mem_pool::pool::Pool; +use def::defs_to_html; +use expr::{expr_to_html}; use roc_builtins::std::StdLib; use roc_can::builtins::builtin_defs_map; use roc_can::scope::Scope; @@ -13,11 +12,9 @@ use roc_load::docs::{DocEntry, TypeAnnotation}; use roc_load::docs::{ModuleDocumentation, RecordField}; use roc_load::file::{LoadedModule, LoadingProblem}; use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; -use roc_parse::ast::Expr; use roc_parse::ident::{parse_ident, Ident}; use roc_parse::parser::{State, SyntaxError}; use roc_region::all::Region; -use roc_types::subs::VarStore; use std::fs; use std::path::{Path, PathBuf}; @@ -130,42 +127,8 @@ pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: & println!("🎉 Docs generated in {}", build_dir.display()); } -// html is written to buf -fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { - - let mut env_pool = Pool::with_capacity(1024); - let mut env_arena = Bump::new(); - - let mut var_store = VarStore::default(); - let dep_idents = IdentIds::exposed_builtins(8); - let exposed_ident_ids = IdentIds::default(); - - let mut env = lang::env::Env::new( - env_module_id, - &mut env_arena, - &mut env_pool, - &mut var_store, - dep_idents, - env_module_ids, - exposed_ident_ids, - ); - - let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); - let region = Region::new(0, 0, 0, 0); - - // TODO remove unwrap - write_expr_to_bump_str_html( - &mut env, - &mut scope, - region, - &expr, - interns, - buf - ).unwrap(); -} - -// converts plain text code to highlighted html -pub fn syntax_highlight_code<'a>( +// converts plain-text code to highlighted html +pub fn syntax_highlight_expr<'a>( arena: &'a Bump, buf: &mut BumpString<'a>, code_str: &'a str, @@ -184,11 +147,30 @@ pub fn syntax_highlight_code<'a>( } Err(fail) => Err(SyntaxError::Expr(fail)), } - // roc_parse::test_helpers::parse_expr_with(&arena, trimmed_code_str).map(|expr| { - // expr.html(buf); - // - // buf.to_string() - // }) +} + +// converts plain-text code to highlighted html +pub fn syntax_highlight_top_level_defs<'a>( + arena: &'a Bump, + buf: &mut BumpString<'a>, + code_str: &'a str, + env_module_id: ModuleId, + env_module_ids: &'a ModuleIds, + interns: &Interns +) -> Result> { + let trimmed_code_str = code_str.trim_end().trim(); + + match roc_parse::test_helpers::parse_defs_with(arena, trimmed_code_str) { + Ok(vec_loc_def) => { + let vec_def = + vec_loc_def.iter().map(|loc| loc.value).collect(); + + defs_to_html(buf, vec_def, env_module_id, env_module_ids, interns); + + Ok(buf.to_string()) + } + Err(err) => Err(err), + } } // TODO improve name, what is main content? @@ -997,7 +979,7 @@ fn markdown_to_html( let code_block_arena = Bump::new(); let mut code_block_buf = BumpString::new_in(&code_block_arena); - match syntax_highlight_code( + match syntax_highlight_expr( &code_block_arena, &mut code_block_buf, code_str, diff --git a/docs/src/static/styles.css b/docs/src/static/styles.css index 94dc026ca1..799d849a86 100644 --- a/docs/src/static/styles.css +++ b/docs/src/static/styles.css @@ -7,7 +7,6 @@ --body-bg-color: #fdfdfd; --border-color: #e9e9e9; --faded-color: #4c4c4c; - --monospace-font; --font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif; --font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; --top-header-height: 67px; @@ -310,22 +309,25 @@ pre { display: none !important; } -.syntax-num { - color: #8080ff; +.syntax-number { + color: #60B7BF; +} +.syntax-string { + color:#F7577C; } +.syntax-bracket { + color:#FF335F; +} .syntax-closure-dash, .syntax-closure-arrow, -.syntax-operator , -.syntax-param-comma +.syntax-operator { - color: #ff0000; + color: #ffffff; } - -.syntax-str { - color:#ffff00; +.syntax-comma { + color: #9573E6; } - .syntax-comment { color: #ff0000; } diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs index 6ee032d9ce..4b0ee3e72a 100644 --- a/docs/tests/insert_syntax_highlighting.rs +++ b/docs/tests/insert_syntax_highlighting.rs @@ -7,11 +7,11 @@ mod insert_doc_syntax_highlighting { use roc_can::env::Env; use roc_can::scope::Scope; use roc_collections::all::MutMap; - use roc_docs::syntax_highlight_code; + use roc_docs::{syntax_highlight_expr, syntax_highlight_top_level_defs}; use roc_module::symbol::{IdentIds, Interns, ModuleIds}; use roc_types::subs::VarStore; - fn expect_html(code_str: &str, want: &str) { + fn expect_html(code_str: &str, want: &str, use_expr: bool) { let code_block_arena = Bump::new(); @@ -24,52 +24,97 @@ mod insert_doc_syntax_highlighting { }; let mut code_block_buf = BumpString::new_in(&code_block_arena); - match syntax_highlight_code( - &code_block_arena, - &mut code_block_buf, - code_str, - mod_id, - &module_ids, - &interns - ) { - Ok(highlighted_code_str) => { - assert_eq!(highlighted_code_str, want); - } - Err(syntax_error) => { - panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) - } - }; + if use_expr { + match syntax_highlight_expr( + &code_block_arena, + &mut code_block_buf, + code_str, + mod_id, + &module_ids, + &interns + ) { + Ok(highlighted_code_str) => { + assert_eq!(highlighted_code_str, want); + } + Err(syntax_error) => { + panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) + } + }; + } else { + match syntax_highlight_top_level_defs( + &code_block_arena, + &mut code_block_buf, + code_str, + mod_id, + &module_ids, + &interns + ) { + Ok(highlighted_code_str) => { + assert_eq!(highlighted_code_str, want); + } + Err(syntax_error) => { + panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) + } + }; + } + } - /*#[test] - fn simple_code_block() { - expect_html( - r#" - f = \x, y -> - b = 6 - c - - "string" - "#, - r#" -
x
:
Nat
-
x
=
-
4
- -
2
- "#, - ); - }*/ + fn expect_html_expr(code_str: &str, want: &str) { + expect_html(code_str, want, true) + } + + fn expect_html_def(code_str: &str, want: &str) { + expect_html(code_str, want, false) + } #[test] - fn simple_code_block() { - expect_html( - r#" - 2 - "#, - r#" -
2
- "#, + fn number_expr() { + expect_html_expr( + "2", + r#"2"#, + ); + } + + #[test] + fn string_expr() { + expect_html_expr( + r#""abc""#, + r#""abc""#, + ); + } + + #[test] + fn empty_list_expr() { + expect_html_expr( + r#"[]"#, + r#"[ ]"#, + ); + } + + #[test] + fn single_elt_list_expr() { + expect_html_expr( + r#"[ 0 ]"#, + r#"[ 0 ]"#, + ); + } + + #[test] + fn multi_elt_list_expr() { + expect_html_expr( + r#"[ "hello", "WoRlD" ]"#, + r#"[ "hello", "WoRlD" ]"#, + ); + } + + // TODO test record, nested records + + #[test] + fn function_def() { + expect_html_def( + r#"main = "Hello, World!""#, + r#"TODO"#, ); } } From 548d806a88a39a23ef8b03784876a7a65c519665 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 4 Oct 2021 19:26:31 +0200 Subject: [PATCH 7/9] def->MarkupNode working --- Cargo.lock | 4 ++ ast/Cargo.toml | 2 + ast/src/lib.rs | 1 + ast/src/module.rs | 39 +++++++++++++ compiler/module/src/symbol.rs | 1 + docs/Cargo.toml | 2 + docs/src/lib.rs | 9 ++- docs/tests/insert_syntax_highlighting.rs | 70 ++++++++++++++++-------- editor/src/editor/main.rs | 39 +------------ editor/src/editor/mvc/ed_model.rs | 2 +- 10 files changed, 103 insertions(+), 66 deletions(-) create mode 100644 ast/src/module.rs diff --git a/Cargo.lock b/Cargo.lock index e3520f0753..126168bb7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3397,8 +3397,10 @@ dependencies = [ "libc", "page_size", "pretty_assertions 0.6.1", + "roc_builtins", "roc_can", "roc_collections", + "roc_load", "roc_module", "roc_parse", "roc_problem", @@ -3593,6 +3595,8 @@ dependencies = [ "roc_parse", "roc_region", "roc_types", + "tempfile", + "uuid", ] [[package]] diff --git a/ast/Cargo.toml b/ast/Cargo.toml index 39bf52a471..a379da9d8e 100644 --- a/ast/Cargo.toml +++ b/ast/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" description = "AST as used by the editor and (soon) docs. In contrast to the compiler, these types do not keep track of a location in a file." [dependencies] +roc_builtins = { path = "../compiler/builtins"} roc_can = { path = "../compiler/can" } roc_collections = { path = "../compiler/collections" } roc_region = { path = "../compiler/region" } @@ -15,6 +16,7 @@ roc_parse = { path = "../compiler/parse" } roc_problem = { path = "../compiler/problem" } roc_types = { path = "../compiler/types" } roc_unify = { path = "../compiler/unify"} +roc_load = { path = "../compiler/load" } arraystring = "0.3.0" bumpalo = { version = "3.6.1", features = ["collections"] } libc = "0.2" diff --git a/ast/src/lib.rs b/ast/src/lib.rs index b3d987f99f..1cf2c1bf7f 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -5,3 +5,4 @@ pub mod lang; pub mod mem_pool; pub mod parse; pub mod solve_type; +pub mod module; diff --git a/ast/src/module.rs b/ast/src/module.rs new file mode 100644 index 0000000000..4d2735a990 --- /dev/null +++ b/ast/src/module.rs @@ -0,0 +1,39 @@ +use std::path::Path; + +use bumpalo::Bump; +use roc_collections::all::MutMap; +use roc_load::file::LoadedModule; + +pub fn load_module(src_file: &Path) -> LoadedModule { + let subs_by_module = MutMap::default(); + + let arena = Bump::new(); + let loaded = roc_load::file::load_and_typecheck( + &arena, + src_file.to_path_buf(), + arena.alloc(roc_builtins::std::standard_stdlib()), + src_file.parent().unwrap_or_else(|| { + panic!( + "src_file {:?} did not have a parent directory but I need to have one.", + src_file + ) + }), + subs_by_module, + 8, + roc_can::builtins::builtin_defs_map, + ); + + match loaded { + Ok(x) => x, + Err(roc_load::file::LoadingProblem::FormattedReport(report)) => { + panic!( + "Failed to load module from src_file {:?}. Report: {:?}", + src_file, report + ); + } + Err(e) => panic!( + "Failed to load module from src_file {:?}: {:?}", + src_file, e + ), + } +} \ No newline at end of file diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index c3e0f46c3a..e3d400bdba 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -70,6 +70,7 @@ impl Symbol { } pub fn ident_str(self, interns: &Interns) -> &IdentStr { + let ident_ids = interns .all_ident_ids .get(&self.module_id()) diff --git a/docs/Cargo.toml b/docs/Cargo.toml index c311423548..883305d1e1 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -25,3 +25,5 @@ bumpalo = { version = "3.2", features = ["collections"] } [dev-dependencies] pretty_assertions = "0.5.1" maplit = "1.0.1" +tempfile = "3.2.0" +uuid = { version = "0.8", features = ["v4"] } diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 3d8d2d09f7..54251da957 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -25,7 +25,7 @@ mod html; mod pattern; pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: &Path) { - let files_docs = load_modules_for_files(filenames, std_lib); + let loaded_modules = load_modules_for_files(filenames, std_lib); let mut arena = Bump::new(); // @@ -34,7 +34,7 @@ pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: & name: "roc/builtins".to_string(), version: "1.0.0".to_string(), docs: "Package introduction or README.".to_string(), - modules: files_docs, + modules: loaded_modules, }; if !build_dir.exists() { @@ -111,7 +111,7 @@ pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: & ) .replace( "", - render_main_content( + render_module_documentation( exports, module_docs, &loaded_module @@ -173,8 +173,7 @@ pub fn syntax_highlight_top_level_defs<'a>( } } -// TODO improve name, what is main content? -fn render_main_content( +fn render_module_documentation( exposed_values: &[&str], module: &ModuleDocumentation, loaded_module: &LoadedModule, diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs index 4b0ee3e72a..655c3dc6b2 100644 --- a/docs/tests/insert_syntax_highlighting.rs +++ b/docs/tests/insert_syntax_highlighting.rs @@ -3,25 +3,21 @@ extern crate pretty_assertions; #[cfg(test)] mod insert_doc_syntax_highlighting { + use std::{fs::File, io::Write, path::PathBuf}; + + use bumpalo::{collections::String as BumpString, Bump}; - use roc_can::env::Env; - use roc_can::scope::Scope; - use roc_collections::all::MutMap; + use roc_ast::module::load_module; use roc_docs::{syntax_highlight_expr, syntax_highlight_top_level_defs}; - use roc_module::symbol::{IdentIds, Interns, ModuleIds}; - use roc_types::subs::VarStore; + use roc_load::file::LoadedModule; + use tempfile::tempdir; + use uuid::Uuid; fn expect_html(code_str: &str, want: &str, use_expr: bool) { + + let loaded_module = make_mock_module(); + let code_block_arena = Bump::new(); - - - let mut module_ids = ModuleIds::default(); - let mod_id = module_ids.get_or_insert(&"ModId123".into()); - - let interns = Interns { - module_ids: module_ids.clone(), - all_ident_ids: IdentIds::exposed_builtins(8), - }; let mut code_block_buf = BumpString::new_in(&code_block_arena); if use_expr { @@ -29,9 +25,9 @@ mod insert_doc_syntax_highlighting { &code_block_arena, &mut code_block_buf, code_str, - mod_id, - &module_ids, - &interns + loaded_module.module_id, + &loaded_module.interns.module_ids, + &loaded_module.interns ) { Ok(highlighted_code_str) => { assert_eq!(highlighted_code_str, want); @@ -45,9 +41,9 @@ mod insert_doc_syntax_highlighting { &code_block_arena, &mut code_block_buf, code_str, - mod_id, - &module_ids, - &interns + loaded_module.module_id, + &loaded_module.interns.module_ids, + &loaded_module.interns ) { Ok(highlighted_code_str) => { assert_eq!(highlighted_code_str, want); @@ -60,6 +56,36 @@ mod insert_doc_syntax_highlighting { } + pub const HELLO_WORLD: &str = r#" +app "test-app" + packages { base: "platform" } + imports [] + provides [ main ] to base + +main = "Hello, world!" + + +"#; + + + fn make_mock_module() -> LoadedModule { + let temp_dir = tempdir().expect("Failed to create temporary directory for test."); + let temp_file_path_buf = + PathBuf::from([Uuid::new_v4().to_string(), ".roc".to_string()].join("")); + let temp_file_full_path = temp_dir.path().join(temp_file_path_buf); + + let mut file = File::create(temp_file_full_path.clone()).expect(&format!( + "Failed to create temporary file for path {:?}", + temp_file_full_path + )); + writeln!(file, "{}", HELLO_WORLD).expect(&format!( + "Failed to write {:?} to file: {:?}", + HELLO_WORLD, file + )); + + load_module(&temp_file_full_path) + } + fn expect_html_expr(code_str: &str, want: &str) { expect_html(code_str, want, true) } @@ -111,10 +137,10 @@ mod insert_doc_syntax_highlighting { // TODO test record, nested records #[test] - fn function_def() { + fn top_level_value_def() { expect_html_def( r#"main = "Hello, World!""#, - r#"TODO"#, + "main = \"Hello, World!\"\n\n", ); } } diff --git a/editor/src/editor/main.rs b/editor/src/editor/main.rs index 4b68ed3f8d..5e6b70439f 100644 --- a/editor/src/editor/main.rs +++ b/editor/src/editor/main.rs @@ -25,10 +25,7 @@ use fs_extra::dir::{copy, ls, CopyOptions, DirEntryAttr, DirEntryValue}; use pipelines::RectResources; use roc_ast::lang::env::Env; use roc_ast::mem_pool::pool::Pool; -use roc_can::builtins::builtin_defs_map; -use roc_collections::all::MutMap; -use roc_load; -use roc_load::file::LoadedModule; +use roc_ast::module::load_module; use roc_module::symbol::IdentIds; use roc_types::subs::VarStore; use std::collections::HashSet; @@ -552,40 +549,6 @@ fn copy_roc_platform_if_not_exists( } } -pub fn load_module(src_file: &Path) -> LoadedModule { - let subs_by_module = MutMap::default(); - - let arena = Bump::new(); - let loaded = roc_load::file::load_and_typecheck( - &arena, - src_file.to_path_buf(), - arena.alloc(roc_builtins::std::standard_stdlib()), - src_file.parent().unwrap_or_else(|| { - panic!( - "src_file {:?} did not have a parent directory but I need to have one.", - src_file - ) - }), - subs_by_module, - 8, - builtin_defs_map, - ); - - match loaded { - Ok(x) => x, - Err(roc_load::file::LoadingProblem::FormattedReport(report)) => { - panic!( - "Failed to load module from src_file {:?}. Report: {:?}", - src_file, report - ); - } - Err(e) => panic!( - "Failed to load module from src_file {:?}: {:?}", - src_file, e - ), - } -} - fn queue_no_file_text( size: &PhysicalSize, text: &str, diff --git a/editor/src/editor/mvc/ed_model.rs b/editor/src/editor/mvc/ed_model.rs index d22f92d934..8d7f85db20 100644 --- a/editor/src/editor/mvc/ed_model.rs +++ b/editor/src/editor/mvc/ed_model.rs @@ -198,7 +198,6 @@ impl<'a> EdModule<'a> { #[cfg(test)] pub mod test_ed_model { use crate::editor::ed_error::EdResult; - use crate::editor::main::load_module; use crate::editor::mvc::ed_model; use crate::editor::resources::strings::HELLO_WORLD; use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection; @@ -211,6 +210,7 @@ pub mod test_ed_model { use ed_model::EdModel; use roc_ast::lang::env::Env; use roc_ast::mem_pool::pool::Pool; + use roc_ast::module::load_module; use roc_load::file::LoadedModule; use roc_module::symbol::IdentIds; use roc_module::symbol::ModuleIds; From 4324b08a30f7e25bd4e52440f2c04f7b278678fb Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 5 Oct 2021 11:58:11 +0200 Subject: [PATCH 8/9] cleanup+fmt+clippy --- ast/src/canonicalization/canonicalize.rs | 3 +- ast/src/lang/core/def/def.rs | 3 +- ast/src/lang/core/expr/expr_to_expr2.rs | 9 ++- ast/src/lib.rs | 2 +- ast/src/module.rs | 2 +- code_markup/src/markup/nodes.rs | 12 ++-- compiler/module/src/symbol.rs | 1 - docs/src/comment_or_new_line.rs | 29 -------- docs/src/def.rs | 79 ++++++---------------- docs/src/expr.rs | 40 +++++------ docs/src/html.rs | 86 +++++++----------------- docs/src/lib.rs | 26 +++---- docs/src/pattern.rs | 52 -------------- docs/tests/insert_syntax_highlighting.rs | 44 +++++++----- 14 files changed, 121 insertions(+), 267 deletions(-) delete mode 100644 docs/src/comment_or_new_line.rs delete mode 100644 docs/src/pattern.rs diff --git a/ast/src/canonicalization/canonicalize.rs b/ast/src/canonicalization/canonicalize.rs index f6a8d00b5c..ff013615d2 100644 --- a/ast/src/canonicalization/canonicalize.rs +++ b/ast/src/canonicalization/canonicalize.rs @@ -147,7 +147,8 @@ fn canonicalize_field<'a>( // Both a label and a value, e.g. `{ name: "blah" }` RequiredValue(label, _, loc_expr) => { let field_var = env.var_store.fresh(); - let (loc_can_expr, output) = expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); + let (loc_can_expr, output) = + expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); Ok(CanonicalField::LabelAndValue { label: label.value, diff --git a/ast/src/lang/core/def/def.rs b/ast/src/lang/core/def/def.rs index 9584175493..1fd54b4828 100644 --- a/ast/src/lang/core/def/def.rs +++ b/ast/src/lang/core/def/def.rs @@ -639,7 +639,8 @@ fn canonicalize_pending_def<'a>( env.closure_name_symbol = Some(*defined_symbol); }; - let (loc_can_expr, can_output) = expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); + let (loc_can_expr, can_output) = + expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region); output.references.union_mut(can_output.references.clone()); diff --git a/ast/src/lang/core/expr/expr_to_expr2.rs b/ast/src/lang/core/expr/expr_to_expr2.rs index 9e96fac7e5..ebe8ba2fc9 100644 --- a/ast/src/lang/core/expr/expr_to_expr2.rs +++ b/ast/src/lang/core/expr/expr_to_expr2.rs @@ -309,7 +309,8 @@ pub fn expr_to_expr2<'a>( let mut output = Output::default(); for (condition, then_branch) in branches.iter() { - let (cond, cond_output) = expr_to_expr2(env, scope, &condition.value, condition.region); + let (cond, cond_output) = + expr_to_expr2(env, scope, &condition.value, condition.region); let (then_expr, then_output) = expr_to_expr2(env, scope, &then_branch.value, then_branch.region); @@ -338,7 +339,8 @@ pub fn expr_to_expr2<'a>( When(loc_cond, branches) => { // Infer the condition expression's type. let cond_var = env.var_store.fresh(); - let (can_cond, mut output) = expr_to_expr2(env, scope, &loc_cond.value, loc_cond.region); + let (can_cond, mut output) = + expr_to_expr2(env, scope, &loc_cond.value, loc_cond.region); // the condition can never be a tail-call output.tail_call = None; @@ -592,7 +594,8 @@ pub fn expr_to_expr2<'a>( // The def as a whole is a tail call iff its return expression is a tail call. // Use its output as a starting point because its tail_call already has the right answer! - let (ret_expr, mut output) = expr_to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region); + let (ret_expr, mut output) = + expr_to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region); output .introduced_variables diff --git a/ast/src/lib.rs b/ast/src/lib.rs index 1cf2c1bf7f..092b86154e 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -3,6 +3,6 @@ mod canonicalization; pub mod constrain; pub mod lang; pub mod mem_pool; +pub mod module; pub mod parse; pub mod solve_type; -pub mod module; diff --git a/ast/src/module.rs b/ast/src/module.rs index 4d2735a990..e744760c42 100644 --- a/ast/src/module.rs +++ b/ast/src/module.rs @@ -36,4 +36,4 @@ pub fn load_module(src_file: &Path) -> LoadedModule { src_file, e ), } -} \ No newline at end of file +} diff --git a/code_markup/src/markup/nodes.rs b/code_markup/src/markup/nodes.rs index 50e1489150..5243a9438b 100644 --- a/code_markup/src/markup/nodes.rs +++ b/code_markup/src/markup/nodes.rs @@ -304,8 +304,8 @@ fn new_markup_node( mark_node_pool.add(node) } -pub fn def2_to_markup<'a, 'b>( - env: &mut Env<'b>, +pub fn def2_to_markup<'a>( + env: &mut Env<'a>, def2: &Def2, def2_node_id: DefId, mark_node_pool: &mut SlowPool, @@ -344,8 +344,8 @@ pub fn def2_to_markup<'a, 'b>( } // make Markup Nodes: generate String representation, assign Highlighting Style -pub fn expr2_to_markup<'a, 'b>( - env: &mut Env<'b>, +pub fn expr2_to_markup<'a>( + env: &mut Env<'a>, expr2: &Expr2, expr2_node_id: ExprId, mark_node_pool: &mut SlowPool, @@ -790,8 +790,8 @@ fn add_header_mn_list( .collect() } -pub fn ast_to_mark_nodes<'a, 'b>( - env: &mut Env<'b>, +pub fn ast_to_mark_nodes<'a>( + env: &mut Env<'a>, ast: &AST, mark_node_pool: &mut SlowPool, interns: &Interns, diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index e3d400bdba..c3e0f46c3a 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -70,7 +70,6 @@ impl Symbol { } pub fn ident_str(self, interns: &Interns) -> &IdentStr { - let ident_ids = interns .all_ident_ids .get(&self.module_id()) diff --git a/docs/src/comment_or_new_line.rs b/docs/src/comment_or_new_line.rs deleted file mode 100644 index 811a879fb2..0000000000 --- a/docs/src/comment_or_new_line.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::html::ToHtml; -use roc_parse::ast::CommentOrNewline; - -impl<'a> ToHtml<'a> for CommentOrNewline<'a> { - fn css_class(&self) -> Option<&'a str> { - match self { - CommentOrNewline::Newline => None, - CommentOrNewline::LineComment(_) => Some("comment"), - CommentOrNewline::DocComment(_) => Some("comment"), - } - } - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - match self { - CommentOrNewline::Newline => { - buf.push('\n'); - } - CommentOrNewline::LineComment(comment) => { - buf.push('#'); - buf.push_str(comment); - buf.push('\n'); - } - CommentOrNewline::DocComment(comment) => { - buf.push_str("##"); - buf.push_str(comment); - buf.push('\n'); - } - } - } -} diff --git a/docs/src/def.rs b/docs/src/def.rs index 6923b933a0..e94c6d32df 100644 --- a/docs/src/def.rs +++ b/docs/src/def.rs @@ -1,27 +1,36 @@ -use roc_ast::{ast_error::ASTResult, lang::{self, core::def::def_to_def2::def_to_def2}, mem_pool::pool::Pool}; +use bumpalo::{collections::String as BumpString, Bump}; +use roc_ast::{ + ast_error::ASTResult, + lang::{self, core::def::def_to_def2::def_to_def2}, + mem_pool::pool::Pool, +}; use roc_code_markup::{markup::nodes::def2_to_markup, slow_pool::SlowPool}; use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; use roc_region::all::Region; -use bumpalo::{Bump, collections::String as BumpString}; use roc_types::subs::VarStore; use crate::html::mark_node_to_html; // html is written to buf -pub fn defs_to_html<'a>(buf: &mut BumpString<'a>, defs: Vec>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { - +pub fn defs_to_html<'a>( + buf: &mut BumpString<'a>, + defs: Vec>, + env_module_id: ModuleId, + env_module_ids: &'a ModuleIds, + interns: &Interns, +) { let mut env_pool = Pool::with_capacity(1024); - let mut env_arena = Bump::new(); + let env_arena = Bump::new(); let mut var_store = VarStore::default(); let dep_idents = IdentIds::exposed_builtins(8); let exposed_ident_ids = IdentIds::default(); let def_arena = Bump::new(); - + let mut env = lang::env::Env::new( env_module_id, - &mut env_arena, + &env_arena, &mut env_pool, &mut var_store, dep_idents, @@ -32,60 +41,13 @@ pub fn defs_to_html<'a>(buf: &mut BumpString<'a>, defs: Vec(buf: &mut BumpString<'a>, def: roc_parse::ast::Def<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { - - let mut env_pool = Pool::with_capacity(1024); - let mut env_arena = Bump::new(); - - let mut var_store = VarStore::default(); - let dep_idents = IdentIds::exposed_builtins(8); - let exposed_ident_ids = IdentIds::default(); - - let def_arena = Bump::new(); - - let mut env = lang::env::Env::new( - env_module_id, - &mut env_arena, - &mut env_pool, - &mut var_store, - dep_idents, - env_module_ids, - exposed_ident_ids, - ); - - let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store); - let region = Region::new(0, 0, 0, 0); - - - // TODO remove unwrap - write_def_to_bump_str_html( - &def_arena, - &mut env, - &mut scope, - region, - &def, - interns, - buf - ).unwrap(); -} - fn write_def_to_bump_str_html<'a, 'b>( arena: &'a Bump, env: &mut lang::env::Env<'a>, @@ -93,9 +55,8 @@ fn write_def_to_bump_str_html<'a, 'b>( region: Region, def: &'a roc_parse::ast::Def<'a>, interns: &Interns, - buf: &mut BumpString<'b> + buf: &mut BumpString<'b>, ) -> ASTResult<()> { - let def2 = def_to_def2(arena, env, scope, def, region); let mut def2_pool = Pool::with_capacity(1024); @@ -105,7 +66,7 @@ fn write_def_to_bump_str_html<'a, 'b>( let def2_markup_id = def2_to_markup( env, - &def2_pool.get(def2_id), + def2_pool.get(def2_id), def2_id, &mut mark_node_pool, interns, diff --git a/docs/src/expr.rs b/docs/src/expr.rs index b7e5b9da90..c7814f60c2 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -1,17 +1,26 @@ -use crate::html::{mark_node_to_html}; -use roc_ast::{ast_error::ASTResult, lang::{self, core::expr::expr_to_expr2::expr_to_expr2}, mem_pool::pool::Pool}; +use crate::html::mark_node_to_html; +use bumpalo::{collections::String as BumpString, Bump}; +use roc_ast::{ + ast_error::ASTResult, + lang::{self, core::expr::expr_to_expr2::expr_to_expr2}, + mem_pool::pool::Pool, +}; use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool}; use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; -use roc_parse::ast::{Expr}; -use roc_region::all::{Region}; -use bumpalo::{Bump, collections::String as BumpString}; +use roc_parse::ast::Expr; +use roc_region::all::Region; use roc_types::subs::VarStore; // html is written to buf -pub fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) { - +pub fn expr_to_html<'a>( + buf: &mut BumpString<'a>, + expr: Expr<'a>, + env_module_id: ModuleId, + env_module_ids: &'a ModuleIds, + interns: &Interns, +) { let mut env_pool = Pool::with_capacity(1024); - let mut env_arena = Bump::new(); + let env_arena = Bump::new(); let mut var_store = VarStore::default(); let dep_idents = IdentIds::exposed_builtins(8); @@ -19,7 +28,7 @@ pub fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: let mut env = lang::env::Env::new( env_module_id, - &mut env_arena, + &env_arena, &mut env_pool, &mut var_store, dep_idents, @@ -31,14 +40,7 @@ pub fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: let region = Region::new(0, 0, 0, 0); // TODO remove unwrap - write_expr_to_bump_str_html( - &mut env, - &mut scope, - region, - &expr, - interns, - buf - ).unwrap(); + write_expr_to_bump_str_html(&mut env, &mut scope, region, &expr, interns, buf).unwrap(); } fn write_expr_to_bump_str_html<'a, 'b>( @@ -47,7 +49,7 @@ fn write_expr_to_bump_str_html<'a, 'b>( region: Region, expr: &'a Expr, interns: &Interns, - buf: &mut BumpString<'b> + buf: &mut BumpString<'b>, ) -> ASTResult<()> { let (expr2, _) = expr_to_expr2(env, scope, expr, region); @@ -58,7 +60,7 @@ fn write_expr_to_bump_str_html<'a, 'b>( let expr2_markup_id = expr2_to_markup( env, - &expr2_pool.get(expr2_id), + expr2_pool.get(expr2_id), expr2_id, &mut mark_node_pool, interns, diff --git a/docs/src/html.rs b/docs/src/html.rs index 7cdb041a6a..4a85663970 100644 --- a/docs/src/html.rs +++ b/docs/src/html.rs @@ -1,69 +1,32 @@ +use bumpalo::collections::String as BumpString; use roc_code_markup::{markup::nodes::MarkupNode, slow_pool::SlowPool}; -use roc_region::all::Located; -use bumpalo::{collections::String as BumpString}; - -pub trait ToHtml<'a> { - fn css_class(&self) -> Option<&'a str>; - - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>); - - fn html(&self, buf: &mut bumpalo::collections::String<'a>) { - let maybe_css_class = self.css_class(); - - if let Some(css_class) = maybe_css_class { - let opening_tag: String = [""].concat(); - - buf.push_str(opening_tag.as_str()); - } - - self.html_body(buf); - - if let Some(_) = maybe_css_class { - buf.push_str(""); - } - } -} - -impl<'a, T> ToHtml<'a> for Located -where - T: ToHtml<'a>, -{ - fn css_class(&self) -> Option<&'a str> { - None - } - - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - let start_col = self.region.start_col as usize; - - let last_newline_to_end = buf.len() - buf.rfind("\n").unwrap_or_else(|| buf.len()); - - if start_col > last_newline_to_end { - let new_spaces = start_col - last_newline_to_end; - buf.push_str((0..new_spaces).map(|_| " ").collect::().as_str()); - }; - - self.value.html(buf); - } -} - // determine appropriate css class for MarkupNode -pub fn mark_node_to_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &mut BumpString<'a>) { - let additional_newlines:usize; - +pub fn mark_node_to_html<'a>( + mark_node: &MarkupNode, + mark_node_pool: &SlowPool, + buf: &mut BumpString<'a>, +) { + let additional_newlines: usize; + match mark_node { - MarkupNode::Nested { children_ids, newlines_at_end, .. } => { + MarkupNode::Nested { + children_ids, + newlines_at_end, + .. + } => { for &child_id in children_ids { - mark_node_to_html( - mark_node_pool.get(child_id), - mark_node_pool, - buf - ) + mark_node_to_html(mark_node_pool.get(child_id), mark_node_pool, buf) } additional_newlines = *newlines_at_end; } - MarkupNode::Text { content, syn_high_style, newlines_at_end, .. } => { + MarkupNode::Text { + content, + syn_high_style, + newlines_at_end, + .. + } => { use roc_code_markup::syntax_highlight::HighlightStyle::*; let css_class = match syn_high_style { @@ -86,7 +49,9 @@ pub fn mark_node_to_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, additional_newlines = *newlines_at_end; } - MarkupNode::Blank { newlines_at_end, .. } => { + MarkupNode::Blank { + newlines_at_end, .. + } => { let mut content_str = " ".to_string(); for _ in 0..*newlines_at_end { @@ -102,17 +67,14 @@ pub fn mark_node_to_html<'a>(mark_node: &MarkupNode, mark_node_pool: &SlowPool, for _ in 0..additional_newlines { buf.push('\n') } - } fn write_html_to_buf<'a>(content: &str, css_class: &'static str, buf: &mut BumpString<'a>) { - let opening_tag: String = [""].concat(); buf.push_str(opening_tag.as_str()); - + buf.push_str(content); buf.push_str(""); } - diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 54251da957..1565fb6527 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -2,7 +2,7 @@ extern crate pulldown_cmark; extern crate roc_load; use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump}; use def::defs_to_html; -use expr::{expr_to_html}; +use expr::expr_to_html; use roc_builtins::std::StdLib; use roc_can::builtins::builtin_defs_map; use roc_can::scope::Scope; @@ -18,11 +18,9 @@ use roc_region::all::Region; use std::fs; use std::path::{Path, PathBuf}; -mod comment_or_new_line; mod def; mod expr; mod html; -mod pattern; pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: &Path) { let loaded_modules = load_modules_for_files(filenames, std_lib); @@ -111,12 +109,7 @@ pub fn generate_docs_html(filenames: Vec, std_lib: StdLib, build_dir: & ) .replace( "", - render_module_documentation( - exports, - module_docs, - &loaded_module - ) - .as_str(), + render_module_documentation(exports, module_docs, loaded_module).as_str(), ); fs::write(module_dir.join("index.html"), rendered_module) @@ -134,7 +127,7 @@ pub fn syntax_highlight_expr<'a>( code_str: &'a str, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, - interns: &Interns + interns: &Interns, ) -> Result> { let trimmed_code_str = code_str.trim_end().trim(); let state = State::new(trimmed_code_str.as_bytes()); @@ -156,15 +149,14 @@ pub fn syntax_highlight_top_level_defs<'a>( code_str: &'a str, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, - interns: &Interns + interns: &Interns, ) -> Result> { let trimmed_code_str = code_str.trim_end().trim(); match roc_parse::test_helpers::parse_defs_with(arena, trimmed_code_str) { Ok(vec_loc_def) => { - let vec_def = - vec_loc_def.iter().map(|loc| loc.value).collect(); - + let vec_def = vec_loc_def.iter().map(|loc| loc.value).collect(); + defs_to_html(buf, vec_def, env_module_id, env_module_ids, interns); Ok(buf.to_string()) @@ -208,7 +200,9 @@ fn render_module_documentation( let mut content = String::new(); - content.push_str(html_to_string("a", vec![("href", href.as_str())], name).as_str()); + content.push_str( + html_to_string("a", vec![("href", href.as_str())], name).as_str(), + ); for type_var in &doc_def.type_vars { content.push(' '); @@ -985,7 +979,7 @@ fn markdown_to_html( loaded_module.module_id, &loaded_module.interns.module_ids, &loaded_module.interns - ) + ) { Ok(highlighted_code_str) => { docs_parser.push(Event::Html(CowStr::from(highlighted_code_str))); diff --git a/docs/src/pattern.rs b/docs/src/pattern.rs deleted file mode 100644 index 094aee8f8c..0000000000 --- a/docs/src/pattern.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::html::ToHtml; -use roc_parse::ast::Pattern; - -impl<'a> ToHtml<'a> for Pattern<'a> { - fn css_class(&self) -> Option<&'a str> { - match self { - // Pattern::Identifier(_) => {} - // Pattern::GlobalTag(_) => {} - // Pattern::PrivateTag(_) => {} - // Pattern::Apply(_, _) => {} - // Pattern::RecordDestructure(_) => {} - // Pattern::RequiredField(_, _) => {} - // Pattern::OptionalField(_, _) => {} - // Pattern::NumLiteral(_) => {} - // Pattern::NonBase10Literal { .. } => {} - // Pattern::FloatLiteral(_) => {} - // Pattern::StrLiteral(_) => {} - // Pattern::Underscore(_) => {} - // Pattern::SpaceBefore(_, _) => {} - // Pattern::SpaceAfter(_, _) => {} - // Pattern::Malformed(_) => {} - // Pattern::MalformedIdent(_, _) => {} - // Pattern::QualifiedIdentifier { .. } => {} - _ => None, - } - } - - fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) { - match self { - Pattern::Identifier(str) => { - buf.push_str(str); - } - // Pattern::GlobalTag(_) => {} - // Pattern::PrivateTag(_) => {} - // Pattern::Apply(_, _) => {} - // Pattern::RecordDestructure(_) => {} - // Pattern::RequiredField(_, _) => {} - // Pattern::OptionalField(_, _) => {} - // Pattern::NumLiteral(_) => {} - // Pattern::NonBase10Literal { .. } => {} - // Pattern::FloatLiteral(_) => {} - // Pattern::StrLiteral(_) => {} - // Pattern::Underscore(_) => {} - // Pattern::SpaceBefore(_, _) => {} - // Pattern::SpaceAfter(_, _) => {} - // Pattern::Malformed(_) => {} - // Pattern::MalformedIdent(_, _) => {} - // Pattern::QualifiedIdentifier { .. } => {} - _ => {} - } - } -} diff --git a/docs/tests/insert_syntax_highlighting.rs b/docs/tests/insert_syntax_highlighting.rs index 655c3dc6b2..a031fbb07b 100644 --- a/docs/tests/insert_syntax_highlighting.rs +++ b/docs/tests/insert_syntax_highlighting.rs @@ -5,7 +5,6 @@ extern crate pretty_assertions; mod insert_doc_syntax_highlighting { use std::{fs::File, io::Write, path::PathBuf}; - use bumpalo::{collections::String as BumpString, Bump}; use roc_ast::module::load_module; use roc_docs::{syntax_highlight_expr, syntax_highlight_top_level_defs}; @@ -14,7 +13,6 @@ mod insert_doc_syntax_highlighting { use uuid::Uuid; fn expect_html(code_str: &str, want: &str, use_expr: bool) { - let loaded_module = make_mock_module(); let code_block_arena = Bump::new(); @@ -27,7 +25,7 @@ mod insert_doc_syntax_highlighting { code_str, loaded_module.module_id, &loaded_module.interns.module_ids, - &loaded_module.interns + &loaded_module.interns, ) { Ok(highlighted_code_str) => { assert_eq!(highlighted_code_str, want); @@ -43,7 +41,7 @@ mod insert_doc_syntax_highlighting { code_str, loaded_module.module_id, &loaded_module.interns.module_ids, - &loaded_module.interns + &loaded_module.interns, ) { Ok(highlighted_code_str) => { assert_eq!(highlighted_code_str, want); @@ -53,7 +51,6 @@ mod insert_doc_syntax_highlighting { } }; } - } pub const HELLO_WORLD: &str = r#" @@ -67,7 +64,6 @@ main = "Hello, world!" "#; - fn make_mock_module() -> LoadedModule { let temp_dir = tempdir().expect("Failed to create temporary directory for test."); let temp_file_path_buf = @@ -96,18 +92,12 @@ main = "Hello, world!" #[test] fn number_expr() { - expect_html_expr( - "2", - r#"2"#, - ); + expect_html_expr("2", r#"2"#); } #[test] fn string_expr() { - expect_html_expr( - r#""abc""#, - r#""abc""#, - ); + expect_html_expr(r#""abc""#, r#""abc""#); } #[test] @@ -134,13 +124,35 @@ main = "Hello, world!" ); } - // TODO test record, nested records + #[test] + fn record_expr() { + expect_html_expr( + r#"{ a: "hello!" }"#, + "{ a: \"hello!\" }", + ); + } #[test] - fn top_level_value_def() { + fn nested_record_expr() { + expect_html_expr( + r#"{ a: { bB: "WoRlD" } }"#, + "{ a: { bB: \"WoRlD\" } }", + ); + } + + #[test] + fn top_level_def_value() { expect_html_def( r#"main = "Hello, World!""#, "main = \"Hello, World!\"\n\n", ); } + + #[test] + fn tld_list() { + expect_html_def( + r#"main = [ 1, 2, 3 ]"#, + "main = [ 1, 2, 3 ]\n\n", + ); + } } From 78e360949873e815a7af583ba946208095a422a0 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 5 Oct 2021 14:51:57 +0200 Subject: [PATCH 9/9] minor cleanup --- docs/src/def.rs | 5 ++--- docs/src/expr.rs | 5 ++--- docs/src/static/index.html | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/src/def.rs b/docs/src/def.rs index e94c6d32df..0c562ade25 100644 --- a/docs/src/def.rs +++ b/docs/src/def.rs @@ -59,14 +59,13 @@ fn write_def_to_bump_str_html<'a, 'b>( ) -> ASTResult<()> { let def2 = def_to_def2(arena, env, scope, def, region); - let mut def2_pool = Pool::with_capacity(1024); - let def2_id = def2_pool.add(def2); + let def2_id = env.pool.add(def2); let mut mark_node_pool = SlowPool::default(); let def2_markup_id = def2_to_markup( env, - def2_pool.get(def2_id), + env.pool.get(def2_id), def2_id, &mut mark_node_pool, interns, diff --git a/docs/src/expr.rs b/docs/src/expr.rs index c7814f60c2..5651ebf056 100644 --- a/docs/src/expr.rs +++ b/docs/src/expr.rs @@ -53,14 +53,13 @@ fn write_expr_to_bump_str_html<'a, 'b>( ) -> ASTResult<()> { let (expr2, _) = expr_to_expr2(env, scope, expr, region); - let mut expr2_pool = Pool::with_capacity(1024); - let expr2_id = expr2_pool.add(expr2); + let expr2_id = env.pool.add(expr2); let mut mark_node_pool = SlowPool::default(); let expr2_markup_id = expr2_to_markup( env, - expr2_pool.get(expr2_id), + env.pool.get(expr2_id), expr2_id, &mut mark_node_pool, interns, diff --git a/docs/src/static/index.html b/docs/src/static/index.html index 48ffc31509..8a1ea794e8 100644 --- a/docs/src/static/index.html +++ b/docs/src/static/index.html @@ -41,7 +41,7 @@