pub fn term() -> console::Term {
console::Term::stdout()
}
pub fn clear() {
let _ = std::process::Command::new("clear").status();
}
pub fn write(term: &console::Term, s: &dyn std::fmt::Display) {
let _ = term.write_str(format!("{}", s).as_str());
}
pub fn getch(term: &console::Term) -> char {
term.read_char().unwrap()
}
pub fn getche(term: &console::Term, ch: Option<char>) -> char {
let new_ch = term.read_char().unwrap();
let _ = match ch {
Some(c) => {
if new_ch != '\n' {
term.write_str(c.to_string().as_str())
} else {
term.write_str(" ".to_string().as_str())
}
}
None => term.write_str(new_ch.to_string().as_str()),
};
return new_ch;
}
pub fn bulk_getche(term: &console::Term, ch: Option<char>, n: u8) -> Vec<char> {
let mut chars: Vec<char> = Vec::new();
for _ in 0..n {
let x = getche(term, ch);
if x == '\n' {
break;
} else {
chars.push(x);
}
}
chars
}
pub fn getk(term: &console::Term) -> console::Key {
term.read_key().unwrap()
}
pub fn get_string(term: &console::Term, ch: Option<char>, n: u8) -> String {
use console::Key;
let mut charlist: Vec<char> = Vec::new();
let mut index: u8 = 0;
while index < n + 1 {
let x = getk(term);
match x {
Key::Enter => break,
Key::Char(s) => {
if index == n {
} else if index == charlist.len() as u8 {
charlist.push(s);
let _ = term.write_str(
format!(
"{}",
match ch {
Some(c) => c,
None => s,
}
)
.as_str(),
);
index += 1;
} else {
charlist[index as usize] = s;
let _ = term.write_str(
format!(
"{}",
match ch {
Some(c) => c,
None => s,
}
)
.as_str(),
);
index += 1;
}
}
Key::ArrowLeft => {
if index != 0 {
let _ = term.write_str("\x1b[D");
index -= 1;
}
}
Key::ArrowRight => {
if index != charlist.len() as u8 {
let _ = term.write_str("\x1b[C");
index += 1;
}
}
Key::Backspace => {
if index == charlist.len() as u8 && index != 0 {
charlist.pop();
let _ = term.write_str("\x1b[D \x1b[D");
index -= 1;
}
}
_ => (),
}
}
charlist.iter().fold(String::new(), |x, y| {
let mut z = x;
z.push(*y);
z
})
}
pub fn menu(term: &console::Term, items: Vec<&dyn core::fmt::Display>) -> u32 {
use console::Key;
let mut i = 0;
let mut new_i = 0;
for item in &items {
let _ = term.write_str(format!("{}\n", item).as_str());
}
for _ in &items {
let _ = term.write_str("\x1b[A\r");
}
loop {
let _ = term.write_str(
format!(
"\r\x1b[2K\x1b[38;2;0;0;0m\x1b[48;2;255;255;255m\
{}\
\x1b[m\x1b[?25l\
",
items[i]
)
.as_str(),
);
let key = getk(term);
match key {
Key::Enter => {
break;
}
Key::ArrowUp => {
if i != 0 {
new_i -= 1;
}
}
Key::ArrowDown => {
if i < items.len() - 1 {
new_i += 1;
}
}
_ => (),
}
if new_i != i {
let _ = term.write_str("\x1b[2K\r");
let _ = term.write_str(format!("{}", items[i]).as_str());
for _ in i..items.len() {
let _ = term.write_str("\x1b[B");
}
for _ in new_i..items.len() {
let _ = term.write_str("\x1b[A");
}
}
i = new_i;
}
for _ in 0..(items.len() - i) {
let _ = term.write_str("\x1b[B\x1b[2K\r");
}
for _ in &items {
let _ = term.write_str("\x1b[A\x1b[2K\r");
}
let _ = term.write_str("\x1b[?25h");
i as u32
}