use lazy_static::lazy_static;
use std::iter::FromIterator;
use std::collections::HashSet;
use std::rc::Rc;
use std::borrow::Cow;
use crate::frontend::data::{
Atom,
Text,
Enclosure,
EnclosureKind,
INLINE_MATH_TAG,
};
use crate::frontend::ast::{Ann, Node, NodeEnvironment, Tag};
pub static LATEX_ENVIRONMENT_NAME_LIST: &'static [&'static str] = &[
"equation",
"split",
];
lazy_static! {
pub static ref LATEX_ENV_NAMES: HashSet<&'static str> = {
HashSet::from_iter(
LATEX_ENVIRONMENT_NAME_LIST.to_vec()
)
};
}
fn to_valid_latex_math<'a>(node: Node<'a>) -> Node<'a> {
fn init_env<'a>(env_name: &'a str, children: Vec<Node<'a>>) -> Node<'a> {
Node::new_fragment(vec![
Node::unannotated_tag_(
"begin",
Node::Enclosure(Ann::unannotated(
Enclosure::new_curly_brace_(Node::unannotated_str(env_name))
))
),
Node::new_fragment(children),
Node::unannotated_tag_(
"end",
Node::Enclosure(Ann::unannotated(
Enclosure::new_curly_brace_(Node::unannotated_str(env_name))
))
),
])
}
fn f<'a>(env: NodeEnvironment, x: Node<'a>) -> Node<'a> {
match x {
Node::Tag(tag) if LATEX_ENV_NAMES.contains(tag.name()) => {
let env_name = *LATEX_ENV_NAMES.get(tag.name()).unwrap();
init_env(
env_name,
tag.children
)
}
Node::Tag(mut tag) => {
tag.children = tag.children
.into_iter()
.collect();
Node::Tag(tag)
}
x => x,
}
}
node.transform(NodeEnvironment::default(), Rc::new(f))
}
pub fn latex_pass<'a>(node: Node<'a>) -> Node<'a> {
match node {
Node::Tag(tag) if tag.has_name("equation") => {
let node = tag.children
.into_iter()
.flat_map(Node::unblock)
.map(to_valid_latex_math)
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join("");
let start = "\\begin{equation}\\begin{split}";
let end = "\\end{split}\\end{equation}";
Node::String(Ann::unannotated(Cow::Owned(format!(
"\\[{}{}{}\\]",
start,
node,
end,
))))
}
Node::Tag(tag) if tag.has_name(INLINE_MATH_TAG) => {
let node = tag.children
.into_iter()
.flat_map(Node::unblock)
.map(to_valid_latex_math)
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join("");
Node::String(Ann::unannotated(Cow::Owned(format!(
"\\({}\\)",
node,
))))
}
Node::Tag(mut tag) => {
tag.children = tag.children
.into_iter()
.map(latex_pass)
.collect();
Node::Tag(tag)
}
Node::Enclosure(mut block) => {
block.data.children = block.data.children
.into_iter()
.map(latex_pass)
.collect();
Node::Enclosure(block)
}
node @ Node::Ident(_) => node,
node @ Node::String(_) => node,
node @ Node::InvalidToken(_) => node,
}
}