//! Konsolen-REPL — Headless-Treiber für Tests und Betrieb ohne GPU. //! //! Liest Zeilen von stdin, gibt sie an `Session::exec` und druckt die //! Ausgabe. Befehls- und Dialoglogik liegen in `session`, damit das //! Fenster-Frontend dieselbe Session ohne Duplikat steuern kann. use std::io::{self, Write}; use crate::session::{Mode, Session}; pub fn run(mut session: Session, signals_path: &str) { println!("wds-Konsole — {} Signale aus {}. `help` für Befehle.", session.game.signals.len(), signals_path); // Reserviertes `[init]`-Signal: KV-Defaults setzen, bevor Stories laufen. for line in session.start() { println!("{line}"); } loop { let Some(input) = read_line(prompt_for(&session.mode)) else { break }; let r = session.exec(input.trim()); for line in r.output { println!("{line}"); } if r.quit { break; } } } /// Prompt je nach Zustand: Befehl, Dialog-Weiterblättern oder Choice-Wahl. fn prompt_for(mode: &Mode) -> &'static str { match mode { Mode::Dialog(d) if !d.choices.is_empty() => " wahl> ", Mode::Dialog(_) => " [Enter] ", Mode::Menu => "menü> ", Mode::FirstPerson => "spiel> ", Mode::Free => "> ", } } /// Zeile von stdin lesen; `None` bei EOF (Ctrl-D) oder Lesefehler. fn read_line(prompt: &str) -> Option { print!("{prompt}"); io::stdout().flush().ok(); let mut buf = String::new(); match io::stdin().read_line(&mut buf) { Ok(0) | Err(_) => None, Ok(_) => Some(buf.trim_end().to_string()), } }