#[macro_export]
macro_rules! vsection {
(@lvl $lvl:expr, $($arg:tt)+) => {
if $crate::VERBOSE.load(std::sync::atomic::Ordering::Relaxed) >= $lvl {
let msg = format!("=== {} ===\n", format!($($arg)+));
println!("{}", msg);
}
};
( $($arg:tt)+) => {
if $crate::VERBOSE.load(std::sync::atomic::Ordering::Relaxed) >= 1 {
let msg = format!("=== {} ===\n", format!($($arg)+));
println!("{}", msg);
}
};
}
#[cfg(feature = "status")]
#[macro_export]
macro_rules! status_line {
(@lvl $lvl:expr, $msg:expr) => {{
if $crate::VERBOSE.load(std::sync::atomic::Ordering::Relaxed) >= $lvl {
Some($crate::status::start_spinner(|| $msg.to_string()))
} else {
None
}
}};
($msg:expr) => {
$crate::status_line!(@lvl 1, $msg)
};
}
#[cfg(feature = "status")]
#[macro_export]
macro_rules! status_line_clear {
() => {{
$crate::status::clear_status_line();
}};
}
#[cfg(feature = "status")]
#[macro_export]
macro_rules! status_line_done {
($msg:expr) => {{
#[cfg(feature = "status")]
$crate::status::finish_status_line($msg);
}};
}
#[cfg(feature = "status")]
pub mod status {
use std::io::{stdout, Write};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::thread;
use std::time::Duration;
use crossterm::{execute, terminal::{ClearType, Clear}, cursor::{MoveToColumn}};
static SPINNER_FRAMES: &[&str] = &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
pub struct SpinnerHandle {
stop: Arc<AtomicBool>,
}
impl SpinnerHandle {
pub fn stop(self){
self.stop.store(true, Ordering::Relaxed);
}
}
pub fn start_spinner<F: Fn() -> String + Send + 'static>(msg_fn: F) -> SpinnerHandle {
let stop = Arc::new(AtomicBool::new(false));
let stop_clone = stop.clone();
thread::spawn(move || {
let mut idx = 0;
while !stop_clone.load(Ordering::Relaxed) {
let spinner = SPINNER_FRAMES[idx % SPINNER_FRAMES.len()];
let msg = format!("{} {}", spinner, msg_fn());
execute!(
stdout(),
MoveToColumn(0),
Clear(ClearType::CurrentLine),
).unwrap();
print!("{}", msg);
stdout().flush().unwrap();
idx += 1;
thread::sleep(Duration::from_millis(100));
}
});
SpinnerHandle {stop}
}
pub fn clear_status_line(){
let _ = execute!(
stdout(),
MoveToColumn(0),
Clear(ClearType::CurrentLine),
);
let _ = stdout().flush();
}
pub fn finish_status_line(msg: &str){
clear_status_line();
println!("{}", msg);
}
}