data_beans/interactive/
mod.rs1pub mod cutoff_tui;
17pub mod stat_tui;
18pub mod ui;
19
20use std::io::{self, IsTerminal, Write};
21
22pub fn tui_available() -> bool {
25 io::stdin().is_terminal() && io::stdout().is_terminal()
26}
27
28#[derive(Debug, Clone)]
30pub enum UserAction {
31 Proceed,
32 AdjustCutoffs(usize, usize),
33 Cancel,
34}
35
36pub fn prompt_user_action(
38 current_row_cutoff: usize,
39 current_col_cutoff: usize,
40) -> anyhow::Result<UserAction> {
41 println!("\nOptions:");
42 println!(" [p] Proceed with current cutoffs");
43 println!(" [a] Adjust cutoffs");
44 println!(" [c] Cancel");
45 print!("\nChoose an option (p/a/c): ");
46 io::stdout().flush()?;
47
48 let mut input = String::new();
49 io::stdin().read_line(&mut input)?;
50 let choice = input.trim().to_lowercase();
51
52 match choice.as_str() {
53 "p" | "proceed" | "y" | "yes" => Ok(UserAction::Proceed),
54 "c" | "cancel" | "n" | "no" => Ok(UserAction::Cancel),
55 "a" | "adjust" => {
56 let new_row_cutoff = prompt_cutoff_value("row", current_row_cutoff)?;
57 let new_col_cutoff = prompt_cutoff_value("column", current_col_cutoff)?;
58 Ok(UserAction::AdjustCutoffs(new_row_cutoff, new_col_cutoff))
59 }
60 _ => {
61 println!("Invalid choice. Cancelling operation.");
62 Ok(UserAction::Cancel)
63 }
64 }
65}
66
67fn prompt_cutoff_value(label: &str, current: usize) -> anyhow::Result<usize> {
69 print!("\nEnter new {} nnz cutoff (current: {}): ", label, current);
70 io::stdout().flush()?;
71
72 let mut input = String::new();
73 io::stdin().read_line(&mut input)?;
74
75 let value = input.trim().parse::<usize>().unwrap_or(current);
76 Ok(value)
77}
78
79pub fn confirm(message: &str) -> anyhow::Result<bool> {
81 print!("{} (y/n): ", message);
82 io::stdout().flush()?;
83
84 let mut input = String::new();
85 io::stdin().read_line(&mut input)?;
86 let choice = input.trim().to_lowercase();
87
88 Ok(matches!(choice.as_str(), "y" | "yes"))
89}