diff --git a/src/context/global_settings.rs b/src/context/global_settings.rs new file mode 100644 index 0000000..a3ad30e --- /dev/null +++ b/src/context/global_settings.rs @@ -0,0 +1,16 @@ +#[derive(Debug)] +pub struct GlobalSettings<'s> { + placeholder: Option<&'s str>, +} + +impl<'s> GlobalSettings<'s> { + pub fn new() -> Self { + GlobalSettings { placeholder: None } + } +} + +impl<'s> Default for GlobalSettings<'s> { + fn default() -> Self { + GlobalSettings::new() + } +} diff --git a/src/context/list.rs b/src/context/list.rs index 27bc998..c0c021f 100644 --- a/src/context/list.rs +++ b/src/context/list.rs @@ -27,6 +27,10 @@ impl<'parent, T> List<'parent, T> { pub fn iter(&self) -> Iter<'_, T> { Iter { next: Some(self) } } + + pub fn iter_list(&self) -> IterList<'_, T> { + Iter { next: Some(self) } + } } pub trait ListType<'parent, T> { @@ -64,3 +68,17 @@ impl<'a, T> Iterator for Iter<'a, T> { ret } } + +pub struct IterList<'a, T> { + next: Link<'a, T>, +} + +impl<'a, T> Iterator for IterList<'a, T> { + type Item = &'a List<'a, T>; + + fn next(&mut self) -> Option { + let ret = self.next; + self.next = self.next.map(|this| this.get_parent()).flatten(); + ret + } +} diff --git a/src/context/mod.rs b/src/context/mod.rs index 6738246..b1a7e6f 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -3,6 +3,7 @@ use crate::error::Res; use crate::parser::OrgSource; mod exiting; +mod global_settings; mod list; mod parser_context; mod parser_with_context; diff --git a/src/context/parser_context.rs b/src/context/parser_context.rs index 99f3b24..b8cdf60 100644 --- a/src/context/parser_context.rs +++ b/src/context/parser_context.rs @@ -1,6 +1,7 @@ use nom::combinator::eof; use super::exiting::ExitClass; +use super::global_settings::GlobalSettings; use super::list::List; use super::DynContextMatcher; use crate::error::Res; @@ -128,33 +129,16 @@ impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { } } -#[derive(Debug)] -pub struct GlobalSettings<'s> { - placeholder: Option<&'s str>, -} - -impl<'s> GlobalSettings<'s> { - pub fn new() -> Self { - GlobalSettings { placeholder: None } - } -} - -impl<'s> Default for GlobalSettings<'s> { - fn default() -> Self { - GlobalSettings::new() - } -} - #[derive(Debug)] pub struct Context<'r, 's> { global_settings: &'s GlobalSettings<'s>, - tree: List<'r, ContextElement<'r, 's>>, + tree: &'r List<'r, ContextElement<'r, 's>>, } impl<'r, 's> Context<'r, 's> { pub fn new( global_settings: &'s GlobalSettings<'s>, - tree: List<'r, ContextElement<'r, 's>>, + tree: &'r List<'r, ContextElement<'r, 's>>, ) -> Self { Self { global_settings, @@ -162,16 +146,6 @@ impl<'r, 's> Context<'r, 's> { } } - pub fn document_context(global_settings: &'s GlobalSettings<'s>) -> Self { - Context::new( - global_settings, - List::new(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: &document_end, - class: ExitClass::Document, - })), - ) - } - pub fn with_additional_node(&self, data: ContextElement<'r, 's>) -> Self { let new_tree = self.tree.push(data); Self { @@ -179,6 +153,24 @@ impl<'r, 's> Context<'r, 's> { tree: new_tree, } } + + pub fn iter(&self) -> super::list::Iter<'r, ContextElement<'r, 's>> { + self.tree.iter() + } + + pub fn iter_context(&self) -> Iter<'r, 's> { + Iter { + next: self.tree.iter_list(), + global_settings: self.global_settings, + } + } + + pub fn get_parent(&self) -> Option { + self.tree.get_parent().map(|parent_tree| Self { + global_settings: self.global_settings, + tree: parent_tree, + }) + } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] @@ -188,3 +180,27 @@ fn document_end<'r, 's>( ) -> Res, OrgSource<'s>> { eof(input) } + +pub struct Iter<'r, 's> { + global_settings: &'s GlobalSettings<'s>, + next: super::list::IterList<'r, ContextElement<'r, 's>>, +} + +impl<'r, 's> Iterator for Iter<'r, 's> { + type Item = Context<'r, 's>; + + fn next(&mut self) -> Option { + let next_tree = self.next.next(); + let ret = next_tree.map(|parent_tree| Context::new(self.global_settings, parent_tree)); + ret + } +} + +impl<'r, 's> ContextElement<'r, 's> { + pub fn document_context() -> Self { + Self::ExitMatcherNode(ExitMatcherNode { + exit_matcher: &document_end, + class: ExitClass::Document, + }) + } +} diff --git a/src/parser/timestamp.rs b/src/parser/timestamp.rs index d924330..fa1e408 100644 --- a/src/parser/timestamp.rs +++ b/src/parser/timestamp.rs @@ -399,10 +399,9 @@ fn time_range_rest_end<'r, 's>( input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // We pop off the most recent context element to get a context tree with just the active/inactive_time_rest_end exit matcher (removing this function from the exit matcher chain) because the 2nd time in the range does not end when a "-TIME" pattern is found. - let parent_node = context.iter().next().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None."); - let parent_tree = ContextTree::branch_from(parent_node); + let parent_node = context.get_parent().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None."); let exit_contents = - recognize(tuple((tag("-"), parser_with_context!(time)(&parent_tree))))(input); + recognize(tuple((tag("-"), parser_with_context!(time)(&parent_node))))(input); exit_contents } diff --git a/src/parser/token.rs b/src/parser/token.rs index bbf6d8e..ea9ea8f 100644 --- a/src/parser/token.rs +++ b/src/parser/token.rs @@ -1,10 +1,14 @@ use std::collections::VecDeque; -use super::Element; -use super::Object; -use super::PlainListItem; -use super::TableCell; -use super::TableRow; +use crate::types::Document; +use crate::types::DocumentElement; +use crate::types::Element; +use crate::types::Heading; +use crate::types::Object; +use crate::types::PlainListItem; +use crate::types::Section; +use crate::types::TableCell; +use crate::types::TableRow; pub enum Token<'r, 's> { Document(&'r Document<'s>), diff --git a/src/parser/util.rs b/src/parser/util.rs index d2d66b8..92a35ec 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -14,7 +14,9 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; @@ -35,7 +37,10 @@ pub fn in_section<'r, 's, 'x>(context: RefContext<'r, 's>, section_name: &'x str } /// Checks if we are currently an immediate child of the given section type -pub fn immediate_in_section<'r, 's, 'x>(context: RefContext<'r, 's>, section_name: &'x str) -> bool { +pub fn immediate_in_section<'r, 's, 'x>( + context: RefContext<'r, 's>, + section_name: &'x str, +) -> bool { for thing in context.iter() { match thing.get_data() { ContextElement::Context(name) if *name == section_name => return true, diff --git a/src/types/document.rs b/src/types/document.rs index faafbc2..957d7b9 100644 --- a/src/types/document.rs +++ b/src/types/document.rs @@ -1,3 +1,5 @@ +use super::Element; +use super::Object; use super::Source; #[derive(Debug)] diff --git a/src/types/element.rs b/src/types/element.rs index 5155189..c279657 100644 --- a/src/types/element.rs +++ b/src/types/element.rs @@ -19,6 +19,8 @@ use super::lesser_element::Planning; use super::lesser_element::SrcBlock; use super::lesser_element::VerseBlock; use super::Drawer; +use super::SetSource; +use super::Source; #[derive(Debug)] pub enum Element<'s> {