orgize/src/elements/dyn_block.rs

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"
)
))
);
}