use crate::Convert;
use std::fmt::format;
type Body = String;
type Meta = String;
type Pkg = String;
pub type UDTuple = (Body, Meta, Pkg);
pub type Item = String;
#[derive(Debug, Clone)]
pub struct Part(pub String, pub Vec<Element>);
#[derive(Debug, Clone)]
pub struct Chapter(pub String, pub Vec<Element>);
#[derive(Debug, Clone)]
pub struct Section(pub String, pub Vec<Element>);
#[derive(Debug, Clone)]
pub struct Paragraph(pub String, pub Option<Vec<Element>>);
#[derive(Debug, Clone)]
pub struct Text(pub String, pub TextType);
#[derive(Debug, Clone)]
pub struct Input(pub String);
#[derive(Debug, Clone)]
pub struct Environment(pub String, pub Vec<Item>);
#[derive(Debug, Clone)]
pub struct UserDefined(pub String, pub Level);
#[derive(Debug, Clone)]
pub struct List(pub ListMode, pub Vec<Item>);
pub type Comment = UserDefined;
#[derive(Debug, Clone)]
pub enum Element {
Part(Part),
Chapter(Chapter),
Section(Section),
Paragraph(Paragraph),
Text(Text),
Input(Input),
Environment(Environment),
UserDefined(UserDefined),
List(List),
}
#[derive(Debug, Clone)]
pub enum TextType {
Normal,
Bold,
Italic,
Underline,
Verbatim,
Roman,
}
#[derive(Debug, Clone)]
pub enum ListMode {
Itemize,
Enumerate,
}
#[derive(Debug, Clone)]
pub enum Level {
Meta,
Body,
Package,
}
impl Element {
pub fn rank(&self) -> u8 {
match self {
Element::Part(_) => 0,
Element::Chapter(_) => 1,
Element::Section(_) => 2,
Element::Paragraph(_) => 3,
Element::UserDefined(_) => 4,
Element::Text(_) => 8,
Element::Input(_) => 7,
Element::Environment(_) => 6,
Element::List(_) => 5,
}
}
pub fn get_vec(&self) -> Option<Vec<Element>> {
match &self {
Element::Part(p) => Some(p.to_owned().1),
Element::Chapter(c) => Some(c.to_owned().1),
Element::Section(s) => Some(s.to_owned().1),
Element::Paragraph(p) => Some(p.to_owned().1.unwrap()),
Element::Text(_) => None,
Element::Input(_) => None,
Element::Environment(e) => None,
Element::UserDefined(_) => None,
Element::List(_) => None,
}
}
pub fn loop_through(&self) -> String {
let vec = match self.get_vec() {
Some(a) => a,
None => return "".to_string(),
};
let mut s = Vec::new();
if vec.is_empty() {
return "".to_string();
} else {
for i in &vec {
s.push(i.to_latex_string());
s.push(i.loop_through())
}
}
s.join(" ")
}
pub fn loop_through_parallel(&self) -> String {
let vec = match self.get_vec() {
Some(a) => a,
None => return "".to_string(),
};
let mut s = Vec::new();
if vec.is_empty() {
return "".to_string();
} else {
for i in &vec {
let r = rayon::join(|| i.clone().to_latex_string(), || i.clone().loop_through());
s.push(r.0);
s.push(r.1);
}
}
s.join(" ")
}
}
impl Part {
pub fn new(text: &str) -> Self {
Self(text.to_string(), Vec::new())
}
}
impl Chapter {
pub fn new(text: &str) -> Self {
Self(text.to_string(), Vec::new())
}
}
impl Section {
pub fn new(text: &str) -> Self {
Self(text.to_string(), Vec::new())
}
}
impl Paragraph {
pub fn new(text: &str) -> Self {
Self(text.to_string(), Some(Vec::new()))
}
}
impl Text {
pub fn new(text: &str, text_type: TextType) -> Self {
Self(text.to_string(), text_type)
}
}
impl Input {
pub fn new(text: &str) -> Self {
Self(text.to_string())
}
}
impl Environment {
pub fn new(text: &str) -> Self {
Self(text.to_string(), Vec::new())
}
pub fn attach_string(&mut self, item: Item) {
self.1.push(item);
}
}
impl List {
pub fn new(list_mode: ListMode, items: &Vec<Item>) -> Self {
Self(list_mode, items.to_owned())
}
}
impl UserDefined {
pub fn new(text: &str, level: Level) -> Self {
Self(text.to_string(), level)
}
pub fn evaluate(&self) -> UDTuple {
match &self.1 {
Level::Body => (self.0.clone(), "".to_owned(), "".to_owned()),
Level::Meta => ("".to_owned(), self.0.clone(), "".to_owned()),
Level::Package => ("".to_owned(), "".to_owned(), self.0.clone()),
}
}
pub fn new_comment(text: &str, level: Level) -> Self {
Self(format!("% {}", text), level)
}
}
#[macro_export]
macro_rules! elements {
($($x:expr),+) => ({
let mut v = Vec::new();
$( v.push(Element::from($x)); )+
v
});
}
impl Convert for Part {
fn to_latex_string(&self) -> String {
format!("\\part{{{}}}", &self.0)
}
}
impl Convert for Chapter {
fn to_latex_string(&self) -> String {
format!("\\chapter{{{}}}", &self.0)
}
}
impl Convert for Section {
fn to_latex_string(&self) -> String {
format!("\\section{{{}}}", &self.0)
}
}
impl Convert for Paragraph {
fn to_latex_string(&self) -> String {
format!("\\paragraph{{{}}}", &self.0)
}
}
impl Convert for Text {
fn to_latex_string(&self) -> String {
let par = "\\par";
let mut text = String::new();
match &self.1 {
TextType::Normal => text = self.0.clone(),
TextType::Bold => {
text = format!("\\textbf{{{}}}", &self.0);
}
TextType::Italic => {
text = format!("\\textit{{{}}}", &self.0);
}
TextType::Roman => {
text = format!("\\textrm{{{}}}", &self.0);
}
TextType::Underline => {
text = format!("\\underline{{{}}}", &self.0);
}
TextType::Verbatim => {
text = format!("\\verb!{}!", &self.0);
}
}
format!("{} {}", par, &text)
}
}
impl Convert for Input {
fn to_latex_string(&self) -> String {
format!("\\input{{{}}}", &self.0)
}
}
impl Convert for Environment {
fn to_latex_string(&self) -> String {
let begin = format!("\\begin{{{}}}", &self.0);
let end = format!("\\end{{{}}}", &self.0);
let mut s = Vec::new();
s.push(begin);
for i in &self.1 {
s.push(i.to_owned());
}
s.push(end);
s.join("\n")
}
}
impl Convert for UserDefined {
fn to_latex_string(&self) -> String {
self.0.clone()
}
}
impl Convert for List {
fn to_latex_string(&self) -> String {
let mode: &str = match &self.0 {
ListMode::Enumerate => "enumerate",
ListMode::Itemize => "itemize",
};
let (begin, end) = (format!("\\begin{{{}}}", mode), format!("\\end{{{}}}", mode));
let mut s = Vec::new();
s.push(begin);
for i in &self.1 {
s.push(format!("\\item {}", &i));
}
s.push(end);
s.join("\n")
}
}
impl Convert for Element {
fn to_latex_string(&self) -> String {
match self {
Element::Part(e) => e.to_latex_string(),
Element::Chapter(e) => e.to_latex_string(),
Element::Section(e) => e.to_latex_string(),
Element::Paragraph(e) => e.to_latex_string(),
Element::Text(e) => e.to_latex_string(),
Element::Input(e) => e.to_latex_string(),
Element::Environment(e) => e.to_latex_string(),
Element::UserDefined(e) => e.to_latex_string(),
Element::List(e) => e.to_latex_string(),
}
}
}
impl From<Part> for Element {
fn from(p: Part) -> Self {
Element::Part(p)
}
}
impl From<Chapter> for Element {
fn from(c: Chapter) -> Self {
Element::Chapter(c)
}
}
impl From<Section> for Element {
fn from(s: Section) -> Self {
Element::Section(s)
}
}
impl From<Paragraph> for Element {
fn from(p: Paragraph) -> Self {
Element::Paragraph(p)
}
}
impl From<Text> for Element {
fn from(t: Text) -> Self {
Element::Text(t)
}
}
impl From<Input> for Element {
fn from(i: Input) -> Self {
Element::Input(i)
}
}
impl From<Environment> for Element {
fn from(e: Environment) -> Self {
Element::Environment(e)
}
}
impl From<UserDefined> for Element {
fn from(u: UserDefined) -> Self {
Element::UserDefined(u)
}
}
impl From<List> for Element {
fn from(l: List) -> Self {
Element::List(l)
}
}
impl From<Element> for String {
fn from(e: Element) -> Self {
e.to_latex_string()
}
}