From 24e3bb54db579fb9aad8df2a591527dc77fe4cb4 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 1 Nov 2026 19:19:49 +0100 Subject: v4.0.7: finish the Phase 1 boundary with a command shell The terminal command line moves to client::shell: a typed line becomes a core Command or an adapter action (connect, login, register, set-credential, host maintenance). ClientCore loses submit_line and the last TUI-shaped effects (Interactive, SetPrompt, ListHosts, ForgetHost, AnimateRoulette); the adapter animates roulette from the Result view. Adds forget-login, which drops the stored credential for the pinned key and keeps trust, distinct from logout (session only) and forget-host (trust too). --- tests/client_core.rs | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'tests/client_core.rs') diff --git a/tests/client_core.rs b/tests/client_core.rs index 722cf0d..49abca2 100644 --- a/tests/client_core.rs +++ b/tests/client_core.rs @@ -6,8 +6,10 @@ use std::time::Duration; use zagan_bet::blackjack::BlackjackState; -use zagan_bet::client::core::{ClientCore, Effect, InteractiveCommand}; +use zagan_bet::client::core::{ClientCore, Effect}; use zagan_bet::client::input::{game_input, Editor, GameInput, Input, Key}; +use zagan_bet::client::shell::{self, Shell}; +use zagan_bet::client::ui::help_lines; use zagan_bet::client::games::response::{ parse_blackjack_response, parse_crash_response, parse_spin_response, }; @@ -31,12 +33,7 @@ struct Screen { } impl Screen { - fn apply( - &mut self, - effects: &[Effect], - sent: &mut Vec, - interactive: &mut Vec, - ) { + fn apply(&mut self, effects: &[Effect], sent: &mut Vec) { for effect in effects { match effect { Effect::Print(lines) => self.lines.extend(lines.iter().cloned()), @@ -57,19 +54,8 @@ impl Screen { self.region_start = None; self.region_len = 0; } - Effect::AnimateRoulette { view, .. } => { - let lines = zagan_bet::client::tui::render_view(view); - if let Some(start) = self.region_start { - self.lines.truncate(start); - } else { - self.region_start = Some(self.lines.len()); - } - self.lines.extend(lines.iter().cloned()); - self.region_len = lines.len(); - } Effect::SendLine(line) => sent.push(line.clone()), - Effect::Interactive(command) => interactive.push(command.clone()), - Effect::Quit | Effect::Disconnect | Effect::ListHosts | Effect::ForgetHost(_) => {} + Effect::Quit | Effect::Disconnect => {} } } } @@ -87,7 +73,6 @@ struct Harness { editor: Editor, screen: Screen, sent: Vec, - interactive: Vec, } impl Harness { @@ -100,13 +85,11 @@ impl Harness { editor: Editor::new(), screen: Screen::default(), sent: Vec::new(), - interactive: Vec::new(), } } fn apply(&mut self, effects: Vec) { - self.screen - .apply(&effects, &mut self.sent, &mut self.interactive); + self.screen.apply(&effects, &mut self.sent); } fn key(&mut self, key: Key) { @@ -119,7 +102,7 @@ impl Harness { } else { match self.editor.handle(key) { Input::Quit => vec![Effect::Quit], - Input::Submit(line) => self.core.submit_line(&line), + Input::Submit(line) => self.dispatch(&line), Input::Print(lines) => vec![Effect::Print(lines)], Input::Prompt | Input::None => Vec::new(), } @@ -128,6 +111,26 @@ impl Harness { self.apply_prompt(); } + /// Route a submitted line the way the terminal adapter does. + fn dispatch(&mut self, line: &str) -> Vec { + match shell::parse(line) { + Shell::Run(command) => self.core.command(command), + Shell::Disconnect => { + self.core.reset_after_disconnect(); + vec![ + Effect::ClearRegion, + Effect::Print(vec!["Disconnected".to_string()]), + ] + } + Shell::Help => vec![Effect::Print(help_lines())], + Shell::Quit => vec![Effect::Quit], + Shell::Empty => Vec::new(), + Shell::Usage(message) => vec![Effect::Print(vec![message])], + // Connect/login prompts are adapter flows, not core state. + _ => Vec::new(), + } + } + fn apply_prompt(&mut self) { if self.core.is_in_game() { return; -- cgit v1.2.3