58 lines
1.5 KiB
Rust
58 lines
1.5 KiB
Rust
use crate::elements::Element;
|
|
use crate::parsers::{take_lines_till, take_until_eol};
|
|
|
|
use nom::{
|
|
bytes::complete::tag_no_case,
|
|
character::complete::{alpha1, space1},
|
|
IResult,
|
|
};
|
|
|
|
#[cfg_attr(test, derive(PartialEq))]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
|
#[derive(Debug)]
|
|
pub struct DynBlock<'a> {
|
|
pub block_name: &'a str,
|
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
|
pub arguments: Option<&'a str>,
|
|
}
|
|
|
|
impl DynBlock<'_> {
|
|
#[inline]
|
|
pub(crate) fn parse(input: &str) -> IResult<&str, (Element<'_>, &str)> {
|
|
let (input, _) = tag_no_case("#+BEGIN:")(input)?;
|
|
let (input, _) = space1(input)?;
|
|
let (input, name) = alpha1(input)?;
|
|
let (input, args) = take_until_eol(input)?;
|
|
|
|
let (input, contents) = take_lines_till(|line| line.eq_ignore_ascii_case("#+END:"))(input)?;
|
|
|
|
Ok((
|
|
input,
|
|
(
|
|
Element::DynBlock(DynBlock {
|
|
block_name: name,
|
|
arguments: if args.is_empty() { None } else { Some(args) },
|
|
}),
|
|
contents,
|
|
),
|
|
))
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn parse() {
|
|
// TODO: testing
|
|
assert_eq!(
|
|
DynBlock::parse("#+BEGIN: clocktable :scope file\nCONTENTS\n#+END:\n"),
|
|
Ok((
|
|
"",
|
|
(
|
|
Element::DynBlock(DynBlock {
|
|
block_name: "clocktable",
|
|
arguments: Some(":scope file"),
|
|
}),
|
|
"CONTENTS\n"
|
|
)
|
|
))
|
|
);
|
|
}
|