aurora-modules 0.1.0

Git, filesystem, system, network, archive, docker, unix, crypto, calculator, QR, color, timer, notes, clipboard, and text processing modules
Documentation
use aurora_core::{AuroraResult, Pipeline, Value};
use std::sync::Mutex;
use std::time::{Duration, Instant};

#[derive(Clone)]
struct TimerEntry {
    name: String,
    total_secs: u64,
    started: Instant,
}

static TIMERS: Mutex<Option<Vec<TimerEntry>>> = Mutex::new(None);

fn get_timers() -> Vec<TimerEntry> {
    let guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
    guard.clone().unwrap_or_default()
}

fn set_timers(timers: Vec<TimerEntry>) {
    let mut guard = TIMERS.lock().unwrap_or_else(|e| e.into_inner());
    *guard = Some(timers);
}

pub fn timer_start(seconds: u64, name: Option<&str>) -> AuroraResult<Pipeline> {
    let name = name.unwrap_or("timer").to_string();
    let entry = TimerEntry {
        name: name.clone(),
        total_secs: seconds,
        started: Instant::now(),
    };

    let mut timers = get_timers();
    timers.push(entry);
    set_timers(timers);

    let name_clone = name.clone();
    std::thread::spawn(move || {
        std::thread::sleep(Duration::from_secs(seconds));
        let _ = std::io::Write::write_all(
            &mut std::io::stdout(),
            format!("\x07\x1b[1;32m=== Timer '{}' finished! ===\x1b[0m\n", name_clone).as_bytes(),
        );
    });

    Ok(Pipeline::table(
        vec!["name".into(), "seconds".into(), "status".into()],
        vec![vec![
            Value::String(name),
            Value::Int(seconds as i64),
            Value::String("started".into()),
        ]],
    ))
}

pub fn timer_stop() -> AuroraResult<Pipeline> {
    let timers = get_timers();
    let count = timers.len();
    set_timers(Vec::new());

    Ok(Pipeline::table(
        vec!["action".into(), "stopped".into()],
        vec![vec![
            Value::String("stop".into()),
            Value::Int(count as i64),
        ]],
    ))
}

pub fn timer_status() -> AuroraResult<Pipeline> {
    let timers = get_timers();
    let mut rows: Vec<Vec<Value>> = Vec::new();

    for timer in &timers {
        let elapsed = timer.started.elapsed().as_secs();
        let remaining = if elapsed >= timer.total_secs {
            0
        } else {
            timer.total_secs - elapsed
        };

        rows.push(vec![
            Value::String(timer.name.clone()),
            Value::Int(remaining as i64),
            Value::Int(timer.total_secs as i64),
        ]);
    }

    Ok(Pipeline::table(
        vec!["name".into(), "remaining".into(), "total".into()],
        rows,
    ))
}