summaryrefslogtreecommitdiff
path: root/src/elements/line.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/elements/line.rs')
-rw-r--r--src/elements/line.rs117
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(())
- }
-}