Merge branch 'latex_environment_properties'
All checks were successful
rustfmt Build rustfmt has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded

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 this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
// TODO: Compare :value
// TODO: Compare :caption // TODO: Compare :caption
// Compare name // Compare name
let name = get_property_quoted_string(emacs, ":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 { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),

View File

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

View File

@ -13,6 +13,7 @@ use super::org_source::OrgSource;
use super::timestamp::inactive_date_range_timestamp; use super::timestamp::inactive_date_range_timestamp;
use super::timestamp::inactive_time_range_timestamp; use super::timestamp::inactive_time_range_timestamp;
use super::timestamp::inactive_timestamp; use super::timestamp::inactive_timestamp;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending; use super::util::org_line_ending;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::RefContext; 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, (timestamp, duration)) = clock_timestamp(context, remaining)?;
let (remaining, _) = tuple((space0, org_line_ending))(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); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

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

View File

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

View File

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

View File

@ -20,6 +20,7 @@ use nom::sequence::tuple;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name; use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
use crate::context::ExitClass; 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(), "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)?; start_of_line(remaining)?;
let (remaining, _leading_whitespace) = space0(input)?; let (remaining, _leading_whitespace) = space0(remaining)?;
let (remaining, (_, name, parameters, _, _)) = tuple(( let (remaining, (_, name, parameters, _, _)) = tuple((
recognize(tuple((tag_no_case("#+begin:"), space1))), recognize(tuple((tag_no_case("#+begin:"), space1))),
name, 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, _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); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

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

View File

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

View File

@ -15,6 +15,7 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name; use super::util::get_name;
use super::util::include_input; use super::util::include_input;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::WORD_CONSTITUENT_CHARACTERS; use super::util::WORD_CONSTITUENT_CHARACTERS;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; 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(), "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)?; start_of_line(remaining)?;
// Cannot be indented. // Cannot be indented.
let (remaining, (_, lbl, _, _, _)) = tuple(( let (remaining, (_, lbl, _, _, _)) = tuple((
tag_no_case("[fn:"), 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<'_>>| { opt(verify(many0(blank_line), |lines: &Vec<OrgSource<'_>>| {
lines.len() <= 2 lines.len() <= 2
})), })),
))(input)?; ))(remaining)?;
let contexts = [ let contexts = [
ContextElement::ConsumeTrailingWhitespace(true), ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::Context("footnote definition"), 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); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::get_name; use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
use crate::context::ContextMatcher; use crate::context::ContextMatcher;
@ -32,9 +33,10 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, LatexEnvironment<'s>> { ) -> Res<OrgSource<'s>, LatexEnvironment<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
start_of_line(input)?; let value_start = remaining;
let (remaining, _leading_whitespace) = space0(input)?; start_of_line(remaining)?;
let (remaining, _leading_whitespace) = space0(remaining)?;
let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple(( let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple((
tag_no_case(r#"\begin{"#), tag_no_case(r#"\begin{"#),
name, 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, _contents) = contents(&latex_environment_end_specialized)(context, remaining)?;
let (remaining, _end) = latex_environment_end_specialized(&parser_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 source = get_consumed(input, remaining);
let value = get_consumed(value_start, value_end);
Ok(( Ok((
remaining, remaining,
LatexEnvironment { LatexEnvironment {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), 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::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name; use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
use crate::context::ContextMatcher; use crate::context::ContextMatcher;
@ -52,8 +53,8 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, VerseBlock<'s>> { ) -> Res<OrgSource<'s>, VerseBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("verse")(context, input)?; let (remaining, _) = lesser_block_begin("verse")(context, remaining)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("verse"); 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, _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 source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@ -108,8 +111,8 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, CommentBlock<'s>> { ) -> Res<OrgSource<'s>, CommentBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("comment")(context, input)?; let (remaining, _) = lesser_block_begin("comment")(context, remaining)?;
let (remaining, _parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("comment"); 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, contents) = parser_with_context!(text_until_exit)(&parser_context)(remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&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 source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@ -144,8 +149,8 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ExampleBlock<'s>> { ) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("example")(context, input)?; let (remaining, _) = lesser_block_begin("example")(context, remaining)?;
let (remaining, parameters) = opt(tuple((space1, example_switches)))(remaining)?; let (remaining, parameters) = opt(tuple((space1, example_switches)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("example"); 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, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&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 source = get_consumed(input, remaining);
let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = { let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = {
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
@ -205,8 +212,8 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ExportBlock<'s>> { ) -> Res<OrgSource<'s>, ExportBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("export")(context, 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. // 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( let (remaining, export_type) = opt(map(
tuple((space1, switch_word, peek(tuple((space0, line_ending))))), 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, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&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 source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@ -249,8 +258,8 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, SrcBlock<'s>> { ) -> Res<OrgSource<'s>, SrcBlock<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("src")(context, 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. // 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) = let (remaining, language) =
opt(map(tuple((space1, switch_word)), |(_, language)| language))(remaining)?; 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, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&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 source = get_consumed(input, remaining);
let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = { let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = {
if let Some(switches) = switches { 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_consumed;
use super::util::get_has_affiliated_keyword; use super::util::get_has_affiliated_keyword;
use super::util::get_name; use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
use crate::context::ExitClass; use crate::context::ExitClass;
@ -33,10 +34,10 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Paragraph<'s>> { ) -> Res<OrgSource<'s>, Paragraph<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let contexts = [ let contexts = [
ContextElement::HasAffiliatedKeyword(HasAffiliatedKeywordInner { ContextElement::HasAffiliatedKeyword(HasAffiliatedKeywordInner {
start_after_affiliated_keywords: input, start_after_affiliated_keywords: remaining,
keywords: &affiliated_keywords, keywords: &affiliated_keywords,
}), }),
ContextElement::ExitMatcherNode(ExitMatcherNode { ContextElement::ExitMatcherNode(ExitMatcherNode {
@ -52,10 +53,12 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
let (remaining, (children, _exit_contents)) = verify( let (remaining, (children, _exit_contents)) = verify(
many_till(standard_set_object_matcher, exit_matcher), many_till(standard_set_object_matcher, exit_matcher),
|(children, _exit_contents)| !children.is_empty(), |(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. // 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); let source = get_consumed(input, remaining);
Ok(( Ok((

View File

@ -81,7 +81,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, PlainList<'s>> { ) -> Res<OrgSource<'s>, PlainList<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let contexts = [ let contexts = [
ContextElement::Context("plain list"), ContextElement::Context("plain list"),
@ -99,7 +99,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
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 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: // 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)?; 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));
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

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

View File

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