59 lines
1.4 KiB
Rust
59 lines
1.4 KiB
Rust
use crossterm::{
|
|
cursor,
|
|
event::{self, Event, KeyCode},
|
|
queue,
|
|
style::{Color, Colors, ResetColor, SetColors},
|
|
terminal,
|
|
};
|
|
use std::io::{stdout, Write};
|
|
|
|
pub fn read_yes_no(prompt: &str, default: bool) -> bool {
|
|
let options = if default { "Y/n" } else { "y/N" };
|
|
let prompt = format!("{prompt} [{options}]: ");
|
|
match read_line(&prompt).and_then(|s| s.chars().next()) {
|
|
Some('Y' | 'y') => true,
|
|
Some('N' | 'n') => false,
|
|
_ => default,
|
|
}
|
|
}
|
|
|
|
pub fn read_line(prompt: &str) -> Option<String> {
|
|
let mut response = String::new();
|
|
let size = terminal::size().unwrap();
|
|
let start_pos = cursor::MoveTo(0, size.1);
|
|
let width = size.0 as usize;
|
|
|
|
queue!(stdout(), start_pos).unwrap();
|
|
print!("{:width$}", " ");
|
|
queue!(stdout(), start_pos).unwrap();
|
|
print!("{prompt}");
|
|
stdout().flush().unwrap();
|
|
|
|
loop {
|
|
if let Ok(Event::Key(event)) = event::read() {
|
|
match event.code {
|
|
KeyCode::Enter => break,
|
|
KeyCode::Char(ch) => response.push(ch),
|
|
KeyCode::Backspace => {
|
|
queue!(stdout(), start_pos).unwrap();
|
|
print!("{:width$}", " ");
|
|
response.pop();
|
|
}
|
|
KeyCode::Esc => return None,
|
|
_ => (),
|
|
}
|
|
}
|
|
queue!(stdout(), start_pos).unwrap();
|
|
print!("{prompt}{response}");
|
|
stdout().flush().unwrap();
|
|
}
|
|
Some(response.trim().into())
|
|
}
|
|
|
|
pub fn color_highlight() {
|
|
queue!(stdout(), SetColors(Colors::new(Color::Black, Color::White))).unwrap();
|
|
}
|
|
|
|
pub fn color_reset() {
|
|
queue!(stdout(), ResetColor).unwrap();
|
|
}
|