pub mod app;
use std::process;
use clearscreen::clear;
use crate::io_util::{input_optional_repeat, input_other_repeat};
use self::app::BasicApp;
const MENU_WHOLE_LINE: &str = "========================================\n";
const MENU_EMPTY_LINE: &str = "= =\n";
pub fn build_menu_string(options: &[&str], exit_text: &str) -> String {
let mut menu = String::new();
menu.push_str(MENU_WHOLE_LINE);
menu.push_str(MENU_EMPTY_LINE);
for (index, option) in options.iter().enumerate() {
let option = format!("{} --- {}", index + 1, option);
menu.push_str(&format!("={:^38}=\n", option));
menu.push_str(MENU_EMPTY_LINE);
}
let exit_text = format!("0 --- {}", exit_text);
menu.push_str(&format!("={:^38}=\n", exit_text));
menu.push_str(MENU_EMPTY_LINE);
menu.push_str(MENU_WHOLE_LINE);
menu
}
pub fn start_app<T>(apps: &mut [T])
where
T: BasicApp,
{
let options: Vec<&'static str> =
apps.iter().map(|app| app.app_name()).collect();
let menu = build_menu_string(options.as_slice(), "Exit");
loop {
clear().unwrap_or_default();
println!("{}", menu);
let input: usize = input_other_repeat("");
match input {
0 => {
clear().unwrap_or_default();
process::exit(0)
}
input if input <= apps.len() => apps[input - 1].menu(),
_ => continue,
}
}
}
type NameAndFunc<'a, T> = (&'a str, fn(&mut T));
pub fn start_menu<T>(app: &mut T, menu_options: &[NameAndFunc<T>])
where
T: BasicApp,
{
let menu = build_menu_string(
menu_options
.iter()
.map(|v| v.0)
.collect::<Vec<_>>()
.as_slice(),
"Back to Main Menu",
);
loop {
clearscreen::clear().unwrap_or_default();
println!("{}", menu);
let input: usize = input_other_repeat("");
match input {
0 => return,
n if n <= menu_options.len() => menu_options[n - 1].1(app),
_ => continue,
}
}
}
pub fn build_options(
description: &str,
options: &[&str],
default: Option<usize>,
) -> String {
let mut option_menu = String::new();
option_menu.push_str(&format!("{}\n", description));
for (index, option) in options.iter().enumerate() {
let additional_text = match default {
Some(value) if value == index + 1 => " (Default)",
_ => "",
};
option_menu.push_str(&format!(
" {} --- {}{}\n",
index + 1,
option,
additional_text
));
}
option_menu
}
pub fn get_option(description: &str, options: &[&str]) -> usize {
let menu = build_options(description, options, None);
let len = options.len();
loop {
match input_other_repeat::<usize>(&menu) {
n if (1..=len).contains(&n) => return n,
_ => continue,
}
}
}
pub fn get_option_or_default(
description: &str,
options: &[&str],
default: usize,
) -> usize {
let menu = build_options(description, options, Some(default));
let len = options.len();
println!("{}", menu);
loop {
let value: usize = match input_optional_repeat("", default) {
v if (1..=len).contains(&v) => v,
_ => {
println!("Invalid Option!");
continue;
}
};
return value;
}
}