Merge branch 'latex_environment_properties'
rustfmt Build rustfmt has succeeded Details
rust-build Build rust-build has succeeded Details
rust-test Build rust-test has succeeded Details
rust-foreign-document-test Build rust-foreign-document-test has succeeded Details

This commit is contained in:
Tom Alexander 2023-10-06 12:02:29 -04:00
commit 627c785e24
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
19 changed files with 193 additions and 79 deletions

View File

@ -2484,8 +2484,6 @@ fn compare_latex_environment<'b, 's>(
let mut this_status = DiffStatus::Good;
let mut message = None;
// TODO: Compare :value
// TODO: Compare :caption
// Compare name
let name = get_property_quoted_string(emacs, ":name")?;
@ -2497,6 +2495,16 @@ fn compare_latex_environment<'b, 's>(
));
}
// Compare value
let value = get_property_quoted_string(emacs, ":value")?;
if value.as_ref().map(String::as_str) != Some(rust.value) {
this_status = DiffStatus::Bad;
message = Some(format!(
"Value mismatch (emacs != rust) {:?} != {:?}",
value, rust.value
));
}
Ok(DiffResult {
status: this_status,
name: rust.get_elisp_name(),

View File

@ -17,6 +17,7 @@ use nom::InputTake;
use super::keyword::affiliated_keyword;
use super::org_source::BracketDepth;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::start_of_line;
use super::OrgSource;
use crate::context::Matcher;
@ -30,15 +31,17 @@ use crate::types::BabelCall;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn babel_call<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, BabelCall<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, _) = tuple((space0, tag("#+"), tag_no_case("call"), tag(":")))(input)?;
start_of_line(remaining)?;
let (remaining, _) = tuple((space0, tag("#+"), tag_no_case("call"), tag(":")))(remaining)?;
if let Ok((remaining, (_, line_break))) = tuple((space0, org_line_ending))(remaining) {
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
return Ok((
remaining,
@ -59,6 +62,8 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
consumed(babel_call_value)(remaining)?;
let (remaining, _ws) = tuple((space0, org_line_ending))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((

View File

@ -13,6 +13,7 @@ use super::org_source::OrgSource;
use super::timestamp::inactive_date_range_timestamp;
use super::timestamp::inactive_time_range_timestamp;
use super::timestamp::inactive_timestamp;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending;
use crate::context::parser_with_context;
use crate::context::RefContext;
@ -36,6 +37,8 @@ pub(crate) fn clock<'b, 'g, 'r, 's>(
let (remaining, (timestamp, duration)) = clock_timestamp(context, remaining)?;
let (remaining, _) = tuple((space0, org_line_ending))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,

View File

@ -13,6 +13,7 @@ use nom::sequence::tuple;
use super::org_source::OrgSource;
use super::util::get_consumed;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending;
use crate::context::parser_with_context;
use crate::context::ContextElement;
@ -43,6 +44,8 @@ pub(crate) fn comment<'b, 'g, 'r, 's>(
let (remaining, mut remaining_lines) =
many0(preceded(not(exit_matcher), comment_line_matcher))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
let mut value = Vec::with_capacity(remaining_lines.len() + 1);
let last_line = remaining_lines.pop();

View File

@ -7,6 +7,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending;
use crate::context::RefContext;
use crate::error::Res;
@ -16,14 +17,16 @@ use crate::types::DiarySexp;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn diary_sexp<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, DiarySexp<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, value) = recognize(tuple((tag("%%("), is_not("\r\n"))))(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(remaining)?;
let (remaining, value) = recognize(tuple((tag("%%("), is_not("\r\n"))))(remaining)?;
let (remaining, _eol) = org_line_ending(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,

View File

@ -14,6 +14,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ExitClass;
@ -44,9 +45,9 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(remaining)?;
let (remaining, _leading_whitespace) = space0(remaining)?;
let (remaining, (_open_colon, drawer_name, _close_colon, _new_line)) = tuple((
tag(":"),
name,
@ -88,6 +89,8 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>(
};
let (remaining, _end) = drawer_end(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((

View File

@ -20,6 +20,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ExitClass;
@ -49,10 +50,10 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
start_of_line(remaining)?;
let (remaining, _leading_whitespace) = space0(remaining)?;
let (remaining, (_, name, parameters, _, _)) = tuple((
recognize(tuple((tag_no_case("#+begin:"), space1))),
name,
@ -96,6 +97,8 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
let (remaining, _end) = dynamic_block_end(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,

View File

@ -21,6 +21,7 @@ use super::footnote_definition::footnote_definition;
use super::greater_block::greater_block;
use super::horizontal_rule::horizontal_rule;
use super::keyword::affiliated_keyword;
use super::keyword::affiliated_keyword_as_regular_keyword;
use super::keyword::keyword;
use super::latex_environment::latex_environment;
use super::lesser_block::comment_block;
@ -33,8 +34,6 @@ use super::paragraph::paragraph;
use super::plain_list::detect_plain_list;
use super::plain_list::plain_list;
use super::table::detect_table;
use super::util::get_consumed;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::RefContext;
use crate::error::CustomError;
@ -42,7 +41,6 @@ use crate::error::MyError;
use crate::error::Res;
use crate::parser::table::org_mode_table;
use crate::types::Element;
use crate::types::SetSource;
pub(crate) const fn element(
can_be_paragraph: bool,
@ -137,7 +135,10 @@ fn _element<'b, 'g, 'r, 's>(
#[cfg(feature = "tracing")]
let _enter = span.enter();
let (remain, kw) = opt(map(affiliated_keyword, Element::Keyword))(remaining)?;
let (remain, kw) = opt(map(
parser_with_context!(affiliated_keyword_as_regular_keyword)(context),
Element::Keyword,
))(remaining)?;
if kw.is_some() {
maybe_element = kw;
remaining = remain;
@ -164,13 +165,7 @@ fn _element<'b, 'g, 'r, 's>(
"No element.",
))));
}
let mut element = maybe_element.expect("The above if-statement ensures this is Some().");
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
element.set_source(source.into());
let element = maybe_element.expect("The above if-statement ensures this is Some().");
Ok((remaining, element))
}

View File

@ -12,6 +12,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending;
use crate::context::parser_with_context;
use crate::context::RefContext;
@ -26,13 +27,15 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, FixedWidthArea<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let fixed_width_area_line_matcher = parser_with_context!(fixed_width_area_line)(context);
let exit_matcher = parser_with_context!(exit_matcher_parser)(context);
let (remaining, first_line) = fixed_width_area_line_matcher(input)?;
let (remaining, first_line) = fixed_width_area_line_matcher(remaining)?;
let (remaining, mut remaining_lines) =
many0(preceded(not(exit_matcher), fixed_width_area_line_matcher))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
let mut value = Vec::with_capacity(remaining_lines.len() + 1);
let last_line = remaining_lines.pop();

View File

@ -15,6 +15,7 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::include_input;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::WORD_CONSTITUENT_CHARACTERS;
use crate::context::parser_with_context;
use crate::context::ContextElement;
@ -43,8 +44,8 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(remaining)?;
// Cannot be indented.
let (remaining, (_, lbl, _, _, _)) = tuple((
tag_no_case("[fn:"),
@ -54,7 +55,7 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
opt(verify(many0(blank_line), |lines: &Vec<OrgSource<'_>>| {
lines.len() <= 2
})),
))(input)?;
))(remaining)?;
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::Context("footnote definition"),
@ -83,6 +84,8 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
}
}
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,

View File

@ -21,6 +21,7 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::in_section;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ContextMatcher;
@ -48,6 +49,7 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Element<'s>> {
let pre_affiliated_keywords_input = input;
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
@ -62,9 +64,24 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
))(remaining)?;
let name = Into::<&str>::into(name);
let (remaining, element) = match name.to_lowercase().as_str() {
"center" => center_block(context, remaining, input, &affiliated_keywords)?,
"quote" => quote_block(context, remaining, input, &affiliated_keywords)?,
_ => special_block(name)(context, remaining, input, &affiliated_keywords)?,
"center" => center_block(
context,
remaining,
pre_affiliated_keywords_input,
&affiliated_keywords,
)?,
"quote" => quote_block(
context,
remaining,
pre_affiliated_keywords_input,
&affiliated_keywords,
)?,
_ => special_block(name)(
context,
remaining,
pre_affiliated_keywords_input,
&affiliated_keywords,
)?,
};
Ok((remaining, element))
}
@ -73,11 +90,16 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
fn center_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
original_input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>,
affiliated_keywords: &Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, (source, children)) =
greater_block_body(context, input, original_input, "center", "center block")?;
let (remaining, (source, children)) = greater_block_body(
context,
input,
pre_affiliated_keywords_input,
"center",
"center block",
)?;
Ok((
remaining,
Element::CenterBlock(CenterBlock {
@ -92,11 +114,16 @@ fn center_block<'b, 'g, 'r, 's>(
fn quote_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
original_input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>,
affiliated_keywords: &Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, (source, children)) =
greater_block_body(context, input, original_input, "quote", "quote block")?;
let (remaining, (source, children)) = greater_block_body(
context,
input,
pre_affiliated_keywords_input,
"quote",
"quote block",
)?;
Ok((
remaining,
Element::QuoteBlock(QuoteBlock {
@ -117,11 +144,11 @@ fn special_block<'s>(
) -> Res<OrgSource<'s>, Element<'s>>
+ 's {
let context_name = format!("special block {}", name);
move |context, input, original_input, affiliated_keywords| {
move |context, input, pre_affiliated_keywords_input, affiliated_keywords| {
_special_block(
context,
input,
original_input,
pre_affiliated_keywords_input,
name,
context_name.as_str(),
affiliated_keywords,
@ -133,14 +160,19 @@ fn special_block<'s>(
fn _special_block<'c, 'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
original_input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>,
name: &'s str,
context_name: &'c str,
affiliated_keywords: &Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?;
let (remaining, (source, children)) =
greater_block_body(context, remaining, original_input, name, context_name)?;
let (remaining, (source, children)) = greater_block_body(
context,
remaining,
pre_affiliated_keywords_input,
name,
context_name,
)?;
Ok((
remaining,
Element::SpecialBlock(SpecialBlock {
@ -157,7 +189,7 @@ fn _special_block<'c, 'b, 'g, 'r, 's>(
fn greater_block_body<'c, 'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
original_input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>,
name: &'c str,
context_name: &'c str,
) -> Res<OrgSource<'s>, (&'s str, Vec<Element<'s>>)> {
@ -202,7 +234,9 @@ fn greater_block_body<'c, 'b, 'g, 'r, 's>(
// Not checking if parent exit matcher is causing exit because the greater_block_end matcher asserts we matched a full greater block
let source = get_consumed(original_input, remaining);
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(pre_affiliated_keywords_input, remaining);
Ok((remaining, (Into::<&str>::into(source), children)))
}

View File

@ -11,7 +11,9 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::RefContext;
use crate::error::Res;
use crate::parser::util::start_of_line;
@ -19,21 +21,24 @@ use crate::types::HorizontalRule;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, HorizontalRule<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, rule) = recognize(tuple((
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(remaining)?;
let (remaining, _rule) = recognize(tuple((
space0,
verify(many1_count(tag("-")), |dashes| *dashes >= 5),
space0,
alt((line_ending, eof)),
)))(input)?;
)))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
HorizontalRule {
source: rule.into(),
source: source.into(),
name: get_name(&affiliated_keywords),
},
))

View File

@ -19,7 +19,9 @@ use nom::sequence::tuple;
use super::org_source::BracketDepth;
use super::org_source::OrgSource;
use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::Matcher;
use crate::context::RefContext;
use crate::error::CustomError;
@ -89,12 +91,29 @@ fn _filtered_keyword<'s, F: Matcher>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn keyword<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Keyword<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, mut kw) = filtered_keyword(regular_keyword_key)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, mut kw) = filtered_keyword(regular_keyword_key)(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
kw.name = get_name(&affiliated_keywords);
kw.source = Into::<&str>::into(source);
Ok((remaining, kw))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn affiliated_keyword_as_regular_keyword<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Keyword<'s>> {
let (remaining, mut kw) = affiliated_keyword(input)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
kw.source = Into::<&str>::into(source);
Ok((remaining, kw))
}

View File

@ -16,6 +16,7 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ContextMatcher;
@ -32,9 +33,10 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, LatexEnvironment<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let value_start = remaining;
start_of_line(remaining)?;
let (remaining, _leading_whitespace) = space0(remaining)?;
let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple((
tag_no_case(r#"\begin{"#),
name,
@ -52,13 +54,18 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
let (remaining, _contents) = contents(&latex_environment_end_specialized)(context, remaining)?;
let (remaining, _end) = latex_environment_end_specialized(&parser_context, remaining)?;
let value_end = remaining;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
let value = get_consumed(value_start, value_end);
Ok((
remaining,
LatexEnvironment {
source: source.into(),
name: get_name(&affiliated_keywords),
value: value.into(),
},
))
}

View File

@ -20,6 +20,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ContextMatcher;
@ -52,8 +53,8 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, VerseBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("verse")(context, input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("verse")(context, remaining)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("verse");
@ -91,6 +92,8 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>(
};
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
@ -108,8 +111,8 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, CommentBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("comment")(context, input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("comment")(context, remaining)?;
let (remaining, _parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("comment");
@ -128,6 +131,8 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>(
let (remaining, contents) = parser_with_context!(text_until_exit)(&parser_context)(remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
@ -144,8 +149,8 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("example")(context, input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("example")(context, remaining)?;
let (remaining, parameters) = opt(tuple((space1, example_switches)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("example");
@ -165,6 +170,8 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = {
if let Some(parameters) = parameters {
@ -205,8 +212,8 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ExportBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("export")(context, input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("export")(context, remaining)?;
// https://orgmode.org/worg/org-syntax.html#Blocks claims that export blocks must have a single word for data but testing shows no data and multi-word data still parses as an export block.
let (remaining, export_type) = opt(map(
tuple((space1, switch_word, peek(tuple((space0, line_ending))))),
@ -231,6 +238,8 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>(
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
@ -249,8 +258,8 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, SrcBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("src")(context, input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("src")(context, remaining)?;
// https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block.
let (remaining, language) =
opt(map(tuple((space1, switch_word)), |(_, language)| language))(remaining)?;
@ -274,6 +283,8 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = {
if let Some(switches) = switches {

View File

@ -14,6 +14,7 @@ use super::util::blank_line;
use super::util::get_consumed;
use super::util::get_has_affiliated_keyword;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ExitClass;
@ -33,10 +34,10 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Paragraph<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let contexts = [
ContextElement::HasAffiliatedKeyword(HasAffiliatedKeywordInner {
start_after_affiliated_keywords: input,
start_after_affiliated_keywords: remaining,
keywords: &affiliated_keywords,
}),
ContextElement::ExitMatcherNode(ExitMatcherNode {
@ -52,10 +53,12 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
let (remaining, (children, _exit_contents)) = verify(
many_till(standard_set_object_matcher, exit_matcher),
|(children, _exit_contents)| !children.is_empty(),
)(input)?;
)(remaining)?;
// Not checking parent exit matcher because if there are any children matched then we have a valid paragraph.
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((

View File

@ -81,7 +81,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, PlainList<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let contexts = [
ContextElement::Context("plain list"),
@ -99,7 +99,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
let mut children = Vec::new();
let mut first_item_indentation: Option<IndentationLevel> = None;
let mut first_item_list_type: Option<PlainListType> = None;
let mut remaining = input;
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:
//
@ -150,6 +150,8 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
children.push((final_child_start, reparsed_final_item));
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,

View File

@ -19,6 +19,7 @@ use super::object_parser::table_cell_set_object;
use super::org_source::OrgSource;
use super::util::exit_matcher_parser;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending;
use crate::context::parser_with_context;
use crate::context::ContextElement;
@ -40,9 +41,9 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Table<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?;
peek(tuple((space0, tag("|"))))(input)?;
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(remaining)?;
peek(tuple((space0, tag("|"))))(remaining)?;
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -60,11 +61,13 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>(
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
let (remaining, (children, _exit_contents)) =
many_till(org_mode_table_row_matcher, exit_matcher)(input)?;
many_till(org_mode_table_row_matcher, exit_matcher)(remaining)?;
let (remaining, formulas) =
many0(parser_with_context!(table_formula_keyword)(context))(remaining)?;
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((

View File

@ -149,6 +149,7 @@ pub struct BabelCall<'s> {
pub struct LatexEnvironment<'s> {
pub source: &'s str,
pub name: Option<&'s str>,
pub value: &'s str,
}
/// A line number used in switches to lesser blocks.