1pub mod terminal;
2pub mod train;
3pub mod smoke;
4pub mod config;
5pub mod render;
6pub mod debug;
7
8use crate::terminal::{Terminal, InputAction};
9use crate::config::Config;
10use crate::render::render_frame;
11use std::thread;
12use std::time::Duration;
13use std::io;
14
15const FRAME_TIME_MS: u64 = 40;
16
17pub fn run<I, T>(args: I) -> io::Result<()>
19where
20 I: IntoIterator<Item = T>,
21 T: AsRef<str>,
22{
23 let config = Config::from_args(args);
24 let terminal = Terminal::new()?;
25
26 let width = terminal.width() as i32;
27 let max_length = if config.logo { 40 } else if config.c51 { 95 } else { 83 };
28
29 let mut pattern = 0usize;
30 let mut paused = false;
31
32 for x in (-(max_length + 10)..=(width + 10)).rev() {
33 match terminal.check_input()? {
35 InputAction::Quit => break,
36 InputAction::Pause => {
37 paused = !paused;
38 if paused {
39 eprintln!("⏸️ PAUSED - Press Space or P to resume, Ctrl+C to quit");
40 }
41 }
42 InputAction::None => {}
43 }
44
45 while paused {
47 thread::sleep(Duration::from_millis(100));
48 match terminal.check_input()? {
49 InputAction::Pause => {
50 paused = false;
51 eprintln!("▶️ RESUMED");
52 }
53 InputAction::Quit => return Ok(()),
54 InputAction::None => {}
55 }
56 }
57
58 render_frame(&terminal, x, pattern, &config)?;
59
60 pattern = (pattern + 1) % 6;
61 thread::sleep(Duration::from_millis(FRAME_TIME_MS));
62 }
63
64 Ok(())
65}