From 86d5f832c8452aad2313489b82eb8fd514215b95 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 22:28:20 +0100 Subject: v0.2.3: add ClientCore and fix the game board rendering --- src/client/ui.rs | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/client/ui.rs (limited to 'src/client/ui.rs') diff --git a/src/client/ui.rs b/src/client/ui.rs new file mode 100644 index 0000000..036c36a --- /dev/null +++ b/src/client/ui.rs @@ -0,0 +1,143 @@ +//! Pure text/history helpers for the client TUI. +//! +//! Nothing here touches the terminal, so it is unit-tested from `tests/` +//! without a PTY. + +struct CommandHelp { + name: &'static str, + usage: &'static str, + description: &'static str, +} + +const COMMANDS: &[CommandHelp] = &[ + CommandHelp { + name: "connect", + usage: "connect :", + description: "connect to the server", + }, + CommandHelp { + name: "send", + usage: "send ", + description: "send a message to the server", + }, + CommandHelp { + name: "disconnect", + usage: "disconnect", + description: "disconnect from the server", + }, + CommandHelp { + name: "ping", + usage: "ping", + description: "ping the server", + }, + CommandHelp { + name: "login", + usage: "login", + description: "login to the server", + }, + CommandHelp { + name: "register", + usage: "register", + description: "register a new user", + }, + CommandHelp { + name: "setcred", + usage: "setcred", + description: "set credentials for a host", + }, + CommandHelp { + name: "logout", + usage: "logout", + description: "logout from the server", + }, + CommandHelp { + name: "info", + usage: "info", + description: "show account and connection info", + }, + CommandHelp { + name: "play", + usage: "play [bet]", + description: "start a game (e.g. play slots 50)", + }, + CommandHelp { + name: "games", + usage: "games", + description: "list available games", + }, + CommandHelp { + name: "help", + usage: "help", + description: "show this message", + }, + CommandHelp { + name: "forget-host", + usage: "forget-host [ip:port]", + description: "clear saved trust fingerprint and credentials", + }, + CommandHelp { + name: "hosts", + usage: "hosts", + description: "list remembered hosts", + }, + CommandHelp { + name: "quit", + usage: "quit", + description: "quit the program", + }, +]; + +pub fn command_names() -> Vec<&'static str> { + COMMANDS.iter().map(|command| command.name).collect() +} + +pub fn help_lines() -> Vec { + let mut lines = vec!["Available commands:".to_string()]; + for command in COMMANDS { + lines.push(format!( + " {:<28} - {}", + command.usage, command.description + )); + } + lines +} + +/// Add a command to the history, skipping blanks and consecutive duplicates. +pub fn record_history(history: &mut Vec, line: &str) { + let line = line.trim(); + if line.is_empty() { + return; + } + if history.last().is_some_and(|last| last == line) { + return; + } + history.push(line.to_string()); +} + +/// Parse the optional bet argument of `play [bet]`. +pub fn parse_bet_arg(raw: &str) -> Result { + let bet = raw + .trim() + .parse::() + .map_err(|_| format!("Invalid bet: {raw}"))?; + if bet < 10 { + return Err("Bet must be at least 10 PLN".to_string()); + } + Ok(bet) +} + +/// Lines to move the cursor up to reach the first line of a region that ends +/// on the current line. `render()` has no trailing newline, so a 7-line board +/// needs `MoveUp(6)`. +pub fn lines_to_move_up(previous_lines: usize) -> u16 { + previous_lines + .saturating_sub(1) + .min(u16::MAX as usize) as u16 +} + +/// Column (0-based) to move to after the given prompt and input text. +pub fn input_cursor_column(prompt_len: usize, input_len: usize) -> u16 { + prompt_len + .saturating_add(input_len) + .min(u16::MAX as usize) as u16 +} -- cgit v1.2.3