feat: Timestamp::time_delta & Headline::is_todo & Headline::is_done

This commit is contained in:
PoiScript 2024-04-09 15:58:55 +08:00
parent f918bf4ca6
commit f9d56cf899
No known key found for this signature in database
GPG key ID: 22C2B1249D99985E
2 changed files with 37 additions and 232 deletions

View file

@ -76,6 +76,30 @@ impl Headline {
})
}
/// ```rust
/// use orgize::{Org, ast::Headline};
///
/// let hdl = Org::parse("* TODO a").first_node::<Headline>().unwrap();
/// assert!(hdl.is_todo());
/// let hdl = Org::parse("* a").first_node::<Headline>().unwrap();
/// assert!(!hdl.is_todo());
/// ```
pub fn is_todo(&self) -> bool {
matches!(self.todo_type(), Some(TodoType::Todo))
}
/// ```rust
/// use orgize::{Org, ast::Headline};
///
/// let hdl = Org::parse("* DONE a").first_node::<Headline>().unwrap();
/// assert!(hdl.is_done());
/// let hdl = Org::parse("* a").first_node::<Headline>().unwrap();
/// assert!(!hdl.is_done());
/// ```
pub fn is_done(&self) -> bool {
matches!(self.todo_type(), Some(TodoType::Done))
}
/// Returns parsed title
///
/// ```rust
@ -250,235 +274,3 @@ impl Headline {
.flat_map(|x| x.children().filter_map(Clock::cast))
}
}
// pub enum DocumentOrHeadline {
// Document(Document),
// Headline(Headline),
// }
// impl From<Document> for DocumentOrHeadline {
// fn from(value: Document) -> Self {
// DocumentOrHeadline::Document(value)
// }
// }
// impl From<Headline> for DocumentOrHeadline {
// fn from(value: Headline) -> Self {
// DocumentOrHeadline::Headline(value)
// }
// }
// impl DocumentOrHeadline {
// pub fn section(&self) -> Option<Section> {
// match self {
// DocumentOrHeadline::Document(v) => v.section(),
// DocumentOrHeadline::Headline(v) => v.section(),
// }
// }
// }
// impl Org {
// /// set the title of this headline
// ///
// /// ```rust
// /// use orgize::Org;
// ///
// /// let mut org = Org::parse("* [#A]");
// /// let hdl = org.document().first_headline().unwrap();
// /// org.set_title(hdl, "world");
// /// assert_eq!(org.to_org(), "* [#A] world");
// /// let hdl = org.document().first_headline().unwrap();
// /// org.set_title(hdl, "world!");
// /// assert_eq!(org.to_org(), "* [#A] world!");
// /// ```
// pub fn set_title(&mut self, headline: Headline, title: &str) -> Option<HeadlineTitle> {
// let bytes = title.as_bytes();
// let title = match memchr(b'\n', bytes) {
// Some(i) if i > 0 && bytes[i] == b'\r' => &title[0..i - 1],
// Some(i) => &title[0..i],
// _ => title,
// };
// let new_title = node(HEADLINE_TITLE, object_nodes(self.create_input(title)));
// if let Some(title) = headline.title() {
// self.green = title.syntax.replace_with(new_title.into_node().unwrap());
// return Some(title);
// }
// let mut child: Vec<_> = headline
// .syntax
// .green()
// .children()
// .map(|ch| ch.to_owned())
// .collect();
// let index = support::child
// .iter()
// .enumerate()
// .filter_map(|(idx, it)| {
// if it.kind() == HEADLINE_STARS.into()
// || it.kind() == HEADLINE_KEYWORD.into()
// || it.kind() == HEADLINE_PRIORITY.into()
// {
// Some(idx + 1)
// } else {
// None
// }
// })
// .last()
// .unwrap_or_default();
// if index == child.len() {
// child.push(token(WHITESPACE, " "));
// child.push(new_title);
// } else if child[index].kind() != WHITESPACE.into() {
// child.insert(index, token(WHITESPACE, " "));
// child.insert(index + 1, new_title);
// } else {
// child.insert(index, new_title);
// }
// self.green = headline
// .syntax
// .replace_with(node(HEADLINE, child).into_node().unwrap());
// None
// }
// /// set the section of this document or headline
// ///
// /// ```rust
// /// use orgize::Org;
// ///
// /// let mut org = Org::parse("* hello");
// ///
// /// let hdl = org.document().first_headline().unwrap();
// /// org.set_section(hdl, "world");
// /// assert_eq!(org.to_org(), "* hello\nworld\n");
// ///
// /// let hdl = org.document().first_headline().unwrap();
// /// org.set_section(hdl, "world!");
// /// assert_eq!(org.to_org(), "* hello\nworld!\n");
// ///
// /// let doc = org.document();
// /// org.set_section(doc, "doc");
// /// assert_eq!(org.to_org(), "doc\n* hello\nworld!\n");
// /// ```
// pub fn set_section(
// &mut self,
// document_or_headline: impl Into<DocumentOrHeadline>,
// section: &str,
// ) -> Option<Section> {
// let document_or_headline = document_or_headline.into();
// let section = section_text(self.create_input(section)).ok()?.1.as_str();
// let section = if section.ends_with('\n') {
// section_node(self.create_input(section)).map(|(_, s)| s)
// } else {
// section_node(self.create_input(&format!("{section}\n"))).map(|(_, s)| s)
// }
// .ok()?;
// if let Some(old) = document_or_headline.section() {
// self.green = old.syntax.replace_with(section.into_node().unwrap());
// return Some(old);
// }
// match document_or_headline {
// DocumentOrHeadline::Document(document) => {
// let mut child: Vec<_> = document
// .syntax
// .green()
// .children()
// .map(|ch| ch.to_owned())
// .collect();
// let headline_idx = child.iter().position(|it| it.kind() == HEADLINE.into());
// if let Some(idx) = headline_idx {
// child.insert(idx, section);
// } else {
// child.push(section);
// }
// self.green = document
// .syntax
// .replace_with(GreenNode::new(DOCUMENT.into(), child));
// None
// }
// DocumentOrHeadline::Headline(headline) => {
// let mut child: Vec<_> = headline
// .syntax
// .green()
// .children()
// .map(|ch| ch.to_owned())
// .collect();
// let new_line_idx = support::child
// .iter()
// .position(|it| it.kind() == NEW_LINE.into());
// if let Some(idx) = new_line_idx {
// // add section *after* newline
// if idx < support::child.len() {
// support::child.insert(idx, section);
// } else {
// support::child.push(section);
// }
// } else {
// support::child.push(token(NEW_LINE, "\n"));
// support::child.push(section);
// }
// self.green = headline
// .syntax
// .replace_with(GreenNode::new(HEADLINE.into(), support::child));
// None
// }
// }
// }
// /// set the level of this headline
// ///
// /// ```rust
// /// use orgize::Org;
// ///
// /// let mut org = Org::parse("** 1\n** 2");
// ///
// /// let hdl = org.document().last_headline().unwrap();
// /// org.set_level(hdl, 1);
// /// assert_eq!(org.to_org(), "** 1\n* 2");
// ///
// /// let hdl = org.document().last_headline().unwrap();
// /// org.set_level(hdl, 3);
// /// assert_eq!(org.to_org(), "** 1\n* 2");
// /// ```
// pub fn set_level(&mut self, headline: Headline, level: usize) {
// if level == 0 {
// return;
// }
// let min_level_in_siblings = headline
// .syntax
// .siblings(rowan::Direction::Next)
// .chain(headline.syntax.siblings(rowan::Direction::Prev))
// .filter_map(Headline::cast)
// .filter_map(|headline| headline.level())
// .min()
// .unwrap_or(1);
// if level <= min_level_in_siblings {
// if let Some(stars) = headline.stars() {
// self.green = stars.replace_with(GreenToken::new(
// SyntaxKind::HEADLINE_STARS.into(),
// "*".repeat(level).as_str(),
// ));
// }
// }
// }
// }

View file

@ -285,4 +285,17 @@ impl Timestamp {
)?,
))
}
/// Returns chrono::TimeDelta between timestamp start and end
///
/// ```rust
/// use orgize::{Org, ast::Timestamp};
///
/// let ts = Org::parse("[2003-09-16 Tue 09:39-10:39]").first_node::<Timestamp>().unwrap();
/// assert_eq!(ts.time_delta().unwrap().num_hours(), 1);
/// ```
#[cfg(feature = "chrono")]
pub fn time_delta(&self) -> Option<chrono::TimeDelta> {
Some(self.end_to_chrono()? - self.start_to_chrono()?)
}
}