Skip to content

Commit 45de3dd

Browse files
committed
prettier print with indentation object
1 parent b45c77c commit 45de3dd

File tree

3 files changed

+102
-18
lines changed

3 files changed

+102
-18
lines changed

src/display.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use std::fmt::Display;
2+
3+
/// Indentation token
4+
#[derive(Debug)]
5+
struct Token {
6+
/// Is followed by a brother
7+
siblings: bool,
8+
/// Is intermediate while printing children
9+
children: bool,
10+
}
11+
12+
impl ToString for Token {
13+
fn to_string(&self) -> String {
14+
let Token { siblings, children } = self;
15+
16+
match (siblings, children) {
17+
(true, true) => "│ ",
18+
(true, false) => "├── ",
19+
(false, true) => " ",
20+
(false, false) => "└── ",
21+
}
22+
.to_string()
23+
}
24+
}
25+
26+
impl Token {
27+
/// Create a new indentation token
28+
fn new(siblings: bool) -> Self {
29+
Token {
30+
siblings,
31+
children: false,
32+
}
33+
}
34+
35+
/// Set children flag before starting displaying children
36+
fn set_children(&mut self) {
37+
self.children = true;
38+
}
39+
}
40+
41+
/// Manages the state during the display operation
42+
#[derive(Debug)]
43+
pub struct Indentation {
44+
tokens: Vec<Token>,
45+
ignore_root: bool,
46+
}
47+
48+
impl Display for Indentation {
49+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50+
let first: usize = if self.ignore_root { 1 } else { 0 };
51+
52+
for token in &self.tokens[first..] {
53+
write!(f, "{}", token.to_string())?;
54+
}
55+
56+
Ok(())
57+
}
58+
}
59+
60+
impl Indentation {
61+
/// Creates a new indentation handler
62+
pub fn new(ignore_root: bool) -> Self {
63+
Indentation {
64+
tokens: Vec::new(),
65+
ignore_root,
66+
}
67+
}
68+
69+
/// Adds a new layer of indentation
70+
pub fn indent(&mut self, siblings: bool) -> &mut Self {
71+
// Setup children mode for previous tokens
72+
let len = self.tokens.len();
73+
if len > 0 {
74+
self.tokens[len - 1].set_children();
75+
}
76+
77+
self.tokens.push(Token::new(siblings));
78+
self
79+
}
80+
81+
/// Removes the last layer of indentation
82+
pub fn deindent(&mut self) -> &mut Self {
83+
self.tokens.pop();
84+
self
85+
}
86+
}

src/lib.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -719,36 +719,34 @@ impl<T: Debug> Debug for Tree<T> {
719719
}
720720
}
721721

722+
// Handles display
723+
mod display;
724+
722725
impl<T: Display> Display for Tree<T> {
723726
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
727+
use display::Indentation;
724728
use iter::Edge;
725729

726-
fn indent(f: &mut Formatter, level: usize) -> Result<(), fmt::Error> {
727-
for _ in 0..level {
728-
write!(f, " ")?;
729-
}
730-
Ok(())
731-
}
732-
733-
let mut level: usize = 0;
730+
let mut indent: Indentation = Indentation::new(true);
734731

735732
for edge in self.root().traverse() {
736733
match edge {
737734
Edge::Open(node) if node.has_children() => {
738-
indent(f, level)?;
739-
write!(f, "{}\n", node.value())?;
740-
level += 1;
735+
indent.indent(node.next_sibling().is_some());
736+
write!(f, "{}{}\n", indent.to_string(), node.value())?;
741737
}
742738
Edge::Open(node) if node.next_sibling().is_some() => {
743-
indent(f, level)?;
744-
write!(f, "{}\n", node.value())?;
739+
indent.indent(node.next_sibling().is_some());
740+
write!(f, "{}{}\n", indent.to_string(), node.value())?;
741+
indent.deindent();
745742
}
746743
Edge::Open(node) => {
747-
indent(f, level)?;
748-
write!(f, "{}\n", node.value())?;
744+
indent.indent(node.next_sibling().is_some());
745+
write!(f, "{}{}\n", indent.to_string(), node.value())?;
746+
indent.deindent();
749747
}
750748
Edge::Close(node) if node.has_children() => {
751-
level -= 1;
749+
indent.deindent();
752750
}
753751
_ => {}
754752
}

tests/tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ fn test_display() {
171171
};
172172

173173
let repr = format!("{tree}");
174-
let expected = "root\n a\n child 1\n b\n child 2\n";
174+
let expected = "root\n├── a\n └── child 1\n└── b\n └── child 2\n";
175175

176176
assert_eq!(repr, expected);
177177

@@ -184,7 +184,7 @@ fn test_display() {
184184
};
185185

186186
let repr = format!("{tree}");
187-
let expected = "root\n a\n b\n x\n y\n c\n";
187+
let expected = "root\n├── a\n├── b\n ├── x\n └── y\n└── c\n";
188188

189189
assert_eq!(repr, expected);
190190
}

0 commit comments

Comments
 (0)