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
|
/// Clears leading and trailing text (whitespace, comments). `KdlNode`s in
|
||||||
/// this document will be unaffected.
|
/// this document will be unaffected.
|
||||||
|
///
|
||||||
|
/// If you need to clear the `KdlNode`s, use [`Self::clear_fmt_recursive`].
|
||||||
pub fn clear_fmt(&mut self) {
|
pub fn clear_fmt(&mut self) {
|
||||||
self.leading = None;
|
self.leading = None;
|
||||||
self.trailing = 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
|
/// Auto-formats this Document, making everything nice while preserving
|
||||||
/// comments.
|
/// comments.
|
||||||
pub fn fmt(&mut self) {
|
pub fn fmt(&mut self) {
|
||||||
|
|
@ -265,6 +276,36 @@ mod test {
|
||||||
|
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn parsing() -> miette::Result<()> {
|
fn parsing() -> miette::Result<()> {
|
||||||
let src = "
|
let src = "
|
||||||
|
|
|
||||||
18
src/entry.rs
18
src/entry.rs
|
|
@ -101,6 +101,13 @@ impl KdlEntry {
|
||||||
pub fn clear_fmt(&mut self) {
|
pub fn clear_fmt(&mut self) {
|
||||||
self.leading = None;
|
self.leading = None;
|
||||||
self.trailing = 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`].
|
/// Gets the custom string representation for this KdlEntry's [`KdlValue`].
|
||||||
|
|
@ -188,6 +195,17 @@ impl FromStr for KdlEntry {
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn new() {
|
fn new() {
|
||||||
let entry = KdlEntry::new(42);
|
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
|
/// Clears leading and trailing text (whitespace, comments), as well as
|
||||||
/// the space before the children block, if any. Individual entries and
|
/// the space before the children block, if any. Individual entries and
|
||||||
/// their formatting will be preserved.
|
/// 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) {
|
pub fn clear_fmt(&mut self) {
|
||||||
self.leading = None;
|
self.leading = None;
|
||||||
self.trailing = None;
|
self.trailing = None;
|
||||||
self.before_children = 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
|
/// Fetches an entry by key. Number keys will look up arguments, strings
|
||||||
/// will look up properties.
|
/// will look up properties.
|
||||||
pub fn get(&self, key: impl Into<NodeKey>) -> Option<&KdlEntry> {
|
pub fn get(&self, key: impl Into<NodeKey>) -> Option<&KdlEntry> {
|
||||||
|
|
@ -509,6 +526,21 @@ impl KdlNode {
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn parsing() -> miette::Result<()> {
|
fn parsing() -> miette::Result<()> {
|
||||||
let node: KdlNode = "\n\t (\"ty\")\"node\" 0xDEADbeef;\n".parse()?;
|
let node: KdlNode = "\n\t (\"ty\")\"node\" 0xDEADbeef;\n".parse()?;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue