textplots 0.8.7

Terminal plotting library.
Documentation
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
use textplots::{Chart, ColorPlot, Shape};

const PRINT_LEN: usize = 100;
const PURPLE: rgb::RGB8 = rgb::RGB8::new(0xE0, 0x80, 0xFF);
const RED: rgb::RGB8 = rgb::RGB8::new(0xFF, 0x00, 0x00);
const GREEN: rgb::RGB8 = rgb::RGB8::new(0x00, 0xFF, 0x00);

const RUN_DURATION_S: u64 = 5;

fn main() {
    let should_run = Arc::new(AtomicBool::new(true));
    let should_run_ctrlc_ref = should_run.clone();

    let mut x: [(f32, f32); PRINT_LEN] = [(0., 0.); PRINT_LEN];
    let mut y: [(f32, f32); PRINT_LEN] = [(0., 0.); PRINT_LEN];
    let mut z: [(f32, f32); PRINT_LEN] = [(0., 0.); PRINT_LEN];

    // hide the cursor so we don't see it flying all over
    let term = console::Term::stdout();
    term.hide_cursor().unwrap();
    term.clear_screen().unwrap();

    // On ctrl+C, reset terminal settings and let the thread know to stop
    ctrlc::set_handler(move || {
        should_run_ctrlc_ref
            .as_ref()
            .store(false, Ordering::Relaxed);
    })
    .unwrap();

    // run until we get ctrl+C or timeout
    let mut time: f32 = 0.;
    let start_time = std::time::SystemTime::now();
    while should_run.as_ref().load(Ordering::Acquire)
        && start_time.elapsed().unwrap().as_secs() < RUN_DURATION_S
    {
        // update our plotting data
        let x_val = time.sin();
        let y_val = (time + std::f32::consts::FRAC_PI_3).sin();
        let z_val = (time + 2. * std::f32::consts::FRAC_PI_3).sin();
        x.copy_within(1..PRINT_LEN, 0);
        y.copy_within(1..PRINT_LEN, 0);
        z.copy_within(1..PRINT_LEN, 0);
        x[PRINT_LEN - 1] = (0., x_val as f32);
        y[PRINT_LEN - 1] = (0., y_val as f32);
        z[PRINT_LEN - 1] = (0., z_val as f32);
        for index in 0..PRINT_LEN {
            x[index].0 += 1.;
            y[index].0 += 1.;
            z[index].0 += 1.;
        }

        time += std::f32::consts::PI / 50.;

        // update our plot
        term.move_cursor_to(0, 0).unwrap();
        Chart::new_with_y_range(200, 100, 0., PRINT_LEN as f32, -1.5, 1.5)
            .linecolorplot(&Shape::Lines(&x), RED)
            .linecolorplot(&Shape::Lines(&y), GREEN)
            .linecolorplot(&Shape::Lines(&z), PURPLE)
            .display();

        std::thread::sleep(std::time::Duration::from_millis(10));
    }

    // re-reveal the cursor
    let term = console::Term::stdout();
    term.show_cursor().unwrap();
}