Support leading whitespace for list items.

This commit is contained in:
Tom Alexander 2023-03-17 16:37:47 -04:00
parent 37070689c6
commit 32897270a5
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 26 additions and 9 deletions

View File

@ -1,4 +1,6 @@
use crate::parser::document; use crate::parser::document;
use crate::parser::item;
use crate::parser::ContextTree;
use tracing::Level; use tracing::Level;
use tracing_subscriber::fmt::format::FmtSpan; use tracing_subscriber::fmt::format::FmtSpan;
@ -18,8 +20,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.with_span_events(FmtSpan::ENTER | FmtSpan::EXIT) .with_span_events(FmtSpan::ENTER | FmtSpan::EXIT)
.finish(); .finish();
tracing::subscriber::set_global_default(subscriber)?; tracing::subscriber::set_global_default(subscriber)?;
let parsed = document(TEST_DOC); // let parsed = document(TEST_DOC);
println!("{}\n\n\n", TEST_DOC); // println!("{}\n\n\n", TEST_DOC);
let initial_context: ContextTree<'_, '_> = ContextTree::new();
let parsed = item(&initial_context, " 1. foo\n");
println!("{:#?}", parsed); println!("{:#?}", parsed);
Ok(()) Ok(())
} }

View File

@ -13,3 +13,5 @@ mod token;
mod util; mod util;
pub use document::document; pub use document::document;
type Context<'r, 's> = &'r parser_context::ContextTree<'r, 's>; type Context<'r, 's> = &'r parser_context::ContextTree<'r, 's>;
pub use parser_context::ContextTree;
pub use plain_list::item;

View File

@ -56,7 +56,7 @@ fn context_paragraph_end<'r, 's>(
paragraph_end(input) paragraph_end(input)
} }
fn paragraph_end(input: &str) -> Res<&str, &str> { pub fn paragraph_end(input: &str) -> Res<&str, &str> {
alt(( alt((
recognize(tuple(( recognize(tuple((
map(line_break, TextElement::LineBreak), map(line_break, TextElement::LineBreak),

View File

@ -4,15 +4,18 @@ use nom::character::complete::anychar;
use nom::character::complete::digit1; use nom::character::complete::digit1;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::consumed; use nom::combinator::consumed;
use nom::combinator::not; use nom::combinator::not;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::multi::many0_count;
use nom::multi::many1; use nom::multi::many1;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::combinator::context_many_till; use super::combinator::context_many_till;
use super::error::Res; use super::error::Res;
use super::paragraph::paragraph_end;
use super::text::space; use super::text::space;
use super::text::text_element; use super::text::text_element;
use super::token::ListItem; 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!() todo!()
} }
fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<'s>> { pub 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(( let (remaining, leading_whitespace) = space0(i)?;
let indent_level = leading_whitespace.len();
let (remaining, (bul, countset, check, tg, sp, (contents, end))) = tuple((
bullet, bullet,
opt(tuple((space, counter_set))), opt(tuple((space, counter_set))),
opt(tuple((space, check_box))), 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, space,
// TODO: This context should probably be something involving the item // TODO: This context should probably be something involving the item
context_many_till(context, text_element, item_end), context_many_till(context, text_element, item_end),
)))(i)?; ))(remaining)?;
let elements = contents let elements = contents
.into_iter() .into_iter()
@ -44,10 +49,16 @@ fn item<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, ListItem<'
}) })
.collect(); .collect();
let source = {
let offset = remaining.as_ptr() as usize - i.as_ptr() as usize;
&i[..offset]
};
let ret = ListItem { let ret = ListItem {
source, source,
leading_whitespace,
bullet: bul, bullet: bul,
counter_set: count.map(|(_spc, count)| count), counter_set: countset.map(|(_spc, count)| count),
check_box: check.map(|(_spc, check)| check), check_box: check.map(|(_spc, check)| check),
item_tag: tg.map(|(_spc, tg)| tg), item_tag: tg.map(|(_spc, tg)| tg),
contents: elements, 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> { pub fn item_end<'r, 's>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, &'s str> {
// todo paragraph_end(i)
todo!()
} }

View File

@ -110,6 +110,7 @@ impl<'a> Source<'a> for PlainList<'a> {
#[derive(Debug)] #[derive(Debug)]
pub struct ListItem<'a> { pub struct ListItem<'a> {
pub source: &'a str, pub source: &'a str,
pub leading_whitespace: &'a str,
pub bullet: &'a str, pub bullet: &'a str,
pub counter_set: Option<&'a str>, pub counter_set: Option<&'a str>,
pub check_box: Option<&'a str>, pub check_box: Option<&'a str>,