Cleanup
This commit is contained in:
+39
-7
@@ -27,7 +27,12 @@
|
||||
//! Dispatch-Reihenfolge: erst Signal-Lookup; steht der Name in der Table,
|
||||
//! laufen alle gemappten Actions. Sonst wird der String direkt als
|
||||
//! Builtin-Aufruf probiert — so wirken Ink-Tags wie `# set has_key true`
|
||||
//! ohne Umweg über signals.toml. Unbekannte Verben werden still ignoriert.
|
||||
//! ohne Umweg über signals.toml.
|
||||
//!
|
||||
//! Unbekannte Verben: aus einer signals.toml-*Action* sind sie immer ein
|
||||
//! Tippfehler und werden nach stderr gemeldet. Im Ink-Tag-Fall-Through bleiben
|
||||
//! sie hingegen still — Tags dürfen bewusst reine Metadaten sein, die (noch)
|
||||
//! kein Verb konsumiert (z.B. ein späteres `# speaker …`).
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs::read_to_string;
|
||||
@@ -51,17 +56,27 @@ pub fn signal_key(name: &str) -> &str {
|
||||
}
|
||||
|
||||
pub fn dispatch(signal: &str, ctx: &mut ActionCtx) {
|
||||
// Signal-Name in der Table? Dann alle gemappten Actions ausführen.
|
||||
// Signal-Name in der Table? Dann alle gemappten Actions ausführen. Ein
|
||||
// unbekanntes Verb in einer Action ist hier immer ein Tippfehler → melden.
|
||||
if let Some(actions) = ctx.signals.get(signal) {
|
||||
let actions = actions.clone(); // entkoppelt vom ctx.signals-Borrow
|
||||
for a in &actions { execute(a, ctx); }
|
||||
for a in &actions {
|
||||
if !execute(a, ctx) {
|
||||
eprintln!("[signal] {signal:?}: unbekanntes Verb in Action {a:?} \
|
||||
— Tippfehler in signals.toml?");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Sonst direkt als Builtin probieren (Ink-Tag-Pfad).
|
||||
execute(signal, ctx);
|
||||
// Sonst direkt als Builtin probieren (Ink-Tag-Pfad). Unbekanntes bleibt
|
||||
// hier still (Tags dürfen bloße Metadaten sein) — Rückgabe verworfen.
|
||||
let _ = execute(signal, ctx);
|
||||
}
|
||||
|
||||
fn execute(cmd: &str, ctx: &mut ActionCtx) {
|
||||
/// Führt einen einzelnen Befehl (`verb args`) aus. Rückgabe: `true`, wenn das
|
||||
/// Verb bekannt war und lief; `false` bei unbekanntem Verb (der Aufrufer
|
||||
/// entscheidet, ob das eine Meldung wert ist — siehe `dispatch`).
|
||||
fn execute(cmd: &str, ctx: &mut ActionCtx) -> bool {
|
||||
// $self → ctx.instance_name. Substituieren bevor wir Verb/Args splitten,
|
||||
// damit Tokens wie `hide_object $self` einheitlich funktionieren. Ohne
|
||||
// instance_name (z.B. `init`-Signal) bleibt `$self` stehen — die Action
|
||||
@@ -87,8 +102,9 @@ fn execute(cmd: &str, ctx: &mut ActionCtx) {
|
||||
"mode" => if let Some(t) = ModeTarget::parse(args) {
|
||||
ctx.actions.push(Action::SetMode(t));
|
||||
},
|
||||
_ => { /* Unbekannter Verb/Tag → still ignorieren */ }
|
||||
_ => return false, // Unbekanntes Verb — der Aufrufer meldet ggf.
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Parst das signals.toml-Subset: `[signal]`-Header gefolgt von einem
|
||||
@@ -195,6 +211,22 @@ mod tests {
|
||||
assert!(game.actions.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typo_verb_in_table_is_tolerated_and_reported() {
|
||||
// Ein Tippfehler-Verb in einer Table-Action wird gemeldet (stderr) und
|
||||
// bleibt ohne Wirkung, während die gültige Nachbar-Action weiter läuft.
|
||||
let mut signals = Signals::new();
|
||||
signals.insert("thing".into(), vec![
|
||||
"st has_key true".into(), // Tippfehler für `set` → No-Op + Meldung
|
||||
"set ok true".into(), // gültig → wirkt
|
||||
]);
|
||||
let mut game = Game::new(signals);
|
||||
let mut ctx = game.action_ctx(None);
|
||||
dispatch("thing", &mut ctx);
|
||||
assert!(!game.kv.contains_key("has_key"), "Tippfehler darf nichts setzen");
|
||||
assert!(game.kv["ok"].coerce_to_bool().unwrap(), "gültige Action wirkt weiter");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_signal_falls_through_to_builtin() {
|
||||
let mut game = Game::new(Signals::new());
|
||||
|
||||
Reference in New Issue
Block a user