diff --git a/src/message/parser.rs b/src/message/parser.rs index 2d2234a..e573c0a 100644 --- a/src/message/parser.rs +++ b/src/message/parser.rs @@ -17,7 +17,7 @@ enum State<'a> { #[derive(Clone, Debug, PartialEq)] pub enum GemtextNode { - Sender(Vec), + Sender(Mailbox), Recipients(Recipients), Timestamp(String), Text(String), @@ -33,12 +33,8 @@ pub enum GemtextNode { impl fmt::Display for GemtextNode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Sender(m) => { - write!(f, "<")?; - m.iter().try_for_each(|m| write!(f, " {m}"))?; - writeln!(f) - }, Self::Recipients(r) => writeln!(f, "{r}"), + Self::Sender(m) => writeln!(f, "{m}"), Self::Timestamp(t) => writeln!(f, "@ {t}"), Self::Text(t) => writeln!(f, "{t}"), Self::Heading1(h) => writeln!(f, "# {h}"), @@ -81,33 +77,31 @@ impl<'a> GemtextNode { } } - fn parse_blockquote(text: &'a str) -> Self { - match text.split_once(char::is_whitespace) { - Some((prefix, suffix)) if prefix == ">" => GemtextNode::Quote(suffix.to_string()), - _ => GemtextNode::Text(text.to_string()), - } - } - fn parse_senders(text: &'a str) -> Self { - let mut split = text.split_whitespace(); - match split.next() { - Some(s) if s == "<" => { - let mut senders: Vec = vec![]; - for s in split { - if let Ok(m) = s.parse() { - senders.push(m); - } else { - return Self::Text(text.to_string()); - } - } - Self::Sender(senders) - } - _ => Self::Text(text.to_string()) + let Some(line) = text.strip_prefix('<') else { + return Self::Text(text.to_string()); + }; + if let Ok(user) = line.parse() { + Self::Sender(user) + } else { + Self::Text(text.to_string()) } } fn parse_recipients(text: &'a str) -> Self { - todo!() + let Some(line) = text.strip_prefix(':') else { + return Self::Text(text.to_string()); + }; + let split = line.split_whitespace(); + let mut recipients: Recipients = Recipients { boxes: vec![] }; + for s in split { + if let Ok(m) = s.parse() { + recipients.boxes.push(m); + } else { + return Self::Text(text.to_string()); + } + } + Self::Recipients(recipients) } fn parse_timestamp(text: &'a str) -> Self { @@ -152,24 +146,51 @@ impl<'a> Parser<'a> { self.lines.push(GemtextNode::parse_list_item(line)); } + fn quote(&mut self, line: &'a str) { + match line.split_once(char::is_whitespace) { + Some((prefix, suffix)) if prefix == ">" => self.state = State::Quote(vec![suffix]), + _ => self.lines.push(GemtextNode::Text(line.to_string())), + } + } + + fn enter_preformatted(&mut self, line: &'a str) { + let alt = if line.len() > 3 { + Some(line[3..].trim()) + } else { + None + }; + let preblk = PreBlk { alt, lines: vec![] }; + self.state = State::Preformatted(preblk); + } + + fn senders(&mut self, line: &'a str) { + self.lines.push(GemtextNode::parse_senders(line)); + } + + fn recipients(&mut self, line: &'a str) { + self.lines.push(GemtextNode::parse_recipients(line)); + } + fn parse_normal(&mut self, line: &'a str) { match line { s if s.starts_with("=>") => self.link(s), s if s.starts_with('#') => self.heading(s), s if s.starts_with('*') => self.list_item(s), - s if s.starts_with('>') => {}, - s if s.starts_with("```") => {}, - s if s.starts_with('<') => {}, - s if s.starts_with(':') => {}, + s if s.starts_with('>') => self.quote(s), + s if s.starts_with("```") => self.enter_preformatted(s), + s if s.starts_with('<') => self.senders(s), + s if s.starts_with(':') => self.recipients(s), s if s.starts_with('@') => {}, s => {}, } } fn parse_preformatted(&mut self, line: &'a str) { + todo!() } fn parse_quote(&mut self, line: &'a str) { + todo!() } }