use std::{collections::HashMap, fs, path::Path};
use super::{ascii::get_builtin_ascii_art, colors::get_builtin_distro_colors};
pub const DEFAULT_ANSI_ALL_COLORS: [&str; 16] = [
"\x1b[1;30m", "\x1b[1;31m", "\x1b[1;32m", "\x1b[1;33m", "\x1b[1;34m", "\x1b[1;35m", "\x1b[1;36m", "\x1b[1;37m", "\x1b[1;90m", "\x1b[1;91m", "\x1b[1;92m", "\x1b[1;93m", "\x1b[1;94m", "\x1b[1;95m", "\x1b[1;96m", "\x1b[1;97m", ];
pub fn get_bar(percent: u8) -> String {
let total_blocks = 14;
let filled_blocks = (percent as usize * total_blocks) / 100;
let empty_blocks = total_blocks - filled_blocks;
let filled = "█".repeat(filled_blocks);
let empty = "░".repeat(empty_blocks);
format!("[{}{}]", filled, empty)
}
pub fn get_terminal_color(color_blocks: &str) -> Vec<String> {
let color_codes: [u8; 8] = [30, 31, 32, 33, 34, 35, 36, 37];
let mut normal = Vec::with_capacity(8);
let mut bold = Vec::with_capacity(8);
for &code in &color_codes {
normal.push(format!("\x1b[{}m{}\x1b[0m", code, color_blocks)); bold.push(format!("\x1b[1;{}m{}\x1b[0m", code, color_blocks)); }
vec![normal.join(""), bold.join("")]
}
pub fn get_custom_ascii(custom_path: &str) -> String {
if let Ok(content) = fs::read_to_string(Path::new(custom_path)) {
return content;
}
"".to_string()
}
pub fn get_ascii_and_colors(ascii_distro: &str) -> String {
if ascii_distro == "off" {
return "".to_string();
}
let ascii_art = get_builtin_ascii_art(ascii_distro);
ascii_art.to_string()
}
pub fn colorize_text(input: String, colors: &HashMap<&str, &str>) -> String {
let mut result = String::new();
for line in input.lines() {
let mut colored = line.to_owned();
for (key, code) in colors {
let placeholder = format!("${{{}}}", key);
colored = colored.replace(&placeholder, code);
}
result.push_str(&colored);
result.push('\n');
}
result
}
pub fn color_palette(
entries: &[(&'static str, &'static str)],
) -> HashMap<&'static str, &'static str> {
let mut map = HashMap::new();
for (k, v) in entries {
map.insert(*k, *v);
if let Some(code) = v.strip_prefix("\x1b[0;") {
let bold_code = format!("\x1b[1;{}", code);
let bold_key = format!("bold.{}", k);
map.insert(
Box::leak(bold_key.into_boxed_str()),
Box::leak(bold_code.into_boxed_str()),
);
}
}
map.insert("reset", "\x1b[0m");
map
}
pub fn get_colors_in_order(color_order: &[u8]) -> HashMap<&'static str, &'static str> {
let mut entries: Vec<(&'static str, &'static str)> = vec![("c0", "\x1b[1;30m")];
let mut used = vec![false; 16];
for (i, &idx) in color_order.iter().enumerate() {
if idx < 16 {
let key: &'static str = Box::leak(format!("c{}", i + 1).into_boxed_str());
entries.push((key, DEFAULT_ANSI_ALL_COLORS[idx as usize]));
used[idx as usize] = true;
}
}
let mut next_index = color_order.len() + 1;
for (i, &color) in DEFAULT_ANSI_ALL_COLORS.iter().enumerate() {
if !used[i] {
let key: &'static str = Box::leak(format!("c{}", next_index).into_boxed_str());
entries.push((key, color));
next_index += 1;
}
}
let mut map = color_palette(&entries);
map.insert("reset", "\x1b[0m");
map
}
pub fn get_custom_colors_order(colors_str_order: &str) -> HashMap<&'static str, &'static str> {
let custom_color_str_list: Vec<&str> = colors_str_order.split(',').map(str::trim).collect();
let all_parsed: Option<Vec<u8>> = custom_color_str_list
.iter()
.map(|s| s.parse::<u8>().ok())
.collect();
let color_list: Vec<u8> = if let Some(list) = all_parsed {
list
} else {
get_builtin_distro_colors(colors_str_order).to_vec()
};
get_colors_in_order(&color_list)
}
pub fn get_distro_colors(distro: &str) -> HashMap<&'static str, &'static str> {
let dist_color = get_builtin_distro_colors(distro);
get_colors_in_order(dist_color)
}