feat: Drawer::name and Headline::clocks

This commit is contained in:
PoiScript 2024-03-15 19:22:08 +08:00
parent b03233ca34
commit 42c47fa5b6
No known key found for this signature in database
GPG key ID: 22C2B1249D99985E
4 changed files with 72 additions and 6 deletions

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use super::{filter_token, SyntaxKind, Token};
use super::{filter_token, Drawer, SyntaxKind, Token};
use crate::ast::PropertyDrawer;
impl PropertyDrawer {
@ -62,3 +62,24 @@ impl PropertyDrawer {
self.iter().collect()
}
}
impl Drawer {
/// ```rust
/// use orgize::{Org, ast::Drawer};
///
/// let org = Org::parse("* Heading\n:LOGBOOK:\n:END:");
/// let drawer = org.first_node::<Drawer>().unwrap();
/// assert_eq!(drawer.name(), "LOGBOOK");
/// ```
pub fn name(&self) -> Token {
self.syntax
.first_child()
.and_then(|n| {
n.children_with_tokens()
.filter_map(|e| e.into_token())
.find(|e| e.kind() == SyntaxKind::TEXT)
})
.map(|t| Token(Some(t)))
.unwrap_or_default()
}
}

View file

@ -1,8 +1,8 @@
use rowan::NodeOrToken;
use rowan::{ast::AstNode, NodeOrToken};
use crate::{syntax::SyntaxKind, SyntaxElement};
use super::{filter_token, Headline, Timestamp, Token};
use super::{filter_token, Clock, Drawer, Headline, Section, Timestamp, Token};
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TodoType {
@ -216,6 +216,39 @@ impl Headline {
.find_map(filter_token(SyntaxKind::TEXT))
})
}
/// Returns an iterator of clock element affiliated with this headline
///
/// ```rust
/// use orgize::{Org, ast::Headline};
///
/// let org = Org::parse(r#"* TODO
/// foo
/// :LOGBOOK:
/// bar
/// CLOCK:
/// CLOCK: [2024-10-12]
/// baz
/// CLOCK: [2024-10-12]
/// [2024-10-12]
/// :END:
/// foo"#);
/// let hdl = org.first_node::<Headline>().unwrap();
/// assert_eq!(hdl.clocks().count(), 2);
/// ```
pub fn clocks(&self) -> impl Iterator<Item = Clock> {
self.syntax
.children()
.flat_map(Section::cast)
.flat_map(|x| x.syntax.children().filter_map(Drawer::cast))
.filter(|d| d.name().eq_ignore_ascii_case("LOGBOOK"))
.filter_map(|d| {
d.syntax
.children()
.find(|children| children.kind() == SyntaxKind::DRAWER_CONTENT)
})
.flat_map(|x| x.children().filter_map(Clock::cast))
}
}
// pub enum DocumentOrHeadline {

View file

@ -11,6 +11,7 @@ use super::{
blank_lines, colon_token, eol_or_eof, line_starts_iter, node, plus_token, trim_line_end,
GreenElement, NodeBuilder,
},
element::element_nodes,
input::Input,
SyntaxKind::*,
};
@ -68,7 +69,11 @@ fn drawer_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
let (input, post_blank) = blank_lines(input)?;
let mut children = vec![begin];
children.extend(pre_blank);
children.push(contents.text_token());
if !contents.is_empty() {
children.push(node(DRAWER_CONTENT, element_nodes(contents)?));
} else {
children.push(node(DRAWER_CONTENT, []));
}
children.push(end);
children.extend(post_blank);
@ -161,7 +166,13 @@ fn parse() {
TEXT@1..7 "DRAWER"
COLON@7..8 ":"
NEW_LINE@8..9 "\n"
TEXT@9..26 " :CUSTOM_ID: id\n"
DRAWER_CONTENT@9..26
PARAGRAPH@9..26
TEXT@9..18 " :CUSTOM"
SUBSCRIPT@18..21
UNDERSCORE@18..19 "_"
TEXT@19..21 "ID"
TEXT@21..26 ": id\n"
DRAWER_END@26..33
WHITESPACE@26..28 " "
COLON@28..29 ":"
@ -186,7 +197,7 @@ fn parse() {
COLON@7..8 ":"
NEW_LINE@8..9 "\n"
BLANK_LINE@9..10 "\n"
TEXT@10..10 ""
DRAWER_CONTENT@10..10
DRAWER_END@10..18
WHITESPACE@10..12 " "
COLON@12..13 ":"

View file

@ -152,6 +152,7 @@ pub enum SyntaxKind {
DRAWER,
DRAWER_BEGIN,
DRAWER_END,
DRAWER_CONTENT,
KEYWORD,
BABEL_CALL,
AFFILIATED_KEYWORD,