use crate::compound::Compound;
use crate::line_parser::LineParser;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CompositeStyle {
Paragraph,
Header(u8), ListItem,
Code,
}
static SPACES: &'static str = " ";
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Composite<'a> {
pub style: CompositeStyle,
pub compounds: Vec<Compound<'a>>,
}
impl<'a> From<Vec<Compound<'a>>> for Composite<'a> {
fn from(compounds: Vec<Compound<'a>>) -> Composite<'a> {
Composite {
style: CompositeStyle::Paragraph,
compounds,
}
}
}
impl<'a> Composite<'a> {
pub fn new() -> Composite<'a> {
Composite {
style: CompositeStyle::Paragraph,
compounds: Vec::new(),
}
}
pub fn from_inline(md: &'a str) -> Composite<'a> {
LineParser::from(md).inline()
}
#[inline(always)]
pub fn is_code(&self) -> bool {
match self.style {
CompositeStyle::Code { .. } => true,
_ => false,
}
}
#[inline(always)]
pub fn is_list_item(&self) -> bool {
match self.style {
CompositeStyle::ListItem { .. } => true,
_ => false,
}
}
#[inline(always)]
pub fn char_length(&self) -> usize {
self.compounds
.iter()
.fold(0, |sum, compound| sum + compound.as_str().chars().count())
}
pub fn trim_left_spaces(&mut self) {
loop {
if self.compounds.len() == 0 {
break;
}
if self.compounds[0].code {
break;
}
self.compounds[0].trim_left_spaces();
if self.compounds[0].is_empty() {
self.compounds.remove(0);
} else {
break;
}
}
}
pub fn trim_right_spaces(&mut self) {
loop {
if self.compounds.len() == 0 {
break;
}
let last = self.compounds.len() - 1;
if self.compounds[last].code {
break;
}
self.compounds[last].trim_right_spaces();
if self.compounds[last].is_empty() {
self.compounds.remove(last);
} else {
break;
}
}
}
pub fn trim_spaces(&mut self) {
self.trim_left_spaces();
self.trim_right_spaces();
}
pub fn is_empty(&self) -> bool {
self.compounds.len() == 0
}
pub fn pad_left(&mut self, nb_added_spaces: usize) {
if nb_added_spaces > 0 {
let nb_added_spaces = nb_added_spaces.min(SPACES.len());
self.compounds.insert(0, Compound::raw_part(&SPACES, 0, nb_added_spaces));
}
}
pub fn pad_right(&mut self, nb_added_spaces: usize) {
if nb_added_spaces > 0 {
let nb_added_spaces = nb_added_spaces.min(SPACES.len());
self.compounds.push(Compound::raw_part(&SPACES, 0, nb_added_spaces));
}
}
}
#[cfg(test)]
mod tests {
use crate::composite::*;
use crate::compound::*;
#[test]
fn composite_trim() {
let mut left = Composite::from_inline(" *some* text ");
left.trim_spaces();
assert_eq!(
left,
Composite {
style: CompositeStyle::Paragraph,
compounds: vec![
Compound::raw_str("some").italic(),
Compound::raw_str(" text"),
]
}
);
}
#[test]
fn composite_trim_keep_code() {
let mut left = Composite::from_inline(" ` ` ");
left.trim_spaces();
assert_eq!(
left,
Composite {
style: CompositeStyle::Paragraph,
compounds: vec![
Compound::raw_str(" ").code(),
]
}
);
}
#[test]
fn empty_composite_trim() {
let mut left = Composite::from_inline(" * * ** `` ** ");
left.trim_left_spaces();
assert_eq!(left.compounds.len(), 0);
}
}