Implement a little more of the Gemtext parser
This commit is contained in:
parent
200dd8b451
commit
a9fcab7006
1 changed files with 53 additions and 32 deletions
|
@ -17,7 +17,7 @@ enum State<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum GemtextNode {
|
pub enum GemtextNode {
|
||||||
Sender(Vec<Mailbox>),
|
Sender(Mailbox),
|
||||||
Recipients(Recipients),
|
Recipients(Recipients),
|
||||||
Timestamp(String),
|
Timestamp(String),
|
||||||
Text(String),
|
Text(String),
|
||||||
|
@ -33,12 +33,8 @@ pub enum GemtextNode {
|
||||||
impl fmt::Display for GemtextNode {
|
impl fmt::Display for GemtextNode {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
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::Recipients(r) => writeln!(f, "{r}"),
|
||||||
|
Self::Sender(m) => writeln!(f, "{m}"),
|
||||||
Self::Timestamp(t) => writeln!(f, "@ {t}"),
|
Self::Timestamp(t) => writeln!(f, "@ {t}"),
|
||||||
Self::Text(t) => writeln!(f, "{t}"),
|
Self::Text(t) => writeln!(f, "{t}"),
|
||||||
Self::Heading1(h) => writeln!(f, "# {h}"),
|
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 {
|
fn parse_senders(text: &'a str) -> Self {
|
||||||
let mut split = text.split_whitespace();
|
let Some(line) = text.strip_prefix('<') else {
|
||||||
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());
|
return Self::Text(text.to_string());
|
||||||
}
|
};
|
||||||
}
|
if let Ok(user) = line.parse() {
|
||||||
Self::Sender(senders)
|
Self::Sender(user)
|
||||||
}
|
} else {
|
||||||
_ => Self::Text(text.to_string())
|
Self::Text(text.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_recipients(text: &'a str) -> Self {
|
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 {
|
fn parse_timestamp(text: &'a str) -> Self {
|
||||||
|
@ -152,24 +146,51 @@ impl<'a> Parser<'a> {
|
||||||
self.lines.push(GemtextNode::parse_list_item(line));
|
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) {
|
fn parse_normal(&mut self, line: &'a str) {
|
||||||
match line {
|
match line {
|
||||||
s if s.starts_with("=>") => self.link(s),
|
s if s.starts_with("=>") => self.link(s),
|
||||||
s if s.starts_with('#') => self.heading(s),
|
s if s.starts_with('#') => self.heading(s),
|
||||||
s if s.starts_with('*') => self.list_item(s),
|
s if s.starts_with('*') => self.list_item(s),
|
||||||
s if s.starts_with('>') => {},
|
s if s.starts_with('>') => self.quote(s),
|
||||||
s if s.starts_with("```") => {},
|
s if s.starts_with("```") => self.enter_preformatted(s),
|
||||||
s if s.starts_with('<') => {},
|
s if s.starts_with('<') => self.senders(s),
|
||||||
s if s.starts_with(':') => {},
|
s if s.starts_with(':') => self.recipients(s),
|
||||||
s if s.starts_with('@') => {},
|
s if s.starts_with('@') => {},
|
||||||
s => {},
|
s => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_preformatted(&mut self, line: &'a str) {
|
fn parse_preformatted(&mut self, line: &'a str) {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_quote(&mut self, line: &'a str) {
|
fn parse_quote(&mut self, line: &'a str) {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue