diff options
Diffstat (limited to 'src/utils/input.rs')
| -rw-r--r-- | src/utils/input.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/utils/input.rs b/src/utils/input.rs new file mode 100644 index 0000000..ebcb3cf --- /dev/null +++ b/src/utils/input.rs @@ -0,0 +1,47 @@ +use anyhow::Result; +use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers}; +use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; +use std::io::{stdout, Write}; + +/// Reads a single character from stdin without requiring Enter +/// Returns the character if it's one of the valid options, or the default if Enter is pressed +pub fn read_single_key(valid_chars: &[char], default: char, prompt: &str) -> Result<char> { + print!("{prompt}"); + stdout().flush()?; + + enable_raw_mode()?; + + let result = loop { + if let Ok(Event::Key(KeyEvent { + code, modifiers, .. + })) = event::read() + { + match code { + KeyCode::Char('c') if modifiers.contains(KeyModifiers::CONTROL) => { + break Err(anyhow::anyhow!("Interrupted")); + } + KeyCode::Char(c) => { + if valid_chars.contains(&c) { + break Ok(c); + } + // Invalid character, continue loop + } + KeyCode::Enter => { + break Ok(default); + } + _ => { + // Other keys are ignored, continue loop + } + } + } + }; + + disable_raw_mode()?; + + // Print the chosen character and newline for clean output + if let Ok(chosen) = &result { + println!("{chosen}"); + } + + result +} |
