Skip to main content

sl/
lib.rs

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
17/// Runs the SL animation with the given arguments.
18pub 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        // Unified input handler
34        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        // If paused, wait for resume signal without advancing animation
46        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}