1pub use log::{Level as LogLevel, Record as LogRecord, debug, error, info, trace, warn};
23
24use std::sync::atomic::{AtomicBool, Ordering};
25
26use cu::Atomic;
27
28#[macro_export]
37macro_rules! fmtand {
38 ($mac:ident !( $($fmt_args:tt)* )) => {{
39 let s = format!($($fmt_args)*);
40 $crate::$mac!("{s}");
41 s
42 }}
43}
44
45pub(crate) static PRINT_LEVEL: Atomic<u8, Print> = Atomic::new_u8(Print::Normal as u8);
46pub(crate) static USE_COLOR: AtomicBool = AtomicBool::new(true);
47
48pub fn color_enabled() -> bool {
50 USE_COLOR.load(Ordering::Acquire)
51}
52
53static ENABLE_TRACE_HINT: AtomicBool = AtomicBool::new(true);
54static ENABLE_PRINT_TIME: AtomicBool = AtomicBool::new(true);
55
56#[inline(always)]
60#[cfg(feature = "print")]
61pub fn disable_trace_hint() {
62 ENABLE_TRACE_HINT.store(false, Ordering::Release);
63}
64
65#[inline(always)]
68pub fn is_trace_hint_enabled() -> bool {
69 ENABLE_TRACE_HINT.load(Ordering::Acquire)
70}
71
72#[inline(always)]
74#[cfg(feature = "print")]
75pub fn disable_print_time() {
76 ENABLE_PRINT_TIME.store(false, Ordering::Release);
77}
78
79#[inline(always)]
82pub fn is_print_time_enabled() -> bool {
83 ENABLE_PRINT_TIME.load(Ordering::Acquire)
84}
85
86#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
88#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
89pub enum Color {
90 Always,
91 Never,
92 #[default]
93 Auto,
94}
95impl std::fmt::Display for Color {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 match self {
98 Self::Always => write!(f, "always"),
99 Self::Never => write!(f, "never"),
100 Self::Auto => write!(f, "auto"),
101 }
102 }
103}
104impl Color {
105 pub fn is_colored_for_stdout(self) -> bool {
107 use std::io::IsTerminal;
108 match self {
109 Self::Always => true,
110 Self::Never => false,
111 Self::Auto => std::io::stdout().is_terminal(),
112 }
113 }
114
115 pub fn from_os_args() -> Self {
118 let mut found_color = false;
120 for x in std::env::args() {
121 if found_color {
122 if x == "always" {
123 return Self::Always;
124 }
125 if x == "never" {
126 return Self::Never;
127 }
128 if x == "auto" {
129 return Self::Auto;
130 }
131 found_color = false;
132 continue;
133 }
134 if x == "--color" {
135 found_color = true;
136 continue;
137 }
138 if x == "--color=always" {
139 return Self::Always;
140 }
141 if x == "--color=never" {
142 return Self::Never;
143 }
144 if x == "--color=auto" {
145 return Self::Auto;
146 }
147 }
148 Self::Auto
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
154#[repr(u8)]
155pub enum Print {
156 QuietQuiet,
157 Quiet,
158 Normal,
159 Verbose,
160 VerboseVerbose,
161}
162impl From<i8> for Print {
163 fn from(value: i8) -> Self {
164 match value {
165 ..=-2 => Self::QuietQuiet,
166 -1 => Self::Quiet,
167 0 => Self::Normal,
168 1 => Self::Verbose,
169 2.. => Self::VerboseVerbose,
170 }
171 }
172}
173impl From<u8> for Print {
174 fn from(value: u8) -> Self {
175 match value {
176 0 => Self::QuietQuiet,
177 1 => Self::Quiet,
178 3 => Self::Verbose,
179 4 => Self::VerboseVerbose,
180 _ => Self::Normal,
181 }
182 }
183}
184impl From<Print> for u8 {
185 fn from(value: Print) -> Self {
186 value as Self
187 }
188}
189impl From<Print> for log::LevelFilter {
190 fn from(value: Print) -> Self {
191 match value {
192 Print::QuietQuiet => log::LevelFilter::Off,
193 Print::Quiet => log::LevelFilter::Error,
194 Print::Normal => log::LevelFilter::Info,
195 Print::Verbose => log::LevelFilter::Debug,
196 Print::VerboseVerbose => log::LevelFilter::Trace,
197 }
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq)]
203#[repr(u8)]
204pub enum Prompt {
205 Interactive,
207 YesOrInteractive,
209 YesOrBlock,
211 Block,
213}
214impl From<u8> for Prompt {
215 fn from(value: u8) -> Self {
216 match value {
217 1 => Self::YesOrInteractive,
218 2 => Self::YesOrBlock,
219 3 => Self::Block,
220 _ => Self::Interactive,
221 }
222 }
223}
224impl From<Prompt> for u8 {
225 fn from(value: Prompt) -> Self {
226 value as Self
227 }
228}
229
230#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
234#[repr(u8)]
235pub enum Lv {
236 Error,
237 Hint,
238 Print,
239 Warn,
240 Info,
241 Debug,
242 Trace,
243
244 Off,
245}
246impl Lv {
247 #[inline(always)]
255 pub fn enabled(self) -> bool {
256 self.can_print(PRINT_LEVEL.get())
257 }
258 pub fn can_print(self, level: Print) -> bool {
260 match self {
261 Lv::Off => false,
262 Lv::Error | Lv::Hint | Lv::Print => level != Print::QuietQuiet,
263 Lv::Warn | Lv::Info => level > Print::Quiet,
264 Lv::Debug => level > Print::Normal,
265 Lv::Trace => level == Print::VerboseVerbose,
266 }
267 }
268}
269impl From<log::Level> for Lv {
270 fn from(value: log::Level) -> Self {
271 match value {
272 log::Level::Error => Self::Error,
273 log::Level::Warn => Self::Warn,
274 log::Level::Info => Self::Info,
275 log::Level::Debug => Self::Debug,
276 log::Level::Trace => Self::Trace,
277 }
278 }
279}
280impl From<Lv> for log::Level {
281 fn from(value: Lv) -> Self {
282 match value {
283 Lv::Error => log::Level::Error,
284 Lv::Hint => log::Level::Warn,
285 Lv::Print => log::Level::Info,
286 Lv::Warn => log::Level::Warn,
287 Lv::Info => log::Level::Info,
288 Lv::Debug => log::Level::Debug,
289 Lv::Trace => log::Level::Trace,
290 Lv::Off => log::Level::Error,
291 }
292 }
293}
294impl From<u8> for Lv {
295 fn from(value: u8) -> Self {
296 match value {
297 0 => Lv::Error,
298 1 => Lv::Hint,
299 2 => Lv::Print,
300 3 => Lv::Warn,
301 4 => Lv::Info,
302 5 => Lv::Debug,
303 6 => Lv::Trace,
304 _ => Lv::Off,
305 }
306 }
307}
308impl From<Lv> for u8 {
309 fn from(value: Lv) -> Self {
310 value as u8
311 }
312}
313
314impl std::fmt::Display for Lv {
315 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
316 match self {
317 Lv::Error => "error".fmt(f),
318 Lv::Hint => "hint".fmt(f),
319 Lv::Print => "print".fmt(f),
320 Lv::Warn => "warn".fmt(f),
321 Lv::Info => "info".fmt(f),
322 Lv::Debug => "debug".fmt(f),
323 Lv::Trace => "trace".fmt(f),
324 Lv::Off => "off".fmt(f),
325 }
326 }
327}
328
329pub const E: Lv = Lv::Error;
331pub const H: Lv = Lv::Hint;
333pub const P: Lv = Lv::Print;
335pub const W: Lv = Lv::Warn;
337pub const I: Lv = Lv::Info;
339pub const D: Lv = Lv::Debug;
341pub const T: Lv = Lv::Trace;