rust_texas/component/
textchunk.rs

1use std::{
2    fs::{read_to_string, File},
3    io::{self, Read},
4};
5
6// use markdown::mdast::Node;
7// #[cfg(feature = "markdown")]
8// use markdown::{to_mdast, ParseOptions};
9
10use crate::prelude::*;
11
12/// Italics and stuff. Also includes the mathy \\(..\\) and \\[...\\], as well as the Scope variant, \\{...\\}
13/// If y'all want more (like \textbb{}, \texttt{}, etc.) please put up an issue.
14/// A few fonts come from packages, which I'm not handling.
15/// You'll get a latex error if you don't also include the package.
16#[derive(Debug, Clone)]
17pub enum TextType {
18    Normal,
19    Bold,
20    Italic,
21    Teletype,
22    MathBold,
23    MathCal,
24    MathBb,
25    MathRm,
26    Underlined,
27    InlineMath,
28    DisplayMath,
29    Scope,
30    Verbatim,
31    Strikethrough,
32}
33
34/// Basic text struct. Typically, a `Paragraph` or `Line` contains a bunch of these.
35/// Can also read from a file, in which case `typ` will be Normal.
36#[derive(Debug, Clone)]
37pub struct TextChunk {
38    body: String,
39    typ: TextType,
40}
41impl AsLatex for TextChunk {
42    fn to_string(&self) -> String {
43        match &self.typ {
44            TextType::Normal => format!("{} ", self.body),
45            TextType::Italic => format!("\\textit{{{}}} ", self.body),
46            TextType::Bold => format!("\\textbf{{{}}} ", self.body),
47            TextType::Teletype => format!("\\texttt{{{}}} ", self.body),
48            TextType::MathBold => format!("\\mathbf{{{}}} ", self.body),
49            TextType::MathCal => format!("\\mathcal{{{}}} ", self.body),
50            TextType::MathBb => format!("\\mathbb{{{}}} ", self.body),
51            TextType::MathRm => format!("\\mathrm{{{}}} ", self.body),
52            TextType::Underlined => format!("\\underline{{{}}} ", self.body),
53            TextType::InlineMath => format!("\\({}\\)", self.body),
54            TextType::DisplayMath => format!("\\[{}\\]", self.body),
55            TextType::Scope => format!("\\{{{}\\}}", self.body),
56            TextType::Verbatim => format!("\\verb|{}|", self.body),
57            TextType::Strikethrough => format!("\\sout{{{}}} ", self.body),
58        }
59    }
60}
61impl Populate for TextChunk {
62    fn attach(&mut self, other: Component) -> TexResult<&mut Self> {
63        if let Component::TextChunk(ch) = other {
64            self.body.push_str(&ch.body);
65            Ok(self)
66        } else {
67            Err(TexError::RankMismatch(other.rank(), 10).into())
68        }
69    }
70    fn attach_vec(&mut self, other: Vec<Component>) -> TexResult<&mut Self> {
71        self.attach_iter(other.into_iter())
72    }
73
74    fn attach_iter<I: Iterator<Item = Component>>(&mut self, other: I) -> TexResult<&mut Self> {
75        for c in other {
76            if let Component::TextChunk(ch) = c {
77                self.body.push_str(&ch.body);
78            } else {
79                return Err(TexError::RankMismatch(c.rank(), 10).into());
80            }
81        }
82
83        Ok(self)
84    }
85}
86impl TextChunk {
87    pub fn new(body: &str, typ: TextType) -> Self {
88        Self {
89            body: body.to_string(),
90            typ,
91        }
92    }
93    pub fn raw(body: &str) -> Self {
94        Self {
95            body: body.to_string(),
96            typ: TextType::Normal,
97        }
98    }
99    pub fn from_file(path: &str) -> Result<Self, io::Error> {
100        let mut f = File::open(path)?;
101        let mut buf = "".to_string();
102        f.read_to_string(&mut buf)?;
103        Ok(Self {
104            body: buf,
105            typ: TextType::Normal,
106        })
107    }
108    pub fn from_file_formatted(path: &str, typ: TextType, esc: &[char]) -> Result<Self, io::Error> {
109        let mut f = File::open(path)?;
110        let mut buf = "".to_string();
111        f.read_to_string(&mut buf)?;
112        Ok(Self {
113            body: escape(&buf, Some(esc)),
114            typ,
115        })
116    }
117    pub fn set_type(&mut self, typ: TextType) {
118        self.typ = typ;
119    }
120}