Alternate Debug Formatting (#20)

* 🧪 `.alternate()` debug formatting

* 🔭 width relative spacing

* 🔪 precision + width

* 💅🔬 pretty int, float, tuple, struct tests

* updates from feedback

1. removed width calculation from iterator
2. added disclaimer to default calculations
3. added test for pretty printing empty grids
This commit is contained in:
Isaac Cloos 2022-08-19 16:10:20 -04:00 committed by GitHub
parent ef2882ab5f
commit 3c02c36274
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -772,8 +772,45 @@ impl<T: fmt::Debug> fmt::Debug for Grid<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[");
if self.cols > 0 {
for (i, _) in self.data.iter().enumerate().step_by(self.cols) {
write!(f, "{:?}", &self.data[i..(i + self.cols)]);
if f.alternate() {
write!(f, "\n");
/*
WARNING
Compound types becoming enormous as the entire `fmt::Debug` width is applied to each item individually.
For tuples and structs define padding and precision arguments manually to improve readability.
*/
let width = f.width().unwrap_or(
/*
Conditionally calculate the longest item by default.
*/
self.data
.iter()
.map(|i| format!("{i:?}").len())
.max()
.unwrap(),
);
let precision = f.precision().unwrap_or(2);
for (i, _) in self.data.iter().enumerate().step_by(self.cols) {
let mut row = self.data[i..(i + self.cols)].iter().peekable();
write!(f, " [");
while let Some(item) = row.next() {
write!(
f,
" {item:width$.precision$?}",
width = width,
precision = precision
);
if row.peek().is_some() {
write!(f, ",");
}
}
write!(f, "]\n");
}
} else {
for (i, _) in self.data.iter().enumerate().step_by(self.cols) {
write!(f, "{:?}", &self.data[i..(i + self.cols)]);
}
}
}
write!(f, "]")
@ -1152,6 +1189,121 @@ mod test {
assert_eq!(format!("{:?}", grid), "[[1, 2, 3][4, 5, 6][7, 8, 9]]");
}
#[test]
fn fmt_pretty_empty() {
let grid: Grid<f32> = grid![];
assert_eq!(format!("{:#?}", grid), "[]");
}
#[test]
fn fmt_pretty_int() {
let grid: Grid<u8> = grid![
[1,2,3]
[4,5,6]
[7,8,95]
];
let expected_output =
r#"[
[ 1, 2, 3]
[ 4, 5, 6]
[ 7, 8, 95]
]"#;
assert_eq!(format!("{:#?}", grid), expected_output);
let expected_output =
r#"[
[ 1, 2, 3]
[ 4, 5, 6]
[ 7, 8, 95]
]"#;
assert_eq!(format!("{:#3?}", grid), expected_output);
}
#[test]
fn fmt_pretty_float() {
let grid: Grid<f32> = grid![
[1.5,2.6,3.44]
[4.775,5.,6.]
[7.1,8.23444,95.55]
];
let expected_output =
r#"[
[ 1.5, 2.6, 3.4]
[ 4.8, 5.0, 6.0]
[ 7.1, 8.2, 95.6]
]"#;
assert_eq!(format!("{:#5.1?}", grid), expected_output);
let expected_output =
r#"[
[ 1.50000, 2.60000, 3.44000]
[ 4.77500, 5.00000, 6.00000]
[ 7.10000, 8.23444, 95.55000]
]"#;
assert_eq!(format!("{:#8.5?}", grid), expected_output);
}
#[test]
fn fmt_pretty_tuple() {
let grid: Grid<(i32, i32)> = grid![
[(5,66), (432, 55)]
[(80, 90), (5, 6)]
];
let expected_output =
r#"[
[ ( 5, 66), ( 432, 55)]
[ ( 80, 90), ( 5, 6)]
]"#;
assert_eq!(format!("{:#?}", grid), expected_output);
let expected_output =
r#"[
[ ( 5, 66), (432, 55)]
[ ( 80, 90), ( 5, 6)]
]"#;
assert_eq!(format!("{:#3?}", grid), expected_output);
}
#[test]
fn fmt_pretty_struct_derived() {
#[derive(Debug)]
struct Person {
_name: String,
_precise_age: f32,
}
impl Person {
fn new(name: &str, precise_age: f32) -> Self {
Person {
_name: name.into(),
_precise_age: precise_age,
}
}
}
let grid: Grid<Person> = grid![
[Person::new("Vic", 24.5), Person::new("Mr. Very Long Name", 1955.)]
[Person::new("Sam", 8.9995), Person::new("John Doe", 40.14)]
];
let expected_output =
r#"[
[ Person { _name: "Vic", _precise_age: 24.50000 }, Person { _name: "Mr. Very Long Name", _precise_age: 1955.00000 }]
[ Person { _name: "Sam", _precise_age: 8.99950 }, Person { _name: "John Doe", _precise_age: 40.14000 }]
]"#;
assert_eq!(format!("{:#5.5?}", grid), expected_output);
}
#[test]
fn clone() {
let grid = grid![[1, 2, 3][4, 5, 6]];