1use md5::{Md5, Digest};
2use std::process::Command as ProcessCommand;
3
4pub mod theme_maps;
5
6pub const BGCOLOR_ENV_VAR: &str = "PLGO_HOSTNAMEBG";
7pub const FGCOLOR_ENV_VAR: &str = "PLGO_HOSTNAMEFG";
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Rgb {
11 pub r: u8,
12 pub g: u8,
13 pub b: u8,
14 pub xterm: u8,
15}
16
17impl Rgb {
18 pub fn new(xterm: u8) -> Self {
19 let mut rgb = Rgb { r: 0, g: 0, b: 0, xterm };
20 rgb.to_rgb();
21 rgb
22 }
23
24 pub fn to_hex(self) -> String {
25 format!("{:02x}{:02x}{:02x}", self.r, self.g, self.b)
26 }
27
28 pub fn to_rgb(&mut self) {
29 (self.r, self.g, self.b) = xterm_to_rgb(self.xterm);
30 }
31}
32
33pub fn xterm_to_rgb(xterm_color: u8) -> (u8, u8, u8) {
34 if xterm_color < 16 {
35 let colors = vec![
36 "000000", "cd0000", "00cd00", "cdcd00", "0000ee", "cd00cd", "00cdcd", "e5e5e5",
37 "7f7f7f", "ff0000", "00ff00", "ffff00", "5c5cff", "ff00ff", "00ffff", "ffffff",
38 ];
39
40 let color = colors[xterm_color as usize];
41 let r = u8::from_str_radix(&color[0..2], 16).unwrap();
42 let g = u8::from_str_radix(&color[2..4], 16).unwrap();
43 let b = u8::from_str_radix(&color[4..6], 16).unwrap();
44
45 return (r, g, b);
46 }
47
48 if xterm_color < 232 {
49 let idx = xterm_color - 16;
50 let red = idx / 36;
51 let green = (idx % 36) / 6;
52 let blue = idx % 6;
53
54 let values = vec![0, 95, 135, 175, 215, 255];
55 let r_color = values[red as usize];
56 let g_color = values[green as usize];
57 let b_color = values[blue as usize];
58
59 return (r_color, g_color, b_color);
60 }
61
62 let gray = 8 + (xterm_color - 232) * 10;
63 return (gray, gray, gray);
64}
65
66pub fn calculate_hostname_background_color(hostname: Option<&str>) -> Rgb {
67 let hn = match hostname {
68 Some(h) => h.to_string(),
69 None => {
70 let output = ProcessCommand::new("hostname")
71 .output()
72 .expect("Failed to execute hostname command");
73
74 String::from_utf8_lossy(&output.stdout)
75 .split('.')
76 .next()
77 .unwrap_or("localhost")
78 .trim()
79 .to_string()
80 }
81 };
82
83 let mut hasher = Md5::new();
84 hasher.update(hn.as_bytes());
85 let hash = hasher.finalize();
86
87 let hex_str = format!("{:x}", hash);
88 let first_two_chars = &hex_str[..2];
89 let color_value = u8::from_str_radix(first_two_chars, 16).unwrap() % 128;
90
91 return Rgb::new(color_value);
92}
93
94pub fn calculate_hostname_foreground_color(bgcolor: Rgb, theme: Option<&str>) -> Result<Rgb, String> {
95 let theme = theme.unwrap_or("default");
96
97 if !theme_maps::THEME_MAP.contains_key(theme) {
98 eprintln!("Warning: Theme '{}' not found. Using default theme.", theme);
99 }
100
101 if let Some(map) = theme_maps::THEME_MAP.get(theme).or_else(|| theme_maps::THEME_MAP.get("default")) {
102 if let Some(color) = map.get(&bgcolor.xterm) {
103 return Ok(Rgb::new(*color));
104 }
105 return Err(format!("Color not found for color: {} theme: {} ", bgcolor.xterm, theme));
106 }
107 return Err(format!("Key not found for theme: {}", theme));
108}
109
110pub fn get_color_from_env(varname: &str) -> Result<Rgb, String> {
111 let env_color = std::env::var(varname).ok();
112 if let Some(bgcolor) = env_color {
113 let xterm_color = match bgcolor.parse::<u8>() {
114 Ok(color) => color,
115 Err(_) => return Err(format!("Unable to parse value of environment variable {}={}", varname, bgcolor)),
116 };
117 return Ok(Rgb::new(xterm_color));
118 }
119 return Err(format!("Environment variable {} is not set", varname));
120}
121
122pub fn output_colors_to_string(bgcolor: Rgb, fgcolor: Rgb, verbose: bool, fgonly: bool, bgonly: bool, iterm: bool, hex: bool) -> String {
123 let (bgcolor_output, fgcolor_output) = if hex {
124 (bgcolor.to_hex(), fgcolor.to_hex())
125 } else {
126 (bgcolor.xterm.to_string(), fgcolor.xterm.to_string())
127 };
128
129 if verbose {
130 return format!("bgcolor: {}, fgcolor: {}", bgcolor_output, fgcolor_output);
131 } else if fgonly {
132 return fgcolor_output;
133 } else if bgonly {
134 return bgcolor_output;
135 } else if iterm {
136 let bgcolor_hex = bgcolor.to_hex();
137 let red = u8::from_str_radix(&bgcolor_hex[0..2], 16).unwrap();
138 let green = u8::from_str_radix(&bgcolor_hex[2..4], 16).unwrap();
139 let blue = u8::from_str_radix(&bgcolor_hex[4..6], 16).unwrap();
140
141 return format!(
142 "\x1b]6;1;bg;red;brightness;{}\x07\x1b]6;1;bg;green;brightness;{}\x07\x1b]6;1;bg;blue;brightness;{}\x07",
143 red, green, blue
144 );
145 } else {
146 return format!("{} {}", bgcolor_output, fgcolor_output);
147 }
148}