From 32897270a5c3b94b22aff4405649f866071a7d89 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 17 Mar 2023 16:37:47 -0400 Subject: [PATCH] Support leading whitespace for list items. --- src/main.rs | 8 ++++++-- src/parser/mod.rs | 2 ++ src/parser/paragraph.rs | 2 +- src/parser/plain_list.rs | 22 ++++++++++++++++------ src/parser/token.rs | 1 + 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index a50a86c..70abb81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ use crate::parser::document; +use crate::parser::item; +use crate::parser::ContextTree; use tracing::Level; use tracing_subscriber::fmt::format::FmtSpan; @@ -18,8 +20,10 @@ fn main() -> Result<(), Box> { .with_span_events(FmtSpan::ENTER | FmtSpan::EXIT) .finish(); tracing::subscriber::set_global_default(subscriber)?; - let parsed = document(TEST_DOC); - println!("{}\n\n\n", TEST_DOC); + // let parsed = document(TEST_DOC); + // println!("{}\n\n\n", TEST_DOC); + let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let parsed = item(&initial_context, " 1. foo\n"); println!("{:#?}", parsed); Ok(()) } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 2f5130b..545ef9f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -13,3 +13,5 @@ mod token; mod util; pub use document::document; type Context<'r, 's> = &'r parser_context::ContextTree<'r, 's>; +pub use parser_context::ContextTree; +pub use plain_list::item; diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index 6097ec8..549c2d4 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -56,7 +56,7 @@ fn context_paragraph_end<'r, 's>( paragraph_end(input) } -fn paragraph_end(input: &str) -> Res<&str, &str> { +pub fn paragraph_end(input: &str) -> Res<&str, &str> { alt(( recognize(tuple(( map(line_break, TextElement::LineBreak), diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 4bb435c..59370a8 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -4,15 +4,18 @@ use nom::character::complete::anychar; use nom::character::complete::digit1; use nom::character::complete::line_ending; use nom::character::complete::one_of; +use nom::character::complete::space0; use nom::combinator::consumed; use nom::combinator::not; use nom::combinator::opt; use nom::combinator::recognize; +use nom::multi::many0_count; use nom::multi::many1; use nom::sequence::tuple; use super::combinator::context_many_till; use super::error::Res; +use super::paragraph::paragraph_end; use super::text::space; use super::text::text_element; use super::token::ListItem; @@ -25,8 +28,10 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, todo!() } -fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<'s>> { - let (remaining, (source, (bul, count, check, tg, sp, (contents, end)))) = consumed(tuple(( +pub fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<'s>> { + let (remaining, leading_whitespace) = space0(i)?; + let indent_level = leading_whitespace.len(); + let (remaining, (bul, countset, check, tg, sp, (contents, end))) = tuple(( bullet, opt(tuple((space, counter_set))), opt(tuple((space, check_box))), @@ -34,7 +39,7 @@ fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<' space, // TODO: This context should probably be something involving the item context_many_till(context, text_element, item_end), - )))(i)?; + ))(remaining)?; let elements = contents .into_iter() @@ -44,10 +49,16 @@ fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<' }) .collect(); + let source = { + let offset = remaining.as_ptr() as usize - i.as_ptr() as usize; + &i[..offset] + }; + let ret = ListItem { source, + leading_whitespace, bullet: bul, - counter_set: count.map(|(_spc, count)| count), + counter_set: countset.map(|(_spc, count)| count), check_box: check.map(|(_spc, check)| check), item_tag: tg.map(|(_spc, tg)| tg), contents: elements, @@ -94,6 +105,5 @@ fn tag_separator<'s>(i: &'s str) -> Res<&'s str, &'s str> { } pub fn item_end<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, &'s str> { - // todo - todo!() + paragraph_end(i) } diff --git a/src/parser/token.rs b/src/parser/token.rs index 3935377..a7eb0b4 100644 --- a/src/parser/token.rs +++ b/src/parser/token.rs @@ -110,6 +110,7 @@ impl<'a> Source<'a> for PlainList<'a> { #[derive(Debug)] pub struct ListItem<'a> { pub source: &'a str, + pub leading_whitespace: &'a str, pub bullet: &'a str, pub counter_set: Option<&'a str>, pub check_box: Option<&'a str>,