tree_display/graphics.rs
1//! Line characters used for drawing tree structures in the terminal.
2//!
3//! This module provides various line styles for tree rendering, from simple ASCII
4//! to Unicode box-drawing characters. You can customize the appearance of tree
5//! lines, corners, and connectors to match your preferred aesthetic.
6
7// ──── API ───────────────────────────────────────────────────────────────────────────────────────
8
9/// Character set used for drawing tree graphics in the terminal.
10///
11/// Each tree display uses a set of five characters to render the hierarchical
12/// structure. Different styles are available for ASCII-only terminals,
13/// Unicode-capable terminals, and various aesthetic preferences.
14///
15/// ## Example
16/// ```no_run
17/// use tree_display::Graphics;
18///
19/// // Use ASCII characters for maximum compatibility
20/// let ascii = Graphics::ASCII;
21///
22/// // Use modern Unicode box-drawing characters
23/// let light = Graphics::LIGHT;
24///
25/// // Customize individual characters
26/// let custom = Graphics::new()
27/// .vertical('│')
28/// .horizontal('─')
29/// .tip('└');
30/// ```
31#[non_exhaustive]
32#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
33pub struct Graphics {
34 /// Character for horizontal lines connecting to labels
35 pub horizontal: char,
36 /// Character for vertical lines connecting tree levels
37 pub vertical: char,
38 /// Character for branch junctions (middle child)
39 pub junction: char,
40 /// Character for the tip/end of a branch (last child)
41 pub tip: char,
42 /// Character for the end of the tree (root connector)
43 pub end: char,
44}
45
46// ──── Predefined themes ─────────────────────────────────────────────────────────────────────────
47
48impl Graphics {
49 /// Minimal graphics with no visible characters (spaces only).
50 ///
51 /// Uses ` ` for all characters, effectively disabling tree lines.
52 pub const BLANK: Self = Self::new().all(' ');
53
54 /// Pure ASCII characters (compatible with all terminals).
55 ///
56 /// Uses `-`, `|`, `+`, `-`, and `` ` `` for tree drawing.
57 pub const ASCII: Self = Self::new()
58 .horizontal('-')
59 .vertical('|')
60 .junction('+')
61 .tip('-')
62 .end('`');
63
64 /// Light-weight Unicode box-drawing characters.
65 ///
66 /// Uses `─`, `│`, `├`, `─`, and `└` for tree drawing.
67 pub const LIGHT: Self = Self::new()
68 .horizontal('─')
69 .vertical('│')
70 .junction('├')
71 .tip('─')
72 .end('└');
73
74 /// Light-weight Unicode box-drawing characters with dotted lines.
75 ///
76 /// Uses `╌`, `│`, `├`, `─`, and `└` for tree drawing.
77 pub const LIGHT_DOTTED: Self = Self::new()
78 .horizontal('╌')
79 .vertical('╎')
80 .junction('├')
81 .tip('─')
82 .end('└');
83
84 /// Light-weight Unicode box-drawing characters with rounded corners.
85 ///
86 /// Uses `─`, `│`, `├`, `─`, and `╰` for tree drawing.
87 pub const LIGHT_ROUNDED: Self = Self::new()
88 .horizontal('─')
89 .vertical('│')
90 .junction('├')
91 .tip('─')
92 .end('╰');
93
94 /// Light-weight Unicode box-drawing characters with dotted lines and rounded corners.
95 ///
96 /// Uses `╌`, `│`, `├`, `─`, and `╰` for tree drawing.
97 pub const LIGHT_DOTTED_ROUNDED: Self = Self::new()
98 .horizontal('╌')
99 .vertical('╎')
100 .junction('├')
101 .tip('─')
102 .end('╰');
103
104 /// Double-line Unicode box-drawing characters.
105 ///
106 /// Uses `═`, `║`, `╠`, `━`, and `╚` for tree drawing.
107 pub const DOUBLE: Self = Self::new()
108 .horizontal('═')
109 .vertical('║')
110 .junction('╠')
111 .tip('━')
112 .end('╚');
113
114 /// Heavy-weight Unicode box-drawing characters.
115 ///
116 /// Uses `━`, `┃`, `┣`, `━`, and `┗` for tree drawing.
117 pub const HEAVY: Self = Self::new()
118 .horizontal('━')
119 .vertical('┃')
120 .junction('┣')
121 .tip('━')
122 .end('┗');
123
124 /// Heavy-weight Unicode box-drawing characters with dotted lines.
125 ///
126 /// Uses `╍`, `╏`, `┣`, `━`, and `┗` for tree drawing.
127 pub const HEAVY_DOTTED: Self = Self::new()
128 .horizontal('╍')
129 .vertical('╏')
130 .junction('┣')
131 .tip('━')
132 .end('┗');
133}
134
135// ──── Utility ───────────────────────────────────────────────────────────────────────────────────
136
137impl Graphics {
138 /// Creates a new [`Graphics`] instance with `LIGHT` characters.
139 pub const fn new() -> Self {
140 Self {
141 horizontal: '─',
142 vertical: '│',
143 junction: '├',
144 tip: '─',
145 end: '└',
146 }
147 }
148
149 /// Sets the horizontal line character.
150 ///
151 /// This character is used for horizontal connections extending from vertical lines to labels.
152 pub const fn horizontal(mut self, c: char) -> Self {
153 self.horizontal = c;
154 self
155 }
156
157 /// Sets the vertical line character.
158 ///
159 /// This character is used for vertical lines that connect tree levels.
160 pub const fn vertical(mut self, c: char) -> Self {
161 self.vertical = c;
162 self
163 }
164
165 /// Sets the junction character.
166 ///
167 /// This character is used at branch junctions where horizontal and vertical lines meet.
168 /// It represents the "T-junction" where a branch splits.
169 pub const fn junction(mut self, c: char) -> Self {
170 self.junction = c;
171 self
172 }
173
174 /// Sets the tip character.
175 ///
176 /// This character is used for the tip/end of a branch (the last child).
177 pub const fn tip(mut self, c: char) -> Self {
178 self.tip = c;
179 self
180 }
181
182 /// Sets the end character.
183 ///
184 /// This character is used at the root of the tree or as the final
185 /// connector in the hierarchy. In some styles, it may be the same
186 /// as the tip character.
187 pub const fn end(mut self, c: char) -> Self {
188 self.end = c;
189 self
190 }
191
192 /// Sets all graphics characters to the same value.
193 ///
194 /// This is a convenience method for quickly creating a uniform style
195 /// where all characters are identical.
196 pub const fn all(mut self, c: char) -> Self {
197 self.horizontal = c;
198 self.vertical = c;
199 self.junction = c;
200 self.tip = c;
201 self.end = c;
202 self
203 }
204}
205
206impl Default for Graphics {
207 /// Creates a new [`Graphics`] instance with `LIGHT` characters.
208 fn default() -> Self {
209 Self::new()
210 }
211}