abscissa_core/terminal/
status.rs1use super::{stderr, stdout};
35use crate::FrameworkError;
36use std::io::Write;
37use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
38
39#[macro_export]
46macro_rules! status_ok {
47 ($status:expr, $msg:expr) => {
48 $crate::terminal::status::Status::new()
49 .justified()
50 .bold()
51 .color($crate::terminal::Color::Green)
52 .status($status)
53 .print_stderr($msg)
54 .unwrap();
55 };
56 ($status:expr, $fmt:expr, $($arg:tt)+) => {
57 $crate::status_ok!($status, format!($fmt, $($arg)+));
58 };
59}
60
61#[macro_export]
68macro_rules! status_info {
69 ($status:expr, $msg:expr) => {
70 $crate::terminal::status::Status::new()
71 .justified()
72 .bold()
73 .color($crate::terminal::Color::Cyan)
74 .status($status)
75 .print_stderr($msg)
76 .unwrap();
77 };
78 ($status:expr, $fmt:expr, $($arg:tt)+) => {
79 $crate::status_info!($status, format!($fmt, $($arg)+));
80 };
81}
82
83#[macro_export]
90macro_rules! status_warn {
91 ($msg:expr) => {
92 $crate::terminal::status::Status::new()
93 .bold()
94 .color($crate::terminal::Color::Yellow)
95 .status("warning:")
96 .print_stderr($msg)
97 .unwrap();
98 };
99 ($fmt:expr, $($arg:tt)+) => {
100 $crate::status_warn!(format!($fmt, $($arg)+));
101 };
102}
103
104#[macro_export]
111macro_rules! status_err {
112 ($msg:expr) => {
113 $crate::terminal::status::Status::new()
114 .bold()
115 .color($crate::terminal::Color::Red)
116 .status("error:")
117 .print_stderr($msg)
118 .unwrap();
119 };
120 ($fmt:expr, $($arg:tt)+) => {
121 $crate::status_err!(format!($fmt, $($arg)+));
122 };
123}
124
125#[macro_export]
132macro_rules! status_attr_ok {
133 ($attr:expr, $msg:expr) => {
134 let attr_delimited = if $attr.len() >= 7 {
136 format!("{}:", $attr)
137 } else {
138 format!("{}:\t", $attr)
139 };
140
141
142 $crate::terminal::status::Status::new()
143 .bold()
144 .color($crate::terminal::Color::Green)
145 .status(attr_delimited)
146 .print_stdout($msg)
147 .unwrap();
148 };
149 ($attr: expr, $fmt:expr, $($arg:tt)+) => {
150 $crate::status_attr_ok!($attr, format!($fmt, $($arg)+));
151 }
152}
153
154#[macro_export]
161macro_rules! status_attr_err {
162 ($attr:expr, $msg:expr) => {
163 let attr_delimited = if $attr.len() >= 7 {
165 format!("{}:", $attr)
166 } else {
167 format!("{}:\t", $attr)
168 };
169
170
171 $crate::terminal::status::Status::new()
172 .bold()
173 .color($crate::terminal::Color::Red)
174 .status(attr_delimited)
175 .print_stdout($msg)
176 .unwrap();
177 };
178 ($attr: expr, $fmt:expr, $($arg:tt)+) => {
179 $crate::status_attr_err!($attr, format!($fmt, $($arg)+));
180 }
181}
182
183#[derive(Clone, Debug, Default)]
185pub struct Status {
186 justified: bool,
188
189 bold: bool,
191
192 color: Option<Color>,
194
195 status: Option<String>,
197}
198
199impl Status {
200 pub fn new() -> Self {
202 Self::default()
203 }
204
205 pub fn justified(mut self) -> Self {
207 self.justified = true;
208 self
209 }
210
211 pub fn bold(mut self) -> Self {
213 self.bold = true;
214 self
215 }
216
217 pub fn color(mut self, c: Color) -> Self {
219 self.color = Some(c);
220 self
221 }
222
223 pub fn status<S>(mut self, msg: S) -> Self
225 where
226 S: ToString,
227 {
228 self.status = Some(msg.to_string());
229 self
230 }
231
232 pub fn print_stdout<S>(self, msg: S) -> Result<(), FrameworkError>
234 where
235 S: AsRef<str>,
236 {
237 self.print(stdout(), msg)
238 }
239
240 pub fn print_stderr<S>(self, msg: S) -> Result<(), FrameworkError>
242 where
243 S: AsRef<str>,
244 {
245 self.print(stderr(), msg)
246 }
247
248 fn print<S>(self, stream: &StandardStream, msg: S) -> Result<(), FrameworkError>
250 where
251 S: AsRef<str>,
252 {
253 let mut s = stream.lock();
254 s.reset()?;
255 s.set_color(ColorSpec::new().set_fg(self.color).set_bold(self.bold))?;
256
257 if let Some(status) = self.status {
258 if self.justified {
259 write!(s, "{:>12}", status)?;
260 } else {
261 write!(s, "{}", status)?;
262 }
263 }
264
265 s.reset()?;
266 let msg = msg.as_ref();
267 if !msg.is_empty() {
268 writeln!(s, " {}", msg)?;
269 }
270 s.flush()?;
271
272 Ok(())
273 }
274}