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