refactor: cleanup utils macros
This commit is contained in:
parent
346ebc83d7
commit
0b355b498c
18 changed files with 285 additions and 297 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use lines::Lines;
|
||||
use memchr::memchr2;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
|
|
@ -7,12 +8,14 @@ pub struct Block;
|
|||
impl Block {
|
||||
// return (name, args, contents-begin, contents-end, end)
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize, usize, usize)> {
|
||||
if src.len() < 17 || !src[0..8].eq_ignore_ascii_case("#+BEGIN_") {
|
||||
debug_assert!(src.starts_with("#+"));
|
||||
|
||||
if !src[2..8].eq_ignore_ascii_case("BEGIN_") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let name = until_while!(src, 8, |c| c == b' ' || c == b'\n', |c: u8| c
|
||||
.is_ascii_alphabetic())?;
|
||||
let name = memchr2(b' ', b'\n', src.as_bytes())
|
||||
.filter(|&i| src.as_bytes()[8..i].iter().all(|c| c.is_ascii_alphabetic()))?;
|
||||
let mut lines = Lines::new(src);
|
||||
let (pre_cont_end, cont_beg, _) = lines.next()?;
|
||||
let args = if pre_cont_end == name {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
use lines::Lines;
|
||||
use memchr::memchr2;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
pub struct DynBlock;
|
||||
|
|
@ -5,17 +8,26 @@ 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)> {
|
||||
if src.len() < 17 || !src[0..9].eq_ignore_ascii_case("#+BEGIN: ") {
|
||||
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 = until_while!(src, 9, |c| c == b' ' || c == b'\n', |c: u8| c
|
||||
.is_ascii_alphabetic())?;
|
||||
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()?;
|
||||
|
||||
let mut pos = 0;
|
||||
for line_end in lines!(src) {
|
||||
if src[pos..line_end].trim().eq_ignore_ascii_case("#+END:") {
|
||||
while let Some((cont_end, end, line)) = lines.next() {
|
||||
if line.trim().eq_ignore_ascii_case("#+END:") {
|
||||
return Some((
|
||||
&src[8..name].trim(),
|
||||
if name == args {
|
||||
|
|
@ -24,11 +36,11 @@ impl DynBlock {
|
|||
Some(&src[name..args].trim())
|
||||
},
|
||||
args,
|
||||
pos,
|
||||
line_end,
|
||||
pre_cont_end,
|
||||
end,
|
||||
));
|
||||
}
|
||||
pos = line_end;
|
||||
pre_cont_end = cont_end;
|
||||
}
|
||||
|
||||
None
|
||||
|
|
@ -45,6 +57,6 @@ CONTENTS
|
|||
#+END:
|
||||
"
|
||||
),
|
||||
Some(("clocktable", Some(":scope file"), 31, 41, 48))
|
||||
Some(("clocktable", Some(":scope file"), 31, 40, 48))
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,19 @@
|
|||
use memchr::memchr;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
pub struct FnDef;
|
||||
|
||||
#[inline]
|
||||
fn valid_label(ch: u8) -> bool {
|
||||
ch.is_ascii_alphanumeric() || ch == b'-' || ch == b'_'
|
||||
}
|
||||
|
||||
impl FnDef {
|
||||
pub fn parse(src: &str) -> Option<(&str, &str, usize)> {
|
||||
if cfg!(test) {
|
||||
starts_with!(src, "[fn:");
|
||||
}
|
||||
debug_assert!(src.starts_with("[fn:"));
|
||||
|
||||
let label = until_while!(src, 4, b']', valid_label)?;
|
||||
|
||||
if label == 4 {
|
||||
return None;
|
||||
}
|
||||
let label = memchr(b']', src.as_bytes()).filter(|&i| {
|
||||
i != 4
|
||||
&& src.as_bytes()[4..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-' || c == b'_')
|
||||
})?;
|
||||
|
||||
let end = eol!(src);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use memchr::{memchr, memchr2};
|
||||
|
||||
pub struct Keyword;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
|
|
@ -25,16 +27,18 @@ pub enum Key<'a> {
|
|||
impl Keyword {
|
||||
// return (key, value, offset)
|
||||
pub fn parse(src: &str) -> Option<(Key<'_>, &str, usize)> {
|
||||
if cfg!(test) {
|
||||
starts_with!(src, "#+");
|
||||
}
|
||||
debug_assert!(src.starts_with("#+"));
|
||||
|
||||
let key_end = until_while!(src, 2, |c| c == b':' || c == b'[', |c: u8| c
|
||||
.is_ascii_alphabetic()
|
||||
|| c == b'_')?;
|
||||
let bytes = src.as_bytes();
|
||||
let key_end = memchr2(b':', b'[', bytes).filter(|&i| {
|
||||
bytes[2..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphabetic() || c == b'_')
|
||||
})?;
|
||||
|
||||
let option = if src.as_bytes()[key_end] == b'[' {
|
||||
let option = until_while!(src, key_end, b']', |c: u8| c != b'\n')?;
|
||||
let option = if bytes[key_end] == b'[' {
|
||||
let option =
|
||||
memchr(b']', bytes).filter(|&i| bytes[key_end..i].iter().all(|&c| c != b'\n'))?;
|
||||
expect!(src, option + 1, b':')?;
|
||||
option + 1
|
||||
} else {
|
||||
|
|
@ -100,8 +104,6 @@ fn parse() {
|
|||
);
|
||||
assert!(Keyword::parse("#+KE Y: VALUE").is_none());
|
||||
assert!(Keyword::parse("#+ KEY: VALUE").is_none());
|
||||
assert!(Keyword::parse("# +KEY: VALUE").is_none());
|
||||
assert!(Keyword::parse(" #+KEY: VALUE").is_none());
|
||||
|
||||
assert_eq!(
|
||||
Keyword::parse("#+RESULTS:"),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl List {
|
|||
let i = bytes
|
||||
.iter()
|
||||
.position(|&c| !c.is_ascii_digit())
|
||||
.unwrap_or_else(|| src.len());
|
||||
.unwrap_or_else(|| src.len() - 1);
|
||||
let c = bytes[i];
|
||||
if !(c == b'.' || c == b')') {
|
||||
return (false, false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue