Skip to main content

servo_base/
print_tree.rs

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 https://mozilla.org/MPL/2.0/. */
4
5use std::fmt::Display;
6
7/// A struct that makes it easier to print out a pretty tree of data, which
8/// can be visually scanned more easily.
9pub struct PrintTree {
10    /// The current level of recursion.
11    level: u32,
12
13    /// An item which is queued up, so that we can determine if we need
14    /// a mid-tree prefix or a branch ending prefix.
15    queued_item: Option<String>,
16}
17
18impl PrintTree {
19    pub fn new(title: impl Display) -> PrintTree {
20        println!("\u{250c} {title}");
21        PrintTree {
22            level: 1,
23            queued_item: None,
24        }
25    }
26
27    /// Descend one level in the tree with the given title string.
28    pub fn new_level(&mut self, queued_title: String) {
29        self.flush_queued_item("\u{251C}\u{2500}");
30
31        self.print_level_prefix();
32
33        let items: Vec<&str> = queued_title.split('\n').collect();
34        println!("\u{251C}\u{2500} {}", items[0]);
35        for i in 1..items.len() {
36            self.print_level_child_indentation();
37            print!("{}", items[i]);
38            if i < items.len() {
39                println!();
40            }
41        }
42
43        self.level += 1;
44    }
45
46    /// Ascend one level in the tree.
47    pub fn end_level(&mut self) {
48        self.flush_queued_item("\u{2514}\u{2500}");
49        self.level -= 1;
50    }
51
52    /// Add an item to the current level in the tree.
53    pub fn add_item(&mut self, text: String) {
54        self.flush_queued_item("\u{251C}\u{2500}");
55        self.queued_item = Some(text);
56    }
57
58    fn print_level_prefix(&self) {
59        for _ in 0..self.level {
60            print!("\u{2502}  ");
61        }
62    }
63
64    fn print_level_child_indentation(&self) {
65        for _ in 0..(self.level + 1) {
66            print!("\u{2502}  ");
67        }
68        print!("{}", " ".repeat(7));
69    }
70
71    fn flush_queued_item(&mut self, prefix: &str) {
72        if let Some(queued_item) = self.queued_item.take() {
73            self.print_level_prefix();
74            let items: Vec<&str> = queued_item.split('\n').collect();
75            println!("{} {}", prefix, items[0]);
76            for i in 1..items.len() {
77                self.print_level_child_indentation();
78                print!("{}", items[i]);
79                if i < items.len() {
80                    println!();
81                }
82            }
83        }
84    }
85}
86
87impl Drop for PrintTree {
88    fn drop(&mut self) {
89        self.flush_queued_item("\u{2514}\u{2500}");
90    }
91}