Skip to content

Commit f862a3f

Browse files
authored
Merge pull request #18 from tamirelazar/fix/help-text
Fix CLI help text defaults, ranges, and pause-style list
2 parents 470f423 + 872afb2 commit f862a3f

2 files changed

Lines changed: 103 additions & 37 deletions

File tree

src/app/runner.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ fn check_auto_reset(
122122
}
123123
}
124124

125+
/// Returns `true` when a key event should immediately exit the application
126+
/// in screensaver mode.
127+
///
128+
/// Any key press exits; key release/repeat events (emitted on some platforms,
129+
/// e.g. Windows) are ignored so a single keystroke does not double-fire.
130+
fn screensaver_exit_on_key(mode: &Mode, key_event: &crossterm::event::KeyEvent) -> bool {
131+
*mode == Mode::Screensaver && key_event.kind == crossterm::event::KeyEventKind::Press
132+
}
133+
125134
/// Runs the interactive simulation loop (Live or Screensaver mode).
126135
///
127136
/// Handles terminal setup, input processing, simulation updates, and rendering
@@ -130,7 +139,7 @@ fn check_auto_reset(
130139
pub fn run_simulation(
131140
sim: &mut Simulation,
132141
args: &Args,
133-
_mode: Mode,
142+
mode: Mode,
134143
palette: cli::Palette,
135144
charset: Charset,
136145
) -> io::Result<()> {
@@ -1169,6 +1178,14 @@ pub fn run_simulation(
11691178
key_event.modifiers.contains(KeyModifiers::SHIFT);
11701179
}
11711180

1181+
// Screensaver mode: any key press exits (mouse events and
1182+
// resizes do not). Checked before overlay/control dispatch so
1183+
// no other handler can swallow the event.
1184+
if screensaver_exit_on_key(&mode, &key_event) {
1185+
should_exit = true;
1186+
break;
1187+
}
1188+
11721189
// GLOBAL EXIT HANDLING -- always allow 'q' to quit regardless of overlay
11731190
if InputPoller::is_exit_key(&key_event) {
11741191
should_exit = true;
@@ -2365,3 +2382,52 @@ pub fn get_terminal_size() -> (usize, usize) {
23652382
Err(_) => (80, 24),
23662383
}
23672384
}
2385+
2386+
#[cfg(test)]
2387+
mod tests {
2388+
use super::*;
2389+
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
2390+
2391+
fn key(code: KeyCode, kind: KeyEventKind) -> KeyEvent {
2392+
KeyEvent {
2393+
code,
2394+
modifiers: KeyModifiers::NONE,
2395+
kind,
2396+
state: KeyEventState::NONE,
2397+
}
2398+
}
2399+
2400+
#[test]
2401+
fn screensaver_exits_on_any_key_press() {
2402+
for code in [
2403+
KeyCode::Char('a'),
2404+
KeyCode::Char(' '),
2405+
KeyCode::Enter,
2406+
KeyCode::Esc,
2407+
KeyCode::Up,
2408+
KeyCode::F(1),
2409+
] {
2410+
assert!(
2411+
screensaver_exit_on_key(&Mode::Screensaver, &key(code, KeyEventKind::Press)),
2412+
"expected screensaver exit for {:?}",
2413+
code
2414+
);
2415+
}
2416+
}
2417+
2418+
#[test]
2419+
fn screensaver_ignores_key_release_and_repeat() {
2420+
let release = key(KeyCode::Char('a'), KeyEventKind::Release);
2421+
let repeat = key(KeyCode::Char('a'), KeyEventKind::Repeat);
2422+
assert!(!screensaver_exit_on_key(&Mode::Screensaver, &release));
2423+
assert!(!screensaver_exit_on_key(&Mode::Screensaver, &repeat));
2424+
}
2425+
2426+
#[test]
2427+
fn non_screensaver_modes_never_exit_on_key() {
2428+
let press = key(KeyCode::Char('a'), KeyEventKind::Press);
2429+
for mode in [Mode::Default, Mode::Live, Mode::Print] {
2430+
assert!(!screensaver_exit_on_key(&mode, &press));
2431+
}
2432+
}
2433+
}

0 commit comments

Comments
 (0)