feat: prompt reads from stdin in CLI (🌀/🎤 table rows, purple answer)
This commit is contained in:
parent
9589958cb1
commit
1ec82cd177
2 changed files with 50 additions and 29 deletions
|
|
@ -102,6 +102,47 @@ pub fn info_line(emoji: &str, key: &str, value: &str) {
|
||||||
println!(" {} {:<name_w$} {}", emoji_cell(emoji), key, value, name_w = NAME_W);
|
println!(" {} {:<name_w$} {}", emoji_cell(emoji), key, value, name_w = NAME_W);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print the prompt "awaiting input" row + the 🎤 answer input prefix.
|
||||||
|
/// The caller should read stdin immediately after this returns.
|
||||||
|
pub fn prompt_waiting(message: &str) {
|
||||||
|
let (payload_w, _result_w) = col_widths();
|
||||||
|
let p = trunc(message, payload_w);
|
||||||
|
// 🌀 row: show message + 🔄 + "awaiting input"
|
||||||
|
println!(
|
||||||
|
" {} {:<name_w$} {:<payload_w$} {} awaiting input",
|
||||||
|
emoji_cell("🌀"), "prompt", p, emoji_cell("🔄"),
|
||||||
|
name_w = NAME_W, payload_w = payload_w,
|
||||||
|
);
|
||||||
|
// 🎤 answer input prefix — no newline, user types here
|
||||||
|
print!(" {} {:<name_w$} › ", emoji_cell("🎤"), "answer", name_w = NAME_W);
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overwrite the 🌀 and 🎤 lines with the final state after input was received.
|
||||||
|
/// Must be called after the user pressed Enter (cursor is on the line after 🎤).
|
||||||
|
pub fn prompt_done(message: &str, answer: &str) {
|
||||||
|
let (payload_w, result_w) = col_widths();
|
||||||
|
let p = trunc(message, payload_w);
|
||||||
|
// Go up 2 lines (🎤 line + 🌀 line), rewrite both
|
||||||
|
print!("\x1b[2A\r\x1b[2K");
|
||||||
|
// Rewrite 🌀 row as done
|
||||||
|
println!(
|
||||||
|
" {} {:<name_w$} {:<payload_w$} {} done",
|
||||||
|
emoji_cell("🌀"), "prompt", p, emoji_cell("✅"),
|
||||||
|
name_w = NAME_W, payload_w = payload_w,
|
||||||
|
);
|
||||||
|
// Clear 🎤 line + rewrite with purple answer
|
||||||
|
print!("\r\x1b[2K");
|
||||||
|
let a = trunc(answer, payload_w + result_w + 4); // answer spans both columns
|
||||||
|
println!(
|
||||||
|
" {} {:<name_w$} {}",
|
||||||
|
emoji_cell("🎤"), "answer", a.purple(),
|
||||||
|
name_w = NAME_W,
|
||||||
|
);
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
crate::logger::write_line("OK", &format!("prompt → {answer}"));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn err(emoji: &str, msg: &str) {
|
pub fn err(emoji: &str, msg: &str) {
|
||||||
println!(" {} {}", emoji_cell(emoji), msg.red());
|
println!(" {} {}", emoji_cell(emoji), msg.red());
|
||||||
crate::logger::write_line("ERROR", msg);
|
crate::logger::write_line("ERROR", msg);
|
||||||
|
|
|
||||||
|
|
@ -360,35 +360,15 @@ async fn handle_message(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerMessage::PromptRequest { request_id, message, title } => {
|
ServerMessage::PromptRequest { request_id, message, title: _ } => {
|
||||||
let _title = title.unwrap_or_else(|| "Helios Remote".to_string());
|
display::prompt_waiting(&message);
|
||||||
#[cfg(windows)]
|
// Read user input from stdin (blocking)
|
||||||
let title = _title.clone();
|
let answer = tokio::task::spawn_blocking(|| {
|
||||||
let payload = trunc(&message, 60);
|
let mut input = String::new();
|
||||||
display::cmd_start("💬", "prompt", &payload);
|
std::io::stdin().read_line(&mut input).ok();
|
||||||
#[cfg(windows)]
|
input.trim().to_string()
|
||||||
{
|
}).await.unwrap_or_default();
|
||||||
use windows::core::PCWSTR;
|
display::prompt_done(&message, &answer);
|
||||||
use windows::Win32::UI::WindowsAndMessaging::{MessageBoxW, MB_OK, MB_ICONINFORMATION, HWND_DESKTOP};
|
|
||||||
let msg_wide: Vec<u16> = message.encode_utf16().chain(std::iter::once(0)).collect();
|
|
||||||
let title_wide: Vec<u16> = title.encode_utf16().chain(std::iter::once(0)).collect();
|
|
||||||
tokio::task::spawn_blocking(move || {
|
|
||||||
unsafe {
|
|
||||||
MessageBoxW(
|
|
||||||
HWND_DESKTOP,
|
|
||||||
PCWSTR(msg_wide.as_ptr()),
|
|
||||||
PCWSTR(title_wide.as_ptr()),
|
|
||||||
MB_OK | MB_ICONINFORMATION,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}).await.ok();
|
|
||||||
display::cmd_done("💬", "prompt", &payload, true, "confirmed");
|
|
||||||
}
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
println!(" [PROMPT] {}", message);
|
|
||||||
display::cmd_done("💬", "prompt", &payload, true, "shown");
|
|
||||||
}
|
|
||||||
ClientMessage::Ack { request_id }
|
ClientMessage::Ack { request_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue