diff options
Diffstat (limited to 'src/elements/line.rs')
-rw-r--r-- | src/elements/line.rs | 117 |
1 files changed, 0 insertions, 117 deletions
diff --git a/src/elements/line.rs b/src/elements/line.rs deleted file mode 100644 index d5c078e..0000000 --- a/src/elements/line.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::*; - -macro_rules! opt { - ($v:expr) => {|s| Some($v(s)) }; -} - -pub struct Line { - pub elements: Vec<LineElement>, -} - -impl Line { - pub fn from_str(raw_string: &str) -> Self { - fn unlabeled_extern_link(target: String) -> Option<LineElement> { - target.contains("/").then( || - LineElement::ExternalLink(ExternalLink { target, label:String::new() }) - ) - } - fn labelled_extern_link(s: String) -> Option<LineElement> { - let (label, target) = match s.split_once("](") { - Some((l, t)) => (l.to_string(), t.to_string()), - None => return None }; - if label.contains("]") || target.contains("]") { return None } - Some(LineElement::ExternalLink(ExternalLink { label, target })) } - const DELIMITERS: [(fn(String)->Option<LineElement>, &str, &str, &str); 7] = [ - ( opt!(LineElement::Bold), "**", "**", "*" ), - ( opt!(LineElement::Italic), "_", "_", "_" ), - ( opt!(LineElement::Monospace), "`", "`", "`" ), - ( opt!(LineElement::Math), "$", "$", "$" ), - ( opt!(LineElement::InternalLink), "[[", "]]", "[]" ), - ( labelled_extern_link, "[", ")", "[]()" ), - ( unlabeled_extern_link, "[", "]", "[]" ), - ]; - let chars: Vec<char> = raw_string.chars().collect(); - let mut elements = Vec::new(); - let mut cached_chars = String::new(); - let mut i = 0; - - let starts_with = |i, p:&str| std::iter::zip(&chars[i..], p.chars()).all(|(a, b)| *a == b); - - 'outer: while let Some(c) = chars.get(i) { - // Only check for opening delimiters that directly follow a whitespace character. - let follows_whitespace = match chars.get(i.wrapping_sub(1)) { - Some(w) => is_whitespace(w), - None => true, - }; - if follows_whitespace { - // Try to parse an opening delimiter. - for (variant, start_delim, end_delim, delim_chars) in DELIMITERS { - // Try to match an opening delimiter with a terminating delimiter. - if starts_with(i, start_delim) { - let s_end = i + start_delim.chars().count(); - let mut e_start = s_end; - let mut e_end = e_start + end_delim.chars().count(); - while e_end <= chars.len() { - e_start += 1; e_end += 1; - let end_is_whitespace = - if let Some(end_char) = chars.get(e_end) { - is_whitespace(end_char) - } else { - e_end == chars.len() - }; - // If the terminating delimiter is found, store the normal - // text and the styled text, and continue to the next character. - if end_is_whitespace && starts_with(e_start, end_delim) { - // Check that there is content within the styled string. - let styled_string: String = chars[s_end..e_start].iter().collect(); - let non_content_chars: Vec<_> = delim_chars.chars().collect(); - if !is_contentful(&styled_string, &non_content_chars) { continue } - if styled_string.len() != styled_string.trim().len() { continue } - let line_element = match variant(styled_string) { - Some(e) => e, - None => continue, - }; - // Commit the normal and styled strings. - if !cached_chars.is_empty() { - let normal_string = std::mem::take(&mut cached_chars); - elements.push(LineElement::Normal(normal_string)); } - elements.push(line_element); - i = e_end; - continue 'outer; - } - } - } - } - } - cached_chars.push(*c); i += 1; - } - if !cached_chars.is_empty() { - let normal_string = std::mem::take(&mut cached_chars); - elements.push(LineElement::Normal(normal_string)); } - Self { elements } - } - - /// Return only the character content, with none of the styling information. - pub fn as_plain_text(&self) -> String { - let mut string = String::new(); - for line_element in &self.elements { - string.push_str(line_element.as_plain_text()) } - return string; - } -} - -impl std::fmt::Display for Line { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - for line_element in &self.elements { - write!(f, "{line_element}")?; } - Ok(()) - } -} - -impl std::fmt::Debug for Line { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - for line_element in &self.elements { - write!(f, "{line_element:?}\n")?; } - Ok(()) - } -} |