use crossterm::{
cursor::{Hide, MoveLeft, MoveRight, MoveUp, Show},
event::{self, Event, KeyCode, KeyEvent},
execute,
style::{Color, Print, ResetColor, SetForegroundColor},
terminal::{disable_raw_mode, enable_raw_mode},
};
use unicode_segmentation::UnicodeSegmentation;
use std::io::stdout;
use std::{thread, time};
pub fn select_from_list(list: &[String], selected: Option<usize>) -> usize {
let mut selection = selected.unwrap_or(0);
let color = get_color();
execute!(stdout(), Hide).expect("Failed to write hide cursor");
enable_raw_mode().expect("Failed to enable raw mode");
loop {
write_list(&list, selection, color);
if let Event::Key(KeyEvent { code, .. }) = event::read().expect("Failed to read event") {
match code {
KeyCode::Esc => {
execute!(stdout(), Show).expect("Failed to write show cursor");
disable_raw_mode().expect("Failed to enable raw mode");
std::process::exit(0)
}
KeyCode::Enter => break,
KeyCode::Up => {
if selection > 0 {
selection -= 1;
}
}
KeyCode::Down => {
if selection < (list.len() - 1) {
selection += 1;
}
}
_ => {}
}
}
clear_list(&list);
thread::sleep(time::Duration::from_millis(50));
}
execute!(stdout(), Show).expect("Failed to write show cursor");
disable_raw_mode().expect("Failed to enable raw mode");
selection
}
pub fn write_column(first: String, second: String, offset: Option<usize>) {
let offset = offset.unwrap_or(20);
let diff = offset - first.graphemes(true).count();
execute!(stdout(), MoveLeft(1), Print(first)).expect("Failed to write first column");
execute!(
stdout(),
MoveRight(diff as u16),
Print(format!("{}\n\r", second))
)
.expect("Failed to write second column");
}
fn write_list(list: &[String], selection: usize, color: Color) {
for (i, item) in list.iter().enumerate() {
if i == selection {
execute!(
stdout(),
SetForegroundColor(color),
Print(format!("{}\n\r", item)),
ResetColor
)
.expect("Failed to write list");
} else {
execute!(stdout(), ResetColor, Print(format!("{}\n\r", item))).expect("Failed to write list");
}
}
execute!(stdout(), ResetColor).expect("Failed to write reset color");
}
fn clear_list(list: &[String]) {
for _ in list {
execute!(stdout(), MoveUp(1)).expect("Failed to write cursor up");
}
}
fn get_color() -> Color {
let conf = crate::config::get_gut_config();
let selected = match conf.get("color") {
Some(color) => color.to_string(),
None => "Red".to_string(),
};
if selected.contains("Black") {
return Color::Black;
} else if selected.contains("Red") {
return Color::Red;
} else if selected.contains("Green") {
return Color::Green;
} else if selected.contains("Yellow") {
return Color::Yellow;
} else if selected.contains("Blue") {
return Color::Blue;
} else if selected.contains("Magenta") {
return Color::Magenta;
} else if selected.contains("Cyan") {
return Color::Cyan;
} else if selected.contains("White") {
return Color::White;
} else {
return Color::Red;
}
}