1 | /// A style is a collection of properties that can format a string |
---|---|
2 | /// using ANSI escape codes. |
3 | /// |
4 | /// # Examples |
5 | /// |
6 | /// ``` |
7 | /// use nu_ansi_term::{Style, Color}; |
8 | /// |
9 | /// let style = Style::new().bold().on(Color::Black); |
10 | /// println!("{}", style.paint( "Bold on black")); |
11 | /// ``` |
12 | #[derive(Eq, PartialEq, Clone, Copy)] |
13 | #[cfg_attr( |
14 | feature = "derive_serde_style", |
15 | derive(serde::Deserialize, serde::Serialize) |
16 | )] |
17 | pub struct Style { |
18 | /// The style's foreground color, if it has one. |
19 | pub foreground: Option<Color>, |
20 | |
21 | /// The style's background color, if it has one. |
22 | pub background: Option<Color>, |
23 | |
24 | /// Whether this style is bold. |
25 | pub is_bold: bool, |
26 | |
27 | /// Whether this style is dimmed. |
28 | pub is_dimmed: bool, |
29 | |
30 | /// Whether this style is italic. |
31 | pub is_italic: bool, |
32 | |
33 | /// Whether this style is underlined. |
34 | pub is_underline: bool, |
35 | |
36 | /// Whether this style is blinking. |
37 | pub is_blink: bool, |
38 | |
39 | /// Whether this style has reverse colors. |
40 | pub is_reverse: bool, |
41 | |
42 | /// Whether this style is hidden. |
43 | pub is_hidden: bool, |
44 | |
45 | /// Whether this style is struckthrough. |
46 | pub is_strikethrough: bool, |
47 | |
48 | /// Wether this style is always displayed starting with a reset code to clear any remaining style artifacts |
49 | pub prefix_with_reset: bool, |
50 | } |
51 | |
52 | impl Style { |
53 | /// Creates a new Style with no properties set. |
54 | /// |
55 | /// # Examples |
56 | /// |
57 | /// ``` |
58 | /// use nu_ansi_term::Style; |
59 | /// |
60 | /// let style = Style::new(); |
61 | /// println!("{}", style.paint( "hi")); |
62 | /// ``` |
63 | pub fn new() -> Style { |
64 | Style::default() |
65 | } |
66 | |
67 | /// Returns a [`Style`] with the `Style.prefix_with_reset` property set. |
68 | /// |
69 | /// # Examples |
70 | /// |
71 | /// ``` |
72 | /// use nu_ansi_term::Style; |
73 | /// |
74 | /// let style = Style::new().reset_before_style(); |
75 | /// println!("{}", style.paint( "hey")); |
76 | /// ``` |
77 | pub const fn reset_before_style(&self) -> Style { |
78 | Style { |
79 | prefix_with_reset: true, |
80 | ..*self |
81 | } |
82 | } |
83 | |
84 | /// Returns a `Style` with the bold property set. |
85 | /// |
86 | /// # Examples |
87 | /// |
88 | /// ``` |
89 | /// use nu_ansi_term::Style; |
90 | /// |
91 | /// let style = Style::new().bold(); |
92 | /// println!("{}", style.paint( "hey")); |
93 | /// ``` |
94 | pub const fn bold(&self) -> Style { |
95 | Style { |
96 | is_bold: true, |
97 | ..*self |
98 | } |
99 | } |
100 | |
101 | /// Returns a `Style` with the dimmed property set. |
102 | /// |
103 | /// # Examples |
104 | /// |
105 | /// ``` |
106 | /// use nu_ansi_term::Style; |
107 | /// |
108 | /// let style = Style::new().dimmed(); |
109 | /// println!("{}", style.paint( "sup")); |
110 | /// ``` |
111 | pub const fn dimmed(&self) -> Style { |
112 | Style { |
113 | is_dimmed: true, |
114 | ..*self |
115 | } |
116 | } |
117 | |
118 | /// Returns a `Style` with the italic property set. |
119 | /// |
120 | /// # Examples |
121 | /// |
122 | /// ``` |
123 | /// use nu_ansi_term::Style; |
124 | /// |
125 | /// let style = Style::new().italic(); |
126 | /// println!("{}", style.paint( "greetings")); |
127 | /// ``` |
128 | pub const fn italic(&self) -> Style { |
129 | Style { |
130 | is_italic: true, |
131 | ..*self |
132 | } |
133 | } |
134 | |
135 | /// Returns a `Style` with the underline property set. |
136 | /// |
137 | /// # Examples |
138 | /// |
139 | /// ``` |
140 | /// use nu_ansi_term::Style; |
141 | /// |
142 | /// let style = Style::new().underline(); |
143 | /// println!("{}", style.paint( "salutations")); |
144 | /// ``` |
145 | pub const fn underline(&self) -> Style { |
146 | Style { |
147 | is_underline: true, |
148 | ..*self |
149 | } |
150 | } |
151 | |
152 | /// Returns a `Style` with the blink property set. |
153 | /// # Examples |
154 | /// |
155 | /// ``` |
156 | /// use nu_ansi_term::Style; |
157 | /// |
158 | /// let style = Style::new().blink(); |
159 | /// println!("{}", style.paint( "wazzup")); |
160 | /// ``` |
161 | pub const fn blink(&self) -> Style { |
162 | Style { |
163 | is_blink: true, |
164 | ..*self |
165 | } |
166 | } |
167 | |
168 | /// Returns a `Style` with the reverse property set. |
169 | /// |
170 | /// # Examples |
171 | /// |
172 | /// ``` |
173 | /// use nu_ansi_term::Style; |
174 | /// |
175 | /// let style = Style::new().reverse(); |
176 | /// println!("{}", style.paint( "aloha")); |
177 | /// ``` |
178 | pub const fn reverse(&self) -> Style { |
179 | Style { |
180 | is_reverse: true, |
181 | ..*self |
182 | } |
183 | } |
184 | |
185 | /// Returns a `Style` with the hidden property set. |
186 | /// |
187 | /// # Examples |
188 | /// |
189 | /// ``` |
190 | /// use nu_ansi_term::Style; |
191 | /// |
192 | /// let style = Style::new().hidden(); |
193 | /// println!("{}", style.paint( "ahoy")); |
194 | /// ``` |
195 | pub const fn hidden(&self) -> Style { |
196 | Style { |
197 | is_hidden: true, |
198 | ..*self |
199 | } |
200 | } |
201 | |
202 | /// Returns a `Style` with the strikethrough property set. |
203 | /// |
204 | /// # Examples |
205 | /// |
206 | /// ``` |
207 | /// use nu_ansi_term::Style; |
208 | /// |
209 | /// let style = Style::new().strikethrough(); |
210 | /// println!("{}", style.paint( "yo")); |
211 | /// ``` |
212 | pub const fn strikethrough(&self) -> Style { |
213 | Style { |
214 | is_strikethrough: true, |
215 | ..*self |
216 | } |
217 | } |
218 | |
219 | /// Returns a `Style` with the foreground color property set. |
220 | /// |
221 | /// # Examples |
222 | /// |
223 | /// ``` |
224 | /// use nu_ansi_term::{Style, Color}; |
225 | /// |
226 | /// let style = Style::new().fg(Color::Yellow); |
227 | /// println!("{}", style.paint( "hi")); |
228 | /// ``` |
229 | pub const fn fg(&self, foreground: Color) -> Style { |
230 | Style { |
231 | foreground: Some(foreground), |
232 | ..*self |
233 | } |
234 | } |
235 | |
236 | /// Returns a `Style` with the background color property set. |
237 | /// |
238 | /// # Examples |
239 | /// |
240 | /// ``` |
241 | /// use nu_ansi_term::{Style, Color}; |
242 | /// |
243 | /// let style = Style::new().on(Color::Blue); |
244 | /// println!("{}", style.paint( "eyyyy")); |
245 | /// ``` |
246 | pub const fn on(&self, background: Color) -> Style { |
247 | Style { |
248 | background: Some(background), |
249 | ..*self |
250 | } |
251 | } |
252 | |
253 | /// Return true if this `Style` has no actual styles, and can be written |
254 | /// without any control characters. |
255 | /// |
256 | /// # Examples |
257 | /// |
258 | /// ``` |
259 | /// use nu_ansi_term::Style; |
260 | /// |
261 | /// assert_eq!(true, Style::default().is_plain()); |
262 | /// assert_eq!(false, Style::default().bold().is_plain()); |
263 | /// ``` |
264 | pub fn is_plain(self) -> bool { |
265 | self == Style::default() |
266 | } |
267 | } |
268 | |
269 | impl Default for Style { |
270 | /// Returns a style with *no* properties set. Formatting text using this |
271 | /// style returns the exact same text. |
272 | /// |
273 | /// ``` |
274 | /// use nu_ansi_term::Style; |
275 | /// assert_eq!(None, Style::default().foreground); |
276 | /// assert_eq!(None, Style::default().background); |
277 | /// assert_eq!(false, Style::default().is_bold); |
278 | /// assert_eq!("txt", Style::default().paint( "txt").to_string()); |
279 | /// ``` |
280 | fn default() -> Style { |
281 | Style { |
282 | foreground: None, |
283 | background: None, |
284 | is_bold: false, |
285 | is_dimmed: false, |
286 | is_italic: false, |
287 | is_underline: false, |
288 | is_blink: false, |
289 | is_reverse: false, |
290 | is_hidden: false, |
291 | is_strikethrough: false, |
292 | prefix_with_reset: false, |
293 | } |
294 | } |
295 | } |
296 | |
297 | // ---- colors ---- |
298 | |
299 | /// A color is one specific type of ANSI escape code, and can refer |
300 | /// to either the foreground or background color. |
301 | /// |
302 | /// These use the standard numeric sequences. |
303 | /// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html> |
304 | #[derive(Eq, PartialEq, Clone, Copy, Debug, Default)] |
305 | #[cfg_attr( |
306 | feature = "derive_serde_style", |
307 | derive(serde::Deserialize, serde::Serialize) |
308 | )] |
309 | pub enum Color { |
310 | /// Color #0 (foreground code `30`, background code `40`). |
311 | /// |
312 | /// This is not necessarily the background color, and using it as one may |
313 | /// render the text hard to read on terminals with dark backgrounds. |
314 | Black, |
315 | |
316 | /// Color #0 (foreground code `90`, background code `100`). |
317 | DarkGray, |
318 | |
319 | /// Color #1 (foreground code `31`, background code `41`). |
320 | Red, |
321 | |
322 | /// Color #1 (foreground code `91`, background code `101`). |
323 | LightRed, |
324 | |
325 | /// Color #2 (foreground code `32`, background code `42`). |
326 | Green, |
327 | |
328 | /// Color #2 (foreground code `92`, background code `102`). |
329 | LightGreen, |
330 | |
331 | /// Color #3 (foreground code `33`, background code `43`). |
332 | Yellow, |
333 | |
334 | /// Color #3 (foreground code `93`, background code `103`). |
335 | LightYellow, |
336 | |
337 | /// Color #4 (foreground code `34`, background code `44`). |
338 | Blue, |
339 | |
340 | /// Color #4 (foreground code `94`, background code `104`). |
341 | LightBlue, |
342 | |
343 | /// Color #5 (foreground code `35`, background code `45`). |
344 | Purple, |
345 | |
346 | /// Color #5 (foreground code `95`, background code `105`). |
347 | LightPurple, |
348 | |
349 | /// Color #5 (foreground code `35`, background code `45`). |
350 | Magenta, |
351 | |
352 | /// Color #5 (foreground code `95`, background code `105`). |
353 | LightMagenta, |
354 | |
355 | /// Color #6 (foreground code `36`, background code `46`). |
356 | Cyan, |
357 | |
358 | /// Color #6 (foreground code `96`, background code `106`). |
359 | LightCyan, |
360 | |
361 | /// Color #7 (foreground code `37`, background code `47`). |
362 | /// |
363 | /// As above, this is not necessarily the foreground color, and may be |
364 | /// hard to read on terminals with light backgrounds. |
365 | White, |
366 | |
367 | /// Color #7 (foreground code `97`, background code `107`). |
368 | LightGray, |
369 | |
370 | /// A color number from 0 to 255, for use in 256-color terminal |
371 | /// environments. |
372 | /// |
373 | /// - colors 0 to 7 are the `Black` to `White` variants respectively. |
374 | /// These colors can usually be changed in the terminal emulator. |
375 | /// - colors 8 to 15 are brighter versions of the eight colors above. |
376 | /// These can also usually be changed in the terminal emulator, or it |
377 | /// could be configured to use the original colors and show the text in |
378 | /// bold instead. It varies depending on the program. |
379 | /// - colors 16 to 231 contain several palettes of bright colors, |
380 | /// arranged in six squares measuring six by six each. |
381 | /// - colors 232 to 255 are shades of grey from black to white. |
382 | /// |
383 | /// It might make more sense to look at a [color chart][cc]. |
384 | /// |
385 | /// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg |
386 | Fixed(u8), |
387 | |
388 | /// A 24-bit Rgb color, as specified by ISO-8613-3. |
389 | Rgb(u8, u8, u8), |
390 | |
391 | /// The default color (foreground code `39`, background codr `49`). |
392 | #[default] |
393 | Default, |
394 | } |
395 | |
396 | impl Color { |
397 | /// Returns a `Style` with the foreground color set to this color. |
398 | /// |
399 | /// # Examples |
400 | /// |
401 | /// ``` |
402 | /// use nu_ansi_term::Color; |
403 | /// |
404 | /// let style = Color::Red.normal(); |
405 | /// println!("{}", style.paint( "hi")); |
406 | /// ``` |
407 | pub fn normal(self) -> Style { |
408 | Style { |
409 | foreground: Some(self), |
410 | ..Style::default() |
411 | } |
412 | } |
413 | |
414 | /// Returns a `Style` with the foreground color set to this color and the |
415 | /// bold property set. |
416 | /// |
417 | /// # Examples |
418 | /// |
419 | /// ``` |
420 | /// use nu_ansi_term::Color; |
421 | /// |
422 | /// let style = Color::Green.bold(); |
423 | /// println!("{}", style.paint( "hey")); |
424 | /// ``` |
425 | pub fn bold(self) -> Style { |
426 | Style { |
427 | foreground: Some(self), |
428 | is_bold: true, |
429 | ..Style::default() |
430 | } |
431 | } |
432 | |
433 | /// Returns a `Style` with the foreground color set to this color and the |
434 | /// dimmed property set. |
435 | /// |
436 | /// # Examples |
437 | /// |
438 | /// ``` |
439 | /// use nu_ansi_term::Color; |
440 | /// |
441 | /// let style = Color::Yellow.dimmed(); |
442 | /// println!("{}", style.paint( "sup")); |
443 | /// ``` |
444 | pub fn dimmed(self) -> Style { |
445 | Style { |
446 | foreground: Some(self), |
447 | is_dimmed: true, |
448 | ..Style::default() |
449 | } |
450 | } |
451 | |
452 | /// Returns a `Style` with the foreground color set to this color and the |
453 | /// italic property set. |
454 | /// |
455 | /// # Examples |
456 | /// |
457 | /// ``` |
458 | /// use nu_ansi_term::Color; |
459 | /// |
460 | /// let style = Color::Blue.italic(); |
461 | /// println!("{}", style.paint( "greetings")); |
462 | /// ``` |
463 | pub fn italic(self) -> Style { |
464 | Style { |
465 | foreground: Some(self), |
466 | is_italic: true, |
467 | ..Style::default() |
468 | } |
469 | } |
470 | |
471 | /// Returns a `Style` with the foreground color set to this color and the |
472 | /// underline property set. |
473 | /// |
474 | /// # Examples |
475 | /// |
476 | /// ``` |
477 | /// use nu_ansi_term::Color; |
478 | /// |
479 | /// let style = Color::Purple.underline(); |
480 | /// println!("{}", style.paint( "salutations")); |
481 | /// ``` |
482 | pub fn underline(self) -> Style { |
483 | Style { |
484 | foreground: Some(self), |
485 | is_underline: true, |
486 | ..Style::default() |
487 | } |
488 | } |
489 | |
490 | /// Returns a `Style` with the foreground color set to this color and the |
491 | /// blink property set. |
492 | /// |
493 | /// # Examples |
494 | /// |
495 | /// ``` |
496 | /// use nu_ansi_term::Color; |
497 | /// |
498 | /// let style = Color::Cyan.blink(); |
499 | /// println!("{}", style.paint( "wazzup")); |
500 | /// ``` |
501 | pub fn blink(self) -> Style { |
502 | Style { |
503 | foreground: Some(self), |
504 | is_blink: true, |
505 | ..Style::default() |
506 | } |
507 | } |
508 | |
509 | /// Returns a `Style` with the foreground color set to this color and the |
510 | /// reverse property set. |
511 | /// |
512 | /// # Examples |
513 | /// |
514 | /// ``` |
515 | /// use nu_ansi_term::Color; |
516 | /// |
517 | /// let style = Color::Black.reverse(); |
518 | /// println!("{}", style.paint( "aloha")); |
519 | /// ``` |
520 | pub fn reverse(self) -> Style { |
521 | Style { |
522 | foreground: Some(self), |
523 | is_reverse: true, |
524 | ..Style::default() |
525 | } |
526 | } |
527 | |
528 | /// Returns a `Style` with the foreground color set to this color and the |
529 | /// hidden property set. |
530 | /// |
531 | /// # Examples |
532 | /// |
533 | /// ``` |
534 | /// use nu_ansi_term::Color; |
535 | /// |
536 | /// let style = Color::White.hidden(); |
537 | /// println!("{}", style.paint( "ahoy")); |
538 | /// ``` |
539 | pub fn hidden(self) -> Style { |
540 | Style { |
541 | foreground: Some(self), |
542 | is_hidden: true, |
543 | ..Style::default() |
544 | } |
545 | } |
546 | |
547 | /// Returns a `Style` with the foreground color set to this color and the |
548 | /// strikethrough property set. |
549 | /// |
550 | /// # Examples |
551 | /// |
552 | /// ``` |
553 | /// use nu_ansi_term::Color; |
554 | /// |
555 | /// let style = Color::Fixed(244).strikethrough(); |
556 | /// println!("{}", style.paint( "yo")); |
557 | /// ``` |
558 | pub fn strikethrough(self) -> Style { |
559 | Style { |
560 | foreground: Some(self), |
561 | is_strikethrough: true, |
562 | ..Style::default() |
563 | } |
564 | } |
565 | |
566 | /// Returns a `Style` thats resets all styling before applying |
567 | /// the foreground color set to this color. |
568 | /// |
569 | /// # Examples |
570 | /// |
571 | /// ``` |
572 | /// use nu_ansi_term::Color; |
573 | /// |
574 | /// let style = Color::Fixed(244).reset_before_style(); |
575 | /// println!("{}", style.paint( "yo")); |
576 | /// ``` |
577 | pub fn reset_before_style(self) -> Style { |
578 | Style { |
579 | foreground: Some(self), |
580 | prefix_with_reset: true, |
581 | ..Style::default() |
582 | } |
583 | } |
584 | |
585 | /// Returns a `Style` with the foreground color set to this color and the |
586 | /// background color property set to the given color. |
587 | /// |
588 | /// # Examples |
589 | /// |
590 | /// ``` |
591 | /// use nu_ansi_term::Color; |
592 | /// |
593 | /// let style = Color::Rgb(31, 31, 31).on(Color::White); |
594 | /// println!("{}", style.paint( "eyyyy")); |
595 | /// ``` |
596 | pub fn on(self, background: Color) -> Style { |
597 | Style { |
598 | foreground: Some(self), |
599 | background: Some(background), |
600 | ..Style::default() |
601 | } |
602 | } |
603 | } |
604 | |
605 | impl From<Color> for Style { |
606 | /// You can turn a `Color` into a `Style` with the foreground color set |
607 | /// with the `From` trait. |
608 | /// |
609 | /// ``` |
610 | /// use nu_ansi_term::{Style, Color}; |
611 | /// let green_foreground = Style::default().fg(Color::Green); |
612 | /// assert_eq!(green_foreground, Color::Green.normal()); |
613 | /// assert_eq!(green_foreground, Color::Green.into()); |
614 | /// assert_eq!(green_foreground, Style::from(Color::Green)); |
615 | /// ``` |
616 | fn from(color: Color) -> Style { |
617 | color.normal() |
618 | } |
619 | } |
620 | |
621 | #[cfg(test)] |
622 | #[cfg(feature = "derive_serde_style")] |
623 | mod serde_json_tests { |
624 | use super::{Color, Style}; |
625 | |
626 | #[test] |
627 | fn color_serialization() { |
628 | let colors = &[ |
629 | Color::Red, |
630 | Color::Blue, |
631 | Color::Rgb(123, 123, 123), |
632 | Color::Fixed(255), |
633 | ]; |
634 | |
635 | assert_eq!( |
636 | serde_json::to_string(&colors).unwrap(), |
637 | "[\" Red\" ,\" Blue\" ,{\" Rgb\" :[123,123,123]},{\" Fixed\" :255}]" |
638 | ); |
639 | } |
640 | |
641 | #[test] |
642 | fn color_deserialization() { |
643 | let colors = [ |
644 | Color::Red, |
645 | Color::Blue, |
646 | Color::Rgb(123, 123, 123), |
647 | Color::Fixed(255), |
648 | ]; |
649 | |
650 | for color in colors { |
651 | let serialized = serde_json::to_string(&color).unwrap(); |
652 | let deserialized: Color = serde_json::from_str(&serialized).unwrap(); |
653 | |
654 | assert_eq!(color, deserialized); |
655 | } |
656 | } |
657 | |
658 | #[test] |
659 | fn style_serialization() { |
660 | let style = Style::default(); |
661 | |
662 | assert_eq!(serde_json::to_string(&style).unwrap(), "{\" foreground\" :null,\" background\" :null,\" is_bold\" :false,\" is_dimmed\" :false,\" is_italic\" :false,\" is_underline\" :false,\" is_blink\" :false,\" is_reverse\" :false,\" is_hidden\" :false,\" is_strikethrough\" :false,\" prefix_with_reset\" :false}".to_string()); |
663 | } |
664 | } |
665 |
Definitions
- Style
- foreground
- background
- is_bold
- is_dimmed
- is_italic
- is_underline
- is_blink
- is_reverse
- is_hidden
- is_strikethrough
- prefix_with_reset
- new
- reset_before_style
- bold
- dimmed
- italic
- underline
- blink
- reverse
- hidden
- strikethrough
- fg
- on
- is_plain
- default
- Color
- Black
- DarkGray
- Red
- LightRed
- Green
- LightGreen
- Yellow
- LightYellow
- Blue
- LightBlue
- Purple
- LightPurple
- Magenta
- LightMagenta
- Cyan
- LightCyan
- White
- LightGray
- Fixed
- Rgb
- Default
- normal
- bold
- dimmed
- italic
- underline
- blink
- reverse
- hidden
- strikethrough
- reset_before_style
- on
Learn Rust with the experts
Find out more