Skip to main content

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}