Progress on the Gemtext parser

This commit is contained in:
Nathan Fisher 2023-06-02 00:26:19 -04:00
parent 60a8e74af3
commit 200dd8b451
3 changed files with 64 additions and 17 deletions

View file

@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
mod error;
mod link;
mod parser;
pub use {error::Error, link::Link, parser::Parser};
pub use {error::Error, link::Link, parser::{GemtextNode, Parser}};
#[derive(Clone, Debug, PartialEq)]
pub struct Recipients {

View file

@ -17,13 +17,14 @@ enum State<'a> {
#[derive(Clone, Debug, PartialEq)]
pub enum GemtextNode {
Sender(Mailbox),
Sender(Vec<Mailbox>),
Recipients(Recipients),
Timestamp(String),
Text(String),
Heading1(String),
Heading2(String),
Heading3(String),
ListItem(String),
Quote(String),
Preformatted(String),
Link(Link),
@ -32,13 +33,18 @@ pub enum GemtextNode {
impl fmt::Display for GemtextNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Sender(m) => writeln!(f, "< {m}"),
Self::Sender(m) => {
write!(f, "<")?;
m.iter().try_for_each(|m| write!(f, " {m}"))?;
writeln!(f)
},
Self::Recipients(r) => writeln!(f, "{r}"),
Self::Timestamp(t) => writeln!(f, "@ {t}"),
Self::Text(t) => writeln!(f, "{t}"),
Self::Heading1(h) => writeln!(f, "# {h}"),
Self::Heading2(h) => writeln!(f, "## {h}"),
Self::Heading3(h) => writeln!(f, "### {h}"),
Self::ListItem(l) => writeln!(f, "* {l}"),
Self::Quote(q) => writeln!(f, "> {q}"),
Self::Preformatted(p) => writeln!(f, "```\n{p}\n```"),
Self::Link(l) => writeln!(f, "=> {l}"),
@ -48,27 +54,56 @@ impl fmt::Display for GemtextNode {
impl<'a> GemtextNode {
fn parse_link(text: &'a str) -> Self {
todo!()
}
fn parse_prompt(text: &'a str) -> Self {
todo!()
if let Ok(link) = text.parse() {
Self::Link(link)
} else {
Self::Text(text.to_string())
}
}
fn parse_heading(text: &'a str) -> Self {
todo!()
if let Some((h, s)) = text.split_once(char::is_whitespace) {
match h {
"#" => Self::Heading1(s.to_string()),
"##" => Self::Heading2(s.to_string()),
"###" => Self::Heading3(s.to_string()),
_ => Self::Text(text.to_string()),
}
} else {
Self::Text(text.to_string())
}
}
fn parse_list_item(text: &'a str) -> Self {
todo!()
match text.split_once(char::is_whitespace) {
Some((pre, s)) if pre == "*" => GemtextNode::ListItem(s.to_string()),
_ => GemtextNode::Text(text.to_string()),
}
}
fn parse_blockquote(text: &'a str) -> Self {
todo!()
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 {
todo!()
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())
}
}
fn parse_recipients(text: &'a str) -> Self {
@ -94,7 +129,7 @@ impl<'a> Parser<'a> {
}
}
fn parse(mut self, raw: &'a str) -> Vec<GemtextNode> {
pub fn parse(mut self, raw: &'a str) -> Vec<GemtextNode> {
for line in raw.lines() {
match self.state {
State::Normal => self.parse_normal(line),
@ -105,11 +140,23 @@ impl<'a> Parser<'a> {
self.lines
}
fn link(&mut self, line: &'a str) {
self.lines.push(GemtextNode::parse_link(line));
}
fn heading(&mut self, line: &'a str) {
self.lines.push(GemtextNode::parse_heading(line));
}
fn list_item(&mut self, line: &'a str) {
self.lines.push(GemtextNode::parse_list_item(line));
}
fn parse_normal(&mut self, line: &'a str) {
match line {
s if s.starts_with("=>") => {},
s if s.starts_with('#') => {},
s if s.starts_with('*') => {},
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('<') => {},

View file

@ -4,7 +4,7 @@ pub use super::{
host::{Error as ParseHostError, Host},
mailbox::{Error as ParseMailboxError, Mailbox},
mailuser::Mailuser,
message::{Error as ParseMessageError, Lines, Message, Recipients},
message::{Error as ParseMessageError, GemtextNode, Message, Recipients},
//receiver,
request::{Error as ParseRequestError, Request},
response::{Error as ParseResponseError, Response},