wipe/src/main.rs

151 lines
4.8 KiB
Rust
Raw Normal View History

2022-04-09 11:01:36 +00:00
use std::io::stdout;
2022-04-09 15:05:43 +00:00
use std::time::Duration;
2022-04-09 10:56:57 +00:00
use anyhow::Error;
2022-04-02 15:19:48 +00:00
use clap::Parser;
2022-04-09 10:56:57 +00:00
use clap::ArgEnum;
2022-04-09 16:25:45 +00:00
use rand::rngs::OsRng;
2022-04-09 10:56:57 +00:00
use crate::animation::Animation;
use crate::animation::circle::CircleAnimation;
2022-04-09 17:29:30 +00:00
use crate::animation::rhombus::RhombusAnimation;
use crate::animation::rotation::RotationAnimation;
2022-04-09 11:01:36 +00:00
use crate::char::SimpleCharSampler;
2022-04-09 16:25:45 +00:00
use crate::choose::{Chooser, Options};
2022-04-09 10:56:57 +00:00
use crate::color::{ColorSampler, SimpleColorSampler};
use crate::fill::circle::CircleFillMode;
use crate::fill::FillMode;
use crate::fill::level::LevelFillMode;
2022-04-09 17:29:30 +00:00
use crate::fill::stripes::StripesFillMode;
2022-04-09 14:07:49 +00:00
use crate::render::{Renderer, SamplerRenderer};
2022-04-09 15:05:43 +00:00
use crate::runner::Runner;
2022-04-09 11:01:36 +00:00
use crate::sampler::ComposedSampler;
use crate::surface::WriteSurface;
2022-04-09 15:05:43 +00:00
use crate::timer::SimpleTimer;
2022-04-09 10:56:57 +00:00
use crate::vec::Vector;
2022-04-02 15:19:48 +00:00
2022-04-03 12:44:26 +00:00
mod color;
2022-04-02 15:20:52 +00:00
mod char;
2022-04-02 15:25:35 +00:00
mod fill;
mod vec;
2022-04-03 14:03:28 +00:00
mod array;
2022-04-06 16:39:20 +00:00
mod surface;
2022-04-08 16:59:52 +00:00
mod animation;
2022-04-08 18:05:00 +00:00
mod sampler;
2022-04-09 14:07:49 +00:00
mod render;
2022-04-09 15:05:43 +00:00
mod timer;
mod runner;
2022-04-09 16:25:45 +00:00
mod choose;
2022-04-02 15:19:48 +00:00
2022-04-09 17:37:57 +00:00
macro_rules! options {
($name:ident { $($opt:ident,)* }) => {
#[derive(Copy, Clone, ArgEnum)]
enum $name {
$($opt,)*
}
impl Options for $name {
fn all() -> Vec<Self> {
vec![$($name::$opt,)*]
}
}
2022-04-09 16:25:45 +00:00
}
}
2022-04-09 17:37:57 +00:00
options!(AnimationType {
Circle,
Rhombus,
Rotation,
});
options!(ColorType {
2022-04-09 10:56:57 +00:00
Red,
Green,
Blue,
LightRed,
LightGreen,
LightBlue,
Grey,
Rainbow,
2022-04-09 17:37:57 +00:00
});
2022-04-09 10:56:57 +00:00
2022-04-09 17:37:57 +00:00
options!(FillModeType {
2022-04-09 10:56:57 +00:00
Circle,
2022-04-09 17:29:30 +00:00
Level,
2022-04-09 17:37:57 +00:00
Stripes,
});
2022-04-09 16:25:45 +00:00
2022-04-02 15:19:48 +00:00
#[derive(Parser)]
2022-04-09 17:37:57 +00:00
#[clap(author = env ! ("CARGO_PKG_AUTHORS"), version = env ! ("CARGO_PKG_VERSION"), about = env ! ("CARGO_PKG_DESCRIPTION"))]
2022-04-02 15:19:48 +00:00
struct Args {
2022-04-09 10:56:57 +00:00
#[clap(short, long, help = "Add animation", arg_enum)]
animation: Vec<AnimationType>,
#[clap(short, long, help = "Add fill mode", arg_enum)]
fill: Vec<FillModeType>,
#[clap(short, long, help = "Add color pallet", arg_enum)]
color: Vec<ColorType>,
2022-04-02 15:20:52 +00:00
#[clap(long, default_value = ".-+%#", help = "Set chars")]
2022-04-09 10:56:57 +00:00
chars: String,
2022-04-09 16:25:45 +00:00
#[clap(long, default_value = "30", help = "Set frames per second")]
fps: u64,
#[clap(long, default_value = "1000", help = "Set duration [milliseconds]")]
duration: u64,
2022-04-09 10:56:57 +00:00
#[clap(long, help = "Set width [default: terminal width]")]
width: Option<usize>,
#[clap(long, help = "Set height [default: terminal height]")]
height: Option<usize>,
}
fn main() -> Result<(), Error> {
let args = Args::parse();
2022-04-09 16:25:45 +00:00
let mut chooser = Chooser::new(OsRng::default());
2022-04-09 10:56:57 +00:00
let terminal = crossterm::terminal::size()?;
let width = args.width.unwrap_or(terminal.0 as usize);
2022-04-09 16:25:45 +00:00
let height = args.height.unwrap_or(terminal.1 as usize);
2022-04-09 10:56:57 +00:00
let size = Vector::from_terminal(width, height);
2022-04-09 16:25:45 +00:00
let delay = Duration::from_micros(1_000_000 / args.fps);
let duration = Duration::from_millis(args.duration);
2022-04-09 10:56:57 +00:00
2022-04-09 16:25:45 +00:00
let animation = create_animation(chooser.choose(args.animation), size);
let fill = create_fill(chooser.choose(args.fill), size);
let color = create_color(chooser.choose(args.color));
2022-04-09 11:01:36 +00:00
let char = Box::new(SimpleCharSampler::new(args.chars));
2022-04-09 15:12:34 +00:00
let sampler = ComposedSampler::new(animation, fill, color, char);
2022-04-09 16:25:45 +00:00
let surface = WriteSurface::new(stdout(), width, height);
2022-04-09 14:07:49 +00:00
2022-04-09 15:12:34 +00:00
let renderer = SamplerRenderer::new(surface, sampler);
2022-04-09 16:25:45 +00:00
let timer = SimpleTimer::new(delay);
let runner = Runner::new(duration, timer, renderer);
2022-04-09 14:07:49 +00:00
2022-04-09 15:05:43 +00:00
runner.run()
2022-04-02 15:19:48 +00:00
}
2022-04-09 10:56:57 +00:00
fn create_animation(animation: AnimationType, size: Vector) -> Box<dyn Animation> {
match animation {
2022-04-09 17:29:30 +00:00
AnimationType::Circle => Box::new(CircleAnimation::new(size)),
AnimationType::Rhombus => Box::new(RhombusAnimation::new(size)),
AnimationType::Rotation => Box::new(RotationAnimation::new(size)),
2022-04-09 10:56:57 +00:00
}
2022-04-02 15:05:49 +00:00
}
2022-04-09 10:56:57 +00:00
fn create_fill(fill: FillModeType, size: Vector) -> Box<dyn FillMode> {
match fill {
FillModeType::Circle => Box::new(CircleFillMode::new(size)),
FillModeType::Level => Box::new(LevelFillMode::new()),
2022-04-09 17:29:30 +00:00
FillModeType::Stripes => Box::new(StripesFillMode::new(size))
2022-04-09 10:56:57 +00:00
}
}
fn create_color(color: ColorType) -> Box<dyn ColorSampler> {
2022-04-09 16:25:45 +00:00
use crossterm::style::Color::*;
2022-04-09 10:56:57 +00:00
match color {
ColorType::Red => Box::new(SimpleColorSampler::new(vec![Yellow, DarkYellow, Red])),
ColorType::Green => Box::new(SimpleColorSampler::new(vec![Cyan, DarkGreen, Green])),
ColorType::Blue => Box::new(SimpleColorSampler::new(vec![Magenta, DarkBlue, Blue])),
ColorType::LightRed => Box::new(SimpleColorSampler::new(vec![White, Yellow, Red])),
ColorType::LightGreen => Box::new(SimpleColorSampler::new(vec![White, Cyan, Green])),
ColorType::LightBlue => Box::new(SimpleColorSampler::new(vec![White, Blue, Magenta])),
ColorType::Grey => Box::new(SimpleColorSampler::new(vec![Black, Grey, White])),
ColorType::Rainbow => Box::new(SimpleColorSampler::new(vec![Magenta, Blue, Green, Yellow, Red]))
}
}