End switches at the first unrecognized word in src blocks.
This commit is contained in:
parent
5f84cd974d
commit
386ad5091d
@ -0,0 +1,3 @@
|
||||
#+begin_example foo -n bar -k baz
|
||||
|
||||
#+end_example
|
@ -9,14 +9,12 @@ use nom::character::complete::space1;
|
||||
use nom::combinator::consumed;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::not;
|
||||
use nom::combinator::opt;
|
||||
use nom::combinator::peek;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::multi::separated_list1;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
@ -27,8 +25,9 @@ use crate::context::ContextElement;
|
||||
use crate::context::ContextMatcher;
|
||||
use crate::context::ExitClass;
|
||||
use crate::context::ExitMatcherNode;
|
||||
use crate::context::Matcher;
|
||||
use crate::context::RefContext;
|
||||
use crate::error::CustomError;
|
||||
use crate::error::MyError;
|
||||
use crate::error::Res;
|
||||
use crate::parser::object_parser::standard_set_object;
|
||||
use crate::parser::util::blank_line;
|
||||
@ -251,9 +250,8 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
|
||||
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
|
||||
let (remaining, _) = lesser_block_begin("src")(context, input)?;
|
||||
// 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(true))), |(_, language)| {
|
||||
language
|
||||
}))(remaining)?;
|
||||
let (remaining, language) =
|
||||
opt(map(tuple((space1, switch_word)), |(_, language)| language))(remaining)?;
|
||||
let (remaining, switches) = opt(src_switches)(remaining)?;
|
||||
let (remaining, parameters) = opt(map(tuple((space1, src_parameters)), |(_, parameters)| {
|
||||
parameters
|
||||
@ -430,14 +428,21 @@ fn _example_src_switches<'s>(
|
||||
let mut use_labels = true;
|
||||
let mut label_format = None;
|
||||
let mut saw_r = false;
|
||||
|
||||
let (remaining, words) = separated_list1(space1, switch_word(stop_at_parameters))(input)?;
|
||||
let (remaining, _post_spaces) = opt(tuple((space0, peek(line_ending))))(remaining)?;
|
||||
let source = input.get_until(remaining);
|
||||
|
||||
let mut matched_a_word = false;
|
||||
let mut remaining = input;
|
||||
let mut last_match_remaining = input;
|
||||
let mut state = SwitchState::Normal;
|
||||
for word in words {
|
||||
'outer: loop {
|
||||
let (remain, word) = opt(switch_word)(remaining)?;
|
||||
let word = match word {
|
||||
Some(word) => word,
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let normalized_word = Into::<&str>::into(word);
|
||||
|
||||
loop {
|
||||
match (&state, normalized_word) {
|
||||
(SwitchState::Normal, "-n") => {
|
||||
@ -510,11 +515,30 @@ fn _example_src_switches<'s>(
|
||||
label_format = Some(normalized_word);
|
||||
state = SwitchState::Normal;
|
||||
}
|
||||
(SwitchState::Normal, _) if stop_at_parameters => {
|
||||
break 'outer;
|
||||
}
|
||||
(SwitchState::Normal, _) => {}
|
||||
};
|
||||
matched_a_word = true;
|
||||
remaining = remain;
|
||||
last_match_remaining = remain;
|
||||
|
||||
let (remain, divider) = opt(space1)(remaining)?;
|
||||
if divider.is_none() {
|
||||
break 'outer;
|
||||
}
|
||||
remaining = remain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !matched_a_word {
|
||||
return Err(nom::Err::Error(CustomError::MyError(MyError("No words."))));
|
||||
}
|
||||
let remaining = last_match_remaining;
|
||||
|
||||
let (remaining, _post_spaces) = opt(tuple((space0, peek(line_ending))))(remaining)?;
|
||||
let source = input.get_until(remaining);
|
||||
|
||||
// Handle state that didn't get processed because we ran out of words.
|
||||
match state {
|
||||
@ -546,18 +570,8 @@ fn _example_src_switches<'s>(
|
||||
))
|
||||
}
|
||||
|
||||
fn switch_word<'s>(stop_at_parameters: bool) -> impl Matcher {
|
||||
move |input| _switch_word(input, stop_at_parameters)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn _switch_word<'s>(
|
||||
input: OrgSource<'s>,
|
||||
stop_at_parameters: bool,
|
||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
if stop_at_parameters {
|
||||
not(tag(":"))(input)?;
|
||||
}
|
||||
fn switch_word<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
alt((
|
||||
map(
|
||||
tuple((tag(r#"""#), is_not("\"\r\n"), tag(r#"""#))),
|
||||
|
Loading…
Reference in New Issue
Block a user