Fix bugs
This commit is contained in:
parent
7f1229b5fe
commit
d4c8e1c897
30 changed files with 552 additions and 177 deletions
|
@ -7,6 +7,7 @@ use rusqlite::Connection;
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -25,7 +26,7 @@ fn parse(
|
||||||
) -> Result<Box<dyn Document<'static>>, String> {
|
) -> Result<Box<dyn Document<'static>>, String> {
|
||||||
// Parse
|
// Parse
|
||||||
//let source = SourceFile::new(input.to_string(), None).unwrap();
|
//let source = SourceFile::new(input.to_string(), None).unwrap();
|
||||||
let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None);
|
let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None, ParseMode::default());
|
||||||
|
|
||||||
if debug_opts.contains(&"ast".to_string()) {
|
if debug_opts.contains(&"ast".to_string()) {
|
||||||
println!("-- BEGIN AST DEBUGGING --");
|
println!("-- BEGIN AST DEBUGGING --");
|
||||||
|
|
|
@ -43,9 +43,10 @@ pub mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
|
use crate::parser::source::SourceFile;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validate_refname_tests() {
|
fn validate_refname_tests() {
|
||||||
|
@ -55,7 +56,12 @@ pub mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(validate_refname(&*doc, " abc ", true), Ok("abc"));
|
assert_eq!(validate_refname(&*doc, " abc ", true), Ok("abc"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::document::Document;
|
use super::document::Document;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
use crate::parser::source::Token;
|
use crate::parser::source::Token;
|
||||||
|
@ -63,7 +64,7 @@ impl Variable for BaseVariable {
|
||||||
));
|
));
|
||||||
|
|
||||||
state.with_state(|new_state| {
|
state.with_state(|new_state| {
|
||||||
let _ = new_state.parser.parse_into(new_state, source, document);
|
let _ = new_state.parser.parse_into(new_state, source, document, ParseMode::default());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -233,7 +234,15 @@ impl Rule for BlockquoteRule {
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("List") }
|
fn previous(&self) -> Option<&'static str> { Some("List") }
|
||||||
|
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
|
if mode.paragraph_only {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
self.start_re
|
self.start_re
|
||||||
.find_at(cursor.source.content(), cursor.pos)
|
.find_at(cursor.source.content(), cursor.pos)
|
||||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||||
|
@ -310,7 +319,7 @@ impl Rule for BlockquoteRule {
|
||||||
let parsed_doc = state.with_state(|new_state| {
|
let parsed_doc = state.with_state(|new_state| {
|
||||||
new_state
|
new_state
|
||||||
.parser
|
.parser
|
||||||
.parse(new_state, entry_src, Some(document))
|
.parse(new_state, entry_src, Some(document), ParseMode::default())
|
||||||
.0
|
.0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -447,7 +456,12 @@ END
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph { Text{ content == "BEFORE" }; };
|
Paragraph { Text{ content == "BEFORE" }; };
|
||||||
|
@ -496,7 +510,12 @@ AFTER
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (_, state) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (_, state) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let style = state
|
let style = state
|
||||||
.shared
|
.shared
|
||||||
|
|
|
@ -26,6 +26,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -309,8 +310,7 @@ impl CodeRule {
|
||||||
Regex::new(
|
Regex::new(
|
||||||
r"``(?:\[((?:\\.|[^\\\\])*?)\])?(?:([^\r\n`]*?)(?:,|\n))?((?:\\(?:.|\n)|[^\\\\])*?)``",
|
r"``(?:\[((?:\\.|[^\\\\])*?)\])?(?:([^\r\n`]*?)(?:,|\n))?((?:\\(?:.|\n)|[^\\\\])*?)``",
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
|
|
||||||
],
|
],
|
||||||
properties: PropertyParser { properties: props },
|
properties: PropertyParser { properties: props },
|
||||||
}
|
}
|
||||||
|
@ -319,10 +319,15 @@ impl CodeRule {
|
||||||
|
|
||||||
impl RegexRule for CodeRule {
|
impl RegexRule for CodeRule {
|
||||||
fn name(&self) -> &'static str { "Code" }
|
fn name(&self) -> &'static str { "Code" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Blockquote") }
|
fn previous(&self) -> Option<&'static str> { Some("Blockquote") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, id: usize) -> bool {
|
||||||
|
return !mode.paragraph_only || id != 0;
|
||||||
|
}
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -710,7 +715,12 @@ fn fact(n: usize) -> usize
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let borrow = doc.content().borrow();
|
let borrow = doc.content().borrow();
|
||||||
let found = borrow
|
let found = borrow
|
||||||
|
@ -756,7 +766,12 @@ fn fact(n: usize) -> usize
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let borrow = doc.content().borrow();
|
let borrow = doc.content().borrow();
|
||||||
let found = borrow
|
let found = borrow
|
||||||
|
@ -806,6 +821,7 @@ test code
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
code_sep { delta_line == 1, delta_start == 0, length == 3 };
|
code_sep { delta_line == 1, delta_start == 0, length == 3 };
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -56,6 +57,8 @@ impl RegexRule for CommentRule {
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -132,7 +135,12 @@ COMMENT ::Test
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -160,6 +168,7 @@ COMMENT ::Test
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::lua::kernel::Kernel;
|
use crate::lua::kernel::Kernel;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::Ref;
|
use std::cell::Ref;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -140,10 +141,13 @@ impl RuleState for CustomStyleState {
|
||||||
let paragraph = document.last_element::<Paragraph>().unwrap();
|
let paragraph = document.last_element::<Paragraph>().unwrap();
|
||||||
let paragraph_end = paragraph
|
let paragraph_end = paragraph
|
||||||
.content
|
.content
|
||||||
.last().map(|last| (
|
.last()
|
||||||
|
.map(|last| {
|
||||||
|
(
|
||||||
last.location().source(),
|
last.location().source(),
|
||||||
last.location().end() - 1..last.location().end(),
|
last.location().end() - 1..last.location().end(),
|
||||||
))
|
)
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
reports.push(
|
reports.push(
|
||||||
|
@ -179,14 +183,20 @@ static STATE_NAME: &str = "elements.custom_style";
|
||||||
pub struct CustomStyleRule;
|
pub struct CustomStyleRule;
|
||||||
|
|
||||||
impl CustomStyleRule {
|
impl CustomStyleRule {
|
||||||
pub fn new() -> Self { Self{} }
|
pub fn new() -> Self { Self {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rule for CustomStyleRule {
|
impl Rule for CustomStyleRule {
|
||||||
fn name(&self) -> &'static str { "Custom Style" }
|
fn name(&self) -> &'static str { "Custom Style" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Style") }
|
fn previous(&self) -> Option<&'static str> { Some("Style") }
|
||||||
|
|
||||||
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
_mode: &ParseMode,
|
||||||
|
state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
let content = cursor.source.content();
|
let content = cursor.source.content();
|
||||||
|
|
||||||
let mut closest_match = usize::MAX;
|
let mut closest_match = usize::MAX;
|
||||||
|
@ -479,6 +489,7 @@ mod tests {
|
||||||
use crate::elements::raw::Raw;
|
use crate::elements::raw::Raw;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
@ -512,7 +523,12 @@ pre |styled| post °Hello°.
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -556,7 +572,12 @@ pre [styled] post (Hello).
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::style::ElementStyle;
|
use crate::parser::style::ElementStyle;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
@ -59,11 +60,18 @@ impl ElemStyleRule {
|
||||||
|
|
||||||
impl Rule for ElemStyleRule {
|
impl Rule for ElemStyleRule {
|
||||||
fn name(&self) -> &'static str { "Element Style" }
|
fn name(&self) -> &'static str { "Element Style" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Script") }
|
fn previous(&self) -> Option<&'static str> { Some("Script") }
|
||||||
|
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
_mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.start_re
|
self.start_re
|
||||||
.find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
.find_at(cursor.source.content(), cursor.pos)
|
||||||
|
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
|
@ -132,7 +140,9 @@ impl Rule for ElemStyleRule {
|
||||||
.with_message("Invalid Style Value")
|
.with_message("Invalid Style Value")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((cursor.source.clone(), matches.get(0).unwrap().range()))
|
Label::new((cursor.source.clone(), matches.get(0).unwrap().range()))
|
||||||
.with_message("Unable to parse json string after style key".to_string())
|
.with_message(
|
||||||
|
"Unable to parse json string after style key".to_string(),
|
||||||
|
)
|
||||||
.with_color(state.parser.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.finish(),
|
.finish(),
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::util::Property;
|
use crate::parser::util::Property;
|
||||||
use crate::parser::util::PropertyMapError;
|
use crate::parser::util::PropertyMapError;
|
||||||
|
@ -189,10 +190,13 @@ impl GraphRule {
|
||||||
|
|
||||||
impl RegexRule for GraphRule {
|
impl RegexRule for GraphRule {
|
||||||
fn name(&self) -> &'static str { "Graphviz" }
|
fn name(&self) -> &'static str { "Graphviz" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Tex") }
|
fn previous(&self) -> Option<&'static str> { Some("Tex") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -441,7 +445,12 @@ Another graph
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Graphviz { width == "200px", dot == "Some graph..." };
|
Graphviz { width == "200px", dot == "Some graph..." };
|
||||||
|
@ -461,7 +470,12 @@ Another graph
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Graphviz { width == "200px", dot == "Some graph..." };
|
Graphviz { width == "200px", dot == "Some graph..." };
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::document::DocumentAccessors;
|
use crate::document::document::DocumentAccessors;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -43,10 +44,13 @@ impl ImportRule {
|
||||||
|
|
||||||
impl RegexRule for ImportRule {
|
impl RegexRule for ImportRule {
|
||||||
fn name(&self) -> &'static str { "Import" }
|
fn name(&self) -> &'static str { "Import" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Paragraph") }
|
fn previous(&self) -> Option<&'static str> { Some("Paragraph") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -165,7 +169,10 @@ impl RegexRule for ImportRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
state.with_state(|new_state| {
|
state.with_state(|new_state| {
|
||||||
let (import_doc, _) = new_state.parser.parse(new_state, import, Some(document));
|
let (import_doc, _) =
|
||||||
|
new_state
|
||||||
|
.parser
|
||||||
|
.parse(new_state, import, Some(document), ParseMode::default());
|
||||||
document.merge(import_doc.content(), import_doc.scope(), Some(&import_as));
|
document.merge(import_doc.content(), import_doc.scope(), Some(&import_as));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -181,27 +188,27 @@ impl RegexRule for ImportRule {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some((sems, tokens)) =
|
||||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||||
{
|
{
|
||||||
// @import
|
// @import
|
||||||
let import = if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n'
|
let import =
|
||||||
{
|
if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n' {
|
||||||
matches.get(0).unwrap().start() + 1
|
matches.get(0).unwrap().start() + 1
|
||||||
}
|
} else {
|
||||||
else
|
matches.get(0).unwrap().start()
|
||||||
{
|
};
|
||||||
matches.get(0).unwrap().start()
|
|
||||||
};
|
|
||||||
sems.add(import..import + 7, tokens.import_import);
|
sems.add(import..import + 7, tokens.import_import);
|
||||||
|
|
||||||
if let Some(import_as) = matches.get(1)
|
if let Some(import_as) = matches.get(1) {
|
||||||
{
|
sems.add(
|
||||||
sems.add(import_as.start()-1..import_as.start(), tokens.import_as_sep);
|
import_as.start() - 1..import_as.start(),
|
||||||
|
tokens.import_as_sep,
|
||||||
|
);
|
||||||
sems.add(import_as.range(), tokens.import_as);
|
sems.add(import_as.range(), tokens.import_as);
|
||||||
sems.add(import_as.end()..import_as.end()+1, tokens.import_as_sep);
|
sems.add(import_as.end()..import_as.end() + 1, tokens.import_as_sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = matches.get(2).unwrap().range();
|
let path = matches.get(2).unwrap().range();
|
||||||
sems.add(path, tokens.import_path);
|
sems.add(path, tokens.import_path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::layout::LayoutHolder;
|
use crate::parser::layout::LayoutHolder;
|
||||||
use crate::parser::layout::LayoutType;
|
use crate::parser::layout::LayoutType;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -232,7 +233,12 @@ impl Element for Layout {
|
||||||
fn location(&self) -> &Token { &self.location }
|
fn location(&self) -> &Token { &self.location }
|
||||||
fn kind(&self) -> ElemKind { ElemKind::Block }
|
fn kind(&self) -> ElemKind { ElemKind::Block }
|
||||||
fn element_name(&self) -> &'static str { "Layout" }
|
fn element_name(&self) -> &'static str { "Layout" }
|
||||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
compiler: &Compiler,
|
||||||
|
document: &dyn Document,
|
||||||
|
_cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
self.layout
|
self.layout
|
||||||
.compile(self.token, self.id, &self.properties, compiler, document)
|
.compile(self.token, self.id, &self.properties, compiler, document)
|
||||||
}
|
}
|
||||||
|
@ -379,10 +385,13 @@ static STATE_NAME: &str = "elements.layout";
|
||||||
|
|
||||||
impl RegexRule for LayoutRule {
|
impl RegexRule for LayoutRule {
|
||||||
fn name(&self) -> &'static str { "Layout" }
|
fn name(&self) -> &'static str { "Layout" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Media") }
|
fn previous(&self) -> Option<&'static str> { Some("Media") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -897,7 +906,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Layout { token == LayoutToken::Begin, id == 0 };
|
Layout { token == LayoutToken::Begin, id == 0 };
|
||||||
|
@ -949,7 +963,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Layout { token == LayoutToken::Begin, id == 0 };
|
Layout { token == LayoutToken::Begin, id == 0 };
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -94,10 +95,13 @@ impl LinkRule {
|
||||||
|
|
||||||
impl RegexRule for LinkRule {
|
impl RegexRule for LinkRule {
|
||||||
fn name(&self) -> &'static str { "Link" }
|
fn name(&self) -> &'static str { "Link" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -314,7 +318,12 @@ Some [link](url).
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -344,7 +353,12 @@ nml.link.push("**BOLD link**", "another url")
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -375,6 +389,7 @@ nml.link.push("**BOLD link**", "another url")
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::document::element::ContainerElement;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -269,9 +270,18 @@ impl ListRule {
|
||||||
|
|
||||||
impl Rule for ListRule {
|
impl Rule for ListRule {
|
||||||
fn name(&self) -> &'static str { "List" }
|
fn name(&self) -> &'static str { "List" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Raw") }
|
fn previous(&self) -> Option<&'static str> { Some("Raw") }
|
||||||
|
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
|
if mode.paragraph_only {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
self.start_re
|
self.start_re
|
||||||
.find_at(cursor.source.content(), cursor.pos)
|
.find_at(cursor.source.content(), cursor.pos)
|
||||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||||
|
@ -406,6 +416,7 @@ impl Rule for ListRule {
|
||||||
|
|
||||||
// Parse entry content
|
// Parse entry content
|
||||||
let token = Token::new(entry_start..end_cursor.pos, end_cursor.source.clone());
|
let token = Token::new(entry_start..end_cursor.pos, end_cursor.source.clone());
|
||||||
|
//println!("content={}", entry_content);
|
||||||
let entry_src = Rc::new(VirtualSource::new(
|
let entry_src = Rc::new(VirtualSource::new(
|
||||||
token.clone(),
|
token.clone(),
|
||||||
"List Entry".to_string(),
|
"List Entry".to_string(),
|
||||||
|
@ -475,7 +486,8 @@ mod tests {
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::{validate_document, validate_semantics};
|
use crate::validate_document;
|
||||||
|
use crate::validate_semantics;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parser() {
|
fn parser() {
|
||||||
|
@ -498,7 +510,7 @@ mod tests {
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let state = ParserState::new(&parser, None);
|
let state = ParserState::new(&parser, None);
|
||||||
let (doc, _) = parser.parse(state, source, None);
|
let (doc, _) = parser.parse(state, source, None, ParseMode::default());
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
ListMarker { numbered == false, kind == MarkerKind::Open };
|
ListMarker { numbered == false, kind == MarkerKind::Open };
|
||||||
|
@ -549,7 +561,8 @@ mod tests {
|
||||||
*[offset=5] First **bold**
|
*[offset=5] First **bold**
|
||||||
Second line
|
Second line
|
||||||
*- Another
|
*- Another
|
||||||
>@
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
.to_string(),
|
.to_string(),
|
||||||
None,
|
None,
|
||||||
|
@ -559,6 +572,7 @@ mod tests {
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
list_bullet { delta_line == 1, delta_start == 1, length == 1 };
|
list_bullet { delta_line == 1, delta_start == 1, length == 1 };
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::element::ReferenceableElement;
|
use crate::document::element::ReferenceableElement;
|
||||||
use crate::document::references::validate_refname;
|
use crate::document::references::validate_refname;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -72,14 +73,21 @@ impl Element for Media {
|
||||||
|
|
||||||
fn as_container(&self) -> Option<&dyn ContainerElement> { Some(self) }
|
fn as_container(&self) -> Option<&dyn ContainerElement> { Some(self) }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
compiler: &Compiler,
|
||||||
|
document: &dyn Document,
|
||||||
|
cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
|
||||||
result.push_str("<div class=\"media\">");
|
result.push_str("<div class=\"media\">");
|
||||||
for medium in &self.media {
|
for medium in &self.media {
|
||||||
result += medium.compile(compiler, document, cursor+result.len())?.as_str();
|
result += medium
|
||||||
|
.compile(compiler, document, cursor + result.len())?
|
||||||
|
.as_str();
|
||||||
}
|
}
|
||||||
result.push_str("</div>");
|
result.push_str("</div>");
|
||||||
|
|
||||||
|
@ -132,7 +140,12 @@ impl Element for Medium {
|
||||||
|
|
||||||
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
compiler: &Compiler,
|
||||||
|
document: &dyn Document,
|
||||||
|
cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
@ -145,10 +158,18 @@ impl Element for Medium {
|
||||||
.width
|
.width
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(String::new(), |w| format!(r#" style="width:{w};""#));
|
.map_or(String::new(), |w| format!(r#" style="width:{w};""#));
|
||||||
result.push_str(format!(r#"<div id="{}" class="medium"{width}>"#, self.refid(compiler, refcount)).as_str());
|
result.push_str(
|
||||||
|
format!(
|
||||||
|
r#"<div id="{}" class="medium"{width}>"#,
|
||||||
|
self.refid(compiler, refcount)
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
result += match self.media_type {
|
result += match self.media_type {
|
||||||
MediaType::IMAGE => format!(r#"<a href="{0}"><img src="{0}"></a>"#, self.uri),
|
MediaType::IMAGE => format!(r#"<a href="{0}"><img src="{0}"></a>"#, self.uri),
|
||||||
MediaType::VIDEO => format!(r#"<video controls{width}><source src="{0}"></video>"#, self.uri
|
MediaType::VIDEO => format!(
|
||||||
|
r#"<video controls{width}><source src="{0}"></video>"#,
|
||||||
|
self.uri
|
||||||
),
|
),
|
||||||
MediaType::AUDIO => {
|
MediaType::AUDIO => {
|
||||||
format!(r#"<audio controls src="{0}"{width}></audio>"#, self.uri)
|
format!(r#"<audio controls src="{0}"{width}></audio>"#, self.uri)
|
||||||
|
@ -158,17 +179,17 @@ impl Element for Medium {
|
||||||
|
|
||||||
let caption = self
|
let caption = self
|
||||||
.caption
|
.caption
|
||||||
.as_ref().map(|cap| format!(
|
.as_ref()
|
||||||
" {}",
|
.map(|cap| format!(" {}", Compiler::sanitize(compiler.target(), cap.as_str())))
|
||||||
Compiler::sanitize(compiler.target(), cap.as_str())
|
|
||||||
))
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
result.push_str(
|
result.push_str(
|
||||||
format!(r#"<p class="medium-refname">({refcount}){caption}</p>"#).as_str(),
|
format!(r#"<p class="medium-refname">({refcount}){caption}</p>"#).as_str(),
|
||||||
);
|
);
|
||||||
if let Some(paragraph) = self.description.as_ref() {
|
if let Some(paragraph) = self.description.as_ref() {
|
||||||
result += paragraph.compile(compiler, document, cursor+result.len())?.as_str();
|
result += paragraph
|
||||||
|
.compile(compiler, document, cursor + result.len())?
|
||||||
|
.as_str();
|
||||||
}
|
}
|
||||||
result.push_str("</div>");
|
result.push_str("</div>");
|
||||||
|
|
||||||
|
@ -214,9 +235,7 @@ impl ReferenceableElement for Medium {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refid(&self, _compiler: &Compiler, refid: usize) -> String {
|
fn refid(&self, _compiler: &Compiler, refid: usize) -> String { format!("medium-{refid}") }
|
||||||
format!("medium-{refid}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[auto_registry::auto_registry(registry = "rules", path = "crate::elements::media")]
|
#[auto_registry::auto_registry(registry = "rules", path = "crate::elements::media")]
|
||||||
|
@ -324,10 +343,13 @@ impl MediaRule {
|
||||||
|
|
||||||
impl RegexRule for MediaRule {
|
impl RegexRule for MediaRule {
|
||||||
fn name(&self) -> &'static str { "Media" }
|
fn name(&self) -> &'static str { "Media" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Graphviz") }
|
fn previous(&self) -> Option<&'static str> { Some("Graphviz") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -433,13 +455,15 @@ impl RegexRule for MediaRule {
|
||||||
.get("width", |_, value| -> Result<String, ()> {
|
.get("width", |_, value| -> Result<String, ()> {
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
})
|
})
|
||||||
.ok().map(|(_, s)| s);
|
.ok()
|
||||||
|
.map(|(_, s)| s);
|
||||||
|
|
||||||
let caption = properties
|
let caption = properties
|
||||||
.get("caption", |_, value| -> Result<String, ()> {
|
.get("caption", |_, value| -> Result<String, ()> {
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
})
|
})
|
||||||
.ok().map(|(_, value)| value);
|
.ok()
|
||||||
|
.map(|(_, value)| value);
|
||||||
|
|
||||||
let description = match matches.get(4) {
|
let description = match matches.get(4) {
|
||||||
Some(content) => {
|
Some(content) => {
|
||||||
|
@ -546,7 +570,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let borrow = doc.content().borrow();
|
let borrow = doc.content().borrow();
|
||||||
let group = borrow.first().as_ref().unwrap().as_container().unwrap();
|
let group = borrow.first().as_ref().unwrap().as_container().unwrap();
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ContainerElement;
|
use crate::document::element::ContainerElement;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -48,7 +49,12 @@ impl Element for Paragraph {
|
||||||
|
|
||||||
fn element_name(&self) -> &'static str { "Paragraph" }
|
fn element_name(&self) -> &'static str { "Paragraph" }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
compiler: &Compiler,
|
||||||
|
document: &dyn Document,
|
||||||
|
cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
if self.content.is_empty() {
|
if self.content.is_empty() {
|
||||||
return Ok(String::new());
|
return Ok(String::new());
|
||||||
}
|
}
|
||||||
|
@ -63,7 +69,9 @@ impl Element for Paragraph {
|
||||||
result.push_str("<p>");
|
result.push_str("<p>");
|
||||||
|
|
||||||
for elems in &self.content {
|
for elems in &self.content {
|
||||||
result += elems.compile(compiler, document, cursor+result.len())?.as_str();
|
result += elems
|
||||||
|
.compile(compiler, document, cursor + result.len())?
|
||||||
|
.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push_str("</p>");
|
result.push_str("</p>");
|
||||||
|
@ -106,11 +114,18 @@ impl ParagraphRule {
|
||||||
|
|
||||||
impl Rule for ParagraphRule {
|
impl Rule for ParagraphRule {
|
||||||
fn name(&self) -> &'static str { "Paragraph" }
|
fn name(&self) -> &'static str { "Paragraph" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Comment") }
|
fn previous(&self) -> Option<&'static str> { Some("Comment") }
|
||||||
|
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
_mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.re
|
self.re
|
||||||
.find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
.find_at(cursor.source.content(), cursor.pos)
|
||||||
|
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match(
|
fn on_match(
|
||||||
|
@ -166,7 +181,12 @@ Last paragraph
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -39,7 +40,12 @@ impl Element for Raw {
|
||||||
|
|
||||||
fn element_name(&self) -> &'static str { "Raw" }
|
fn element_name(&self) -> &'static str { "Raw" }
|
||||||
|
|
||||||
fn compile(&self, _compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
_compiler: &Compiler,
|
||||||
|
_document: &dyn Document,
|
||||||
|
_cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
Ok(self.content.clone())
|
Ok(self.content.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,10 +79,13 @@ impl RawRule {
|
||||||
|
|
||||||
impl RegexRule for RawRule {
|
impl RegexRule for RawRule {
|
||||||
fn name(&self) -> &'static str { "Raw" }
|
fn name(&self) -> &'static str { "Raw" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Variable Substitution") }
|
fn previous(&self) -> Option<&'static str> { Some("Variable Substitution") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
|
@ -271,7 +280,7 @@ mod tests {
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -285,7 +294,12 @@ Break{?[kind=block] Raw?}NewParagraph{?<b>?}
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph;
|
Paragraph;
|
||||||
|
@ -308,7 +322,12 @@ Break%<nml.raw.push("block", "Raw")>%NewParagraph%<nml.raw.push("inline", "<b>")
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph;
|
Paragraph;
|
||||||
|
|
|
@ -22,6 +22,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::references::validate_refname;
|
use crate::document::references::validate_refname;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -227,10 +228,13 @@ impl ReferenceRule {
|
||||||
|
|
||||||
impl RegexRule for ReferenceRule {
|
impl RegexRule for ReferenceRule {
|
||||||
fn name(&self) -> &'static str { "Reference" }
|
fn name(&self) -> &'static str { "Reference" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Text") }
|
fn previous(&self) -> Option<&'static str> { Some("Text") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -449,7 +453,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Section;
|
Section;
|
||||||
|
@ -476,7 +485,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::document::document::Document;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::Kernel;
|
use crate::lua::kernel::Kernel;
|
||||||
use crate::lua::kernel::KernelContext;
|
use crate::lua::kernel::KernelContext;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -79,10 +80,13 @@ impl ScriptRule {
|
||||||
|
|
||||||
impl RegexRule for ScriptRule {
|
impl RegexRule for ScriptRule {
|
||||||
fn name(&self) -> &'static str { "Script" }
|
fn name(&self) -> &'static str { "Script" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Import") }
|
fn previous(&self) -> Option<&'static str> { Some("Import") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, id: usize) -> bool { !mode.paragraph_only || id != 0 }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -244,9 +248,12 @@ impl RegexRule for ScriptRule {
|
||||||
)) as Rc<dyn Source>;
|
)) as Rc<dyn Source>;
|
||||||
|
|
||||||
state.with_state(|new_state| {
|
state.with_state(|new_state| {
|
||||||
new_state
|
new_state.parser.parse_into(
|
||||||
.parser
|
new_state,
|
||||||
.parse_into(new_state, parse_source, document);
|
parse_source,
|
||||||
|
document,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,7 +357,12 @@ Evaluation: %<! make_ref("hello", "id")>%
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph;
|
Paragraph;
|
||||||
|
@ -393,6 +405,7 @@ end
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
script_sep { delta_line == 1, delta_start == 0, length == 2 };
|
script_sep { delta_line == 1, delta_start == 0, length == 2 };
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::Element;
|
||||||
use crate::document::element::ReferenceableElement;
|
use crate::document::element::ReferenceableElement;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -168,10 +169,13 @@ pub mod section_kind {
|
||||||
|
|
||||||
impl RegexRule for SectionRule {
|
impl RegexRule for SectionRule {
|
||||||
fn name(&self) -> &'static str { "Section" }
|
fn name(&self) -> &'static str { "Section" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Custom Style") }
|
fn previous(&self) -> Option<&'static str> { Some("Custom Style") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -327,15 +331,17 @@ impl RegexRule for SectionRule {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
if let Some((sems, tokens)) =
|
||||||
|
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||||
{
|
{
|
||||||
sems.add(matches.get(1).unwrap().range(), tokens.section_heading);
|
sems.add(matches.get(1).unwrap().range(), tokens.section_heading);
|
||||||
if let Some(reference) = matches.get(2)
|
if let Some(reference) = matches.get(2) {
|
||||||
{
|
sems.add(
|
||||||
sems.add(reference.start()-1..reference.end()+1, tokens.section_reference);
|
reference.start() - 1..reference.end() + 1,
|
||||||
|
tokens.section_reference,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(kind) = matches.get(3)
|
if let Some(kind) = matches.get(3) {
|
||||||
{
|
|
||||||
sems.add(kind.range(), tokens.section_kind);
|
sems.add(kind.range(), tokens.section_kind);
|
||||||
}
|
}
|
||||||
sems.add(matches.get(5).unwrap().range(), tokens.section_name);
|
sems.add(matches.get(5).unwrap().range(), tokens.section_name);
|
||||||
|
@ -452,7 +458,8 @@ mod tests {
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::{validate_document, validate_semantics};
|
use crate::validate_document;
|
||||||
|
use crate::validate_semantics;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -472,7 +479,12 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Section { depth == 1, title == "1" };
|
Section { depth == 1, title == "1" };
|
||||||
|
@ -502,7 +514,12 @@ nml.section.push("6", 6, "", "refname")
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Section { depth == 1, title == "1" };
|
Section { depth == 1, title == "1" };
|
||||||
|
@ -529,7 +546,7 @@ nml.section.push("6", 6, "", "refname")
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let state = ParserState::new(&parser, None);
|
let state = ParserState::new(&parser, None);
|
||||||
let (_, state) = parser.parse(state, source, None);
|
let (_, state) = parser.parse(state, source, None, ParseMode::default());
|
||||||
|
|
||||||
let style = state
|
let style = state
|
||||||
.shared
|
.shared
|
||||||
|
@ -547,8 +564,7 @@ nml.section.push("6", 6, "", "refname")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn semantics()
|
fn semantics() {
|
||||||
{
|
|
||||||
let source = Rc::new(SourceFile::with_content(
|
let source = Rc::new(SourceFile::with_content(
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
r#"
|
r#"
|
||||||
|
@ -560,21 +576,26 @@ nml.section.push("6", 6, "", "refname")
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (_, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None);
|
let (_, state) = parser.parse(
|
||||||
|
ParserState::new_with_semantics(&parser, None),
|
||||||
|
source.clone(),
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||||
section_name { delta_line == 0, delta_start == 1 };
|
section_name { delta_line == 0, delta_start == 1 };
|
||||||
|
|
||||||
section_heading { delta_line == 1, delta_start == 0, length == 2 };
|
section_heading { delta_line == 1, delta_start == 0, length == 2 };
|
||||||
section_reference { delta_line == 0, delta_start == 2, length == 4 };
|
section_reference { delta_line == 0, delta_start == 2, length == 4 };
|
||||||
section_kind { delta_line == 0, delta_start == 4, length == 1 };
|
section_kind { delta_line == 0, delta_start == 4, length == 1 };
|
||||||
section_name { delta_line == 0, delta_start == 1 };
|
section_name { delta_line == 0, delta_start == 1 };
|
||||||
|
|
||||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||||
section_reference { delta_line == 0, delta_start == 1, length == 9 };
|
section_reference { delta_line == 0, delta_start == 1, length == 9 };
|
||||||
section_kind { delta_line == 0, delta_start == 9, length == 2 };
|
section_kind { delta_line == 0, delta_start == 9, length == 2 };
|
||||||
section_name { delta_line == 0, delta_start == 2 };
|
section_name { delta_line == 0, delta_start == 2 };
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -167,10 +168,13 @@ static STATE_NAME: &str = "elements.style";
|
||||||
|
|
||||||
impl RegexRule for StyleRule {
|
impl RegexRule for StyleRule {
|
||||||
fn name(&self) -> &'static str { "Style" }
|
fn name(&self) -> &'static str { "Style" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Layout") }
|
fn previous(&self) -> Option<&'static str> { Some("Layout") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -316,7 +320,12 @@ __`UNDERLINE+EM`__
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -357,7 +366,12 @@ terminated here%<nml.style.toggle("Italic")>%
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -399,6 +413,7 @@ __teかst__ *another*
|
||||||
ParserState::new_with_semantics(&parser, None),
|
ParserState::new_with_semantics(&parser, None),
|
||||||
source.clone(),
|
source.clone(),
|
||||||
None,
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
validate_semantics!(state, source.clone(), 0,
|
validate_semantics!(state, source.clone(), 0,
|
||||||
|
|
|
@ -29,6 +29,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -114,7 +115,9 @@ impl FormattedTex {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) { panic!("Unable to read `latex2svg` stdout: {}", e) }
|
if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) {
|
||||||
|
panic!("Unable to read `latex2svg` stdout: {}", e)
|
||||||
|
}
|
||||||
println!("Done!");
|
println!("Done!");
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
@ -303,10 +306,13 @@ impl TexRule {
|
||||||
|
|
||||||
impl RegexRule for TexRule {
|
impl RegexRule for TexRule {
|
||||||
fn name(&self) -> &'static str { "Tex" }
|
fn name(&self) -> &'static str { "Tex" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Code") }
|
fn previous(&self) -> Option<&'static str> { Some("Code") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -407,14 +413,16 @@ impl RegexRule for TexRule {
|
||||||
.get("caption", |_, value| -> Result<String, ()> {
|
.get("caption", |_, value| -> Result<String, ()> {
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
})
|
})
|
||||||
.ok().map(|(_, value)| value);
|
.ok()
|
||||||
|
.map(|(_, value)| value);
|
||||||
|
|
||||||
// Environ
|
// Environ
|
||||||
let tex_env = properties
|
let tex_env = properties
|
||||||
.get("env", |_, value| -> Result<String, ()> {
|
.get("env", |_, value| -> Result<String, ()> {
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
})
|
})
|
||||||
.ok().map(|(_, value)| value)
|
.ok()
|
||||||
|
.map(|(_, value)| value)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
state.push(
|
state.push(
|
||||||
|
@ -548,7 +556,12 @@ $[kind=block,env=another] e^{i\pi}=-1$
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||||
|
@ -576,7 +589,12 @@ $[env=another] e^{i\pi}=-1$
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
let (doc, _) = parser.parse(
|
||||||
|
ParserState::new(&parser, None),
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
ParseMode::default(),
|
||||||
|
);
|
||||||
|
|
||||||
validate_document!(doc.content().borrow(), 0,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -24,12 +25,7 @@ pub struct Text {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Text {
|
impl Text {
|
||||||
pub fn new(location: Token, content: String) -> Text {
|
pub fn new(location: Token, content: String) -> Text { Text { location, content } }
|
||||||
Text {
|
|
||||||
location,
|
|
||||||
content,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for Text {
|
impl Element for Text {
|
||||||
|
@ -37,7 +33,12 @@ impl Element for Text {
|
||||||
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
||||||
fn element_name(&self) -> &'static str { "Text" }
|
fn element_name(&self) -> &'static str { "Text" }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
compiler: &Compiler,
|
||||||
|
_document: &dyn Document,
|
||||||
|
_cursor: usize,
|
||||||
|
) -> Result<String, String> {
|
||||||
Ok(Compiler::sanitize(compiler.target(), self.content.as_str()))
|
Ok(Compiler::sanitize(compiler.target(), self.content.as_str()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,9 +52,15 @@ impl TextRule {
|
||||||
|
|
||||||
impl Rule for TextRule {
|
impl Rule for TextRule {
|
||||||
fn name(&self) -> &'static str { "Text" }
|
fn name(&self) -> &'static str { "Text" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
||||||
|
|
||||||
fn next_match(&self, _state: &ParserState, _cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
_mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
_cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::document::variable::PathVariable;
|
||||||
use crate::document::variable::Variable;
|
use crate::document::variable::Variable;
|
||||||
use crate::lsp::semantic::Semantics;
|
use crate::lsp::semantic::Semantics;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
|
use crate::parser::parser::ParseMode;
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -119,10 +120,13 @@ impl VariableRule {
|
||||||
|
|
||||||
impl RegexRule for VariableRule {
|
impl RegexRule for VariableRule {
|
||||||
fn name(&self) -> &'static str { "Variable" }
|
fn name(&self) -> &'static str { "Variable" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Element Style") }
|
fn previous(&self) -> Option<&'static str> { Some("Element Style") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||||
|
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
@ -257,17 +261,18 @@ impl RegexRule for VariableRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
if let Some((sems, tokens)) =
|
||||||
|
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||||
{
|
{
|
||||||
let name = matches.get(2).unwrap().range();
|
let name = matches.get(2).unwrap().range();
|
||||||
if let Some(kind) = matches.get(1).map(|m| m.range()) {
|
if let Some(kind) = matches.get(1).map(|m| m.range()) {
|
||||||
sems.add(kind.start-1..kind.start, tokens.variable_operator);
|
sems.add(kind.start - 1..kind.start, tokens.variable_operator);
|
||||||
sems.add(kind, tokens.variable_kind);
|
sems.add(kind, tokens.variable_kind);
|
||||||
} else {
|
} else {
|
||||||
sems.add(name.start-1..name.start, tokens.variable_operator);
|
sems.add(name.start - 1..name.start, tokens.variable_operator);
|
||||||
}
|
}
|
||||||
sems.add(name.clone(), tokens.variable_name);
|
sems.add(name.clone(), tokens.variable_name);
|
||||||
sems.add(name.end..name.end+1, tokens.variable_sep);
|
sems.add(name.end..name.end + 1, tokens.variable_sep);
|
||||||
let value = matches.get(3).unwrap().range();
|
let value = matches.get(3).unwrap().range();
|
||||||
sems.add(value.clone(), tokens.variable_value);
|
sems.add(value.clone(), tokens.variable_value);
|
||||||
}
|
}
|
||||||
|
@ -297,8 +302,7 @@ impl RegexRule for VariableRule {
|
||||||
let mut value: Option<String> = None;
|
let mut value: Option<String> = None;
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
if let Some(var) = ctx.document.get_variable(name.as_str())
|
if let Some(var) = ctx.document.get_variable(name.as_str()) {
|
||||||
{
|
|
||||||
value = Some(var.to_string());
|
value = Some(var.to_string());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -328,10 +332,13 @@ impl VariableSubstitutionRule {
|
||||||
|
|
||||||
impl RegexRule for VariableSubstitutionRule {
|
impl RegexRule for VariableSubstitutionRule {
|
||||||
fn name(&self) -> &'static str { "Variable Substitution" }
|
fn name(&self) -> &'static str { "Variable Substitution" }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { Some("Variable") }
|
fn previous(&self) -> Option<&'static str> { Some("Variable") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
|
@ -351,7 +358,9 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
.with_message("Empty variable name")
|
.with_message("Empty variable name")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((token.source(), matches.get(0).unwrap().range()))
|
Label::new((token.source(), matches.get(0).unwrap().range()))
|
||||||
.with_message("Missing variable name for substitution".to_string())
|
.with_message(
|
||||||
|
"Missing variable name for substitution".to_string(),
|
||||||
|
)
|
||||||
.with_color(state.parser.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.finish(),
|
.finish(),
|
||||||
|
@ -366,7 +375,9 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
.with_message("Invalid variable name")
|
.with_message("Invalid variable name")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((token.source(), name.range()))
|
Label::new((token.source(), name.range()))
|
||||||
.with_message("Variable names contains leading spaces".to_string())
|
.with_message(
|
||||||
|
"Variable names contains leading spaces".to_string(),
|
||||||
|
)
|
||||||
.with_color(state.parser.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.with_help("Remove leading spaces")
|
.with_help("Remove leading spaces")
|
||||||
|
@ -382,7 +393,9 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
.with_message("Invalid variable name")
|
.with_message("Invalid variable name")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((token.source(), name.range()))
|
Label::new((token.source(), name.range()))
|
||||||
.with_message("Variable names contains trailing spaces".to_string())
|
.with_message(
|
||||||
|
"Variable names contains trailing spaces".to_string(),
|
||||||
|
)
|
||||||
.with_color(state.parser.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.with_help("Remove trailing spaces")
|
.with_help("Remove trailing spaces")
|
||||||
|
@ -392,20 +405,21 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// Invalid name
|
// Invalid name
|
||||||
if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str()) {
|
if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str())
|
||||||
result.push(
|
{
|
||||||
Report::build(ReportKind::Error, token.source(), name.start())
|
result.push(
|
||||||
.with_message("Invalid variable name")
|
Report::build(ReportKind::Error, token.source(), name.start())
|
||||||
.with_label(
|
.with_message("Invalid variable name")
|
||||||
Label::new((token.source(), name.range()))
|
.with_label(
|
||||||
.with_message(msg)
|
Label::new((token.source(), name.range()))
|
||||||
.with_color(state.parser.colors().error),
|
.with_message(msg)
|
||||||
)
|
.with_color(state.parser.colors().error),
|
||||||
.finish(),
|
)
|
||||||
);
|
.finish(),
|
||||||
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get variable
|
// Get variable
|
||||||
match document.get_variable(name.as_str()) {
|
match document.get_variable(name.as_str()) {
|
||||||
|
@ -433,12 +447,13 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
|
|
||||||
variable.parse(state, token.clone(), document);
|
variable.parse(state, token.clone(), document);
|
||||||
|
|
||||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
if let Some((sems, tokens)) =
|
||||||
|
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||||
{
|
{
|
||||||
let name = matches.get(1).unwrap().range();
|
let name = matches.get(1).unwrap().range();
|
||||||
sems.add(name.start-1..name.start, tokens.variable_sub_sep);
|
sems.add(name.start - 1..name.start, tokens.variable_sub_sep);
|
||||||
sems.add(name.clone(), tokens.variable_sub_name);
|
sems.add(name.clone(), tokens.variable_sub_name);
|
||||||
sems.add(name.end..name.end+1, tokens.variable_sub_sep);
|
sems.add(name.end..name.end + 1, tokens.variable_sub_sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
|
@ -2,9 +2,9 @@ mod cache;
|
||||||
mod compiler;
|
mod compiler;
|
||||||
mod document;
|
mod document;
|
||||||
mod elements;
|
mod elements;
|
||||||
|
mod lsp;
|
||||||
mod lua;
|
mod lua;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod lsp;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::BufWriter;
|
use std::io::BufWriter;
|
||||||
|
|
|
@ -5,9 +5,9 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::DocumentEnd;
|
use crate::document::element::DocumentEnd;
|
||||||
use crate::document::langdocument::LangDocument;
|
use crate::document::langdocument::LangDocument;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::lsp::semantic::Semantics;
|
|
||||||
use crate::lsp::semantic::SemanticsData;
|
use crate::lsp::semantic::SemanticsData;
|
||||||
|
|
||||||
|
use super::parser::ParseMode;
|
||||||
use super::parser::Parser;
|
use super::parser::Parser;
|
||||||
use super::parser::ParserState;
|
use super::parser::ParserState;
|
||||||
use super::parser::ReportColors;
|
use super::parser::ReportColors;
|
||||||
|
@ -37,8 +37,7 @@ impl LangParser {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register rules
|
// Register rules
|
||||||
for rule in super::rule::get_rule_registry()
|
for rule in super::rule::get_rule_registry() {
|
||||||
{
|
|
||||||
s.add_rule(rule).unwrap();
|
s.add_rule(rule).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,16 +58,19 @@ impl Parser for LangParser {
|
||||||
state: ParserState<'p, 'a>,
|
state: ParserState<'p, 'a>,
|
||||||
source: Rc<dyn Source>,
|
source: Rc<dyn Source>,
|
||||||
parent: Option<&'doc dyn Document<'doc>>,
|
parent: Option<&'doc dyn Document<'doc>>,
|
||||||
|
mode: ParseMode,
|
||||||
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>) {
|
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>) {
|
||||||
let doc = LangDocument::new(source.clone(), parent);
|
let doc = LangDocument::new(source.clone(), parent);
|
||||||
|
|
||||||
// Insert semantics into state
|
// Insert semantics into state
|
||||||
if let (Some(_), Some(semantics)) = (source.clone().downcast_rc::<SourceFile>().ok(), state.shared.semantics.as_ref())
|
if let (Some(_), Some(semantics)) = (
|
||||||
{
|
source.clone().downcast_rc::<SourceFile>().ok(),
|
||||||
|
state.shared.semantics.as_ref(),
|
||||||
|
) {
|
||||||
let mut b = semantics.borrow_mut();
|
let mut b = semantics.borrow_mut();
|
||||||
if !b.sems.contains_key(&source)
|
if !b.sems.contains_key(&source) {
|
||||||
{
|
b.sems
|
||||||
b.sems.insert(source.clone(), SemanticsData::new(source.clone()));
|
.insert(source.clone(), SemanticsData::new(source.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +88,7 @@ impl Parser for LangParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (rule_pos, mut result) = state.update_matches(&cursor);
|
let (rule_pos, mut result) = state.update_matches(&mode, &cursor);
|
||||||
|
|
||||||
// Unmatched content
|
// Unmatched content
|
||||||
let text_content =
|
let text_content =
|
||||||
|
@ -125,13 +127,12 @@ impl Parser for LangParser {
|
||||||
super::state::Scope::DOCUMENT,
|
super::state::Scope::DOCUMENT,
|
||||||
));
|
));
|
||||||
|
|
||||||
if parent.is_none()
|
if parent.is_none() {
|
||||||
{
|
|
||||||
state.push(
|
state.push(
|
||||||
&doc,
|
&doc,
|
||||||
Box::new(DocumentEnd(Token::new(
|
Box::new(DocumentEnd(Token::new(
|
||||||
doc.source().content().len()..doc.source().content().len(),
|
doc.source().content().len()..doc.source().content().len(),
|
||||||
doc.source(),
|
doc.source(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -144,12 +145,13 @@ impl Parser for LangParser {
|
||||||
state: ParserState<'p, 'a>,
|
state: ParserState<'p, 'a>,
|
||||||
source: Rc<dyn Source>,
|
source: Rc<dyn Source>,
|
||||||
document: &'doc dyn Document<'doc>,
|
document: &'doc dyn Document<'doc>,
|
||||||
|
mode: ParseMode,
|
||||||
) -> ParserState<'p, 'a> {
|
) -> ParserState<'p, 'a> {
|
||||||
let content = source.content();
|
let content = source.content();
|
||||||
let mut cursor = Cursor::new(0usize, source.clone());
|
let mut cursor = Cursor::new(0usize, source.clone());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (rule_pos, mut result) = state.update_matches(&cursor);
|
let (rule_pos, mut result) = state.update_matches(&mode, &cursor);
|
||||||
|
|
||||||
// Unmatched content
|
// Unmatched content
|
||||||
let text_content =
|
let text_content =
|
||||||
|
|
|
@ -147,7 +147,10 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
|
|
||||||
/// Constructs a new state with semantics enabled
|
/// Constructs a new state with semantics enabled
|
||||||
/// See [`ParserState::new`] for mote information
|
/// See [`ParserState::new`] for mote information
|
||||||
pub fn new_with_semantics(parser: &'a dyn Parser, parent: Option<&'a ParserState<'a, 'b>>) -> Self {
|
pub fn new_with_semantics(
|
||||||
|
parser: &'a dyn Parser,
|
||||||
|
parent: Option<&'a ParserState<'a, 'b>>,
|
||||||
|
) -> Self {
|
||||||
let matches = parser.rules().iter().map(|_| (0, None)).collect::<Vec<_>>();
|
let matches = parser.rules().iter().map(|_| (0, None)).collect::<Vec<_>>();
|
||||||
let shared = if let Some(parent) = &parent {
|
let shared = if let Some(parent) = &parent {
|
||||||
parent.shared.clone()
|
parent.shared.clone()
|
||||||
|
@ -199,7 +202,11 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
/// Notes that the result of every call to [`Rule::next_match`] gets stored
|
/// Notes that the result of every call to [`Rule::next_match`] gets stored
|
||||||
/// in a table: [`ParserState::matches`]. Until the cursor steps over a
|
/// in a table: [`ParserState::matches`]. Until the cursor steps over a
|
||||||
/// position in the table, `next_match` won't be called.
|
/// position in the table, `next_match` won't be called.
|
||||||
pub fn update_matches(&self, cursor: &Cursor) -> (Cursor, Option<(usize, Box<dyn Any>)>) {
|
pub fn update_matches(
|
||||||
|
&self,
|
||||||
|
mode: &ParseMode,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> (Cursor, Option<(usize, Box<dyn Any>)>) {
|
||||||
let mut matches_borrow = self.matches.borrow_mut();
|
let mut matches_borrow = self.matches.borrow_mut();
|
||||||
|
|
||||||
self.parser
|
self.parser
|
||||||
|
@ -212,7 +219,7 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*matched_at, *match_data) = match rule.next_match(self, cursor) {
|
(*matched_at, *match_data) = match rule.next_match(&mode, self, cursor) {
|
||||||
None => (usize::MAX, None),
|
None => (usize::MAX, None),
|
||||||
Some((mut pos, mut data)) => {
|
Some((mut pos, mut data)) => {
|
||||||
// Check if escaped
|
// Check if escaped
|
||||||
|
@ -233,7 +240,7 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next potential match
|
// Find next potential match
|
||||||
(pos, data) = match rule.next_match(self, &cursor.at(pos + 1)) {
|
(pos, data) = match rule.next_match(&mode, self, &cursor.at(pos + 1)) {
|
||||||
Some((new_pos, new_data)) => (new_pos, new_data),
|
Some((new_pos, new_data)) => (new_pos, new_data),
|
||||||
None => (usize::MAX, data), // Stop iterating
|
None => (usize::MAX, data), // Stop iterating
|
||||||
}
|
}
|
||||||
|
@ -308,24 +315,28 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
/// # Error
|
/// # Error
|
||||||
///
|
///
|
||||||
/// Returns an error if `rule_name` was not found in the parser's ruleset.
|
/// Returns an error if `rule_name` was not found in the parser's ruleset.
|
||||||
pub fn reset_match(&self, rule_name: &str) -> Result<(), String>
|
pub fn reset_match(&self, rule_name: &str) -> Result<(), String> {
|
||||||
{
|
if self
|
||||||
if self.parser.rules().iter()
|
.parser
|
||||||
|
.rules()
|
||||||
|
.iter()
|
||||||
.zip(self.matches.borrow_mut().iter_mut())
|
.zip(self.matches.borrow_mut().iter_mut())
|
||||||
.try_for_each(|(rule, (match_pos, match_data))| {
|
.try_for_each(|(rule, (match_pos, match_data))| {
|
||||||
if rule.name() != rule_name { return Ok(()) }
|
if rule.name() != rule_name {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
*match_pos = 0;
|
*match_pos = 0;
|
||||||
match_data.take();
|
match_data.take();
|
||||||
Err(())
|
Err(())
|
||||||
}).is_ok()
|
})
|
||||||
|
.is_ok()
|
||||||
{
|
{
|
||||||
return Err(format!("Could not find rule: {rule_name}"));
|
return Err(format!("Could not find rule: {rule_name}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resurcively reset
|
// Resurcively reset
|
||||||
if let Some(parent) = self.parent
|
if let Some(parent) = self.parent {
|
||||||
{
|
|
||||||
return parent.reset_match(rule_name);
|
return parent.reset_match(rule_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +344,18 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ParseMode {
|
||||||
|
pub paragraph_only: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ParseMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
paragraph_only: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Parser {
|
pub trait Parser {
|
||||||
/// Gets the colors for formatting errors
|
/// Gets the colors for formatting errors
|
||||||
///
|
///
|
||||||
|
@ -365,6 +388,7 @@ pub trait Parser {
|
||||||
state: ParserState<'p, 'a>,
|
state: ParserState<'p, 'a>,
|
||||||
source: Rc<dyn Source>,
|
source: Rc<dyn Source>,
|
||||||
parent: Option<&'doc dyn Document<'doc>>,
|
parent: Option<&'doc dyn Document<'doc>>,
|
||||||
|
mode: ParseMode,
|
||||||
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>);
|
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>);
|
||||||
|
|
||||||
/// Parse [`Source`] into an already existing [`Document`]
|
/// Parse [`Source`] into an already existing [`Document`]
|
||||||
|
@ -384,6 +408,7 @@ pub trait Parser {
|
||||||
state: ParserState<'p, 'a>,
|
state: ParserState<'p, 'a>,
|
||||||
source: Rc<dyn Source>,
|
source: Rc<dyn Source>,
|
||||||
document: &'doc dyn Document<'doc>,
|
document: &'doc dyn Document<'doc>,
|
||||||
|
mode: ParseMode,
|
||||||
) -> ParserState<'p, 'a>;
|
) -> ParserState<'p, 'a>;
|
||||||
|
|
||||||
/// Adds a rule to the parser.
|
/// Adds a rule to the parser.
|
||||||
|
@ -444,8 +469,11 @@ pub trait Parser {
|
||||||
|
|
||||||
if let Some(_s) = source.downcast_ref::<VirtualSource>() {
|
if let Some(_s) = source.downcast_ref::<VirtualSource>() {
|
||||||
let start = location.start()
|
let start = location.start()
|
||||||
+ if location.source().content().as_bytes()[location.start()]
|
+ if location.source().content().as_bytes()[location.start()] == b'\n' {
|
||||||
== b'\n' { 1 } else { 0 };
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
report.labels.push(
|
report.labels.push(
|
||||||
Label::new((location.source(), start..location.end()))
|
Label::new((location.source(), start..location.end()))
|
||||||
.with_message("In evaluation of")
|
.with_message("In evaluation of")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::layout::LayoutHolder;
|
use super::layout::LayoutHolder;
|
||||||
|
use super::parser::ParseMode;
|
||||||
use super::parser::ParserState;
|
use super::parser::ParserState;
|
||||||
use super::source::Cursor;
|
use super::source::Cursor;
|
||||||
use super::source::Source;
|
use super::source::Source;
|
||||||
|
@ -73,7 +74,13 @@ pub trait Rule: Downcast {
|
||||||
fn previous(&self) -> Option<&'static str>;
|
fn previous(&self) -> Option<&'static str>;
|
||||||
|
|
||||||
/// Finds the next match starting from [`cursor`]
|
/// Finds the next match starting from [`cursor`]
|
||||||
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
mode: &ParseMode,
|
||||||
|
state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)>;
|
||||||
|
|
||||||
/// Callback when rule matches
|
/// Callback when rule matches
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -110,6 +117,9 @@ pub trait RegexRule {
|
||||||
/// Returns the rule's regexes
|
/// Returns the rule's regexes
|
||||||
fn regexes(&self) -> &[regex::Regex];
|
fn regexes(&self) -> &[regex::Regex];
|
||||||
|
|
||||||
|
/// Wheter parsing for the rule is enabled
|
||||||
|
fn enabled(&self, mode: &ParseMode, index: usize) -> bool;
|
||||||
|
|
||||||
/// Callback on regex rule match
|
/// Callback on regex rule match
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -127,13 +137,22 @@ pub trait RegexRule {
|
||||||
|
|
||||||
impl<T: RegexRule + 'static> Rule for T {
|
impl<T: RegexRule + 'static> Rule for T {
|
||||||
fn name(&self) -> &'static str { RegexRule::name(self) }
|
fn name(&self) -> &'static str { RegexRule::name(self) }
|
||||||
|
|
||||||
fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) }
|
fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) }
|
||||||
|
|
||||||
/// Finds the next match starting from [`cursor`]
|
/// Finds the next match starting from [`cursor`]
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(
|
||||||
|
&self,
|
||||||
|
mode: &ParseMode,
|
||||||
|
_state: &ParserState,
|
||||||
|
cursor: &Cursor,
|
||||||
|
) -> Option<(usize, Box<dyn Any>)> {
|
||||||
let content = cursor.source.content();
|
let content = cursor.source.content();
|
||||||
let mut found: Option<(usize, usize)> = None;
|
let mut found: Option<(usize, usize)> = None;
|
||||||
self.regexes().iter().enumerate().for_each(|(id, re)| {
|
self.regexes().iter().enumerate().for_each(|(id, re)| {
|
||||||
|
if !RegexRule::enabled(self, mode, id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if let Some(m) = re.find_at(content.as_str(), cursor.pos) {
|
if let Some(m) = re.find_at(content.as_str(), cursor.pos) {
|
||||||
found = found
|
found = found
|
||||||
.map(|(f_pos, f_id)| {
|
.map(|(f_pos, f_id)| {
|
||||||
|
|
|
@ -60,7 +60,8 @@ macro_rules! impl_elementstyle {
|
||||||
serde_json::from_str::<$t>(json)
|
serde_json::from_str::<$t>(json)
|
||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
.map(|obj| {
|
.map(|obj| {
|
||||||
std::rc::Rc::new(obj) as std::rc::Rc<dyn $crate::parser::style::ElementStyle>
|
std::rc::Rc::new(obj)
|
||||||
|
as std::rc::Rc<dyn $crate::parser::style::ElementStyle>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::document::document::DocumentAccessors;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
|
|
||||||
|
use super::parser::ParseMode;
|
||||||
use super::parser::ParserState;
|
use super::parser::ParserState;
|
||||||
use super::source::Source;
|
use super::source::Source;
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ pub fn parse_paragraph<'a>(
|
||||||
let parsed = state.with_state(|new_state| -> Box<dyn Document> {
|
let parsed = state.with_state(|new_state| -> Box<dyn Document> {
|
||||||
new_state
|
new_state
|
||||||
.parser
|
.parser
|
||||||
.parse(new_state, source.clone(), Some(document))
|
.parse(new_state, source.clone(), Some(document), ParseMode { paragraph_only: true })
|
||||||
.0
|
.0
|
||||||
});
|
});
|
||||||
if parsed.content().borrow().len() > 1 {
|
if parsed.content().borrow().len() > 1 {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use parser::langparser::LangParser;
|
use parser::langparser::LangParser;
|
||||||
|
use parser::parser::ParseMode;
|
||||||
use parser::parser::Parser;
|
use parser::parser::Parser;
|
||||||
use parser::parser::ParserState;
|
use parser::parser::ParserState;
|
||||||
use parser::source::SourceFile;
|
use parser::source::SourceFile;
|
||||||
|
@ -42,7 +43,7 @@ impl Backend {
|
||||||
// Which will require a dyn Document to work
|
// Which will require a dyn Document to work
|
||||||
let source = Rc::new(SourceFile::with_content(params.uri.to_string(), params.text.clone(), None));
|
let source = Rc::new(SourceFile::with_content(params.uri.to_string(), params.text.clone(), None));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None);
|
let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None, ParseMode::default());
|
||||||
|
|
||||||
if let Some(sems) = state.shared.semantics.as_ref()
|
if let Some(sems) = state.shared.semantics.as_ref()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue