orgize/src/elements/dyn_block.rs
2019-02-07 23:38:17 +08:00

62 lines
1.6 KiB
Rust

use crate::lines::Lines;
use memchr::memchr2;
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug)]
pub struct DynBlock;
impl DynBlock {
// return (name, parameters, contents-begin, contents-end, end)
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize, usize, usize)> {
debug_assert!(src.starts_with("#+"));
if !src[2..9].eq_ignore_ascii_case("BEGIN: ") {
return None;
}
let bytes = src.as_bytes();
let args = eol!(src);
let name = memchr2(b' ', b'\n', &bytes[9..])
.map(|i| i + 9)
.filter(|&i| {
src.as_bytes()[9..i]
.iter()
.all(|&c| c.is_ascii_alphabetic())
})?;
let mut lines = Lines::new(src);
let (mut pre_cont_end, _, _) = lines.next()?;
for (cont_end, end, line) in lines {
if line.trim().eq_ignore_ascii_case("#+END:") {
return Some((
&src[8..name].trim(),
if name == args {
None
} else {
Some(&src[name..args].trim())
},
args,
pre_cont_end,
end,
));
}
pre_cont_end = cont_end;
}
None
}
}
#[test]
fn parse() {
// TODO: testing
assert_eq!(
DynBlock::parse(
r"#+BEGIN: clocktable :scope file
CONTENTS
#+END:
"
),
Some(("clocktable", Some(":scope file"), 31, 40, 48))
)
}