Skip to content
Snippets Groups Projects
main.rs 2.51 KiB
#[macro_use]
extern crate lazy_static;

use clap::Parser;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader};

mod lol;

#[derive(Parser)]
#[command(
    author,
    about,
    version,
    after_help = "Examples:\n\tdotacat f - g\tOutput f's contents, then stdin, then g's contents.\n\tfortune | dotacat\tDisplay a rainbow cookie."
)]
struct CmdOpts {
    #[arg(short = 'p', long, default_value = "1.0")]
    /// Rainbow spread
    spread: f64,

    /// Rainbow frequency
    #[arg(short = 'F', long, default_value = "0.1")]
    freq: f64,

    /// Rainbow seed, 0 = random
    #[arg(short = 'S', long, default_value = "0.0")]
    seed: f64,

    /// Invert fg and bg
    #[arg(short = 'i', long)]
    invert: bool,

    /// Files to concatenate(`-` for STDIN)
    files: Vec<String>,
}

fn read_line() -> Option<(String, usize)> {
    let mut input = String::new();
    match stdin().read_line(&mut input) {
        Ok(n) => Some((input, n)),
        _ => None,
    }
}

fn main() {
    let opts: CmdOpts = CmdOpts::parse();

    let mut files = opts.files;
    if files.is_empty() {
        files.push("-".to_string());
    }

    let mut seed: f64 = opts.seed;
    if seed.abs() < 0.00001 {
        seed = rand::random::<f64>() * 1_000_000.0;
    }

    for file_path in files {
        if file_path == "-" {
            while let Some((x, n)) = read_line() {
                if lol::print_rainbow(&x, opts.freq, seed, opts.spread, opts.invert).is_err() {
                    std::process::exit(1);
                }
                if n == 0 {
                    // EOF
                    break;
                }
                seed += 1.0;
            }
        } else {
            let file = match File::open(&file_path) {
                Ok(x) => x,
                Err(e) => {
                    eprintln!("Could not open {file_path}: {e}.");
                    continue;
                }
            };
            let buf = BufReader::new(file);
            for x in buf.lines() {
                match x {
                    Ok(x) => {
                        if lol::print_rainbow(&x, opts.freq, seed, opts.spread, opts.invert)
                            .is_err()
                        {
                            std::process::exit(1);
                        }
                        seed += 1.0;
                    }
                    Err(e) => {
                        eprintln!("Error while reading {file_path}: {e}.");
                        continue;
                    }
                }
            }
        }
    }
}