use std::fmt::{self, Display, Formatter};
use std::ops::Deref;
use std::slice::Iter;
use equations::Align;
use lists::List;
use paragraph::Paragraph;
use section::Section;
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Document {
pub class: DocumentClass,
pub preamble: Preamble,
elements: Vec<Element>,
}
impl Document {
pub fn new(document_class: DocumentClass) -> Self {
Document {
class: document_class,
..Default::default()
}
}
pub fn push<E>(&mut self, element: E) -> &mut Self
where
E: Into<Element>,
{
self.elements.push(element.into());
self
}
pub fn iter(&self) -> Iter<Element> {
self.elements.iter()
}
pub fn push_doc(&mut self, doc: &Document) -> &mut Self {
for element in doc.iter() {
self.push(element.clone());
}
self
}
}
impl Deref for Document {
type Target = Vec<Element>;
fn deref(&self) -> &Self::Target {
&self.elements
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Element {
Para(Paragraph),
Section(Section),
TableOfContents,
TitlePage,
ClearPage,
Align(Align),
Environment(String, Vec<String>),
UserDefined(String),
List(List),
Input(String),
#[doc(hidden)]
_Other,
}
impl From<Paragraph> for Element {
fn from(other: Paragraph) -> Self {
Element::Para(other)
}
}
impl<'a> From<&'a str> for Element {
fn from(other: &'a str) -> Self {
Element::Para(Paragraph::from(other))
}
}
impl From<List> for Element {
fn from(other: List) -> Self {
Element::List(other)
}
}
impl From<Align> for Element {
fn from(other: Align) -> Self {
Element::Align(other)
}
}
impl From<Section> for Element {
fn from(other: Section) -> Self {
Element::Section(other)
}
}
impl<S, I> From<(S, I)> for Element
where
S: AsRef<str>,
I: IntoIterator,
I::Item: AsRef<str>,
{
fn from(other: (S, I)) -> Self {
let (name, lines) = other;
Element::Environment(
name.as_ref().to_string(),
lines.into_iter().map(|s| s.as_ref().to_string()).collect(),
)
}
}
#[derive(Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum DocumentClass {
Article,
Book,
Report,
Part,
Other(String),
}
impl Default for DocumentClass {
fn default() -> Self {
DocumentClass::Article
}
}
impl Display for DocumentClass {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
DocumentClass::Article => write!(f, "article"),
DocumentClass::Book => write!(f, "book"),
DocumentClass::Report => write!(f, "report"),
DocumentClass::Part => write!(f, ""),
DocumentClass::Other(ref s) => write!(f, "{}", *s),
}
}
}
impl Extend<Element> for Document {
fn extend<T: IntoIterator<Item=Element>>(&mut self, iter:T) {
for elem in iter {
self.push(elem);
}
}
}
#[derive(Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum PreambleElement {
UsePackage {
package: String,
argument: Option<String>,
},
UserDefined(String),
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Preamble {
pub author: Option<String>,
pub title: Option<String>,
contents: Vec<PreambleElement>,
}
impl Preamble {
pub fn author(&mut self, name: &str) -> &mut Self {
self.author = Some(name.to_string());
self
}
pub fn title(&mut self, name: &str) -> &mut Self {
self.title = Some(name.to_string());
self
}
pub fn use_package(&mut self, name: &str) -> &mut Self {
self.contents.push(PreambleElement::UsePackage {
package: name.to_string(),
argument: None,
});
self
}
pub fn iter(&self) -> Iter<PreambleElement> {
self.contents.iter()
}
pub fn is_empty(&self) -> bool {
self.contents.is_empty()
}
pub fn push<E>(&mut self, element: E) -> &mut Self
where
E: Into<PreambleElement>,
{
self.contents.push(element.into());
self
}
}
impl Extend<PreambleElement> for Preamble {
fn extend<T: IntoIterator<Item=PreambleElement>>(&mut self, iter:T) {
for elem in iter {
self.push(elem);
}
}
}