Implement the new fields for babel call.
This commit is contained in:
parent
2e7db0f8bd
commit
68a220aa1c
@ -5,3 +5,5 @@
|
||||
#+call: dolar cat(dog)
|
||||
|
||||
#+call: (bat)
|
||||
|
||||
#+call:
|
||||
|
@ -4,7 +4,6 @@ use nom::bytes::complete::tag_no_case;
|
||||
use nom::character::complete::anychar;
|
||||
use nom::character::complete::one_of;
|
||||
use nom::character::complete::space0;
|
||||
use nom::combinator::consumed;
|
||||
use nom::combinator::opt;
|
||||
use nom::combinator::peek;
|
||||
use nom::combinator::recognize;
|
||||
@ -43,32 +42,10 @@ where
|
||||
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,
|
||||
BabelCall {
|
||||
source: Into::<&str>::into(source),
|
||||
affiliated_keywords: parse_affiliated_keywords(
|
||||
context.get_global_settings(),
|
||||
affiliated_keywords,
|
||||
),
|
||||
value: Into::<&str>::into(line_break.take(0)),
|
||||
call: None,
|
||||
inside_header: None,
|
||||
arguments: None,
|
||||
end_header: None,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let (remaining, _ws) = space0(remaining)?;
|
||||
let (remaining, (value, babel_call_value)) = consumed(babel_call_value)(remaining)?;
|
||||
let (remaining, _ws) = tuple((space0, org_line_ending))(remaining)?;
|
||||
let (remaining, babel_call_value) = babel_call_value(remaining)?;
|
||||
|
||||
let (remaining, _trailing_ws) =
|
||||
let (remaining, post_blank) =
|
||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||
let source = get_consumed(input, remaining);
|
||||
|
||||
@ -80,17 +57,22 @@ where
|
||||
context.get_global_settings(),
|
||||
affiliated_keywords,
|
||||
),
|
||||
value: Into::<&str>::into(value).trim_end(),
|
||||
value: Into::<&str>::into(babel_call_value.value),
|
||||
call: babel_call_value.call.map(Into::<&str>::into),
|
||||
inside_header: babel_call_value.inside_header.map(Into::<&str>::into),
|
||||
arguments: babel_call_value.arguments.map(Into::<&str>::into),
|
||||
end_header: babel_call_value.end_header.map(Into::<&str>::into),
|
||||
post_blank: post_blank.map(Into::<&str>::into),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BabelCallValue<'s> {
|
||||
/// The entire string to the right of "#+call: " without the trailing line break.
|
||||
value: OrgSource<'s>,
|
||||
|
||||
/// The function name which may contain a line break if there are no headers/arguments.
|
||||
call: Option<OrgSource<'s>>,
|
||||
inside_header: Option<OrgSource<'s>>,
|
||||
arguments: Option<OrgSource<'s>>,
|
||||
@ -99,13 +81,45 @@ struct BabelCallValue<'s> {
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_value<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, BabelCallValue<'s>> {
|
||||
let (remaining, call) = opt(babel_call_call)(input)?;
|
||||
let (remaining, inside_header) = opt(inside_header)(remaining)?;
|
||||
let (remaining, arguments) = opt(arguments)(remaining)?;
|
||||
let (remaining, end_header) = opt(end_header)(remaining)?;
|
||||
alt((
|
||||
babel_call_value_without_headers,
|
||||
babel_call_value_with_headers,
|
||||
))(input)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_value_without_headers<'s>(
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, BabelCallValue<'s>> {
|
||||
let (remaining, value) = babel_call_call_with_headers(input)?;
|
||||
let (remaining, _ws) = tuple((space0, org_line_ending))(remaining)?;
|
||||
let call = get_consumed(input, remaining);
|
||||
Ok((
|
||||
remaining,
|
||||
BabelCallValue {
|
||||
value,
|
||||
call: Some(call),
|
||||
inside_header: None,
|
||||
arguments: None,
|
||||
end_header: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_value_with_headers<'s>(
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, BabelCallValue<'s>> {
|
||||
let (remaining, call) = opt(babel_call_call_with_headers)(input)?;
|
||||
let (remaining, inside_header) = opt(inside_header)(remaining)?;
|
||||
let (remaining, arguments) = opt(arguments)(remaining)?;
|
||||
let (remaining, end_header) = opt(end_header)(remaining)?;
|
||||
let value = get_consumed(input, remaining);
|
||||
let (remaining, _ws) = tuple((space0, org_line_ending))(remaining)?;
|
||||
Ok((
|
||||
remaining,
|
||||
BabelCallValue {
|
||||
value,
|
||||
call,
|
||||
inside_header,
|
||||
arguments: arguments.flatten(),
|
||||
@ -115,14 +129,15 @@ fn babel_call_value<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, BabelCallVal
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_call<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
fn babel_call_call_with_headers<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
// When babel call contains no arguments or headers (for example: "#+call: lorem ipsum\n") then the trailing line break is part of the call. Otherwise, it is not.
|
||||
verify(
|
||||
recognize(many_till(
|
||||
anychar,
|
||||
alt((
|
||||
peek(recognize(one_of("[("))),
|
||||
peek(alt((
|
||||
recognize(one_of("[(")),
|
||||
recognize(tuple((space0, org_line_ending))),
|
||||
)),
|
||||
))),
|
||||
)),
|
||||
|s| s.len() > 0,
|
||||
)(input)
|
||||
@ -232,19 +247,3 @@ fn impl_balanced_bracket<
|
||||
};
|
||||
Ok((remaining, contents))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nom::combinator::opt;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn simple_call() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = OrgSource::new("()");
|
||||
let (remaining, call) = opt(babel_call_call)(input)?;
|
||||
assert_eq!(Into::<&str>::into(remaining), "()");
|
||||
assert!(call.is_none());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ pub struct BabelCall<'s> {
|
||||
pub inside_header: Option<&'s str>,
|
||||
pub arguments: Option<&'s str>,
|
||||
pub end_header: Option<&'s str>,
|
||||
pub post_blank: Option<&'s str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -438,11 +439,15 @@ impl<'s> StandardProperties<'s> for BabelCall<'s> {
|
||||
}
|
||||
|
||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||
todo!()
|
||||
None
|
||||
}
|
||||
|
||||
fn get_post_blank(&self) -> PostBlank {
|
||||
todo!()
|
||||
self.post_blank
|
||||
.map(|text| text.lines().count())
|
||||
.unwrap_or(0)
|
||||
.try_into()
|
||||
.expect("Too much post-blank to fit into a PostBlank.")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user