Compare commits
No commits in common. "48d2064d0c8ccb012a0cb6bf9fe560701a2f99ef" and "d91279c1f21b8e2a0d604b514a856b5ecab283b0" have entirely different histories.
48d2064d0c
...
d91279c1f2
13 changed files with 33 additions and 404 deletions
|
@ -1,4 +1,3 @@
|
||||||
use std::cell::Ref;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -21,8 +20,6 @@ pub struct Compiler {
|
||||||
cache: Option<RefCell<Connection>>,
|
cache: Option<RefCell<Connection>>,
|
||||||
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
||||||
// TODO: External references, i.e resolved later
|
// TODO: External references, i.e resolved later
|
||||||
|
|
||||||
sections_counter: RefCell<Vec<usize>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
|
@ -38,34 +35,9 @@ impl Compiler {
|
||||||
target,
|
target,
|
||||||
cache: cache.map(|con| RefCell::new(con)),
|
cache: cache.map(|con| RefCell::new(con)),
|
||||||
reference_count: RefCell::new(HashMap::new()),
|
reference_count: RefCell::new(HashMap::new()),
|
||||||
sections_counter: RefCell::new(vec![]),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the section counter for a given depth
|
|
||||||
/// This function modifies the section counter
|
|
||||||
pub fn section_counter(&self, depth: usize) -> Ref<'_, Vec<usize>>
|
|
||||||
{
|
|
||||||
// Increment current counter
|
|
||||||
if self.sections_counter.borrow().len() == depth {
|
|
||||||
self.sections_counter.borrow_mut().last_mut()
|
|
||||||
.map(|id| *id += 1);
|
|
||||||
return Ref::map(self.sections_counter.borrow(), |b| &*b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close
|
|
||||||
while self.sections_counter.borrow().len() > depth {
|
|
||||||
self.sections_counter.borrow_mut().pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open
|
|
||||||
while self.sections_counter.borrow().len() < depth {
|
|
||||||
self.sections_counter.borrow_mut().push(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref::map(self.sections_counter.borrow(), |b| &*b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sanitizes text for a [`Target`]
|
/// Sanitizes text for a [`Target`]
|
||||||
pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
|
pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
|
||||||
match target {
|
match target {
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::str::FromStr;
|
||||||
use crate::compiler::compiler::Compiler;
|
use crate::compiler::compiler::Compiler;
|
||||||
use crate::elements::reference::Reference;
|
use crate::elements::reference::Reference;
|
||||||
use crate::parser::source::Token;
|
use crate::parser::source::Token;
|
||||||
use crate::parser::util::PropertyParser;
|
|
||||||
use downcast_rs::impl_downcast;
|
use downcast_rs::impl_downcast;
|
||||||
use downcast_rs::Downcast;
|
use downcast_rs::Downcast;
|
||||||
|
|
||||||
|
@ -63,15 +62,10 @@ pub trait ReferenceableElement: Element {
|
||||||
fn refcount_key(&self) -> &'static str;
|
fn refcount_key(&self) -> &'static str;
|
||||||
|
|
||||||
/// Creates the reference element
|
/// Creates the reference element
|
||||||
fn compile_reference(
|
fn compile_reference(&self, compiler: &Compiler, document: &dyn Document, reference: &Reference, refid: usize) -> Result<String, String>;
|
||||||
&self,
|
|
||||||
compiler: &Compiler,
|
|
||||||
document: &dyn Document,
|
|
||||||
reference: &Reference,
|
|
||||||
refid: usize,
|
|
||||||
) -> Result<String, String>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait ContainerElement: Element {
|
pub trait ContainerElement: Element {
|
||||||
/// Gets the contained elements
|
/// Gets the contained elements
|
||||||
fn contained(&self) -> &Vec<Box<dyn Element>>;
|
fn contained(&self) -> &Vec<Box<dyn Element>>;
|
||||||
|
|
|
@ -3,4 +3,3 @@ pub mod references;
|
||||||
pub mod langdocument;
|
pub mod langdocument;
|
||||||
pub mod element;
|
pub mod element;
|
||||||
pub mod variable;
|
pub mod variable;
|
||||||
pub mod style;
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
use std::cell::Ref;
|
|
||||||
use std::cell::RefMut;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use downcast_rs::impl_downcast;
|
|
||||||
use downcast_rs::Downcast;
|
|
||||||
|
|
||||||
/// Styling for an element
|
|
||||||
pub trait ElementStyle: Downcast + core::fmt::Debug {
|
|
||||||
/// The style key
|
|
||||||
fn key(&self) -> &'static str;
|
|
||||||
|
|
||||||
/// Attempts to create a new style from a [`json`] string
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Will fail if deserialization fails
|
|
||||||
fn from_json(&self, json: &str) -> Result<Rc<dyn ElementStyle>, String>;
|
|
||||||
|
|
||||||
/// Serializes sytle into json string
|
|
||||||
fn to_json(&self) -> String;
|
|
||||||
}
|
|
||||||
impl_downcast!(ElementStyle);
|
|
||||||
|
|
||||||
pub trait StyleHolder {
|
|
||||||
/// gets a reference to all defined styles
|
|
||||||
fn styles(&self) -> Ref<'_, HashMap<String, Rc<dyn ElementStyle>>>;
|
|
||||||
|
|
||||||
/// gets a (mutable) reference to all defined styles
|
|
||||||
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>>;
|
|
||||||
|
|
||||||
/// Checks if a given style key is registered
|
|
||||||
fn is_registered(&self, style_key: &str) -> bool {
|
|
||||||
self.styles().contains_key(style_key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the current active style for an element
|
|
||||||
/// NOTE: Will panic if a style is not defined for a given element
|
|
||||||
/// If you need to process user input, use [`is_registered`]
|
|
||||||
fn current_style(&self, style_key: &str) -> Rc<dyn ElementStyle> {
|
|
||||||
self.styles().get(style_key).map(|rc| rc.clone()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the [`style`]
|
|
||||||
fn set_style(&self, style: Rc<dyn ElementStyle>) {
|
|
||||||
self.styles_mut().insert(style.key().to_string(), style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! impl_elementstyle {
|
|
||||||
($t:ty, $key:expr) => {
|
|
||||||
impl ElementStyle for $t {
|
|
||||||
fn key(&self) -> &'static str { $key }
|
|
||||||
|
|
||||||
fn from_json(&self, json: &str) -> Result<std::rc::Rc<dyn ElementStyle>, String> {
|
|
||||||
serde_json::from_str::<$t>(json)
|
|
||||||
.map_err(|e| e.to_string())
|
|
||||||
.map(|obj| std::rc::Rc::new(obj) as std::rc::Rc<dyn ElementStyle>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
use std::ops::Range;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use ariadne::{Fmt, Label, Report, ReportKind};
|
|
||||||
use regex::{Captures, Regex};
|
|
||||||
|
|
||||||
use crate::document::document::Document;
|
|
||||||
use crate::document::{self};
|
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::rule::RegexRule;
|
|
||||||
use crate::parser::source::Source;
|
|
||||||
use crate::parser::source::Token;
|
|
||||||
|
|
||||||
use super::variable::VariableRule;
|
|
||||||
|
|
||||||
pub struct ElemStyleRule {
|
|
||||||
re: [Regex; 1],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ElemStyleRule {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
re: [Regex::new(r"(?:^|\n)@@(.*?)=((?:\\\n|.)*)").unwrap()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegexRule for ElemStyleRule {
|
|
||||||
fn name(&self) -> &'static str { "Element Style" }
|
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
|
||||||
&self,
|
|
||||||
_: usize,
|
|
||||||
parser: &dyn Parser,
|
|
||||||
_document: &'a dyn Document,
|
|
||||||
token: Token,
|
|
||||||
matches: Captures,
|
|
||||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
|
||||||
let mut reports = vec![];
|
|
||||||
|
|
||||||
let style = if let Some(key) = matches.get(1)
|
|
||||||
{
|
|
||||||
let trimmed = key.as_str().trim_start().trim_end();
|
|
||||||
|
|
||||||
// Check if empty
|
|
||||||
if trimmed.is_empty()
|
|
||||||
{
|
|
||||||
reports.push(
|
|
||||||
Report::build(ReportKind::Error, token.source(), key.start())
|
|
||||||
.with_message("Empty Style Key")
|
|
||||||
.with_label(
|
|
||||||
Label::new((token.source(), key.range()))
|
|
||||||
.with_message(format!(
|
|
||||||
"Expected a non-empty style key",
|
|
||||||
))
|
|
||||||
.with_color(parser.colors().error),
|
|
||||||
)
|
|
||||||
.finish());
|
|
||||||
return reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if key exists
|
|
||||||
if !parser.is_registered(trimmed)
|
|
||||||
{
|
|
||||||
reports.push(
|
|
||||||
Report::build(ReportKind::Error, token.source(), key.start())
|
|
||||||
.with_message("Unknown Style Key")
|
|
||||||
.with_label(
|
|
||||||
Label::new((token.source(), key.range()))
|
|
||||||
.with_message(format!(
|
|
||||||
"Could not find a style with key: {}",
|
|
||||||
trimmed.fg(parser.colors().info)
|
|
||||||
))
|
|
||||||
.with_color(parser.colors().error),
|
|
||||||
)
|
|
||||||
.finish());
|
|
||||||
|
|
||||||
return reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.current_style(trimmed)
|
|
||||||
} else { panic!("Unknown error") };
|
|
||||||
|
|
||||||
// Get value
|
|
||||||
let new_style = if let Some(value) = matches.get(2) {
|
|
||||||
let value_str = match VariableRule::validate_value(value.as_str()) {
|
|
||||||
Err(err) => {
|
|
||||||
reports.push(
|
|
||||||
Report::build(ReportKind::Error, token.source(), value.start())
|
|
||||||
.with_message("Invalid Style Value")
|
|
||||||
.with_label(
|
|
||||||
Label::new((token.source(), value.range()))
|
|
||||||
.with_message(format!(
|
|
||||||
"Value `{}` is not allowed: {err}",
|
|
||||||
value.as_str().fg(parser.colors().highlight)
|
|
||||||
))
|
|
||||||
.with_color(parser.colors().error),
|
|
||||||
)
|
|
||||||
.finish());
|
|
||||||
return reports;
|
|
||||||
}
|
|
||||||
Ok(value) => value,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attempt to serialize
|
|
||||||
match style.from_json(value_str.as_str())
|
|
||||||
{
|
|
||||||
Err(err) => {
|
|
||||||
reports.push(
|
|
||||||
Report::build(ReportKind::Error, token.source(), value.start())
|
|
||||||
.with_message("Invalid Style Value")
|
|
||||||
.with_label(
|
|
||||||
Label::new((token.source(), value.range()))
|
|
||||||
.with_message(format!(
|
|
||||||
"Failed to serialize `{}` into style with key `{}`: {err}",
|
|
||||||
value_str.fg(parser.colors().highlight),
|
|
||||||
style.key().fg(parser.colors().info)
|
|
||||||
))
|
|
||||||
.with_color(parser.colors().error),
|
|
||||||
)
|
|
||||||
.finish());
|
|
||||||
return reports;
|
|
||||||
},
|
|
||||||
Ok(style) => style,
|
|
||||||
}
|
|
||||||
} else { panic!("Unknown error") };
|
|
||||||
|
|
||||||
parser.set_style(new_style);
|
|
||||||
|
|
||||||
reports
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,4 +16,3 @@ pub mod style;
|
||||||
pub mod tex;
|
pub mod tex;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod variable;
|
pub mod variable;
|
||||||
pub mod elemstyle;
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use crate::parser::parser::Parser;
|
||||||
|
|
||||||
use super::code::CodeRule;
|
use super::code::CodeRule;
|
||||||
use super::comment::CommentRule;
|
use super::comment::CommentRule;
|
||||||
use super::elemstyle::ElemStyleRule;
|
|
||||||
use super::graphviz::GraphRule;
|
use super::graphviz::GraphRule;
|
||||||
use super::import::ImportRule;
|
use super::import::ImportRule;
|
||||||
use super::layout::LayoutRule;
|
use super::layout::LayoutRule;
|
||||||
|
@ -25,7 +24,6 @@ pub fn register<P: Parser>(parser: &mut P) {
|
||||||
parser.add_rule(Box::new(ParagraphRule::new()), None).unwrap();
|
parser.add_rule(Box::new(ParagraphRule::new()), None).unwrap();
|
||||||
parser.add_rule(Box::new(ImportRule::new()), None).unwrap();
|
parser.add_rule(Box::new(ImportRule::new()), None).unwrap();
|
||||||
parser.add_rule(Box::new(ScriptRule::new()), None).unwrap();
|
parser.add_rule(Box::new(ScriptRule::new()), None).unwrap();
|
||||||
parser.add_rule(Box::new(ElemStyleRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(VariableRule::new()), None).unwrap();
|
parser.add_rule(Box::new(VariableRule::new()), None).unwrap();
|
||||||
parser.add_rule(Box::new(VariableSubstitutionRule::new()), None).unwrap();
|
parser.add_rule(Box::new(VariableSubstitutionRule::new()), None).unwrap();
|
||||||
parser.add_rule(Box::new(RawRule::new()), None).unwrap();
|
parser.add_rule(Box::new(RawRule::new()), None).unwrap();
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl RegexRule for ScriptRule {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::elements::link::Link;
|
use crate::elements::link::Link;
|
||||||
use crate::elements::list::ListEntry;
|
use crate::elements::list::ListEntry;
|
||||||
use crate::elements::list::ListMarker;
|
use crate::elements::list::ListMarker;
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::style::Style;
|
use crate::elements::style::Style;
|
||||||
|
|
|
@ -17,8 +17,6 @@ use mlua::Error::BadArgument;
|
||||||
use mlua::Function;
|
use mlua::Function;
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use section_style::SectionLinkPos;
|
|
||||||
use section_style::SectionStyle;
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -26,78 +24,30 @@ use std::sync::Arc;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Section {
|
pub struct Section {
|
||||||
pub(self) location: Token,
|
pub(self) location: Token,
|
||||||
/// Title of the section
|
pub(self) title: String, // Section title
|
||||||
pub(self) title: String,
|
pub(self) depth: usize, // Section depth
|
||||||
/// Depth i.e number of '#'
|
pub(self) kind: u8, // Section kind, e.g numbered, unnumbred, ...
|
||||||
pub(self) depth: usize,
|
pub(self) reference: Option<String>, // Section reference name
|
||||||
/// [`section_kind`]
|
|
||||||
pub(self) kind: u8,
|
|
||||||
/// Section reference name
|
|
||||||
pub(self) reference: Option<String>,
|
|
||||||
/// Style of the section
|
|
||||||
pub(self) style: Rc<section_style::SectionStyle>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for Section {
|
impl Element for Section {
|
||||||
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 { "Section" }
|
fn element_name(&self) -> &'static str { "Section" }
|
||||||
|
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
||||||
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
// Section numbering
|
|
||||||
let number = if (self.kind & section_kind::NO_NUMBER) == section_kind::NO_NUMBER {
|
|
||||||
let numbering = compiler.section_counter(self.depth);
|
|
||||||
let number = " ".to_string()
|
|
||||||
+ numbering
|
|
||||||
.iter()
|
|
||||||
.map(|n| n.to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(".")
|
|
||||||
.as_str();
|
|
||||||
number
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.style.link_pos == SectionLinkPos::None {
|
|
||||||
return Ok(format!(
|
|
||||||
r#"<h{0} id="{1}">{number}{2}</h{0}>"#,
|
|
||||||
self.depth,
|
|
||||||
Compiler::refname(compiler.target(), self.title.as_str()),
|
|
||||||
Compiler::sanitize(compiler.target(), self.title.as_str())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let refname = Compiler::refname(compiler.target(), self.title.as_str());
|
|
||||||
let link = format!(
|
|
||||||
"<a class=\"section-link\" href=\"#{refname}\">{}</a>",
|
|
||||||
Compiler::sanitize(compiler.target(), self.style.link.as_str())
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.style.link_pos == SectionLinkPos::After {
|
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
r#"<h{0} id="{1}">{number}{2}{link}</h{0}>"#,
|
r#"<h{0} id="{1}">{2}</h{0}>"#,
|
||||||
self.depth,
|
self.depth,
|
||||||
Compiler::refname(compiler.target(), self.title.as_str()),
|
Compiler::refname(compiler.target(), self.title.as_str()),
|
||||||
Compiler::sanitize(compiler.target(), self.title.as_str())
|
Compiler::sanitize(compiler.target(), self.title.as_str())
|
||||||
))
|
))
|
||||||
} else
|
},
|
||||||
// Before
|
|
||||||
{
|
|
||||||
Ok(format!(
|
|
||||||
r#"<h{0} id="{1}">{link}{number}{2}</h{0}>"#,
|
|
||||||
self.depth,
|
|
||||||
Compiler::refname(compiler.target(), self.title.as_str()),
|
|
||||||
Compiler::sanitize(compiler.target(), self.title.as_str())
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Target::LATEX => Err("Unimplemented compiler".to_string()),
|
Target::LATEX => Err("Unimplemented compiler".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReferenceableElement for Section {
|
impl ReferenceableElement for Section {
|
||||||
|
@ -186,12 +136,12 @@ impl RegexRule for SectionRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
// [Optional] Reference name
|
// [Optional] Reference name
|
||||||
let section_refname =
|
let section_refname = matches.get(2).map_or_else(
|
||||||
matches.get(2).map_or_else(
|
|
||||||
|| None,
|
|| None,
|
||||||
|refname| {
|
|refname| {
|
||||||
// Check for duplicate reference
|
// Check for duplicate reference
|
||||||
if let Some(elem_reference) = document.get_reference(refname.as_str()) {
|
if let Some(elem_reference) = document.get_reference(refname.as_str())
|
||||||
|
{
|
||||||
let elem = document.get_from_reference(&elem_reference).unwrap();
|
let elem = document.get_from_reference(&elem_reference).unwrap();
|
||||||
|
|
||||||
result.push(
|
result.push(
|
||||||
|
@ -289,12 +239,6 @@ impl RegexRule for SectionRule {
|
||||||
_ => panic!("Empty section name"),
|
_ => panic!("Empty section name"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get style
|
|
||||||
let style = parser
|
|
||||||
.current_style(section_style::STYLE_KEY)
|
|
||||||
.downcast_rc::<SectionStyle>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
parser.push(
|
parser.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Section {
|
Box::new(Section {
|
||||||
|
@ -303,7 +247,6 @@ impl RegexRule for SectionRule {
|
||||||
depth: section_depth,
|
depth: section_depth,
|
||||||
kind: section_kind,
|
kind: section_kind,
|
||||||
reference: section_refname,
|
reference: section_refname,
|
||||||
style,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -336,13 +279,6 @@ impl RegexRule for SectionRule {
|
||||||
|
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
// Get style
|
|
||||||
let style = ctx
|
|
||||||
.parser
|
|
||||||
.current_style(section_style::STYLE_KEY)
|
|
||||||
.downcast_rc::<SectionStyle>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.parser.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Section {
|
Box::new(Section {
|
||||||
|
@ -351,7 +287,6 @@ impl RegexRule for SectionRule {
|
||||||
depth,
|
depth,
|
||||||
kind,
|
kind,
|
||||||
reference,
|
reference,
|
||||||
style,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -365,42 +300,4 @@ impl RegexRule for SectionRule {
|
||||||
|
|
||||||
Some(bindings)
|
Some(bindings)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_styles(&self, parser: &dyn Parser) {
|
|
||||||
parser.set_style(Rc::new(SectionStyle::default()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod section_style {
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use crate::document::style::ElementStyle;
|
|
||||||
use crate::impl_elementstyle;
|
|
||||||
|
|
||||||
pub static STYLE_KEY: &'static str = "style.section";
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
pub enum SectionLinkPos {
|
|
||||||
Before,
|
|
||||||
After,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct SectionStyle {
|
|
||||||
pub link_pos: SectionLinkPos,
|
|
||||||
pub link: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SectionStyle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
link_pos: SectionLinkPos::After,
|
|
||||||
link: "🔗".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_elementstyle!(SectionStyle, STYLE_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl VariableRule {
|
||||||
return Ok(name);
|
return Ok(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_value(original_value: &str) -> Result<String, String> {
|
pub fn validate_value(_colors: &ReportColors, original_value: &str) -> Result<String, String> {
|
||||||
let mut escaped = 0usize;
|
let mut escaped = 0usize;
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
for c in original_value.trim_start().trim_end().chars() {
|
for c in original_value.trim_start().trim_end().chars() {
|
||||||
|
@ -93,7 +93,7 @@ impl VariableRule {
|
||||||
escaped += 1
|
escaped += 1
|
||||||
} else if c == '\n' {
|
} else if c == '\n' {
|
||||||
match escaped {
|
match escaped {
|
||||||
0 => return Err("Unknown error wile capturing value".to_string()),
|
0 => return Err("Unknown error wile capturing variable".to_string()),
|
||||||
// Remove '\n'
|
// Remove '\n'
|
||||||
1 => {}
|
1 => {}
|
||||||
// Insert '\n'
|
// Insert '\n'
|
||||||
|
@ -202,7 +202,7 @@ impl RegexRule for VariableRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
let var_value = match matches.get(3) {
|
let var_value = match matches.get(3) {
|
||||||
Some(value) => match VariableRule::validate_value(value.as_str()) {
|
Some(value) => match VariableRule::validate_value(&parser.colors(), value.as_str()) {
|
||||||
Ok(var_value) => var_value,
|
Ok(var_value) => var_value,
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
result.push(
|
result.push(
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use std::cell::Ref;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -16,8 +15,6 @@ use crate::document::element::DocumentEnd;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::langdocument::LangDocument;
|
use crate::document::langdocument::LangDocument;
|
||||||
use crate::document::style::ElementStyle;
|
|
||||||
use crate::document::style::StyleHolder;
|
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::registrar::register;
|
use crate::elements::registrar::register;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
|
@ -45,7 +42,6 @@ pub struct LangParser {
|
||||||
pub err_flag: RefCell<bool>,
|
pub err_flag: RefCell<bool>,
|
||||||
pub state: RefCell<StateHolder>,
|
pub state: RefCell<StateHolder>,
|
||||||
pub kernels: RefCell<HashMap<String, Kernel>>,
|
pub kernels: RefCell<HashMap<String, Kernel>>,
|
||||||
pub styles: RefCell<HashMap<String, Rc<dyn ElementStyle>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LangParser {
|
impl LangParser {
|
||||||
|
@ -56,21 +52,12 @@ impl LangParser {
|
||||||
err_flag: RefCell::new(false),
|
err_flag: RefCell::new(false),
|
||||||
state: RefCell::new(StateHolder::new()),
|
state: RefCell::new(StateHolder::new()),
|
||||||
kernels: RefCell::new(HashMap::new()),
|
kernels: RefCell::new(HashMap::new()),
|
||||||
styles: RefCell::new(HashMap::new()),
|
|
||||||
};
|
};
|
||||||
// Register rules
|
|
||||||
register(&mut s);
|
register(&mut s);
|
||||||
|
|
||||||
|
|
||||||
// Register default kernel
|
|
||||||
s.kernels
|
s.kernels
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert("main".to_string(), Kernel::new(&s));
|
.insert("main".to_string(), Kernel::new(&s));
|
||||||
|
|
||||||
// Register default styles
|
|
||||||
for rule in &s.rules {
|
|
||||||
rule.register_styles(&s);
|
|
||||||
}
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,11 +292,3 @@ impl KernelHolder for LangParser {
|
||||||
self.get_kernel(name.as_str()).unwrap()
|
self.get_kernel(name.as_str()).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyleHolder for LangParser {
|
|
||||||
fn styles(&self) -> Ref<'_, HashMap<String, Rc<dyn ElementStyle>>> { self.styles.borrow() }
|
|
||||||
|
|
||||||
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>> {
|
|
||||||
self.styles.borrow_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ use super::source::Source;
|
||||||
use super::state::StateHolder;
|
use super::state::StateHolder;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::style::StyleHolder;
|
|
||||||
use crate::lua::kernel::KernelHolder;
|
use crate::lua::kernel::KernelHolder;
|
||||||
use ariadne::Color;
|
use ariadne::Color;
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ impl ReportColors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Parser: KernelHolder + StyleHolder {
|
pub trait Parser: KernelHolder {
|
||||||
/// Gets the colors for formatting errors
|
/// Gets the colors for formatting errors
|
||||||
///
|
///
|
||||||
/// When colors are disabled, all colors should resolve to empty string
|
/// When colors are disabled, all colors should resolve to empty string
|
||||||
|
|
|
@ -25,10 +25,7 @@ pub trait Rule {
|
||||||
match_data: Option<Box<dyn Any>>,
|
match_data: Option<Box<dyn Any>>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
||||||
/// Export bindings to lua
|
/// Export bindings to lua
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>>;
|
||||||
|
|
||||||
/// Registers default styles
|
|
||||||
fn register_styles(&self, _parser: &dyn Parser) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Debug for dyn Rule {
|
impl core::fmt::Debug for dyn Rule {
|
||||||
|
@ -92,8 +89,7 @@ pub trait RegexRule {
|
||||||
matches: regex::Captures,
|
matches: regex::Captures,
|
||||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
|
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
|
||||||
|
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>>;
|
||||||
fn register_styles(&self, _parser: &dyn Parser) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RegexRule> Rule for T {
|
impl<T: RegexRule> Rule for T {
|
||||||
|
@ -151,8 +147,4 @@ impl<T: RegexRule> Rule for T {
|
||||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||||
self.lua_bindings(lua)
|
self.lua_bindings(lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_styles(&self, parser: &dyn Parser) {
|
|
||||||
self.register_styles(parser);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue