mirror of https://github.com/kdl-org/kdl-rs.git
feat(fmt): Add clear_fmt_recursive method (#45)
Fixes #46 When comparing two different `KdlNode` or `KdlDocument`, it's useful to have a "canonical" representation where formatting differences do not matter. `clear_fmt` removes all formatting from a `KdlNode`, but does not apply recursively, as a result, it doesn't create a canonical representation. `clear_fmt_recursive` solves this by applying `clear_fmt` recursively to the contents of the node.
This commit is contained in:
parent
b3ea4a87ee
commit
cd2d6e42b1
|
|
@ -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 = "
|
||||
|
|
|
|||
18
src/entry.rs
18
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);
|
||||
|
|
|
|||
32
src/node.rs
32
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<NodeKey>) -> 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()?;
|
||||
|
|
|
|||
Loading…
Reference in New Issue