flower_pot/
lib.rs

1
2#![warn(missing_docs)]
3
4//! Constants and simple functions for invoking ANSI control codes used for text-styling in terminals (including color codes). No support for cursor movement or any other control codes.
5//!
6//! This crate provides constant bindings for text-styling ANSI control codes like `BOLD` (bound to the string `\x1b[1m`) and `GREEN` (bound to `\x1b[32m`):
7//!
8//! ```
9//! use flower_pot::*;
10//!
11//! println!("{GREEN}ok{RESET}");           // prints a green "ok"
12//! println!("{BOLD}{RED}error!{RESET}");   // prints a bold, red "error!"
13//! println!("{BLUE_BG}cloud{RESET}");      // prints white text on a blue background
14//!
15//! // Note that you must print the RESET code after the end of
16//! // the text you want styled, or else all text printed to the
17//! // terminal after that point will also be styled that way,
18//! // including text outputted by other programs.
19//!
20//! ```
21//!
22//! It also provides functions to invoke the 8-bit color palette:
23//!
24//! ```
25//! use flower_pot::*;
26//!
27//! // Prints text in "palette-color #237" (often a shade of grey)
28//! // with a background color of "palette-color #214" (often a
29//! // shade of orange):
30//!
31//! println!("{}{}example text{RESET}", color_256(237), color_256_bg(214));
32//!
33//! ```
34//!
35//! And functions that invoke truecolor functionality for terminals that support it:
36//!
37//! ```
38//! use flower_pot::*;
39//!
40//! // Prints text in RGB color [127, 45, 68] with a background
41//! // color of RGB color [0, 255, 255]:
42//!
43//! println!("{}{}example text{RESET}", truecolor(127, 45, 68), truecolor_bg(0, 255, 255));
44//!
45//! ```
46//!
47//! The functions `color_256`, `color_256_bg`, `truecolor`, and `truecolor_bg` all return Strings.
48//!
49//! Note that not all terminals support all of the codes defined in this library. The basic workflow of ANSI control codes is that a program outputs sequences of special characters describing what it wants (such as "make the following text bold" or "make the following text green") to stdout, and then the terminal that the program is running in decides what to do with those characters. The codes themselves are reasonably well-standardized, but not every terminal understands all of them. Some terminals might ignore some codes, or might do weird things when you use them (such as displaying the text following the code incorrectly). This is a feature of the ANSI control code ecosystem, and not something a library can fix.
50//!
51//! Once you've outputted a control code, all text that follows it will be styled in the manner requested. If you want to go back to unstyled text, output the `RESET` code or one of the more specific style-resetting codes such as `NOT_UNDERLINED`.
52//!
53//! The list of control codes is taken from [the Wikipedia page on ANSI control codes](https://en.wikipedia.org/wiki/ANSI_escape_code). Codes which are not widely supported (as reported by Wikipedia) are marked as such below.
54//!
55//! The named colors covered by ANSI control codes are `BLACK`, `RED`, `GREEN`, `YELLOW`, `BLUE`, `MAGENTA`, `CYAN`, and `WHITE`, and these are available as foreground and background colors, along with "bright" versions which are also available as foreground and background colors. If you want shades of gray, you can try 8-bit colors in the range of **232** (darkest grey) to **255** (lightest grey) or use truecolor. Among the text-styling codes, I find `BOLD`, `DIM`, `ITALIC`, `UNDERLINE`, and `RESET` to be the most commonly useful.
56
57// Styles: 0-29.
58
59/// Unset all styles and return to default text formatting.
60pub const RESET:                    &'static str = "\x1b[0m";
61/// Make the following text bold.
62pub const BOLD:                     &'static str = "\x1b[1m";
63/// Make the following text dim.
64pub const DIM:                      &'static str = "\x1b[2m";
65/// Make the following text italic.
66pub const ITALIC:                   &'static str = "\x1b[3m";
67/// Underline the following text.
68pub const UNDERLINE:                &'static str = "\x1b[4m";
69/// Make the following text blink slowly.
70pub const SLOW_BLINK:               &'static str = "\x1b[5m";
71/// Make the following text blink quickly. Not widely supported according to Wikipedia.
72pub const RAPID_BLINK:              &'static str = "\x1b[6m";
73/// Swap the current foreground color and current background color for the following text.
74pub const INVERTED:                 &'static str = "\x1b[7m";
75/// Hide the following text. Not widely supported according to Wikipedia.
76pub const HIDDEN:                   &'static str = "\x1b[8m";
77/// Make the following text strikethrough. Not supported in Terminal.app according to Wikipedia.
78pub const STRIKETHROUGH:            &'static str = "\x1b[9m";
79/// Switch to the default font.
80pub const DEFAULT_FONT:             &'static str = "\x1b[10m";
81/// Switch to alternative font #1.
82pub const ALT_FONT_1:               &'static str = "\x1b[11m";
83/// Switch to alternative font #2.
84pub const ALT_FONT_2:               &'static str = "\x1b[12m";
85/// Switch to alternative font #3.
86pub const ALT_FONT_3:               &'static str = "\x1b[13m";
87/// Switch to alternative font #4.
88pub const ALT_FONT_4:               &'static str = "\x1b[14m";
89/// Switch to alternative font #5.
90pub const ALT_FONT_5:               &'static str = "\x1b[15m";
91/// Switch to alternative font #6.
92pub const ALT_FONT_6:               &'static str = "\x1b[16m";
93/// Switch to alternative font #7.
94pub const ALT_FONT_7:               &'static str = "\x1b[17m";
95/// Switch to alternative font #8.
96pub const ALT_FONT_8:               &'static str = "\x1b[18m";
97/// Switch to alternative font #9.
98pub const ALT_FONT_9:               &'static str = "\x1b[19m";
99/// Switch to Fraktur font. Rarely supported according to Wikipedia.
100pub const FRAKTUR:                  &'static str = "\x1b[20m";
101/// Double-underline the following text. **WARNING:** this constant contains the exact same control
102/// code as the constant `NOT_BOLD`, because different terminals interpret the code to mean
103/// different things. If you use either constant, be aware that your text may be rendered
104/// differently by different terminals.
105pub const DOUBLE_UNDERLINE:         &'static str = "\x1b[21m";
106/// Make the following text not bold. **WARNING:** this constant contains the exact same control
107/// code as the constant `DOUBLE_UNDERLINE`, because different terminals interpret the code to mean
108/// different things. If you use either constant, be aware that your text may be rendered
109/// differently by different terminals.
110pub const NOT_BOLD:                 &'static str = "\x1b[21m";
111/// Return to ordinary intensity (neither bold nor dim) for the following text.
112pub const NORMAL_INTENSITY:         &'static str = "\x1b[22m";
113/// Make the following text neither bold nor italic.
114pub const NEITHER_BOLD_NOR_ITALIC:  &'static str = "\x1b[23m";
115/// Make the following text not underlined.
116pub const NOT_UNDERLINED:           &'static str = "\x1b[24m";
117/// Make the following text not blink.
118pub const NOT_BLINKING:             &'static str = "\x1b[25m";
119/// Use a font with proportional spacing (i.e., a non-monospace font) for the following text.
120/// Rarely supported according to Wikipedia.
121pub const PROPORTIONAL_SPACING:     &'static str = "\x1b[26m";
122/// Unswap the foreground and background colors for the following text.
123pub const NOT_INVERTED:             &'static str = "\x1b[27m";
124/// Make the following text not hidden.
125pub const NOT_HIDDEN:               &'static str = "\x1b[28m";
126/// Make the following text not strikethrough.
127pub const NOT_STRIKETHROUGH:        &'static str = "\x1b[29m";
128
129/// Set forground color to black for the following text.
130pub const BLACK:                    &'static str = "\x1b[30m";
131/// Set foreground color to red for the following text.
132pub const RED:                      &'static str = "\x1b[31m";
133/// Set foreground color to green for the following text.
134pub const GREEN:                    &'static str = "\x1b[32m";
135/// Set foreground color to yellow for the following text.
136pub const YELLOW:                   &'static str = "\x1b[33m";
137/// Set foreground color to blue for the following text.
138pub const BLUE:                     &'static str = "\x1b[34m";
139/// Set foreground color to magenta for the following text.
140pub const MAGENTA:                  &'static str = "\x1b[35m";
141/// Set foreground color to cyan for the following text.
142pub const CYAN:                     &'static str = "\x1b[36m";
143/// Set foreground color to white for the following text.
144pub const WHITE:                    &'static str = "\x1b[37m";
145
146/// Set the foreground color for the following text to the *n*th color in the 256-color palette. Commonly, the set of 256 available colors consists of the 8 named foreground colors, the 8 bright versions of these colors, a 6×6×6 RGB cube (for a total of 216 colors distributed evenly across RGB-space), and then a scale of 24 shades of gray. Different terminals may differ in what colors they provide here.
147
148pub fn color_256(n: u8) -> String {
149    format!("\x1b[38;5;{n}m")
150}
151
152/// Set the foreground color to the RGB value (r, g, b). Not supported on all terminals. Terminals which do support this feature are called "truecolor terminals".
153
154pub fn truecolor(r: u8, g: u8, b: u8) -> String {
155    format!("\x1b[38;2;{r};{g};{b}m")
156}
157
158/// Return to the default foreground color for the following text.
159pub const DEFAULT:                  &'static str = "\x1b[39m";
160
161/// Set background color to black for the following text.
162pub const BLACK_BG:                 &'static str = "\x1b[40m";
163/// Set background color to red for the following text.
164pub const RED_BG:                   &'static str = "\x1b[41m";
165/// Set background color to green for the following text.
166pub const GREEN_BG:                 &'static str = "\x1b[42m";
167/// Set background color to yellow for the following text.
168pub const YELLOW_BG:                &'static str = "\x1b[43m";
169/// Set background color to blue for the following text.
170pub const BLUE_BG:                  &'static str = "\x1b[44m";
171/// Set background color to magenta for the following text.
172pub const MAGENTA_BG:               &'static str = "\x1b[45m";
173/// Set background color to cyan for the following text.
174pub const CYAN_BG:                  &'static str = "\x1b[46m";
175/// Set background color to white for the following text.
176pub const WHITE_BG:                 &'static str = "\x1b[47m";
177
178/// Set the background color for the following text to the *n*th color in the 256-color palette. Commonly, the set of 256 available colors consists of the 8 named background colors, the 8 bright versions of these colors, a 6×6×6 RGB cube (for a total of 216 colors distributed evenly across RGB-space), and then a scale of 24 shades of gray. Different terminals may differ in what colors they provide here.
179
180pub fn color_256_bg(n: u8) -> String {
181    format!("\x1b[48;5;{n}m")
182}
183
184/// Set the background color to the RGB value (r, g, b). Not supported on all terminals. Terminals which do support this feature are called "truecolor terminals".
185
186pub fn truecolor_bg(r: u8, g: u8, b: u8) -> String {
187    format!("\x1b[48;2;{r};{g};{b}m")
188}
189
190/// Return to the default background color for the following text.
191pub const DEFAULT_BG:               &'static str = "\x1b[49m";
192
193/// Return to a non-proportionally spaced font for the following text. Rarely meaningful because
194/// the `PROPORTIONAL_SPACING` control code is rarely supported to begin with.
195pub const NO_PROPORTIONAL_SPACING:  &'static str = "\x1b[50m";
196/// Frame the following text.
197pub const FRAMED:                   &'static str = "\x1b[51m";
198/// Encircle the following text.
199pub const ENCIRCLED:                &'static str = "\x1b[52m";
200/// Add an overline to the following text.
201pub const OVERLINE:                 &'static str = "\x1b[53m";
202/// Make the following text neither framed nor encircled.
203pub const NEITHER_FRAMED_NOR_ENCIRCLED:
204                                    &'static str = "\x1b[54m";
205/// Make the following text not overlined.
206pub const NOT_OVERLINED:            &'static str = "\x1b[55m";
207
208/// Set the foreground color to bright black for the following text.
209pub const BRIGHT_BLACK:             &'static str = "\x1b[90m";
210/// Set the foreground color to bright red for the following text.
211pub const BRIGHT_RED:               &'static str = "\x1b[91m";
212/// Set the foreground color to bright green for the following text.
213pub const BRIGHT_GREEN:             &'static str = "\x1b[92m";
214/// Set the foreground color to bright yellow for the following text.
215pub const BRIGHT_YELLOW:            &'static str = "\x1b[93m";
216/// Set the foreground color to bright blue for the following text.
217pub const BRIGHT_BLUE:              &'static str = "\x1b[94m";
218/// Set the foreground color to bright magenta for the following text.
219pub const BRIGHT_MAGENTA:           &'static str = "\x1b[95m";
220/// Set the foreground color to bright cyan for the following text.
221pub const BRIGHT_CYAN:              &'static str = "\x1b[96m";
222/// Set the foreground color to bright white for the following text.
223pub const BRIGHT_WHITE:             &'static str = "\x1b[97m";
224
225/// Set the background color to bright black for the following text.
226pub const BRIGHT_BLACK_BG:          &'static str = "\x1b[100m";
227/// Set the background color to bright red for the following text.
228pub const BRIGHT_RED_BG:            &'static str = "\x1b[101m";
229/// Set the background color to bright green for the following text.
230pub const BRIGHT_GREEN_BG:          &'static str = "\x1b[102m";
231/// Set the background color to bright yellow for the following text.
232pub const BRIGHT_YELLOW_BG:         &'static str = "\x1b[103m";
233/// Set the background color to bright blue for the following text.
234pub const BRIGHT_BLUE_BG:           &'static str = "\x1b[104m";
235/// Set the background color to bright magenta for the following text.
236pub const BRIGHT_MAGENTA_BG:        &'static str = "\x1b[105m";
237/// Set the background color to bright cyan for the following text.
238pub const BRIGHT_CYAN_BG:           &'static str = "\x1b[106m";
239/// Set the background color to bright white for the following text.
240pub const BRIGHT_WHITE_BG:          &'static str = "\x1b[107m";
241
242// Test (requires manual inspection of outputs).
243
244#[cfg(test)]
245mod tests {
246    use super::*;
247
248    #[test]
249    fn print_and_verify_visually() {
250        println!();
251        println!("{GREEN}green{RESET}");
252        println!("{BOLD}{RED}BOLD RED{RESET}");
253        println!("normal {WHITE}white {BRIGHT_WHITE}bright white{RESET}");
254        println!("{BLUE}blue {BRIGHT_BLUE}bright blue{RESET}");
255        println!("normal {ITALIC}italic {BOLD}and bold {UNDERLINE}and underline{RESET}");
256        println!("normal {DOUBLE_UNDERLINE}double underline{RESET}");
257        println!("normal {ENCIRCLED}encircled{RESET}");
258        println!("normal {FRAMED}framed{RESET}");
259        println!("normal {OVERLINE}overline{RESET}");
260
261        println!(
262            "{}g{}r{}e{}y{}s{}c{}a{}l{}e{} {}c{}o{}l{}o{}r{}s{}",
263            color_256(232),
264            color_256(235),
265            color_256(238),
266            color_256(241),
267            color_256(244),
268            color_256(247),
269            color_256(250),
270            color_256(253),
271            color_256(255),
272            RESET,
273            color_256_bg(255),
274            color_256_bg(251),
275            color_256_bg(247),
276            color_256_bg(243),
277            color_256_bg(239),
278            color_256_bg(235),
279            RESET,
280        );
281
282        println!(
283            "{}r{}a{}i{}n{}b{}o{}w{}i{}c{} {}c{}o{}l{}o{}r{}s{}",
284            color_256(132),
285            color_256(135),
286            color_256(138),
287            color_256(141),
288            color_256(144),
289            color_256(147),
290            color_256(150),
291            color_256(153),
292            color_256(155),
293            RESET,
294            color_256_bg(155),
295            color_256_bg(151),
296            color_256_bg(147),
297            color_256_bg(143),
298            color_256_bg(139),
299            color_256_bg(135),
300            RESET,
301        );
302
303        println!(
304            "{BOLD}{}t{}r{}u{}e{}c{}o{}l{}o{}r{} {BOLD}{}r{}a{}i{}n{}b{}o{}w{}",
305            truecolor(255, 0, 0),
306            truecolor(170, 0, 0),
307            truecolor(90, 0, 0),
308            truecolor(30, 0, 0),
309            truecolor(0, 30, 0),
310            truecolor(0, 90, 0),
311            truecolor(0, 170, 0),
312            truecolor(0, 200, 0),
313            truecolor(0, 255, 0),
314            RESET,
315            truecolor_bg(0, 255, 0),
316            truecolor_bg(0, 150, 0),
317            truecolor_bg(0, 50, 0),
318            truecolor_bg(0, 0, 50),
319            truecolor_bg(0, 0, 150),
320            truecolor_bg(0, 0, 170),
321            truecolor_bg(0, 0, 255),
322            RESET,
323        );
324
325        println!("hidden: {HIDDEN}hidden{NOT_HIDDEN} revealed");
326        println!("{}green fg {}reset fg", truecolor(0, 255, 0),    DEFAULT);
327        println!("{}green bg {}reset bg", truecolor_bg(0, 255, 0), DEFAULT_BG);
328        println!();
329
330        println!("{GREEN}ok{RESET}");           // prints a green "ok"
331        println!("{BOLD}{RED}error!{RESET}");   // prints a bold, red "error!"
332        println!("{BLUE_BG}cloud{RESET}");      // prints
333        println!();
334
335        println!("{}{}example text{RESET}", color_256(237), color_256_bg(214));
336        println!("{}{}truecolor text{RESET}", truecolor(127, 45, 68), truecolor_bg(0, 255, 255));
337        println!();
338
339        println!("{SLOW_BLINK}slow blink{RESET}");
340        println!("{RAPID_BLINK}rapid blink{RESET}");
341        println!("{ALT_FONT_1}alt font 1{RESET}");
342        println!("{ALT_FONT_2}alt font 2{RESET}");
343        println!("{ALT_FONT_3}alt font 3{RESET}");
344        println!("{FRAKTUR}Fraktur font{RESET}");
345        println!("{DEFAULT_FONT}default font{RESET}");
346        println!("{INVERTED}{GREEN}green fg but it's bg{RESET}");
347        println!();
348    }
349}
350