From 352b3959299e30d5b94ce1397a082f7872ec5320 Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Tue, 22 Oct 2024 22:13:10 +0200 Subject: [PATCH] Range resolving --- src/elements/blockquote.rs | 4 +-- src/elements/code.rs | 6 ++--- src/elements/graphviz.rs | 4 +-- src/elements/layout.rs | 4 +-- src/elements/link.rs | 25 ++++--------------- src/elements/list.rs | 4 +-- src/elements/media.rs | 4 +-- src/elements/raw.rs | 4 +-- src/elements/reference.rs | 2 +- src/elements/script.rs | 51 ++++++++++++++------------------------ src/elements/tex.rs | 4 +-- src/lsp/semantic.rs | 1 - src/main.rs | 2 +- src/parser/source.rs | 2 -- src/parser/util.rs | 45 +++++++++++++-------------------- 15 files changed, 60 insertions(+), 102 deletions(-) diff --git a/src/elements/blockquote.rs b/src/elements/blockquote.rs index d54af18..fb5cb4c 100644 --- a/src/elements/blockquote.rs +++ b/src/elements/blockquote.rs @@ -33,7 +33,7 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::source::VirtualSource; use crate::parser::style::StyleHolder; -use crate::parser::util::process_escaped; +use crate::parser::util::escape_text; use crate::parser::util::Property; use crate::parser::util::PropertyParser; @@ -209,7 +209,7 @@ impl BlockquoteRule { &self, m: Match, ) -> Result<(Option, Option, Option), String> { - let processed = process_escaped('\\', "]", m.as_str()); + let processed = escape_text('\\', "]", m.as_str()); let pm = self.properties.parse(processed.as_str())?; let author = pm diff --git a/src/elements/code.rs b/src/elements/code.rs index 5d5b1ec..cbb1230 100644 --- a/src/elements/code.rs +++ b/src/elements/code.rs @@ -357,7 +357,7 @@ impl RegexRule for CodeRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => { reports.push( @@ -421,9 +421,9 @@ impl RegexRule for CodeRule { }; let mut code_content = if index == 0 { - util::process_escaped('\\', "```", matches.get(4).unwrap().as_str()) + util::escape_text('\\', "```", matches.get(4).unwrap().as_str()) } else { - util::process_escaped('\\', "``", matches.get(3).unwrap().as_str()) + util::escape_text('\\', "``", matches.get(3).unwrap().as_str()) }; if code_content.bytes().last() == Some(b'\n') // Remove newline diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs index fd205ff..c715dd7 100644 --- a/src/elements/graphviz.rs +++ b/src/elements/graphviz.rs @@ -227,7 +227,7 @@ impl RegexRule for GraphRule { return reports; } Some(content) => { - let processed = util::process_escaped( + let processed = util::escape_text( '\\', "[/graph]", content.as_str().trim_start().trim_end(), @@ -270,7 +270,7 @@ impl RegexRule for GraphRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => { reports.push( diff --git a/src/elements/layout.rs b/src/elements/layout.rs index 5907755..daa7e12 100644 --- a/src/elements/layout.rs +++ b/src/elements/layout.rs @@ -15,7 +15,7 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::state::RuleState; use crate::parser::state::Scope; -use crate::parser::util::process_escaped; +use crate::parser::util::escape_text; use ariadne::Fmt; use ariadne::Label; use ariadne::Report; @@ -361,7 +361,7 @@ impl LayoutRule { }, Some(props) => { let trimmed = props.as_str().trim_start().trim_end(); - let content = process_escaped('\\', "]", trimmed); + let content = escape_text('\\', "]", trimmed); match layout_type.parse_properties(content.as_str()) { Ok(props) => Ok(props), Err(err) => { diff --git a/src/elements/link.rs b/src/elements/link.rs index 0214da6..74c6d1e 100644 --- a/src/elements/link.rs +++ b/src/elements/link.rs @@ -371,26 +371,10 @@ nml.link.push("**BOLD link**", "another url") #[test] fn semantics() { - let source = Rc::new(SourceFile::with_content( - "".to_string(), - r#" - [la(*testi*nk](url) - "# - .to_string(), - None, - )); - let parser = LangParser::default(); - let (_, state) = parser.parse( - ParserState::new_with_semantics(&parser, None), - source.clone(), - None, - ParseMode::default(), - ); - println!("{:#?}", state.shared.semantics); - return; let source = Rc::new(SourceFile::with_content( "".to_string(), r#" -[li**n**k](url) + - [la\](*testi*nk](url) "# .to_string(), None, @@ -404,9 +388,10 @@ nml.link.push("**BOLD link**", "another url") ); validate_semantics!(state, source.clone(), 0, - link_display_sep { delta_line == 1, delta_start == 0, length == 1 }; - style_marker { delta_line == 0, delta_start == 3, length == 2 }; - style_marker { delta_line == 0, delta_start == 3, length == 2 }; + list_bullet { delta_line == 1, delta_start == 1, length == 1 }; + link_display_sep { delta_line == 0, delta_start == 2, length == 1 }; + style_marker { delta_line == 0, delta_start == 6, length == 1 }; + style_marker { delta_line == 0, delta_start == 6, length == 1 }; link_display_sep { delta_line == 0, delta_start == 3, length == 1 }; link_url_sep { delta_line == 0, delta_start == 1, length == 1 }; link_url { delta_line == 0, delta_start == 1, length == 3 }; diff --git a/src/elements/list.rs b/src/elements/list.rs index 42eb166..538d3bd 100644 --- a/src/elements/list.rs +++ b/src/elements/list.rs @@ -20,7 +20,7 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::source::VirtualSource; use crate::parser::util; -use crate::parser::util::process_escaped; +use crate::parser::util::escape_text; use crate::parser::util::Property; use crate::parser::util::PropertyMapError; use crate::parser::util::PropertyParser; @@ -196,7 +196,7 @@ impl ListRule { } fn parse_properties(&self, m: Match) -> Result<(Option, Option), String> { - let processed = process_escaped('\\', "]", m.as_str()); + let processed = escape_text('\\', "]", m.as_str()); let pm = self.properties.parse(processed.as_str())?; let offset = match pm.get("offset", |_, s| s.parse::()) { diff --git a/src/elements/media.rs b/src/elements/media.rs index 29b67cd..d2cd47d 100644 --- a/src/elements/media.rs +++ b/src/elements/media.rs @@ -306,7 +306,7 @@ impl MediaRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => Err( Report::build(ReportKind::Error, token.source(), props.start()) @@ -382,7 +382,7 @@ impl RegexRule for MediaRule { matches.get(2).unwrap(), MediaRule::validate_uri(matches.get(2).unwrap().as_str()), ) { - (_, Ok(uri)) => util::process_escaped('\\', ")", uri), + (_, Ok(uri)) => util::escape_text('\\', ")", uri), (m, Err(err)) => { reports.push( Report::build(ReportKind::Error, token.source(), m.start()) diff --git a/src/elements/raw.rs b/src/elements/raw.rs index f35efcf..23bc6b6 100644 --- a/src/elements/raw.rs +++ b/src/elements/raw.rs @@ -118,7 +118,7 @@ impl RegexRule for RawRule { } Some(content) => { let processed = - util::process_escaped('\\', "?}", content.as_str().trim_start().trim_end()); + util::escape_text('\\', "?}", content.as_str().trim_start().trim_end()); if processed.is_empty() { reports.push( @@ -155,7 +155,7 @@ impl RegexRule for RawRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => { reports.push( diff --git a/src/elements/reference.rs b/src/elements/reference.rs index caff5ee..5b43a5a 100644 --- a/src/elements/reference.rs +++ b/src/elements/reference.rs @@ -206,7 +206,7 @@ impl ReferenceRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => Err( Report::build(ReportKind::Error, token.source(), props.start()) diff --git a/src/elements/script.rs b/src/elements/script.rs index 0020a58..6bdbd98 100644 --- a/src/elements/script.rs +++ b/src/elements/script.rs @@ -10,6 +10,7 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::source::VirtualSource; use crate::parser::util; +use crate::parser::util::escape_source; use ariadne::Fmt; use ariadne::Label; use ariadne::Report; @@ -127,41 +128,27 @@ impl RegexRule for ScriptRule { } }; - let kernel_data = matches - .get(if index == 0 { 2 } else { 3 }) - .and_then(|code| { - let trimmed = code.as_str().trim_start().trim_end(); - (!trimmed.is_empty()).then_some((trimmed, code.range())) - }) - .or_else(|| { - reports.push( - Report::build(ReportKind::Warning, token.source(), token.start()) - .with_message("Invalid kernel code") - .with_label( - Label::new((token.source(), token.start() + 1..token.end())) - .with_message("Kernel code is empty") - .with_color(state.parser.colors().warning), - ) - .finish(), - ); - - None - }); - - if kernel_data.is_none() { - return reports; - } - - let (kernel_content, kernel_range) = kernel_data.unwrap(); - let source = Rc::new(VirtualSource::new( - Token::new(kernel_range, token.source()), - format!( + let script_range = matches.get(if index == 0 { 2 } else { 3 }).unwrap().range(); + let source = escape_source(token.source(), script_range.clone(), format!( ":LUA:{kernel_name}#{}#{}", token.source().name(), matches.get(0).unwrap().start() - ), - util::process_escaped('\\', ">@", kernel_content), - )) as Rc; + ), '\\', ">@"); + if source.content().is_empty() + { + reports.push( + Report::build(ReportKind::Warning, token.source(), token.start()) + .with_message("Invalid kernel code") + .with_label( + Label::new((token.source(), script_range)) + .with_message("Kernel code is empty") + .with_color(state.parser.colors().warning), + ) + .finish(), + ); + return reports; + } + let execute = |lua: &Lua| { let chunk = lua.load(source.content()).set_name(kernel_name); diff --git a/src/elements/tex.rs b/src/elements/tex.rs index a00e249..17b221e 100644 --- a/src/elements/tex.rs +++ b/src/elements/tex.rs @@ -286,7 +286,7 @@ impl TexRule { }, Some(props) => { let processed = - util::process_escaped('\\', "]", props.as_str().trim_start().trim_end()); + util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => Err( Report::build(ReportKind::Error, token.source(), props.start()) @@ -344,7 +344,7 @@ impl RegexRule for TexRule { return reports; } Some(content) => { - let processed = util::process_escaped( + let processed = util::escape_text( '\\', ["|$", "$"][index], content.as_str().trim_start().trim_end(), diff --git a/src/lsp/semantic.rs b/src/lsp/semantic.rs index 5e6ee59..fdeea28 100644 --- a/src/lsp/semantic.rs +++ b/src/lsp/semantic.rs @@ -320,7 +320,6 @@ impl<'a> Semantics<'a> { let mut tokens = self.sems.tokens.borrow_mut(); let mut cursor = self.sems.cursor.borrow_mut(); let mut current = cursor.clone(); - println!("range={range:#?}"); cursor.move_to(range.start); while cursor.pos != range.end { diff --git a/src/main.rs b/src/main.rs index 3dc9690..b47bb03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ fn main() -> ExitCode { let args: Vec = env::args().collect(); let program = args[0].clone(); - let mut opts = Options::new(); + slet mut opts = Options::new(); opts.optopt("i", "input", "Input path", "PATH"); opts.optopt("o", "output", "Output path", "PATH"); opts.optopt("d", "database", "Cache database location", "PATH"); diff --git a/src/parser/source.rs b/src/parser/source.rs index 4afaaaa..a5cb50f 100644 --- a/src/parser/source.rs +++ b/src/parser/source.rs @@ -176,7 +176,6 @@ pub fn original_range(source: Rc, mut range: Range) -> (Rc String { /// Transforms source into a new [`VirtualSource`]. Transforms range from source by /// detecting escaped tokens. /// +/// # Notes +/// +/// If you only need to escape content that won't be parsed, use [`process_escaped`] instead. pub fn escape_source(source: Rc, range: Range, name: String, escape: char, token: &'static str) -> Rc { let content = &source.content()[range.clone()]; @@ -144,23 +147,6 @@ pub fn escape_source(source: Rc, range: Range, name: String, )) } -pub fn app() -{ - let mut s = String::new(); - - let source = Rc::new(SourceFile::with_content( - "test".to_string(), - "a\\\\\\```b".into(), - None, - )); - let src = escape_source(source.clone(), 0..source.content().len(), "sub".to_string(), '\\', "```"); - println!("{}", src.content()); - let range = 0..src.content().len(); - println!("{:#?}", range); - let orange = original_range(src.clone(), range); - println!("{:#?}", orange); -} - /// Processed a string and escapes a single token out of it /// Escaped characters other than the [`token`] will be not be treated as escaped /// @@ -169,9 +155,12 @@ pub fn app() /// assert_eq!(process_escaped('\\', "%", "escaped: \\%, also escaped: \\\\\\%, untouched: \\a"), /// "escaped: %, also escaped: \\%, untouched: \\a"); /// ``` -/// TODO: Make this function return a delta to pass to the semantics, maybe store it in the virtualsource, so this function should return a source... -#[deprecated] -pub fn process_escaped>(escape: char, token: &'static str, content: S) -> String { +/// +/// # Notes +/// +/// If you need to create a source, do not use this function, use [`escape_source`] instead +/// as it will populate an offsets to get accurate diagnostics and semantics. +pub fn escape_text>(escape: char, token: &'static str, content: S) -> String { let mut processed = String::new(); let mut escaped = 0; let mut token_it = token.chars().peekable(); @@ -522,7 +511,7 @@ mod tests { #[test] fn process_escaped_tests() { assert_eq!( - process_escaped( + escape_text( '\\', "%", "escaped: \\%, also escaped: \\\\\\%, untouched: \\a" @@ -530,27 +519,27 @@ mod tests { "escaped: %, also escaped: \\%, untouched: \\a" ); assert_eq!( - process_escaped('"', "><)))°>", "Escaped fish: \"><)))°>"), + escape_text('"', "><)))°>", "Escaped fish: \"><)))°>"), "Escaped fish: ><)))°>".to_string() ); assert_eq!( - process_escaped('\\', "]", "Escaped \\]"), + escape_text('\\', "]", "Escaped \\]"), "Escaped ]".to_string() ); assert_eq!( - process_escaped('\\', "]", "Unescaped \\\\]"), + escape_text('\\', "]", "Unescaped \\\\]"), "Unescaped \\\\]".to_string() ); assert_eq!( - process_escaped('\\', "]", "Escaped \\\\\\]"), + escape_text('\\', "]", "Escaped \\\\\\]"), "Escaped \\]".to_string() ); assert_eq!( - process_escaped('\\', "]", "Unescaped \\\\\\\\]"), + escape_text('\\', "]", "Unescaped \\\\\\\\]"), "Unescaped \\\\\\\\]".to_string() ); - assert_eq!(process_escaped('\\', ")", "A\\)B\\"), "A)B".to_string(),); - assert_eq!(process_escaped('\\', ")", "A\\)B\\\\"), "A)B\\".to_string(),); + assert_eq!(escape_text('\\', ")", "A\\)B\\"), "A)B".to_string(),); + assert_eq!(escape_text('\\', ")", "A\\)B\\\\"), "A)B\\".to_string(),); } #[test]