Switch to putting radio targets in the global settings instead of the context tree.
This commit is contained in:
		
							parent
							
								
									71180d19fb
								
							
						
					
					
						commit
						0ef141d65e
					
				| @ -1,16 +1,19 @@ | ||||
| #[derive(Debug)] | ||||
| pub struct GlobalSettings<'s> { | ||||
|     #[allow(dead_code)] | ||||
|     placeholder: Option<&'s str>, | ||||
| use crate::types::Object; | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct GlobalSettings<'g, 's> { | ||||
|     pub radio_targets: Vec<&'g Vec<Object<'s>>>, | ||||
| } | ||||
| 
 | ||||
| impl<'s> GlobalSettings<'s> { | ||||
| impl<'g, 's> GlobalSettings<'g, 's> { | ||||
|     pub fn new() -> Self { | ||||
|         GlobalSettings { placeholder: None } | ||||
|         GlobalSettings { | ||||
|             radio_targets: Vec::new(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'s> Default for GlobalSettings<'s> { | ||||
| impl<'g, 's> Default for GlobalSettings<'g, 's> { | ||||
|     fn default() -> Self { | ||||
|         GlobalSettings::new() | ||||
|     } | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| use std::marker::PhantomData; | ||||
| 
 | ||||
| use nom::combinator::eof; | ||||
| use nom::IResult; | ||||
| 
 | ||||
| @ -10,7 +12,6 @@ use crate::error::CustomError; | ||||
| use crate::error::MyError; | ||||
| use crate::error::Res; | ||||
| use crate::parser::OrgSource; | ||||
| use crate::types::Object; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum ContextElement<'r, 's> { | ||||
| @ -23,12 +24,8 @@ pub enum ContextElement<'r, 's> { | ||||
|     /// Indicates if elements should consume the whitespace after them.
 | ||||
|     ConsumeTrailingWhitespace(bool), | ||||
| 
 | ||||
|     /// The contents of a radio target.
 | ||||
|     ///
 | ||||
|     /// If any are found, this will force a 2nd parse through the
 | ||||
|     /// org-mode document since text needs to be re-parsed to look for
 | ||||
|     /// radio links matching the contents of radio targets.
 | ||||
|     RadioTarget(Vec<&'r Vec<Object<'s>>>), | ||||
|     /// This is just here to use the 's lifetime until I'm sure we can eliminate it from ContextElement.
 | ||||
|     Placeholder(PhantomData<&'s str>), | ||||
| } | ||||
| 
 | ||||
| pub struct ExitMatcherNode<'r> { | ||||
| @ -47,13 +44,13 @@ impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct Context<'g, 'r, 's> { | ||||
|     global_settings: &'g GlobalSettings<'g>, | ||||
|     global_settings: &'g GlobalSettings<'g, 's>, | ||||
|     tree: List<'r, &'r ContextElement<'r, 's>>, | ||||
| } | ||||
| 
 | ||||
| impl<'g, 'r, 's> Context<'g, 'r, 's> { | ||||
|     pub fn new( | ||||
|         global_settings: &'g GlobalSettings<'g>, | ||||
|         global_settings: &'g GlobalSettings<'g, 's>, | ||||
|         tree: List<'r, &'r ContextElement<'r, 's>>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
| @ -89,6 +86,17 @@ impl<'g, 'r, 's> Context<'g, 'r, 's> { | ||||
|         self.tree.get_data() | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_global_settings(&self) -> &'g GlobalSettings<'g, 's> { | ||||
|         self.global_settings | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_global_settings<'gg>(&self, new_settings: &'gg GlobalSettings<'gg, 's>) -> Context<'gg, 'r, 's> { | ||||
|         Context { | ||||
|             global_settings: new_settings, | ||||
|             tree: self.tree.clone(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] | ||||
|     pub fn check_exit_matcher( | ||||
|         &'r self, | ||||
| @ -145,7 +153,7 @@ fn document_end<'b, 'g, 'r, 's>( | ||||
| } | ||||
| 
 | ||||
| pub struct Iter<'g, 'r, 's> { | ||||
|     global_settings: &'g GlobalSettings<'g>, | ||||
|     global_settings: &'g GlobalSettings<'g, 's>, | ||||
|     next: super::list::IterList<'r, &'r ContextElement<'r, 's>>, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -95,8 +95,9 @@ fn document_org_source<'b, 'g, 'r, 's>( | ||||
|             .map(|rt| &rt.children) | ||||
|             .collect(); | ||||
|         if !all_radio_targets.is_empty() { | ||||
|             let parser_context = ContextElement::RadioTarget(all_radio_targets); | ||||
|             let parser_context = context.with_additional_node(&parser_context); | ||||
|             let mut new_global_settings = context.get_global_settings().clone(); | ||||
|             new_global_settings.radio_targets = all_radio_targets; | ||||
|             let parser_context = context.with_global_settings(&new_global_settings); | ||||
|             let (remaining, document) = _document(&parser_context, input) | ||||
|                 .map(|(rem, out)| (Into::<&str>::into(rem), out))?; | ||||
|             return Ok((remaining.into(), document)); | ||||
|  | ||||
| @ -27,14 +27,7 @@ pub fn radio_link<'b, 'g, 'r, 's>( | ||||
|     context: RefContext<'b, 'g, 'r, 's>, | ||||
|     input: OrgSource<'s>, | ||||
| ) -> Res<OrgSource<'s>, RadioLink<'s>> { | ||||
|     let radio_targets = context | ||||
|         .iter() | ||||
|         .filter_map(|context_element| match context_element { | ||||
|             ContextElement::RadioTarget(targets) => Some(targets), | ||||
|             _ => None, | ||||
|         }) | ||||
|         .flatten(); | ||||
|     for radio_target in radio_targets { | ||||
|     for radio_target in &context.get_global_settings().radio_targets { | ||||
|         let rematched_target = rematch_target(context, radio_target, input); | ||||
|         if let Ok((remaining, rematched_target)) = rematched_target { | ||||
|             let (remaining, _) = space0(remaining)?; | ||||
| @ -149,12 +142,14 @@ mod tests { | ||||
|     fn plain_text_radio_target() { | ||||
|         let input = OrgSource::new("foo bar baz"); | ||||
|         let radio_target_match = vec![Object::PlainText(PlainText { source: "bar" })]; | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let global_settings = { | ||||
|             let mut global_settings = GlobalSettings::default(); | ||||
|             global_settings.radio_targets = vec![&radio_target_match]; | ||||
|             global_settings | ||||
|         }; | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let document_context = ContextElement::RadioTarget(vec![&radio_target_match]); | ||||
|         let document_context = initial_context.with_additional_node(&document_context); | ||||
|         let paragraph_matcher = parser_with_context!(element(true))(&document_context); | ||||
|         let paragraph_matcher = parser_with_context!(element(true))(&initial_context); | ||||
|         let (remaining, first_paragraph) = paragraph_matcher(input).expect("Parse first paragraph"); | ||||
|         let first_paragraph = match first_paragraph { | ||||
|             Element::Paragraph(paragraph) => paragraph, | ||||
| @ -182,12 +177,14 @@ mod tests { | ||||
|             source: "*bar*", | ||||
|             children: vec![Object::PlainText(PlainText { source: "bar" })], | ||||
|         })]; | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let global_settings = { | ||||
|             let mut global_settings = GlobalSettings::default(); | ||||
|             global_settings.radio_targets = vec![&radio_target_match]; | ||||
|             global_settings | ||||
|         }; | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let document_context = ContextElement::RadioTarget(vec![&radio_target_match]); | ||||
|         let document_context = initial_context.with_additional_node(&document_context); | ||||
|         let paragraph_matcher = parser_with_context!(element(true))(&document_context); | ||||
|         let paragraph_matcher = parser_with_context!(element(true))(&initial_context); | ||||
|         let (remaining, first_paragraph) = | ||||
|             paragraph_matcher(input.into()).expect("Parse first paragraph"); | ||||
|         let first_paragraph = match first_paragraph { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander