Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
use std::io::{stdout, Stdout, Write};
6
7
/// A struct that makes it easier to print out a pretty tree of data, which
8
/// can be visually scanned more easily.
9
pub struct PrintTree<W>
10
where
11
W: Write
12
{
13
/// The current level of recursion.
14
level: u32,
15
16
/// An item which is queued up, so that we can determine if we need
17
/// a mid-tree prefix or a branch ending prefix.
18
queued_item: Option<String>,
19
20
/// The sink to print to.
21
sink: W,
22
}
23
24
/// A trait that makes it easy to describe a pretty tree of data,
25
/// regardless of the printing destination, to either print it
26
/// directly to stdout, or serialize it as in the debugger
27
pub trait PrintTreePrinter {
28
fn new_level(&mut self, title: String);
29
fn end_level(&mut self);
30
fn add_item(&mut self, text: String);
31
}
32
33
impl PrintTree<Stdout> {
34
pub fn new(title: &str) -> Self {
35
PrintTree::new_with_sink(title, stdout())
36
}
37
}
38
39
impl<W> PrintTree<W>
40
where
41
W: Write
42
{
43
pub fn new_with_sink(title: &str, mut sink: W) -> Self {
44
writeln!(sink, "\u{250c} {}", title).unwrap();
45
PrintTree {
46
level: 1,
47
queued_item: None,
48
sink,
49
}
50
}
51
52
fn print_level_prefix(&mut self) {
53
for _ in 0 .. self.level {
54
write!(self.sink, "\u{2502} ").unwrap();
55
}
56
}
57
58
fn flush_queued_item(&mut self, prefix: &str) {
59
if let Some(queued_item) = self.queued_item.take() {
60
self.print_level_prefix();
61
writeln!(self.sink, "{} {}", prefix, queued_item).unwrap();
62
}
63
}
64
}
65
66
// The default `println!` based printer
67
impl<W> PrintTreePrinter for PrintTree<W>
68
where
69
W: Write
70
{
71
/// Descend one level in the tree with the given title.
72
fn new_level(&mut self, title: String) {
73
self.flush_queued_item("\u{251C}\u{2500}");
74
75
self.print_level_prefix();
76
writeln!(self.sink, "\u{251C}\u{2500} {}", title).unwrap();
77
78
self.level = self.level + 1;
79
}
80
81
/// Ascend one level in the tree.
82
fn end_level(&mut self) {
83
self.flush_queued_item("\u{2514}\u{2500}");
84
self.level = self.level - 1;
85
}
86
87
/// Add an item to the current level in the tree.
88
fn add_item(&mut self, text: String) {
89
self.flush_queued_item("\u{251C}\u{2500}");
90
self.queued_item = Some(text);
91
}
92
}
93
94
impl<W> Drop for PrintTree<W>
95
where
96
W: Write
97
{
98
fn drop(&mut self) {
99
self.flush_queued_item("\u{9492}\u{9472}");
100
}
101
}
102
103
pub trait PrintableTree {
104
fn print_with<T: PrintTreePrinter>(&self, pt: &mut T);
105
}