term-saver 0.1.1

Have you ever wanted to install screensaver in your terminal? Please visit a therapist.
mod cli;

use clap::{error::ErrorKind, CommandFactory, Parser};
use cli::Cli;
use crossterm::{cursor, style, terminal, ExecutableCommand, QueueableCommand};
use std::{
    io::{self, Write},
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
    thread::sleep,
    time::Duration,
};

fn main() {
    let cli = Cli::parse();
    let mut cmd = Cli::command();

    if let Err(err) = term_saver(&cli.text, cli.moves_per_second) {
        cmd.error(ErrorKind::Io, err).exit()
    }
}

fn term_saver(text: &str, moves_per_second: u32) -> Result<(), io::Error> {
    let mut stdout = io::stdout();

    let text_length = text.chars().count() as u16;

    let mut moving_right = true;
    let mut moving_top = false;

    let mut x = 0;
    let mut y = 0;

    stdout
        .execute(cursor::Hide)?
        .execute(terminal::EnterAlternateScreen)?;

    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();

    let _ = ctrlc::set_handler(move || {
        r.store(false, Ordering::SeqCst);
    });

    let sleep_duration = Duration::new(0, 1_000_000_000 / moves_per_second);

    while running.load(Ordering::SeqCst) {
        stdout.execute(terminal::Clear(terminal::ClearType::CurrentLine))?;

        let (width, height) = crossterm::terminal::size()?;

        if moving_right {
            x += 1;
        } else {
            x -= 1;
        }

        if moving_top {
            y -= 1;
        } else {
            y += 1;
        }

        if x == width - text_length || x == 0 {
            moving_right = !moving_right;
        }

        if y == height - 1 || y == 0 {
            moving_top = !moving_top;
        }

        stdout
            .queue(cursor::MoveTo(x, y))?
            .queue(style::Print(text))?
            .flush()?;

        sleep(sleep_duration);
    }

    stdout
        .execute(cursor::Show)?
        .execute(terminal::LeaveAlternateScreen)?;

    Ok(())
}