diff --git a/src/document.rs b/src/document.rs index f63bf17..2fd3cf1 100644 --- a/src/document.rs +++ b/src/document.rs @@ -180,11 +180,22 @@ impl KdlDocument { /// Clears leading and trailing text (whitespace, comments). `KdlNode`s in /// this document will be unaffected. + /// + /// If you need to clear the `KdlNode`s, use [`Self::clear_fmt_recursive`]. pub fn clear_fmt(&mut self) { self.leading = None; self.trailing = None; } + /// Clears leading and trailing text (whitespace, comments), also clearing + /// all the `KdlNode`s in the document. + pub fn clear_fmt_recursive(&mut self) { + self.clear_fmt(); + for node in self.nodes.iter_mut() { + node.clear_fmt_recursive(); + } + } + /// Auto-formats this Document, making everything nice while preserving /// comments. pub fn fmt(&mut self) { @@ -265,6 +276,36 @@ mod test { use super::*; + #[test] + fn canonical_clear_fmt() -> miette::Result<()> { + let left_src = r#" +// There is a node here +first_node /*with cool comments, too */ param=1.03e2 /-"commented" "argument" { + // With nested nodes too + nested 1 2 3 + nested_2 "hi" "world" // this one is cool +} +second_node param=153 { nested one=1 two=2; }"#; + let right_src = r#" +first_node param=103.0 "argument" { + // Different indentation, because + // Why not + nested 1 2 3 + nested_2 "hi" /* actually, "hello" */ "world" +} +// There is a node here +second_node /* This time, the comment is here */ param=153 { + nested one=1 two=2 +}"#; + let mut left_doc: KdlDocument = left_src.parse()?; + let mut right_doc: KdlDocument = right_src.parse()?; + assert_ne!(left_doc, right_doc); + left_doc.clear_fmt_recursive(); + right_doc.clear_fmt_recursive(); + assert_eq!(left_doc, right_doc); + Ok(()) + } + #[test] fn parsing() -> miette::Result<()> { let src = " diff --git a/src/entry.rs b/src/entry.rs index d2c7769..6b04f26 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -101,6 +101,13 @@ impl KdlEntry { pub fn clear_fmt(&mut self) { self.leading = None; self.trailing = None; + self.value_repr = None; + if let Some(ty) = &mut self.ty { + ty.clear_fmt(); + } + if let Some(name) = &mut self.name { + name.clear_fmt(); + } } /// Gets the custom string representation for this KdlEntry's [`KdlValue`]. @@ -188,6 +195,17 @@ impl FromStr for KdlEntry { mod test { use super::*; + #[test] + fn reset_value_repr() -> miette::Result<()> { + let mut left_entry: KdlEntry = " name=1.03e2".parse()?; + let mut right_entry: KdlEntry = " name=103.0".parse()?; + assert_ne!(left_entry, right_entry); + left_entry.clear_fmt(); + right_entry.clear_fmt(); + assert_eq!(left_entry, right_entry); + Ok(()) + } + #[test] fn new() { let entry = KdlEntry::new(42); diff --git a/src/node.rs b/src/node.rs index 0585465..1e15fef 100644 --- a/src/node.rs +++ b/src/node.rs @@ -119,12 +119,29 @@ impl KdlNode { /// Clears leading and trailing text (whitespace, comments), as well as /// the space before the children block, if any. Individual entries and /// their formatting will be preserved. + /// + /// If you want to clear formatting on all children and entries as well, + /// use [`Self::clear_fmt_recursive`]. pub fn clear_fmt(&mut self) { self.leading = None; self.trailing = None; self.before_children = None; } + /// Clears leading and trailing text (whitespace, comments), as well as + /// the space before the children block, if any. Individual entries and + /// children formatting will also be cleared. + pub fn clear_fmt_recursive(&mut self) { + self.clear_fmt(); + self.name.clear_fmt(); + if let Some(children) = &mut self.children { + children.clear_fmt_recursive(); + } + for entry in self.entries.iter_mut() { + entry.clear_fmt(); + } + } + /// Fetches an entry by key. Number keys will look up arguments, strings /// will look up properties. pub fn get(&self, key: impl Into) -> Option<&KdlEntry> { @@ -509,6 +526,21 @@ impl KdlNode { mod test { use super::*; + #[test] + fn canonical_clear_fmt() -> miette::Result<()> { + let mut left_node: KdlNode = r#"node /-"commented" param_name=103.000 { + // This is a nested node + nested 1 2 3 + }"# + .parse()?; + let mut right_node: KdlNode = "node param_name=103.0 { nested 1 2 3; }".parse()?; + assert_ne!(left_node, right_node); + left_node.clear_fmt_recursive(); + right_node.clear_fmt_recursive(); + assert_eq!(left_node, right_node); + Ok(()) + } + #[test] fn parsing() -> miette::Result<()> { let node: KdlNode = "\n\t (\"ty\")\"node\" 0xDEADbeef;\n".parse()?;