1use crate::{Color, ColorSpec};
8use std::fmt;
9use std::io;
10
11pub fn ansi_spec<W: io::Write>(
20 mut wtr: W,
21 spec: &ColorSpec,
22) -> io::Result<()> {
23 if spec.reset() {
24 write!(wtr, "\x1B[0m")?;
25 }
26 if spec.bold() {
27 write!(wtr, "\x1B[1m")?;
28 }
29 if spec.dimmed() {
30 write!(wtr, "\x1B[2m")?;
31 }
32 if spec.italic() {
33 write!(wtr, "\x1B[3m")?;
34 }
35 if spec.underline() {
36 write!(wtr, "\x1B[4m")?;
37 }
38 if spec.strikethrough() {
39 write!(wtr, "\x1B[9m")?;
40 }
41 if let Some(c) = spec.fg() {
42 ansi_color(&mut wtr, c, false)?;
43 }
44 if let Some(c) = spec.bg() {
45 ansi_color(&mut wtr, c, true)?;
46 }
47 if spec.intense() && spec.fg().is_some() {
48 write!(wtr, "\x1B[1m")?;
49 }
50 Ok(())
51}
52
53pub fn ansi_color<W: io::Write>(
62 mut wtr: W,
63 color: &Color,
64 bg: bool,
65) -> io::Result<()> {
66 match *color {
67 Color::Black => {
68 if bg {
69 write!(wtr, "\x1B[40m")
70 } else {
71 write!(wtr, "\x1B[30m")
72 }
73 }
74 Color::Blue => {
75 if bg {
76 write!(wtr, "\x1B[44m")
77 } else {
78 write!(wtr, "\x1B[34m")
79 }
80 }
81 Color::Green => {
82 if bg {
83 write!(wtr, "\x1B[42m")
84 } else {
85 write!(wtr, "\x1B[32m")
86 }
87 }
88 Color::Red => {
89 if bg {
90 write!(wtr, "\x1B[41m")
91 } else {
92 write!(wtr, "\x1B[31m")
93 }
94 }
95 Color::Cyan => {
96 if bg {
97 write!(wtr, "\x1B[46m")
98 } else {
99 write!(wtr, "\x1B[36m")
100 }
101 }
102 Color::Magenta => {
103 if bg {
104 write!(wtr, "\x1B[45m")
105 } else {
106 write!(wtr, "\x1B[35m")
107 }
108 }
109 Color::Yellow => {
110 if bg {
111 write!(wtr, "\x1B[43m")
112 } else {
113 write!(wtr, "\x1B[33m")
114 }
115 }
116 Color::White => {
117 if bg {
118 write!(wtr, "\x1B[47m")
119 } else {
120 write!(wtr, "\x1B[37m")
121 }
122 }
123 Color::Ansi256(n) => {
124 if bg {
125 write!(wtr, "\x1B[48;5;{n}m")
126 } else {
127 write!(wtr, "\x1B[38;5;{n}m")
128 }
129 }
130 Color::Rgb(r, g, b) => {
131 if bg {
132 write!(wtr, "\x1B[48;2;{r};{g};{b}m")
133 } else {
134 write!(wtr, "\x1B[38;2;{r};{g};{b}m")
135 }
136 }
137 }
138}
139
140pub fn ansi_color_only(fg: Option<Color>, bg: Option<Color>) -> AnsiColor {
146 AnsiColor { fg, bg }
147}
148
149pub struct AnsiColor {
153 fg: Option<Color>,
154 bg: Option<Color>,
155}
156
157impl fmt::Display for AnsiColor {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 let mut buf = Vec::new();
160 if let Some(ref c) = self.fg {
161 ansi_color(&mut buf, c, false).map_err(|_| fmt::Error)?;
162 }
163 if let Some(ref c) = self.bg {
164 ansi_color(&mut buf, c, true).map_err(|_| fmt::Error)?;
165 }
166 write!(f, "{}", String::from_utf8_lossy(&buf))
167 }
168}