use crate::lang::{
elements::{Located, MathInline},
parsers::{
utils::{
capture, context, cow_str, locate, not_contains, take_line_until1,
},
IResult, Span,
},
};
use nom::{
character::complete::char,
combinator::{map, map_parser},
sequence::delimited,
};
#[inline]
pub fn math_inline(input: Span) -> IResult<Located<MathInline>> {
fn inner(input: Span) -> IResult<MathInline> {
map(
map_parser(
delimited(
char('$'),
not_contains("%%", take_line_until1("$")),
char('$'),
),
cow_str,
),
MathInline::new,
)(input)
}
context("Math Inline", locate(capture(inner)))(input)
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn math_inline_should_fail_if_input_empty() {
let input = Span::from("");
assert!(math_inline(input).is_err());
}
#[test]
fn math_inline_should_fail_if_does_not_start_with_dollar_sign() {
let input = Span::from(r"\sum_i a_i^2 = 1$");
assert!(math_inline(input).is_err());
}
#[test]
fn math_inline_should_fail_if_does_not_end_with_dollar_sign() {
let input = Span::from(r"$\sum_i a_i^2 = 1");
assert!(math_inline(input).is_err());
}
#[test]
fn math_inline_should_fail_if_end_is_on_next_line() {
let input = Span::from(indoc! {r"
$\sum_i a_i^2 = 1
$
"});
assert!(math_inline(input).is_err());
}
#[test]
fn math_inline_should_consume_all_text_between_dollar_signs_as_formula() {
let input = Span::from(r"$\sum_i a_i^2 = 1$");
let (input, m) = math_inline(input).unwrap();
assert!(input.is_empty(), "Math inline not consumed");
assert_eq!(m.as_str(), r"\sum_i a_i^2 = 1");
}
}