Implement check_exit_matcher.
This commit is contained in:
parent
8502a8830d
commit
15e8d1ab77
@ -1,10 +1,13 @@
|
|||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
use super::exiting::ExitClass;
|
use super::exiting::ExitClass;
|
||||||
use super::global_settings::GlobalSettings;
|
use super::global_settings::GlobalSettings;
|
||||||
use super::list::List;
|
use super::list::List;
|
||||||
use super::DynContextMatcher;
|
use super::DynContextMatcher;
|
||||||
use super::RefContext;
|
use super::RefContext;
|
||||||
|
use crate::error::CustomError;
|
||||||
|
use crate::error::MyError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::OrgSource;
|
use crate::parser::OrgSource;
|
||||||
use crate::types::Object;
|
use crate::types::Object;
|
||||||
@ -169,6 +172,56 @@ impl<'r, 's> Context<'r, 's> {
|
|||||||
tree: parent_tree.clone(),
|
tree: parent_tree.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_data(&self) -> &ContextElement<'r, 's> {
|
||||||
|
self.tree.get_data()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
pub fn check_exit_matcher(
|
||||||
|
&'r self,
|
||||||
|
i: OrgSource<'s>,
|
||||||
|
) -> IResult<OrgSource<'s>, OrgSource<'s>, CustomError<OrgSource<'s>>> {
|
||||||
|
let mut current_class_filter = ExitClass::Gamma;
|
||||||
|
for current_node in self.iter_context() {
|
||||||
|
let context_element = current_node.get_data();
|
||||||
|
match context_element {
|
||||||
|
ContextElement::ExitMatcherNode(exit_matcher) => {
|
||||||
|
if exit_matcher.class as u32 <= current_class_filter as u32 {
|
||||||
|
current_class_filter = exit_matcher.class;
|
||||||
|
let local_result = (exit_matcher.exit_matcher)(¤t_node, i);
|
||||||
|
if local_result.is_ok() {
|
||||||
|
return local_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// TODO: Make this a specific error instead of just a generic MyError
|
||||||
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"NoExit".into(),
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicates if elements should consume the whitespace after them.
|
||||||
|
///
|
||||||
|
/// Defaults to true.
|
||||||
|
pub fn should_consume_trailing_whitespace(&self) -> bool {
|
||||||
|
self._should_consume_trailing_whitespace().unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _should_consume_trailing_whitespace(&self) -> Option<bool> {
|
||||||
|
for current_node in self.iter() {
|
||||||
|
match current_node {
|
||||||
|
ContextElement::ConsumeTrailingWhitespace(should) => {
|
||||||
|
return Some(*should);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
@ -17,8 +17,6 @@ use nom::multi::many_till;
|
|||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use super::element::Element;
|
|
||||||
use super::object::Object;
|
|
||||||
use super::org_source::convert_error;
|
use super::org_source::convert_error;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::token::AllTokensIterator;
|
use super::token::AllTokensIterator;
|
||||||
@ -26,6 +24,14 @@ use super::token::Token;
|
|||||||
use super::util::exit_matcher_parser;
|
use super::util::exit_matcher_parser;
|
||||||
use super::util::get_consumed;
|
use super::util::get_consumed;
|
||||||
use super::util::start_of_line;
|
use super::util::start_of_line;
|
||||||
|
use crate::context::parser_with_context;
|
||||||
|
use crate::context::Context;
|
||||||
|
use crate::context::ContextElement;
|
||||||
|
use crate::context::ExitClass;
|
||||||
|
use crate::context::ExitMatcherNode;
|
||||||
|
use crate::context::GlobalSettings;
|
||||||
|
use crate::context::List;
|
||||||
|
use crate::context::RefContext;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::comment::comment;
|
use crate::parser::comment::comment;
|
||||||
use crate::parser::element_parser::element;
|
use crate::parser::element_parser::element;
|
||||||
@ -34,11 +40,19 @@ use crate::parser::planning::planning;
|
|||||||
use crate::parser::property_drawer::property_drawer;
|
use crate::parser::property_drawer::property_drawer;
|
||||||
use crate::parser::util::blank_line;
|
use crate::parser::util::blank_line;
|
||||||
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
|
use crate::types::Document;
|
||||||
|
use crate::types::DocumentElement;
|
||||||
|
use crate::types::Element;
|
||||||
|
use crate::types::Heading;
|
||||||
|
use crate::types::Object;
|
||||||
|
use crate::types::Section;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn document(input: &str) -> Res<&str, Document> {
|
pub fn document(input: &str) -> Res<&str, Document> {
|
||||||
let initial_context = Context::default();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let wrapped_input = OrgSource::new(input);
|
let wrapped_input = OrgSource::new(input);
|
||||||
let (remaining, document) = _document(&initial_context, wrapped_input)
|
let (remaining, document) = _document(&initial_context, wrapped_input)
|
||||||
.map(|(rem, out)| (Into::<&str>::into(rem), out))
|
.map(|(rem, out)| (Into::<&str>::into(rem), out))
|
||||||
@ -58,9 +72,9 @@ pub fn document(input: &str) -> Res<&str, Document> {
|
|||||||
.map(|rt| &rt.children)
|
.map(|rt| &rt.children)
|
||||||
.collect();
|
.collect();
|
||||||
if !all_radio_targets.is_empty() {
|
if !all_radio_targets.is_empty() {
|
||||||
let initial_context = initial_context
|
let parser_context = ContextElement::RadioTarget(all_radio_targets);
|
||||||
.with_additional_node(ContextElement::RadioTarget(all_radio_targets));
|
let parser_context = initial_context.with_additional_node(&parser_context);
|
||||||
let (remaining, document) = _document(&initial_context, wrapped_input)
|
let (remaining, document) = _document(&parser_context, wrapped_input)
|
||||||
.map(|(rem, out)| (Into::<&str>::into(rem), out))
|
.map(|(rem, out)| (Into::<&str>::into(rem), out))
|
||||||
.map_err(convert_error)?;
|
.map_err(convert_error)?;
|
||||||
return Ok((remaining.into(), document));
|
return Ok((remaining.into(), document));
|
||||||
@ -96,15 +110,21 @@ fn zeroth_section<'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Section<'s>> {
|
) -> Res<OrgSource<'s>, Section<'s>> {
|
||||||
// TODO: The zeroth section is specialized so it probably needs its own parser
|
// TODO: The zeroth section is specialized so it probably needs its own parser
|
||||||
let parser_context = context
|
let contexts = [
|
||||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
ContextElement::ConsumeTrailingWhitespace(true),
|
||||||
.with_additional_node(ContextElement::Context("section"))
|
ContextElement::Context("section"),
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Document,
|
class: ExitClass::Document,
|
||||||
exit_matcher: §ion_end,
|
exit_matcher: §ion_end,
|
||||||
}));
|
}),
|
||||||
|
];
|
||||||
|
let parser_context = context
|
||||||
|
.with_additional_node(&contexts[0])
|
||||||
|
.with_additional_node(&contexts[1])
|
||||||
|
.with_additional_node(&contexts[2]);
|
||||||
|
let without_consuming_whitespace_context = ContextElement::ConsumeTrailingWhitespace(false);
|
||||||
let without_consuming_whitespace_context =
|
let without_consuming_whitespace_context =
|
||||||
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
|
parser_context.with_additional_node(&without_consuming_whitespace_context);
|
||||||
|
|
||||||
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
||||||
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
||||||
@ -150,13 +170,18 @@ fn section<'r, 's>(
|
|||||||
mut input: OrgSource<'s>,
|
mut input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Section<'s>> {
|
) -> Res<OrgSource<'s>, Section<'s>> {
|
||||||
// TODO: The zeroth section is specialized so it probably needs its own parser
|
// TODO: The zeroth section is specialized so it probably needs its own parser
|
||||||
let parser_context = context
|
let contexts = [
|
||||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
ContextElement::ConsumeTrailingWhitespace(true),
|
||||||
.with_additional_node(ContextElement::Context("section"))
|
ContextElement::Context("section"),
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Document,
|
class: ExitClass::Document,
|
||||||
exit_matcher: §ion_end,
|
exit_matcher: §ion_end,
|
||||||
}));
|
}),
|
||||||
|
];
|
||||||
|
let parser_context = context
|
||||||
|
.with_additional_node(&contexts[0])
|
||||||
|
.with_additional_node(&contexts[1])
|
||||||
|
.with_additional_node(&contexts[2]);
|
||||||
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
||||||
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
||||||
let (mut remaining, (planning_element, property_drawer_element)) = tuple((
|
let (mut remaining, (planning_element, property_drawer_element)) = tuple((
|
||||||
@ -204,8 +229,9 @@ fn section_end<'r, 's>(
|
|||||||
|
|
||||||
const fn heading(
|
const fn heading(
|
||||||
parent_stars: usize,
|
parent_stars: usize,
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Heading<'s>> {
|
) -> impl for<'b, 'r, 's> Fn(RefContext<'b, 'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Heading<'s>>
|
||||||
move |context: Context, input: OrgSource<'_>| _heading(context, input, parent_stars)
|
{
|
||||||
|
move |context, input: OrgSource<'_>| _heading(context, input, parent_stars)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@ -270,11 +296,11 @@ fn headline<'r, 's>(
|
|||||||
Vec<&'s str>,
|
Vec<&'s str>,
|
||||||
),
|
),
|
||||||
> {
|
> {
|
||||||
let parser_context =
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
||||||
class: ExitClass::Document,
|
class: ExitClass::Document,
|
||||||
exit_matcher: &headline_title_end,
|
exit_matcher: &headline_title_end,
|
||||||
}));
|
});
|
||||||
|
let parser_context = context.with_additional_node(&parser_context);
|
||||||
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
|
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
|
||||||
|
|
||||||
let (
|
let (
|
||||||
|
@ -16,21 +16,26 @@ use nom::multi::many1;
|
|||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use super::greater_element::PlainList;
|
use super::element_parser::element;
|
||||||
use super::greater_element::PlainListItem;
|
use super::object_parser::standard_set_object;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::util::non_whitespace_character;
|
use super::util::non_whitespace_character;
|
||||||
use super::Context;
|
use crate::context::parser_with_context;
|
||||||
use super::Object;
|
use crate::context::ContextElement;
|
||||||
|
use crate::context::ExitClass;
|
||||||
|
use crate::context::ExitMatcherNode;
|
||||||
|
use crate::context::RefContext;
|
||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::element_parser::element;
|
|
||||||
use crate::parser::util::blank_line;
|
use crate::parser::util::blank_line;
|
||||||
use crate::parser::util::exit_matcher_parser;
|
use crate::parser::util::exit_matcher_parser;
|
||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
use crate::parser::util::start_of_line;
|
use crate::parser::util::start_of_line;
|
||||||
|
use crate::types::Object;
|
||||||
|
use crate::types::PlainList;
|
||||||
|
use crate::types::PlainListItem;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub fn detect_plain_list<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
|
pub fn detect_plain_list<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
|
||||||
@ -59,13 +64,19 @@ pub fn plain_list<'r, 's>(
|
|||||||
context: RefContext<'_, 'r, 's>,
|
context: RefContext<'_, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, PlainList<'s>> {
|
) -> Res<OrgSource<'s>, PlainList<'s>> {
|
||||||
let parser_context = context
|
let contexts = [
|
||||||
.with_additional_node(ContextElement::Context("plain list"))
|
ContextElement::Context("plain list"),
|
||||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
ContextElement::ConsumeTrailingWhitespace(true),
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
exit_matcher: &plain_list_end,
|
exit_matcher: &plain_list_end,
|
||||||
}));
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
let parser_context = context
|
||||||
|
.with_additional_node(&contexts[0])
|
||||||
|
.with_additional_node(&contexts[1])
|
||||||
|
.with_additional_node(&contexts[2]);
|
||||||
// children stores tuple of (input string, parsed object) so we can re-parse the final item
|
// children stores tuple of (input string, parsed object) so we can re-parse the final item
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
let mut first_item_indentation: Option<usize> = None;
|
let mut first_item_indentation: Option<usize> = None;
|
||||||
@ -107,8 +118,8 @@ pub fn plain_list<'r, 's>(
|
|||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let final_item_context =
|
let final_item_context = ContextElement::ConsumeTrailingWhitespace(false);
|
||||||
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
|
let final_item_context = parser_context.with_additional_node(&final_item_context);
|
||||||
let (remaining, reparsed_final_item) =
|
let (remaining, reparsed_final_item) =
|
||||||
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
|
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
|
||||||
children.push((final_child_start, reparsed_final_item));
|
children.push((final_child_start, reparsed_final_item));
|
||||||
@ -164,12 +175,16 @@ pub fn plain_list_item<'r, 's>(
|
|||||||
};
|
};
|
||||||
let (remaining, _ws) = item_tag_post_gap(context, remaining)?;
|
let (remaining, _ws) = item_tag_post_gap(context, remaining)?;
|
||||||
let exit_matcher = plain_list_item_end(indent_level);
|
let exit_matcher = plain_list_item_end(indent_level);
|
||||||
let parser_context = context
|
let contexts = [
|
||||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
ContextElement::ConsumeTrailingWhitespace(true),
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
exit_matcher: &exit_matcher,
|
exit_matcher: &exit_matcher,
|
||||||
}));
|
}),
|
||||||
|
];
|
||||||
|
let parser_context = context
|
||||||
|
.with_additional_node(&contexts[0])
|
||||||
|
.with_additional_node(&contexts[1]);
|
||||||
|
|
||||||
let (mut remaining, (mut children, _exit_contents)) = many_till(
|
let (mut remaining, (mut children, _exit_contents)) = many_till(
|
||||||
include_input(parser_with_context!(element(true))(&parser_context)),
|
include_input(parser_with_context!(element(true))(&parser_context)),
|
||||||
@ -177,8 +192,8 @@ pub fn plain_list_item<'r, 's>(
|
|||||||
)(remaining)?;
|
)(remaining)?;
|
||||||
|
|
||||||
if !children.is_empty() && !context.should_consume_trailing_whitespace() {
|
if !children.is_empty() && !context.should_consume_trailing_whitespace() {
|
||||||
let final_item_context =
|
let final_item_context = ContextElement::ConsumeTrailingWhitespace(false);
|
||||||
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
|
let final_item_context = parser_context.with_additional_node(&final_item_context);
|
||||||
let (final_child_start, _original_final_child) = children
|
let (final_child_start, _original_final_child) = children
|
||||||
.pop()
|
.pop()
|
||||||
.expect("if-statement already checked that children was non-empty.");
|
.expect("if-statement already checked that children was non-empty.");
|
||||||
@ -249,9 +264,10 @@ fn plain_list_end<'r, 's>(
|
|||||||
|
|
||||||
const fn plain_list_item_end(
|
const fn plain_list_item_end(
|
||||||
indent_level: usize,
|
indent_level: usize,
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> impl for<'b, 'r, 's> Fn(RefContext<'b, 'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>>
|
||||||
|
{
|
||||||
let line_indented_lte_matcher = line_indented_lte(indent_level);
|
let line_indented_lte_matcher = line_indented_lte(indent_level);
|
||||||
move |context: Context, input: OrgSource<'_>| {
|
move |context, input: OrgSource<'_>| {
|
||||||
_plain_list_item_end(context, input, &line_indented_lte_matcher)
|
_plain_list_item_end(context, input, &line_indented_lte_matcher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,8 +279,8 @@ const fn plain_list_item_end(
|
|||||||
fn _plain_list_item_end<'r, 's>(
|
fn _plain_list_item_end<'r, 's>(
|
||||||
context: RefContext<'_, 'r, 's>,
|
context: RefContext<'_, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
line_indented_lte_matcher: impl for<'rr, 'ss> Fn(
|
line_indented_lte_matcher: impl for<'bb, 'rr, 'ss> Fn(
|
||||||
Context<'rr, 'ss>,
|
RefContext<'bb, 'rr, 'ss>,
|
||||||
OrgSource<'ss>,
|
OrgSource<'ss>,
|
||||||
) -> Res<OrgSource<'ss>, OrgSource<'ss>>,
|
) -> Res<OrgSource<'ss>, OrgSource<'ss>>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
@ -277,8 +293,9 @@ fn _plain_list_item_end<'r, 's>(
|
|||||||
|
|
||||||
const fn line_indented_lte(
|
const fn line_indented_lte(
|
||||||
indent_level: usize,
|
indent_level: usize,
|
||||||
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> impl for<'b, 'r, 's> Fn(RefContext<'b, 'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>>
|
||||||
move |context: Context, input: OrgSource<'_>| _line_indented_lte(context, input, indent_level)
|
{
|
||||||
|
move |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"))]
|
||||||
@ -301,11 +318,11 @@ fn item_tag<'r, 's>(
|
|||||||
context: RefContext<'_, 'r, 's>,
|
context: RefContext<'_, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
|
) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
|
||||||
let parser_context =
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
||||||
class: ExitClass::Gamma,
|
class: ExitClass::Gamma,
|
||||||
exit_matcher: &item_tag_end,
|
exit_matcher: &item_tag_end,
|
||||||
}));
|
});
|
||||||
|
let parser_context = context.with_additional_node(&parser_context);
|
||||||
let (remaining, (children, _exit_contents)) = verify(
|
let (remaining, (children, _exit_contents)) = verify(
|
||||||
many_till(
|
many_till(
|
||||||
// TODO: Should this be using a different set like the minimal set?
|
// TODO: Should this be using a different set like the minimal set?
|
||||||
@ -353,14 +370,16 @@ fn item_tag_post_gap<'r, 's>(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parser::parser_context::ContextTree;
|
use crate::context::Context;
|
||||||
use crate::parser::parser_with_context::parser_with_context;
|
use crate::context::GlobalSettings;
|
||||||
use crate::parser::Source;
|
use crate::context::List;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn plain_list_item_empty() {
|
fn plain_list_item_empty() {
|
||||||
let input = OrgSource::new("1.");
|
let input = OrgSource::new("1.");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context);
|
let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context);
|
||||||
let (remaining, result) = plain_list_item_matcher(input).unwrap();
|
let (remaining, result) = plain_list_item_matcher(input).unwrap();
|
||||||
assert_eq!(Into::<&str>::into(remaining), "");
|
assert_eq!(Into::<&str>::into(remaining), "");
|
||||||
@ -370,7 +389,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn plain_list_item_simple() {
|
fn plain_list_item_simple() {
|
||||||
let input = OrgSource::new("1. foo");
|
let input = OrgSource::new("1. foo");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context);
|
let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context);
|
||||||
let (remaining, result) = plain_list_item_matcher(input).unwrap();
|
let (remaining, result) = plain_list_item_matcher(input).unwrap();
|
||||||
assert_eq!(Into::<&str>::into(remaining), "");
|
assert_eq!(Into::<&str>::into(remaining), "");
|
||||||
@ -380,7 +401,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn plain_list_empty() {
|
fn plain_list_empty() {
|
||||||
let input = OrgSource::new("1.");
|
let input = OrgSource::new("1.");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
||||||
let (remaining, result) = plain_list_matcher(input).unwrap();
|
let (remaining, result) = plain_list_matcher(input).unwrap();
|
||||||
assert_eq!(Into::<&str>::into(remaining), "");
|
assert_eq!(Into::<&str>::into(remaining), "");
|
||||||
@ -390,7 +413,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn plain_list_simple() {
|
fn plain_list_simple() {
|
||||||
let input = OrgSource::new("1. foo");
|
let input = OrgSource::new("1. foo");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
||||||
let (remaining, result) = plain_list_matcher(input).unwrap();
|
let (remaining, result) = plain_list_matcher(input).unwrap();
|
||||||
assert_eq!(Into::<&str>::into(remaining), "");
|
assert_eq!(Into::<&str>::into(remaining), "");
|
||||||
@ -401,7 +426,9 @@ mod tests {
|
|||||||
fn plain_list_cant_start_line_with_asterisk() {
|
fn plain_list_cant_start_line_with_asterisk() {
|
||||||
// Plain lists with an asterisk bullet must be indented or else they would be a headline
|
// Plain lists with an asterisk bullet must be indented or else they would be a headline
|
||||||
let input = OrgSource::new("* foo");
|
let input = OrgSource::new("* foo");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
||||||
let result = plain_list_matcher(input);
|
let result = plain_list_matcher(input);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
@ -411,7 +438,9 @@ mod tests {
|
|||||||
fn indented_can_start_line_with_asterisk() {
|
fn indented_can_start_line_with_asterisk() {
|
||||||
// Plain lists with an asterisk bullet must be indented or else they would be a headline
|
// Plain lists with an asterisk bullet must be indented or else they would be a headline
|
||||||
let input = OrgSource::new(" * foo");
|
let input = OrgSource::new(" * foo");
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
let plain_list_matcher = parser_with_context!(plain_list)(&initial_context);
|
||||||
let result = plain_list_matcher(input);
|
let result = plain_list_matcher(input);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
@ -429,7 +458,9 @@ mod tests {
|
|||||||
ipsum
|
ipsum
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
||||||
let (remaining, result) =
|
let (remaining, result) =
|
||||||
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
||||||
@ -455,7 +486,9 @@ mod tests {
|
|||||||
|
|
||||||
baz"#,
|
baz"#,
|
||||||
);
|
);
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
||||||
let (remaining, result) =
|
let (remaining, result) =
|
||||||
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
||||||
@ -486,7 +519,9 @@ baz"#,
|
|||||||
|
|
||||||
dolar"#,
|
dolar"#,
|
||||||
);
|
);
|
||||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
let global_settings = GlobalSettings::default();
|
||||||
|
let initial_context = ContextElement::document_context();
|
||||||
|
let initial_context = Context::new(&global_settings, List::new(&initial_context));
|
||||||
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
let plain_list_matcher = parser_with_context!(element(true))(&initial_context);
|
||||||
let (remaining, result) =
|
let (remaining, result) =
|
||||||
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
plain_list_matcher(input).expect("Should parse the plain list successfully.");
|
||||||
|
@ -7,13 +7,18 @@ use nom::combinator::verify;
|
|||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
|
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
|
use super::util::exit_matcher_parser;
|
||||||
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
||||||
use super::Context;
|
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::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
use crate::parser::Target;
|
use crate::types::Target;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub fn target<'r, 's>(
|
pub fn target<'r, 's>(
|
||||||
@ -25,11 +30,11 @@ pub fn target<'r, 's>(
|
|||||||
!c.is_whitespace() && !"<>\n".contains(*c)
|
!c.is_whitespace() && !"<>\n".contains(*c)
|
||||||
}))(remaining)?;
|
}))(remaining)?;
|
||||||
|
|
||||||
let parser_context =
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
exit_matcher: &target_end,
|
exit_matcher: &target_end,
|
||||||
}));
|
});
|
||||||
|
let parser_context = context.with_additional_node(&parser_context);
|
||||||
let (remaining, _body) = recognize(many_till(
|
let (remaining, _body) = recognize(many_till(
|
||||||
anychar,
|
anychar,
|
||||||
parser_with_context!(exit_matcher_parser)(&parser_context),
|
parser_with_context!(exit_matcher_parser)(&parser_context),
|
||||||
|
@ -20,7 +20,6 @@ use super::org_source::OrgSource;
|
|||||||
use super::radio_link::RematchObject;
|
use super::radio_link::RematchObject;
|
||||||
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::Context;
|
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
use crate::context::ExitClass;
|
use crate::context::ExitClass;
|
||||||
use crate::context::ExitMatcherNode;
|
use crate::context::ExitMatcherNode;
|
||||||
|
Loading…
Reference in New Issue
Block a user