Parse the babel call.
This commit is contained in:
parent
343af41f78
commit
68e392811e
3
org_mode_samples/lesser_element/babel_call/empty.org
Normal file
3
org_mode_samples/lesser_element/babel_call/empty.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+call:
|
||||
|
||||
#+call:
|
@ -0,0 +1,3 @@
|
||||
#+call: foo[inside](bar="baz")[outside]
|
||||
|
||||
#+call: foo[](bar="baz")[]
|
@ -0,0 +1 @@
|
||||
#+call: foo(bar="baz"
|
@ -1 +1,7 @@
|
||||
#+call: foo(bar="baz")
|
||||
|
||||
#+call: lorem ipsum
|
||||
|
||||
#+call: dolar cat(dog)
|
||||
|
||||
#+call: (bat)
|
||||
|
3
org_mode_samples/lesser_element/babel_call/spaces.org
Normal file
3
org_mode_samples/lesser_element/babel_call/spaces.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+call: foo [inside] (bar="baz") [outside]
|
||||
|
||||
#+call: foo (bar="baz") [outside]
|
@ -2403,7 +2403,7 @@ fn compare_babel_call<'b, 's>(
|
||||
let mut this_status = DiffStatus::Good;
|
||||
let mut message = None;
|
||||
|
||||
// TODO: Compare :call :inside-header :arguments :end-header
|
||||
// TODO: Compare :inside-header :end-header
|
||||
|
||||
// TODO: Compare :caption
|
||||
// Compare name
|
||||
@ -2417,19 +2417,55 @@ fn compare_babel_call<'b, 's>(
|
||||
}
|
||||
|
||||
// Compare value
|
||||
let value = unquote(
|
||||
get_property(emacs, ":value")?
|
||||
.ok_or("Emacs keywords should have a :value")?
|
||||
.as_atom()?,
|
||||
)?;
|
||||
let value = get_property_quoted_string(emacs, ":value")?.unwrap_or(String::new());
|
||||
if value != rust.value {
|
||||
this_status = DiffStatus::Bad;
|
||||
message = Some(format!(
|
||||
"Mismatchs keyword values (emacs != rust) {:?} != {:?}",
|
||||
"Value mismatch (emacs != rust) {:?} != {:?}",
|
||||
value, rust.value
|
||||
))
|
||||
}
|
||||
|
||||
// Compare call
|
||||
let call = get_property_quoted_string(emacs, ":call")?;
|
||||
if call.as_ref().map(String::as_str) != rust.call {
|
||||
this_status = DiffStatus::Bad;
|
||||
message = Some(format!(
|
||||
"Call mismatch (emacs != rust) {:?} != {:?}",
|
||||
call, rust.call
|
||||
))
|
||||
}
|
||||
|
||||
// Compare arguments
|
||||
let arguments = get_property_quoted_string(emacs, ":arguments")?;
|
||||
if arguments.as_ref().map(String::as_str) != rust.arguments {
|
||||
this_status = DiffStatus::Bad;
|
||||
message = Some(format!(
|
||||
"Arguments mismatch (emacs != rust) {:?} != {:?}",
|
||||
arguments, rust.arguments
|
||||
))
|
||||
}
|
||||
|
||||
// Compare inside header
|
||||
let inside_header = get_property_quoted_string(emacs, ":inside-header")?;
|
||||
if inside_header.as_ref().map(String::as_str) != rust.inside_header {
|
||||
this_status = DiffStatus::Bad;
|
||||
message = Some(format!(
|
||||
"Inside header mismatch (emacs != rust) {:?} != {:?}",
|
||||
inside_header, rust.inside_header
|
||||
))
|
||||
}
|
||||
|
||||
// Compare end header
|
||||
let end_header = get_property_quoted_string(emacs, ":end-header")?;
|
||||
if end_header.as_ref().map(String::as_str) != rust.end_header {
|
||||
this_status = DiffStatus::Bad;
|
||||
message = Some(format!(
|
||||
"End header mismatch (emacs != rust) {:?} != {:?}",
|
||||
end_header, rust.end_header
|
||||
))
|
||||
}
|
||||
|
||||
Ok(DiffResult {
|
||||
status: this_status,
|
||||
name: rust.get_elisp_name(),
|
||||
|
@ -1,10 +1,14 @@
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
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;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
@ -12,6 +16,7 @@ use nom::InputTake;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::util::get_name;
|
||||
use super::util::start_of_line;
|
||||
use super::OrgSource;
|
||||
use crate::context::RefContext;
|
||||
use crate::error::Res;
|
||||
@ -26,8 +31,8 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
|
||||
) -> Res<OrgSource<'s>, BabelCall<'s>> {
|
||||
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
|
||||
|
||||
let (remaining, (consumed_input, (_, _, parsed_key, _))) =
|
||||
consumed(tuple((space0, tag("#+"), tag_no_case("call"), tag(":"))))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, _) = tuple((space0, tag("#+"), tag_no_case("call"), tag(":")))(input)?;
|
||||
|
||||
if let Ok((remaining, (_, line_break))) = tuple((space0, org_line_ending))(remaining) {
|
||||
let source = get_consumed(input, remaining);
|
||||
@ -37,13 +42,17 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
|
||||
source: Into::<&str>::into(source),
|
||||
name: get_name(&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, parsed_value) =
|
||||
recognize(many_till(anychar, peek(tuple((space0, org_line_ending)))))(remaining)?;
|
||||
let (remaining, (value, (call, inside_header, arguments, end_header))) =
|
||||
consumed(babel_call_value)(remaining)?;
|
||||
let (remaining, _ws) = tuple((space0, org_line_ending))(remaining)?;
|
||||
|
||||
let source = get_consumed(input, remaining);
|
||||
@ -53,7 +62,106 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
|
||||
BabelCall {
|
||||
source: Into::<&str>::into(source),
|
||||
name: get_name(&affiliated_keywords),
|
||||
value: Into::<&str>::into(parsed_value),
|
||||
value: Into::<&str>::into(value).trim_end(),
|
||||
call: call.map(Into::<&str>::into),
|
||||
inside_header: inside_header.map(Into::<&str>::into),
|
||||
arguments: arguments.map(Into::<&str>::into),
|
||||
end_header: end_header.map(Into::<&str>::into),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_value<'s>(
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<
|
||||
OrgSource<'s>,
|
||||
(
|
||||
Option<OrgSource<'s>>,
|
||||
Option<OrgSource<'s>>,
|
||||
Option<OrgSource<'s>>,
|
||||
Option<OrgSource<'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)?;
|
||||
Ok((
|
||||
remaining,
|
||||
(call, inside_header, arguments.flatten(), end_header),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn babel_call_call<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
verify(
|
||||
recognize(many_till(
|
||||
anychar,
|
||||
alt((
|
||||
peek(recognize(one_of("[("))),
|
||||
recognize(tuple((space0, org_line_ending))),
|
||||
)),
|
||||
)),
|
||||
|s| s.len() > 0,
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn inside_header<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
let (remaining, _) = tag("[")(input)?;
|
||||
|
||||
let contents_start = remaining;
|
||||
let (remaining, contents) = opt(recognize(many_till(
|
||||
anychar,
|
||||
alt((
|
||||
peek(recognize(one_of("]"))),
|
||||
recognize(tuple((space0, org_line_ending))),
|
||||
)),
|
||||
)))(remaining)?;
|
||||
let (remaining, _) = tag("]")(remaining)?;
|
||||
Ok((remaining, contents.unwrap_or(contents_start.take(0))))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn arguments<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
|
||||
let (remaining, _) = tag("(")(input)?;
|
||||
|
||||
let (remaining, contents) = opt(verify(
|
||||
recognize(many_till(
|
||||
anychar,
|
||||
alt((
|
||||
peek(recognize(one_of(")"))),
|
||||
recognize(tuple((space0, org_line_ending))),
|
||||
)),
|
||||
)),
|
||||
|s| s.len() > 0,
|
||||
))(remaining)?;
|
||||
let (remaining, _) = tag(")")(remaining)?;
|
||||
Ok((remaining, contents))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn end_header<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
let (remaining, _) = space0(input)?;
|
||||
verify(
|
||||
recognize(many_till(anychar, peek(tuple((space0, org_line_ending))))),
|
||||
|s| s.len() > 0,
|
||||
)(remaining)
|
||||
}
|
||||
|
||||
#[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_eq!(call, None);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,10 @@ pub struct BabelCall<'s> {
|
||||
pub source: &'s str,
|
||||
pub name: Option<&'s str>,
|
||||
pub value: &'s str,
|
||||
pub call: Option<&'s str>,
|
||||
pub inside_header: Option<&'s str>,
|
||||
pub arguments: Option<&'s str>,
|
||||
pub end_header: Option<&'s str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user