rust_texas/document/
mod.rs1use std::collections::HashMap;
2
3use crate::prelude::*;
4
5mod doc_class;
6mod metadata;
7mod package;
8
9pub use doc_class::*;
10pub use metadata::*;
11pub use package::*;
12
13#[derive(Debug, Clone)]
18pub struct Document {
19 packages: Vec<Package>,
21 pub metadata: Metadata,
22 components: Vec<Component>,
23 commands: HashMap<String, Command>,
24 img: bool,
26 href: bool,
27 scratch: bool,
28 graphics_path: Vec<String>,
29}
30impl AsLatex for Document {
31 fn to_string(&self) -> String {
32 let dc = self.metadata.class.to_string();
33 let pkgs = self
34 .packages
35 .iter()
36 .map(|x| x.to_string())
37 .collect::<String>();
38 let md = if !self.scratch {
39 self.metadata.to_string()
40 } else {
41 "\n".to_string()
42 };
43 let beamer_init_frames: String = if self.metadata.class.typ == DocumentClassType::Beamer {
44 let title_frame = Frame::with_components("", vec![textchunk!(r"\titlepage", "normal")]);
46
47 let mut toc = "".to_string();
48 if self.metadata.tableofcontents {
49 toc = Frame::with_components("", vec![textchunk!(r"\tableofcontents", "normal")])
50 .to_string();
51 };
52
53 format!("{}\n{}\n", title_frame.to_string(), toc)
54 } else {
55 "\n".to_string()
56 };
57 let body = beamer_init_frames
58 + &self
59 .components
60 .iter()
61 .map(|x| x.to_string())
62 .collect::<String>();
63
64 let cmd = self
65 .commands
66 .iter()
67 .map(|x| format!("{} \n", x.1.declare()))
68 .collect::<String>();
69
70 let gpath = if self.graphics_path.len() > 0 {
71 format!(
72 "\\graphicspath{{{}}} \n",
73 self.graphics_path
74 .iter()
75 .map(|x| format!("{{{}}}, ", x))
76 .collect::<String>()
77 )
78 } else {
79 "".to_string()
80 };
81 format!(
82 "{}\n{}\n{}\n{}\\begin{{document}}\n{}\n{}\n\\end{{document}}",
83 dc, pkgs, cmd, gpath, md, body
84 )
85 }
86}
87impl Document {
88 pub fn new(class: DocumentClass) -> Self {
89 let mut out = Self {
90 packages: vec![],
92 metadata: Metadata::new(class, "title", &["author"]),
93 components: vec![],
94 commands: HashMap::new(),
95 img: true,
97 href: true,
98 scratch: false,
99 graphics_path: vec![".".to_string()],
100 };
101 out.new_package(package!("graphicx"));
102 out.new_package(package!("hyperref"));
103 out
104 }
105
106 pub fn get_command(&self, cmd: &str) -> TexResult<Command> {
107 match self.commands.get(cmd) {
108 Some(s) => Ok(s.clone()),
109 None => Err(TexError::Undefined.into()),
110 }
111 }
112
113 pub fn scratch(&mut self) {
114 self.scratch = true;
115 }
116
117 pub fn new_command(&mut self, c: Command) {
118 self.commands.insert(c.name.clone(), c);
119 }
120
121 pub fn new_component(&mut self, new: Component) {
122 self.components.push(new);
123 }
124
125 pub fn set_md(&mut self, title: &str, author: &[&str]) {
126 self.metadata.title = title.to_string();
127 self.metadata.author = author.iter().map(|x| x.to_string()).collect();
128 }
129
130 pub fn new_package(&mut self, new: Package) {
131 self.packages.push(new);
132 }
133
134 pub fn enable_graphicx(&mut self, path: &str) {
135 self.img = true;
136 self.new_package(package!("graphicx"));
137 self.graphics_path = vec![path.to_string()];
138 }
139
140 pub fn disable_graphicx(&mut self) {
141 self.img = false;
142 self.packages.retain(|x| x.name != "graphicx");
143 self.graphics_path = vec![];
144 }
145
146 pub fn enable_hyperref(&mut self) {
147 self.href = true;
148 self.new_package(package!("hyperref"));
149 }
150
151 pub fn disable_hyperref(&mut self) {
152 self.href = false;
153 self.packages.retain(|x| x.name != "hyperref");
154 }
155
156 pub fn push_gpath(&mut self, path: &str) {
157 self.graphics_path.push(path.to_string());
158 }
159}
160impl Opt for Document {
161 fn add_option(&mut self, opt: &str) {
162 self.metadata.class.add_option(opt);
163 }
164}
165impl Populate for Document {
166 fn attach(&mut self, other: Component) -> TexResult<&mut Self> {
167 self.new_component(other);
168 Ok(self)
169 }
170
171 fn attach_iter<I: Iterator<Item = Component>>(&mut self, other: I) -> TexResult<&mut Self> {
172 for i in other {
173 self.attach(i)?;
174 }
175 Ok(self)
176 }
177
178 fn attach_vec(&mut self, other: Vec<Component>) -> TexResult<&mut Self> {
179 self.attach_iter(other.into_iter())
180 }
181}