diff --git a/Cargo.toml b/Cargo.toml index 9f35dbc..9e28699 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,6 @@ keywords = ["orgmode","emacs","parser"] travis-ci = { repository = "PoiScript/orgize" } [dependencies] +bytecount = "0.5.1" jetscii = "0.4.3" memchr = "2" diff --git a/src/lib.rs b/src/lib.rs index 1b191a3..06c1e90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,5 +62,6 @@ pub mod headline; mod lines; pub mod objects; mod parser; +pub mod tools; pub use parser::{Event, Parser}; diff --git a/src/tools.rs b/src/tools.rs new file mode 100644 index 0000000..71eed53 --- /dev/null +++ b/src/tools.rs @@ -0,0 +1,44 @@ +use crate::elements::{fn_def, keyword, Key}; +use crate::headline::Headline; +use memchr::memchr; + +type Headlines<'a> = Vec>; +type Keywords<'a> = Vec<(Key<'a>, &'a str)>; +type Footnotes<'a> = Vec<&'a str>; + +pub fn metadata(src: &str) -> (Headlines<'_>, Keywords<'_>, Footnotes<'_>) { + let mut headlines = Vec::new(); + let mut keywords = Vec::new(); + let mut footnotes = Vec::new(); + + for line in src.lines().filter(|l| !l.is_empty()) { + if line.starts_with('*') { + let level = memchr(b' ', line.as_bytes()).unwrap_or_else(|| line.len()); + if line.as_bytes()[0..level].iter().all(|&c| c == b'*') { + headlines.push(Headline::parse(line).0) + } + } else if line.starts_with("#+") { + if let Some((key, value, _)) = keyword::parse(line) { + keywords.push((key, value)) + } + } else if line.starts_with("[fn:") { + if let Some((label, _, _)) = fn_def::parse(line) { + footnotes.push(label) + } + } + } + + (headlines, keywords, footnotes) +} + +pub fn toc(src: &str) -> Headlines<'_> { + metadata(src).0 +} + +pub fn keywords(src: &str) -> Keywords<'_> { + metadata(src).1 +} + +pub fn fn_def(src: &str) -> Footnotes<'_> { + metadata(src).2 +}