1 use once_cell::sync::Lazy;
2 use std::sync::{Arc, Mutex};
3
4 #[derive(Debug, Clone)]
5 pub struct TreeSymbols {
6 /// A vertical base of the tree (│)
7 pub continued: &'static str,
8
9 /// Symbol for joining the first branch in a group (├)
10 pub join_first: &'static str,
11
12 /// Symbol for joining the last branch in a group (└)
13 pub join_last: &'static str,
14
15 /// Symbol for joining a branch that is not first or last in its group (├)
16 pub join_inner: &'static str,
17
18 /// Symbol for joining a branch if it is the only one in its group (├)
19 pub join_only: &'static str,
20
21 /// A repeated branch token (─)
22 pub branch: &'static str,
23
24 /// End of a leaf (╼)
25 pub leaf: &'static str,
26
27 pub multiline_first: Option<&'static str>,
28 pub multiline_continued: Option<&'static str>,
29 }
30
31 #[derive(Debug, Clone)]
32 pub struct TreeConfig {
33 pub symbols: TreeSymbols,
34
35 /// Aside from the first branch, `indent` is equal to the number of spaces a child branch is
36 /// shifted from its parent.
37 pub indent: usize,
38
39 pub show_first_level: bool,
40 }
41 impl TreeSymbols {
new() -> Self42 pub fn new() -> Self {
43 Self {
44 continued: "│",
45 join_first: "├",
46 join_inner: "├",
47 join_last: "└",
48 join_only: "└",
49 branch: "─",
50 leaf: "╼ ",
51 multiline_first: None,
52 multiline_continued: None,
53 }
54 }
with_pipes() -> Self55 pub fn with_pipes() -> Self {
56 Self {
57 continued: "║",
58 join_first: "╠",
59 join_inner: "╠",
60 join_last: "╚",
61 join_only: "╚",
62 branch: "═",
63 leaf: "╼ ",
64 multiline_first: None,
65 multiline_continued: None,
66 }
67 }
with_thick() -> Self68 pub fn with_thick() -> Self {
69 Self {
70 continued: "┃",
71 join_first: "┣",
72 join_inner: "┣",
73 join_last: "┗",
74 join_only: "┗",
75 branch: "━",
76 leaf: "╼ ",
77 multiline_first: None,
78 multiline_continued: None,
79 }
80 }
with_rounded() -> Self81 pub fn with_rounded() -> Self {
82 Self {
83 continued: "│",
84 join_first: "├",
85 join_inner: "├",
86 join_last: "╰",
87 join_only: "╰",
88 branch: "─",
89 leaf: "╼ ",
90 multiline_first: None,
91 multiline_continued: None,
92 }
93 }
with_dashed() -> Self94 pub fn with_dashed() -> Self {
95 Self {
96 continued: "┊",
97 join_first: "┊",
98 join_inner: "┊",
99 join_last: "'",
100 join_only: "'",
101 branch: "╌",
102 leaf: "- ",
103 multiline_first: None,
104 multiline_continued: None,
105 }
106 }
107
continued(mut self, sym: &'static str) -> Self108 pub fn continued(mut self, sym: &'static str) -> Self {
109 self.continued = sym;
110 self
111 }
join_first(mut self, sym: &'static str) -> Self112 pub fn join_first(mut self, sym: &'static str) -> Self {
113 self.join_first = sym;
114 self
115 }
join_inner(mut self, sym: &'static str) -> Self116 pub fn join_inner(mut self, sym: &'static str) -> Self {
117 self.join_inner = sym;
118 self
119 }
join_last(mut self, sym: &'static str) -> Self120 pub fn join_last(mut self, sym: &'static str) -> Self {
121 self.join_last = sym;
122 self
123 }
join_only(mut self, sym: &'static str) -> Self124 pub fn join_only(mut self, sym: &'static str) -> Self {
125 self.join_only = sym;
126 self
127 }
128
branch(mut self, sym: &'static str) -> Self129 pub fn branch(mut self, sym: &'static str) -> Self {
130 self.branch = sym;
131 self
132 }
leaf(mut self, sym: &'static str) -> Self133 pub fn leaf(mut self, sym: &'static str) -> Self {
134 self.leaf = sym;
135 self
136 }
multiline_first(mut self, sym: &'static str) -> Self137 pub fn multiline_first(mut self, sym: &'static str) -> Self {
138 self.multiline_first = Some(sym);
139 self
140 }
multiline_continued(mut self, sym: &'static str) -> Self141 pub fn multiline_continued(mut self, sym: &'static str) -> Self {
142 self.multiline_continued = Some(sym);
143 self
144 }
145 }
146
147 impl TreeConfig {
new() -> Self148 pub fn new() -> Self {
149 Self {
150 symbols: TreeSymbols::new(),
151 indent: 2,
152 show_first_level: false,
153 }
154 }
with_symbols(symbols: TreeSymbols) -> Self155 pub fn with_symbols(symbols: TreeSymbols) -> Self {
156 Self {
157 symbols,
158 indent: 2,
159 show_first_level: false,
160 }
161 }
indent(mut self, x: usize) -> Self162 pub fn indent(mut self, x: usize) -> Self {
163 self.indent = x;
164 self
165 }
show_first_level(mut self) -> Self166 pub fn show_first_level(mut self) -> Self {
167 self.show_first_level = true;
168 self
169 }
hide_first_level(mut self) -> Self170 pub fn hide_first_level(mut self) -> Self {
171 self.show_first_level = false;
172 self
173 }
symbols(mut self, x: TreeSymbols) -> Self174 pub fn symbols(mut self, x: TreeSymbols) -> Self {
175 self.symbols = x;
176 self
177 }
178 }
179
180 impl Default for TreeSymbols {
default() -> Self181 fn default() -> Self {
182 tree_config_symbols()
183 }
184 }
185 impl Default for TreeConfig {
default() -> Self186 fn default() -> Self {
187 tree_config()
188 }
189 }
190
191 static DEFAULT_CONFIG: Lazy<Arc<Mutex<TreeConfig>>> =
192 Lazy::new(|| -> Arc<Mutex<TreeConfig>> { Arc::new(Mutex::new(TreeConfig::new())) });
193
194 /// Set the default tree config
set_tree_config(x: TreeConfig)195 pub fn set_tree_config(x: TreeConfig) {
196 *DEFAULT_CONFIG.lock().unwrap() = x;
197 }
198
199 /// The default tree config
tree_config() -> TreeConfig200 pub fn tree_config() -> TreeConfig {
201 DEFAULT_CONFIG.lock().unwrap().clone()
202 }
203
204 /// Set the default tree symbols config
set_tree_config_symbols(x: TreeSymbols)205 pub fn set_tree_config_symbols(x: TreeSymbols) {
206 DEFAULT_CONFIG.lock().unwrap().symbols = x;
207 }
208
209 /// The default tree symbols config
tree_config_symbols() -> TreeSymbols210 pub fn tree_config_symbols() -> TreeSymbols {
211 DEFAULT_CONFIG.lock().unwrap().symbols.clone()
212 }
213
214 /// The default tree symbols config
update_tree_config<F: FnMut(&mut TreeConfig)>(mut update: F)215 pub fn update_tree_config<F: FnMut(&mut TreeConfig)>(mut update: F) {
216 let mut x = DEFAULT_CONFIG.lock().unwrap();
217 update(&mut x);
218 }
219
220 /// The default tree symbols config
update_tree_config_symbols<F: FnMut(&mut TreeSymbols)>(mut update: F)221 pub fn update_tree_config_symbols<F: FnMut(&mut TreeSymbols)>(mut update: F) {
222 let mut x = DEFAULT_CONFIG.lock().unwrap();
223 update(&mut x.symbols);
224 }
225