Compare commits

..

5 Commits

Author SHA1 Message Date
Tom Alexander
7a4dc20dc9
Implement the new fields for plain list.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has failed
rust-build Build rust-build has succeeded
rust-test Build rust-test has failed
2023-12-15 15:59:00 -05:00
Tom Alexander
022dda06eb
Implement the new fields for plain list item. 2023-12-15 15:52:53 -05:00
Tom Alexander
7b88a2d248
Implement the new fields for broken end bullshitium. 2023-12-15 15:40:17 -05:00
Tom Alexander
fce5b92091
Remove leading blank lines from document contents. 2023-12-15 15:30:46 -05:00
Tom Alexander
45a506334c
Remove leading blank lines from heading contents. 2023-12-15 15:20:31 -05:00
6 changed files with 55 additions and 36 deletions

View File

@ -73,14 +73,18 @@ pub(crate) fn broken_end<'b, 'g, 'r, 's>(
}; };
Ok((remaining, paragraph)) Ok((remaining, paragraph))
} else { } else {
let (remaining, _trailing_ws) = let (remaining, post_blank) =
maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?; maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?;
let body = Into::<&str>::into(input.get_until(lead_in_remaining));
Ok(( Ok((
remaining, remaining,
Paragraph::of_text( Paragraph::of_text_full(
input.get_until(remaining).into(), input.get_until(remaining).into(),
input.get_until(lead_in_remaining).into(), body,
if body.len() > 0 { Some(body) } else { None },
post_blank.map(Into::<&str>::into),
), ),
)) ))
} }

View File

@ -181,8 +181,10 @@ fn _document<'b, 'g, 'r, 's>(
let zeroth_section_matcher = parser_with_context!(zeroth_section)(context); let zeroth_section_matcher = parser_with_context!(zeroth_section)(context);
let heading_matcher = parser_with_context!(heading(0))(context); let heading_matcher = parser_with_context!(heading(0))(context);
let (remaining, _blank_lines) = many0(blank_line)(input)?; let (remaining, _blank_lines) = many0(blank_line)(input)?;
let contents_begin = remaining;
let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?; let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?;
let (remaining, children) = many0(heading_matcher)(remaining)?; let (remaining, children) = many0(heading_matcher)(remaining)?;
let contents = get_consumed(contents_begin, remaining);
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@ -192,6 +194,11 @@ fn _document<'b, 'g, 'r, 's>(
path: None, path: None,
zeroth_section, zeroth_section,
children, children,
contents: if contents.len() > 0 {
Some(Into::<&str>::into(contents))
} else {
None
},
}, },
)) ))
} }

View File

@ -66,7 +66,7 @@ fn _heading<'b, 'g, 'r, 's>(
let (remaining, pre_headline) = headline(context, input, parent_star_count)?; let (remaining, pre_headline) = headline(context, input, parent_star_count)?;
let section_matcher = bind_context!(section, context); let section_matcher = bind_context!(section, context);
let heading_matcher = bind_context!(heading(pre_headline.star_count), context); let heading_matcher = bind_context!(heading(pre_headline.star_count), context);
let contents_begin = remaining; let (contents_begin, _) = opt(many0(blank_line))(remaining)?;
let (remaining, maybe_section) = let (remaining, maybe_section) =
opt(map(section_matcher, DocumentElement::Section))(remaining)?; opt(map(section_matcher, DocumentElement::Section))(remaining)?;
let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?; let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?;

View File

@ -7,6 +7,7 @@ use nom::character::complete::multispace1;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0; use nom::character::complete::space0;
use nom::character::complete::space1; use nom::character::complete::space1;
use nom::combinator::consumed;
use nom::combinator::eof; use nom::combinator::eof;
use nom::combinator::map; use nom::combinator::map;
use nom::combinator::not; use nom::combinator::not;
@ -152,6 +153,7 @@ where
let mut children = Vec::new(); let mut children = Vec::new();
let mut first_item_indentation: Option<IndentationLevel> = None; let mut first_item_indentation: Option<IndentationLevel> = None;
let mut first_item_list_type: Option<PlainListType> = None; let mut first_item_list_type: Option<PlainListType> = None;
let contents_begin = remaining;
let mut remaining = remaining; let mut remaining = remaining;
// The final list item does not consume trailing blank lines (which instead get consumed by the list). We have three options here: // The final list item does not consume trailing blank lines (which instead get consumed by the list). We have three options here:
@ -195,7 +197,8 @@ where
))); )));
} }
let (remaining, _trailing_ws) = let contents = get_consumed(contents_begin, remaining);
let (remaining, post_blank) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@ -208,6 +211,8 @@ where
), ),
list_type: first_item_list_type.expect("Plain lists require at least one element."), list_type: first_item_list_type.expect("Plain lists require at least one element."),
children: children.into_iter().map(|(_start, item)| item).collect(), children: children.into_iter().map(|(_start, item)| item).collect(),
contents: Some(Into::<&str>::into(contents)),
post_blank: post_blank.map(Into::<&str>::into),
}, },
)) ))
} }
@ -265,7 +270,7 @@ fn plain_list_item<'b, 'g, 'r, 's>(
let maybe_contentless_item: Res<OrgSource<'_>, ()> = let maybe_contentless_item: Res<OrgSource<'_>, ()> =
detect_contentless_item_contents(&parser_context, remaining); detect_contentless_item_contents(&parser_context, remaining);
if let Ok((_rem, _ws)) = maybe_contentless_item { if let Ok((_rem, _ws)) = maybe_contentless_item {
let (remaining, _trailing_ws) = if tuple(( let (remaining, post_blank) = if tuple((
blank_line, blank_line,
bind_context!(final_item_whitespace_cutoff, context), bind_context!(final_item_whitespace_cutoff, context),
))(remaining) ))(remaining)
@ -291,6 +296,12 @@ fn plain_list_item<'b, 'g, 'r, 's>(
.unwrap_or(Vec::new()), .unwrap_or(Vec::new()),
pre_blank: 0, pre_blank: 0,
children: Vec::new(), children: Vec::new(),
contents: None,
post_blank: if post_blank.len() > 0 {
Some(Into::<&str>::into(post_blank))
} else {
None
},
}, },
), ),
)); ));
@ -301,13 +312,13 @@ fn plain_list_item<'b, 'g, 'r, 's>(
.filter(|b| *b == b'\n') .filter(|b| *b == b'\n')
.count(); .count();
let (remaining, (children, _exit_contents)) = many_till( let (remaining, (contents, (children, _exit_contents))) = consumed(many_till(
include_input(bind_context!(element(true), &parser_context)), include_input(bind_context!(element(true), &parser_context)),
bind_context!(exit_matcher_parser, &parser_context), bind_context!(exit_matcher_parser, &parser_context),
)(remaining)?; ))(remaining)?;
// We have to use the parser_context here to include the whitespace cut-off // We have to use the parser_context here to include the whitespace cut-off
let (remaining, _trailing_ws) = let (remaining, post_blank) =
maybe_consume_trailing_whitespace_if_not_exiting(&final_whitespace_context, remaining)?; maybe_consume_trailing_whitespace_if_not_exiting(&final_whitespace_context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
@ -329,6 +340,12 @@ fn plain_list_item<'b, 'g, 'r, 's>(
pre_blank: PlainListItemPreBlank::try_from(pre_blank) pre_blank: PlainListItemPreBlank::try_from(pre_blank)
.expect("pre-blank cannot be larger than 2."), .expect("pre-blank cannot be larger than 2."),
children: children.into_iter().map(|(_start, item)| item).collect(), children: children.into_iter().map(|(_start, item)| item).collect(),
contents: if contents.len() > 0 {
Some(contents.into())
} else {
None
},
post_blank: post_blank.map(Into::<&str>::into),
}, },
), ),
)); ));

View File

@ -1,6 +1,5 @@
use std::path::PathBuf; use std::path::PathBuf;
use super::remove_trailing::RemoveTrailing;
use super::Element; use super::Element;
use super::NodeProperty; use super::NodeProperty;
use super::Object; use super::Object;
@ -18,6 +17,7 @@ pub struct Document<'s> {
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
pub zeroth_section: Option<Section<'s>>, pub zeroth_section: Option<Section<'s>>,
pub children: Vec<Heading<'s>>, pub children: Vec<Heading<'s>>,
pub contents: Option<&'s str>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -63,28 +63,7 @@ impl<'s> StandardProperties<'s> for Document<'s> {
} }
fn get_contents<'b>(&'b self) -> Option<&'s str> { fn get_contents<'b>(&'b self) -> Option<&'s str> {
let post_blank = self.get_post_blank(); self.contents
let mut content_lines = self
.source
.split_inclusive('\n')
.remove_trailing(post_blank);
let first_line = content_lines.next();
let last_line = content_lines.last().or(first_line);
match (first_line, last_line) {
(None, None) => None,
(None, Some(_)) | (Some(_), None) => unreachable!(),
(Some(first_line), Some(last_line)) => {
let first_line_offset = first_line.as_ptr() as usize;
let last_line_offset = last_line.as_ptr() as usize + last_line.len();
let source_offset = self.source.as_ptr() as usize;
debug_assert!(super::lesser_element::is_slice_of(self.source, first_line));
debug_assert!(super::lesser_element::is_slice_of(self.source, last_line));
Some(
&self.source[(first_line_offset - source_offset)
..(last_line_offset - first_line_offset)],
)
}
}
} }
fn get_post_blank(&self) -> PostBlank { fn get_post_blank(&self) -> PostBlank {

View File

@ -13,6 +13,8 @@ pub struct PlainList<'s> {
pub affiliated_keywords: AffiliatedKeywords<'s>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub list_type: PlainListType, pub list_type: PlainListType,
pub children: Vec<PlainListItem<'s>>, pub children: Vec<PlainListItem<'s>>,
pub contents: Option<&'s str>, // TODO: Can contents ever be None?
pub post_blank: Option<&'s str>,
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -35,6 +37,8 @@ pub struct PlainListItem<'s> {
pub tag: Vec<Object<'s>>, pub tag: Vec<Object<'s>>,
pub pre_blank: PlainListItemPreBlank, pub pre_blank: PlainListItemPreBlank,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
pub contents: Option<&'s str>,
pub post_blank: Option<&'s str>,
} }
pub type PlainListItemCounter = u16; pub type PlainListItemCounter = u16;
@ -140,11 +144,15 @@ impl<'s> StandardProperties<'s> for PlainList<'s> {
} }
fn get_contents<'b>(&'b self) -> Option<&'s str> { fn get_contents<'b>(&'b self) -> Option<&'s str> {
todo!() self.contents
} }
fn get_post_blank(&self) -> PostBlank { fn get_post_blank(&self) -> PostBlank {
todo!() self.post_blank
.map(|text| text.lines().count())
.unwrap_or(0)
.try_into()
.expect("Too much post-blank to fit into a PostBlank.")
} }
} }
@ -154,11 +162,15 @@ impl<'s> StandardProperties<'s> for PlainListItem<'s> {
} }
fn get_contents<'b>(&'b self) -> Option<&'s str> { fn get_contents<'b>(&'b self) -> Option<&'s str> {
todo!() self.contents
} }
fn get_post_blank(&self) -> PostBlank { fn get_post_blank(&self) -> PostBlank {
todo!() self.post_blank
.map(|text| text.lines().count())
.unwrap_or(0)
.try_into()
.expect("Too much post-blank to fit into a PostBlank.")
} }
} }