2023-09-08 15:08:16 -04:00
|
|
|
use nom::combinator::opt;
|
|
|
|
use nom::combinator::recognize;
|
|
|
|
use nom::combinator::verify;
|
|
|
|
use nom::multi::many0;
|
|
|
|
use nom::multi::many_till;
|
|
|
|
use nom::sequence::tuple;
|
|
|
|
|
|
|
|
use super::headline::detect_headline;
|
|
|
|
use super::org_source::OrgSource;
|
|
|
|
use super::util::exit_matcher_parser;
|
|
|
|
use super::util::get_consumed;
|
|
|
|
use crate::context::parser_with_context;
|
|
|
|
use crate::context::ContextElement;
|
|
|
|
use crate::context::ExitClass;
|
|
|
|
use crate::context::ExitMatcherNode;
|
|
|
|
use crate::context::RefContext;
|
|
|
|
use crate::error::Res;
|
|
|
|
use crate::parser::comment::comment;
|
|
|
|
use crate::parser::element_parser::element;
|
|
|
|
use crate::parser::planning::planning;
|
|
|
|
use crate::parser::property_drawer::property_drawer;
|
|
|
|
use crate::parser::util::blank_line;
|
|
|
|
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
|
|
|
use crate::types::Element;
|
|
|
|
use crate::types::Section;
|
|
|
|
|
2023-10-09 18:00:48 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
2023-09-11 13:13:28 -04:00
|
|
|
pub(crate) fn zeroth_section<'b, 'g, 'r, 's>(
|
2023-09-08 15:08:16 -04:00
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Section<'s>> {
|
|
|
|
let contexts = [
|
|
|
|
ContextElement::ConsumeTrailingWhitespace(true),
|
|
|
|
ContextElement::Context("section"),
|
|
|
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
|
|
class: ExitClass::Document,
|
|
|
|
exit_matcher: §ion_end,
|
|
|
|
}),
|
|
|
|
];
|
|
|
|
let parser_context = context.with_additional_node(&contexts[0]);
|
|
|
|
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
|
|
|
let parser_context = parser_context.with_additional_node(&contexts[2]);
|
|
|
|
let without_consuming_whitespace_context = ContextElement::ConsumeTrailingWhitespace(false);
|
|
|
|
let without_consuming_whitespace_context =
|
|
|
|
parser_context.with_additional_node(&without_consuming_whitespace_context);
|
|
|
|
|
|
|
|
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
|
|
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
|
|
|
|
|
|
|
let (remaining, comment_and_property_drawer_element) = opt(tuple((
|
|
|
|
opt(parser_with_context!(comment)(
|
|
|
|
&without_consuming_whitespace_context,
|
|
|
|
)),
|
|
|
|
parser_with_context!(property_drawer)(context),
|
|
|
|
many0(blank_line),
|
|
|
|
)))(input)?;
|
|
|
|
|
|
|
|
let (remaining, (mut children, _exit_contents)) = verify(
|
|
|
|
many_till(element_matcher, exit_matcher),
|
|
|
|
|(children, _exit_contents)| {
|
|
|
|
!children.is_empty() || comment_and_property_drawer_element.is_some()
|
|
|
|
},
|
|
|
|
)(remaining)?;
|
|
|
|
|
|
|
|
comment_and_property_drawer_element.map(|(comment, property_drawer, _ws)| {
|
|
|
|
children.insert(0, Element::PropertyDrawer(property_drawer));
|
|
|
|
comment
|
|
|
|
.map(Element::Comment)
|
|
|
|
.map(|ele| children.insert(0, ele));
|
|
|
|
});
|
|
|
|
|
|
|
|
let (remaining, _trailing_ws) =
|
|
|
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
|
|
|
|
|
|
|
let source = get_consumed(input, remaining);
|
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
Section {
|
|
|
|
source: source.into(),
|
|
|
|
children,
|
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2023-10-09 18:00:48 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
2023-09-11 13:13:28 -04:00
|
|
|
pub(crate) fn section<'b, 'g, 'r, 's>(
|
2023-09-08 15:08:16 -04:00
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
mut input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Section<'s>> {
|
|
|
|
let contexts = [
|
|
|
|
ContextElement::ConsumeTrailingWhitespace(true),
|
|
|
|
ContextElement::Context("section"),
|
|
|
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
|
|
class: ExitClass::Document,
|
|
|
|
exit_matcher: §ion_end,
|
|
|
|
}),
|
|
|
|
];
|
|
|
|
let parser_context = context.with_additional_node(&contexts[0]);
|
|
|
|
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
|
|
|
let parser_context = parser_context.with_additional_node(&contexts[2]);
|
|
|
|
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
|
|
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
|
|
|
let (mut remaining, (planning_element, property_drawer_element)) = tuple((
|
|
|
|
opt(parser_with_context!(planning)(&parser_context)),
|
|
|
|
opt(parser_with_context!(property_drawer)(&parser_context)),
|
|
|
|
))(input)?;
|
|
|
|
if planning_element.is_none() && property_drawer_element.is_none() {
|
|
|
|
let (remain, _ws) = many0(blank_line)(remaining)?;
|
|
|
|
remaining = remain;
|
|
|
|
input = remain;
|
|
|
|
}
|
|
|
|
let (remaining, (mut children, _exit_contents)) = verify(
|
|
|
|
many_till(element_matcher, exit_matcher),
|
|
|
|
|(children, _exit_contents)| {
|
|
|
|
!children.is_empty() || property_drawer_element.is_some() || planning_element.is_some()
|
|
|
|
},
|
|
|
|
)(remaining)?;
|
|
|
|
property_drawer_element
|
|
|
|
.map(Element::PropertyDrawer)
|
|
|
|
.map(|ele| children.insert(0, ele));
|
|
|
|
planning_element
|
|
|
|
.map(Element::Planning)
|
|
|
|
.map(|ele| children.insert(0, ele));
|
|
|
|
|
|
|
|
let (remaining, _trailing_ws) =
|
|
|
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
|
|
|
|
|
|
|
let source = get_consumed(input, remaining);
|
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
Section {
|
|
|
|
source: source.into(),
|
|
|
|
children,
|
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2023-10-09 18:00:48 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(_context))
|
|
|
|
)]
|
2023-09-08 15:08:16 -04:00
|
|
|
fn section_end<'b, 'g, 'r, 's>(
|
|
|
|
_context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
|
|
recognize(detect_headline)(input)
|
|
|
|
}
|