Something went wrong. Try again.
Minimal TUI for managing containerized projects
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122use std::io::Write;
use color_eyre::eyre::{ContextCompat, Result};use console::{Key, Term, style};use fuzzy_matcher::skim::SkimMatcherV2;use itertools::Itertools;
pub fn input_text(term: &mut Term, default: &str, name: &str) -> Result<String> { let mut text = default.to_string();
term.show_cursor()?; write!(term, "{}: {}", name, text)?;
loop { term.clear_line()?; write!(term, "{}: {}", name, text)?;
let key = match term.read_key() { Ok(key) => key, Err(err) => { term.show_cursor()?; return Err(err.into()); } };
match key { Key::Enter => { writeln!(term)?; term.hide_cursor()?; return Ok(text); } Key::Backspace => { text.pop(); } Key::Char(char) => { text += &char.to_string(); } _ => {} } }}
pub fn input_selection<T: Clone>(term: &mut Term, data: Vec<(String, T)>, name: &str) -> Result<T> { let mut filter = "".to_string();
write!(term, "{}:", name)?;
loop { let matcher = SkimMatcherV2::default(); let matches = data .iter() .filter_map(|(text, data)| { matcher .fuzzy(text, &filter, true) .map(|some| (data, text, some)) }) .sorted_by(|(_, _, fuzzy_a), (_, _, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) .enumerate() .map(|(index, (path, path_str, fuzzy))| { ( highlight_search(path_str, &fuzzy.1, index != 0), path, path_str, ) }) .collect_vec();
term.clear_line()?;
if matches.is_empty() { write!(term, "{}: {}", name, filter)?; } else { write!( term, "{}: {}", name, matches.iter().map(|(path, _, _)| path).join(" ") )?; }
let key = match term.read_key() { Ok(key) => key, Err(err) => { term.show_cursor()?; return Err(err.into()); } }; match key { Key::Enter => { let (_, data, text) = matches.first().context(format!("no {} Selected", name))?;
term.clear_line()?; writeln!(term, "{}: {}", name, text)?; break Ok((*data).clone()); } Key::Backspace => { filter.pop(); } Key::Char(char) => { filter += &char.to_string(); } _ => {} } }}
fn highlight_search(text: &str, highlighted_letters: &[usize], is_dark: bool) -> String { text.chars() .enumerate() .map(|(index, c)| { match (is_dark, highlighted_letters.contains(&index)) { (false, true) => style(c).red().to_string(), (false, false) => c.to_string(), //dark red (true, true) => style(c).color256(8).bold().to_string(), //light gray (true, false) => style(c).color256(8).to_string(), } }) .collect()}