feat: support top-level properties drawer (#78)
This commit is contained in:
parent
2f31fd4b10
commit
9b8aec02a4
5 changed files with 31 additions and 9 deletions
|
|
@ -2,29 +2,35 @@ use rowan::ast::AstNode;
|
|||
|
||||
use crate::Org;
|
||||
|
||||
use super::{Document, Keyword, SyntaxKind};
|
||||
use super::{Document, Keyword};
|
||||
|
||||
impl Document {
|
||||
/// Returns an iterator of keywords in zeroth section
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::Document};
|
||||
///
|
||||
/// let org = Org::parse(r#"
|
||||
/// #+TITLE: hello
|
||||
/// #+TITLE: world
|
||||
/// #+DATE: tody
|
||||
/// #+AUTHOR: poi"#);
|
||||
/// #+DATE: today
|
||||
/// #+AUTHOR: poi
|
||||
/// * headline
|
||||
/// #+SOMETHING:"#);
|
||||
/// let doc = org.first_node::<Document>().unwrap();
|
||||
/// assert_eq!(doc.keywords().count(), 4);
|
||||
/// ```
|
||||
pub fn keywords(&self) -> impl Iterator<Item = Keyword> {
|
||||
self.syntax
|
||||
.first_child()
|
||||
.filter(|c| c.kind() == SyntaxKind::SECTION)
|
||||
self.section()
|
||||
.into_iter()
|
||||
.flat_map(|section| section.children().filter_map(Keyword::cast))
|
||||
.flat_map(|section| section.syntax.children().filter_map(Keyword::cast))
|
||||
}
|
||||
|
||||
/// Returns the value in `#+TITLE`
|
||||
/// Returns the value in top-level `#+TITLE`
|
||||
///
|
||||
/// Multiple `#+TITLE` are joined with spaces.
|
||||
///
|
||||
/// Returns `None` if file doesn't contain `#+TITLE`
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::Document};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const nodes = [
|
|||
first_child: [
|
||||
["section", "Section"],
|
||||
["first_headline", "Headline"],
|
||||
["properties", "PropertyDrawer"],
|
||||
],
|
||||
last_child: [["last_headline", "Headline"]],
|
||||
children: [["headlines", "Headline"]],
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ impl Document {
|
|||
pub fn first_headline(&self) -> Option<Headline> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn properties(&self) -> Option<PropertyDrawer> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn last_headline(&self) -> Option<Headline> {
|
||||
super::last_child(&self.syntax)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use nom::{combinator::opt, IResult};
|
|||
|
||||
use super::{
|
||||
combinator::{blank_lines, node, GreenElement},
|
||||
drawer::property_drawer_node,
|
||||
headline::{headline_node, section_node},
|
||||
input::Input,
|
||||
SyntaxKind::*,
|
||||
|
|
@ -16,8 +17,17 @@ pub fn document_node(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
}
|
||||
|
||||
fn document_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
||||
if input.is_empty() {
|
||||
return Ok((input, node(DOCUMENT, [])));
|
||||
}
|
||||
|
||||
let mut children = vec![];
|
||||
|
||||
let (input, property_drawer) = opt(property_drawer_node)(input)?;
|
||||
if let Some(property_drawer) = property_drawer {
|
||||
children.push(property_drawer);
|
||||
}
|
||||
|
||||
let (input, pre_blank) = blank_lines(input)?;
|
||||
|
||||
children.extend(pre_blank);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ fn drawer_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
fn property_drawer_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
||||
let (input, (begin, name)) = drawer_begin_node(input)?;
|
||||
|
||||
if name != "PROPERTIES" {
|
||||
if !name.eq_ignore_ascii_case("properties") {
|
||||
return Err(nom::Err::Error(()));
|
||||
}
|
||||
|
||||
|
|
@ -97,8 +97,10 @@ fn property_drawer_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
children.extend(&mut it);
|
||||
let (input, _) = it.finish()?;
|
||||
let (input, end) = drawer_end_node(input)?;
|
||||
let (input, post_blank) = blank_lines(input)?;
|
||||
|
||||
children.push(end);
|
||||
children.extend(post_blank);
|
||||
|
||||
Ok((input, node(PROPERTY_DRAWER, children)))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue