Compare commits
No commits in common. "03faa7257f34a35ba9a718222b9e9807a7449a10" and "ad3f47864ae00c1673325d0e1059a6f10066dc78" have entirely different histories.
03faa7257f
...
ad3f47864a
@ -265,14 +265,13 @@ fn _lesser_block_end<'r, 's, 'x>(
|
|||||||
Ok((remaining, source))
|
Ok((remaining, source))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parser for the beginning of a lesser block
|
fn lesser_block_begin(
|
||||||
///
|
current_name: &str,
|
||||||
/// current_name MUST be lowercase. We do not do the conversion ourselves because it is not allowed in a const fn.
|
|
||||||
const fn lesser_block_begin(
|
|
||||||
current_name: &'static str,
|
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
// TODO: Since this is a const fn, is there ANY way to "generate" functions at compile time?
|
let current_name_lower = current_name.to_lowercase();
|
||||||
move |context: Context, input: OrgSource<'_>| _lesser_block_begin(context, input, current_name)
|
move |context: Context, input: OrgSource<'_>| {
|
||||||
|
_lesser_block_begin(context, input, current_name_lower.as_str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
@ -112,6 +112,9 @@ pub enum ContextElement<'r, 's> {
|
|||||||
ExitMatcherNode(ExitMatcherNode<'r>),
|
ExitMatcherNode(ExitMatcherNode<'r>),
|
||||||
Context(&'r str),
|
Context(&'r str),
|
||||||
|
|
||||||
|
/// Stores the indentation level of the current list item.
|
||||||
|
ListItem(usize),
|
||||||
|
|
||||||
/// Stores the name of the greater block.
|
/// Stores the name of the greater block.
|
||||||
GreaterBlock(&'s str),
|
GreaterBlock(&'s str),
|
||||||
|
|
||||||
|
@ -135,12 +135,12 @@ pub fn plain_list_item<'r, 's>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (remaining, _ws) = space1(remaining)?;
|
let (remaining, _ws) = space1(remaining)?;
|
||||||
let exit_matcher = plain_list_item_end(indent_level);
|
|
||||||
let parser_context = context
|
let parser_context = context
|
||||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
||||||
|
.with_additional_node(ContextElement::ListItem(indent_level))
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
exit_matcher: &exit_matcher,
|
exit_matcher: &plain_list_item_end,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let (remaining, (children, _exit_contents)) = verify(
|
let (remaining, (children, _exit_contents)) = verify(
|
||||||
@ -194,55 +194,47 @@ fn plain_list_end<'r, 's>(
|
|||||||
)))(input)
|
)))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn plain_list_item_end(
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
indent_level: usize,
|
fn plain_list_item_end<'r, 's>(
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
||||||
let line_indented_lte_matcher = line_indented_lte(indent_level);
|
|
||||||
move |context: Context, input: OrgSource<'_>| {
|
|
||||||
_plain_list_item_end(context, input, &line_indented_lte_matcher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(
|
|
||||||
feature = "tracing",
|
|
||||||
tracing::instrument(ret, level = "debug", skip(line_indented_lte_matcher))
|
|
||||||
)]
|
|
||||||
fn _plain_list_item_end<'r, 's>(
|
|
||||||
context: Context<'r, 's>,
|
context: Context<'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
line_indented_lte_matcher: impl for<'rr, 'ss> Fn(
|
|
||||||
Context<'rr, 'ss>,
|
|
||||||
OrgSource<'ss>,
|
|
||||||
) -> Res<OrgSource<'ss>, OrgSource<'ss>>,
|
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
recognize(tuple((
|
recognize(tuple((
|
||||||
opt(blank_line),
|
opt(blank_line),
|
||||||
parser_with_context!(line_indented_lte_matcher)(context),
|
parser_with_context!(line_indented_lte)(context),
|
||||||
)))(input)
|
)))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn line_indented_lte(
|
|
||||||
indent_level: usize,
|
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
||||||
move |context: Context, input: OrgSource<'_>| _line_indented_lte(context, input, indent_level)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn _line_indented_lte<'r, 's>(
|
fn line_indented_lte<'r, 's>(
|
||||||
context: Context<'r, 's>,
|
context: Context<'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
indent_level: usize,
|
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
|
let current_item_indent_level: &usize =
|
||||||
|
get_context_item_indent(context).ok_or(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"Not inside a plain list item".into(),
|
||||||
|
))))?;
|
||||||
|
|
||||||
let matched = recognize(verify(
|
let matched = recognize(verify(
|
||||||
tuple((space0::<OrgSource<'_>, _>, non_whitespace_character)),
|
tuple((space0::<OrgSource<'_>, _>, non_whitespace_character)),
|
||||||
// It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
|
// It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
|
||||||
|(_space0, _anychar)| _space0.len() <= indent_level,
|
|(_space0, _anychar)| _space0.len() <= *current_item_indent_level,
|
||||||
))(input)?;
|
))(input)?;
|
||||||
|
|
||||||
Ok(matched)
|
Ok(matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_context_item_indent<'r, 's>(context: Context<'r, 's>) -> Option<&'r usize> {
|
||||||
|
for thing in context.iter() {
|
||||||
|
match thing.get_data() {
|
||||||
|
ContextElement::ListItem(depth) => return Some(depth),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user