compare_properties table.
This commit is contained in:
		
							parent
							
								
									7af5359e00
								
							
						
					
					
						commit
						62815621e4
					
				| @ -1,3 +1,4 @@ | ||||
| use std::collections::BTreeSet; | ||||
| use std::fmt::Debug; | ||||
| use std::str::FromStr; | ||||
| 
 | ||||
| @ -208,6 +209,59 @@ pub(crate) fn compare_property_list_of_quoted_string< | ||||
|     Ok(ComparePropertiesResult::NoChange) | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn compare_property_set_of_quoted_string< | ||||
|     'a, | ||||
|     'b, | ||||
|     's, | ||||
|     'x, | ||||
|     R, | ||||
|     RV: AsRef<str> + std::fmt::Debug + Ord + 'a + ?Sized, | ||||
|     RI: Iterator<Item = &'a RV>, | ||||
|     RG: Fn(R) -> Option<RI>, | ||||
| >( | ||||
|     _source: &'s str, | ||||
|     emacs: &'b Token<'s>, | ||||
|     rust_node: R, | ||||
|     emacs_field: &'x str, | ||||
|     rust_value_getter: RG, | ||||
| ) -> Result<ComparePropertiesResult<'b, 's>, Box<dyn std::error::Error>> { | ||||
|     let value = get_property(emacs, emacs_field)? | ||||
|         .map(Token::as_list) | ||||
|         .map_or(Ok(None), |r| r.map(Some))?; | ||||
|     let empty = Vec::new(); | ||||
|     let value = value.unwrap_or(&empty); | ||||
|     let rust_value = rust_value_getter(rust_node); | ||||
|     let rust_value = if let Some(rust_value) = rust_value { | ||||
|         let slices: BTreeSet<&str> = rust_value.map(|rv| rv.as_ref()).collect(); | ||||
|         slices | ||||
|     } else { | ||||
|         BTreeSet::new() | ||||
|     }; | ||||
|     let value: Vec<&str> = value | ||||
|         .iter() | ||||
|         .map(|e| e.as_atom()) | ||||
|         .collect::<Result<Vec<_>, _>>()?; | ||||
|     let value: Vec<String> = value | ||||
|         .into_iter() | ||||
|         .map(unquote) | ||||
|         .collect::<Result<Vec<_>, _>>()?; | ||||
|     let value: BTreeSet<&str> = value.iter().map(|e| e.as_str()).collect(); | ||||
|     let mismatched: Vec<_> = value | ||||
|         .symmetric_difference(&rust_value) | ||||
|         .map(|val| *val) | ||||
|         .collect(); | ||||
|     if !mismatched.is_empty() { | ||||
|         let this_status = DiffStatus::Bad; | ||||
|         let message = Some(format!( | ||||
|             "{} mismatch. Mismatched values: {}", | ||||
|             emacs_field, | ||||
|             mismatched.join(", ") | ||||
|         )); | ||||
|         return Ok(ComparePropertiesResult::SelfChange(this_status, message)); | ||||
|     } | ||||
|     Ok(ComparePropertiesResult::NoChange) | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn compare_property_boolean<'b, 's, 'x, R, RG: Fn(R) -> bool>( | ||||
|     _source: &'s str, | ||||
|     emacs: &'b Token<'s>, | ||||
|  | ||||
| @ -12,6 +12,7 @@ use super::compare_field::compare_property_list_of_ast_nodes; | ||||
| use super::compare_field::compare_property_list_of_quoted_string; | ||||
| use super::compare_field::compare_property_numeric; | ||||
| use super::compare_field::compare_property_quoted_string; | ||||
| use super::compare_field::compare_property_set_of_quoted_string; | ||||
| use super::compare_field::compare_property_single_ast_node; | ||||
| use super::compare_field::compare_property_unquoted_atom; | ||||
| use super::elisp_fact::ElispFact; | ||||
| @ -1676,80 +1677,61 @@ fn compare_table<'b, 's>( | ||||
|     emacs: &'b Token<'s>, | ||||
|     rust: &'b Table<'s>, | ||||
| ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { | ||||
|     let children = emacs.as_list()?; | ||||
|     let mut child_status = Vec::new(); | ||||
|     let mut this_status = DiffStatus::Good; | ||||
|     let mut child_status = Vec::new(); | ||||
|     let mut message = None; | ||||
| 
 | ||||
|     // TODO: Compare :caption
 | ||||
|     // Compare name
 | ||||
|     let name = get_property_quoted_string(emacs, ":name")?; | ||||
|     if name.as_ref().map(String::as_str) != rust.name { | ||||
|         this_status = DiffStatus::Bad; | ||||
|         message = Some(format!( | ||||
|             "Name mismatch (emacs != rust) {:?} != {:?}", | ||||
|             name, rust.name | ||||
|         )); | ||||
|     } | ||||
|     compare_children( | ||||
|         source, | ||||
|         emacs, | ||||
|         &rust.children, | ||||
|         &mut child_status, | ||||
|         &mut this_status, | ||||
|         &mut message, | ||||
|     )?; | ||||
| 
 | ||||
|     // Compare formulas
 | ||||
|     //
 | ||||
|     // :tblfm is either nil or a list () filled with quoted strings containing the value for any tblfm keywords at the end of the table.
 | ||||
|     let emacs_formulas = get_property(emacs, ":tblfm")?; | ||||
|     if let Some(emacs_formulas) = emacs_formulas { | ||||
|         let emacs_formulas = emacs_formulas.as_list()?; | ||||
|         if emacs_formulas.len() != rust.formulas.len() { | ||||
|             this_status = DiffStatus::Bad; | ||||
|             message = Some(format!( | ||||
|                 "Formulas do not match (emacs != rust): {:?} != {:?}", | ||||
|                 emacs_formulas, rust.formulas | ||||
|             )) | ||||
|         } else { | ||||
|             let atoms = emacs_formulas | ||||
|                 .into_iter() | ||||
|                 .map(Token::as_atom) | ||||
|                 .collect::<Result<Vec<_>, _>>()?; | ||||
|             let unquoted = atoms | ||||
|                 .into_iter() | ||||
|                 .map(unquote) | ||||
|                 .collect::<Result<BTreeSet<_>, _>>()?; | ||||
|             for kw in &rust.formulas { | ||||
|                 if !unquoted.contains(kw.value) { | ||||
|                     this_status = DiffStatus::Bad; | ||||
|                     message = Some(format!("Could not find formula in emacs: {}", kw.value)) | ||||
|                 } | ||||
|     for diff in compare_properties!( | ||||
|         source, | ||||
|         emacs, | ||||
|         rust, | ||||
|         ( | ||||
|             EmacsField::Optional(":name"), | ||||
|             |r| r.name, | ||||
|             compare_property_quoted_string | ||||
|         ), | ||||
|         ( | ||||
|             EmacsField::Optional(":caption"), | ||||
|             compare_identity, | ||||
|             compare_noop | ||||
|         ), | ||||
|         ( | ||||
|             EmacsField::Required(":tblfm"), | ||||
|             |r| if r.formulas.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some(r.formulas.iter().map(|kw| kw.value)) | ||||
|             }, | ||||
|             compare_property_set_of_quoted_string | ||||
|         ), | ||||
|         ( | ||||
|             EmacsField::Optional(":type"), | ||||
|             |_| Some("org"), | ||||
|             compare_property_unquoted_atom | ||||
|         ), | ||||
|         ( | ||||
|             EmacsField::Required(":value"), | ||||
|             compare_identity, | ||||
|             compare_property_always_nil | ||||
|         ) | ||||
|     ) { | ||||
|         match diff { | ||||
|             ComparePropertiesResult::NoChange => {} | ||||
|             ComparePropertiesResult::SelfChange(new_status, new_message) => { | ||||
|                 this_status = new_status; | ||||
|                 message = new_message | ||||
|             } | ||||
|             ComparePropertiesResult::DiffEntry(diff_entry) => child_status.push(diff_entry), | ||||
|         } | ||||
|     } else { | ||||
|         if !rust.formulas.is_empty() { | ||||
|             this_status = DiffStatus::Bad; | ||||
|             message = Some(format!( | ||||
|                 "Formulas do not match (emacs != rust): {:?} != {:?}", | ||||
|                 emacs_formulas, rust.formulas | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Compare type
 | ||||
|     let table_type = get_property_unquoted_atom(emacs, ":type")?.expect("Table should have a type"); | ||||
|     if table_type != "org" { | ||||
|         this_status = DiffStatus::Bad; | ||||
|         message = Some(format!( | ||||
|             "Table type mismatch (emacs != rust) {:?} != {:?}", | ||||
|             table_type, "org" | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     // Compare value
 | ||||
|     let value = get_property(emacs, ":value")?; | ||||
|     if value.is_some() { | ||||
|         // I don't know what :value is for, but it seems to always be nil. This is here to alert me to value being non-nil so I can investigate.
 | ||||
|         this_status = DiffStatus::Bad; | ||||
|         message = Some(format!("Non-nil value {:?}", value)) | ||||
|     } | ||||
| 
 | ||||
|     for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { | ||||
|         child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); | ||||
|     } | ||||
| 
 | ||||
|     Ok(DiffResult { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander