Implement a little more of the Gemtext parser

This commit is contained in:
Nathan Fisher 2023-06-02 09:55:10 -04:00
parent 200dd8b451
commit a9fcab7006

View file

@ -17,7 +17,7 @@ enum State<'a> {
#[derive(Clone, Debug, PartialEq)]
pub enum GemtextNode {
Sender(Vec<Mailbox>),
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<Mailbox> = 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!()
}
}