2025-01-05 04:33:47 +01:00
|
|
|
use yansi::{Color, Paint};
|
|
|
|
|
|
|
|
use crate::config::InstallConfig;
|
|
|
|
|
|
|
|
pub fn print_config(conf: &InstallConfig) {
|
|
|
|
println!("🚀 Install Configuration:");
|
|
|
|
|
|
|
|
let mut root_info = Tree::new();
|
|
|
|
|
|
|
|
let mut drive_info = Tree::new();
|
|
|
|
drive_info.add_str(format!(
|
|
|
|
"💾 {} {}",
|
|
|
|
conf.drive.boot.paint(Color::Red),
|
|
|
|
"[EFI]".paint(Color::Blue)
|
|
|
|
));
|
|
|
|
drive_info.add_str(format!(
|
|
|
|
"{} {} {}",
|
|
|
|
if conf.drive.encryption.is_some() {
|
|
|
|
"🔒"
|
|
|
|
} else {
|
|
|
|
"💾"
|
|
|
|
},
|
|
|
|
conf.drive.root.paint(Color::Red),
|
|
|
|
"[ROOT]".paint(Color::Blue)
|
|
|
|
));
|
|
|
|
|
|
|
|
root_info.add_tree("💾 Drive Selection", drive_info);
|
|
|
|
|
|
|
|
let mut general_info = Tree::new();
|
|
|
|
|
|
|
|
general_info.add_str(format!(
|
|
|
|
"💎 {} {}",
|
|
|
|
"Mode:".paint(Color::Yellow),
|
|
|
|
conf.general.mode
|
|
|
|
));
|
|
|
|
general_info.add_str(format!(
|
2025-01-05 11:04:26 +01:00
|
|
|
"🖥️ {} {}",
|
2025-01-05 04:33:47 +01:00
|
|
|
"Hostname:".paint(Color::Yellow),
|
|
|
|
conf.general.hostname
|
|
|
|
));
|
|
|
|
general_info.add_str(format!(
|
2025-01-05 11:04:26 +01:00
|
|
|
"⌨️ {} {} {}",
|
2025-01-05 04:33:47 +01:00
|
|
|
"Keyboard:".paint(Color::Yellow),
|
|
|
|
conf.general.keyboard_layout,
|
|
|
|
conf.general
|
|
|
|
.keyboard_variant
|
|
|
|
.as_ref()
|
|
|
|
.unwrap_or(&String::new())
|
|
|
|
));
|
|
|
|
general_info.add_str(format!(
|
|
|
|
"🌍 {} {}",
|
|
|
|
"Locale:".paint(Color::Yellow),
|
|
|
|
conf.general.locale
|
|
|
|
));
|
|
|
|
general_info.add_str(format!(
|
|
|
|
"⌛ {} {}",
|
|
|
|
"Timezone:".paint(Color::Yellow),
|
|
|
|
conf.general.timezone
|
|
|
|
));
|
2025-01-05 04:48:28 +01:00
|
|
|
if conf.general.root_password.is_some() {
|
|
|
|
general_info.add_str(format!(
|
|
|
|
"🔑 {} {}",
|
|
|
|
"Root Password".paint(Color::Yellow),
|
|
|
|
"✔️".paint(Color::Green)
|
|
|
|
));
|
|
|
|
}
|
2025-01-05 04:33:47 +01:00
|
|
|
|
|
|
|
root_info.add_tree("🔨 General", general_info);
|
|
|
|
|
|
|
|
let mut pkg_info = Tree::new();
|
|
|
|
|
2025-01-05 04:48:28 +01:00
|
|
|
if conf.pkg.docker.unwrap_or_default() {
|
2025-01-05 04:33:47 +01:00
|
|
|
pkg_info.add_str(format!("🐳 Docker {}", "✔️".paint(Color::Green)));
|
|
|
|
}
|
|
|
|
|
2025-01-05 04:48:28 +01:00
|
|
|
if conf.pkg.virtualization.unwrap_or_default() {
|
2025-01-05 04:33:47 +01:00
|
|
|
pkg_info.add_str(format!("🎃 Virtualization {}", "✔️".paint(Color::Green)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if !conf.pkg.pkg.is_empty() {
|
|
|
|
pkg_info.add_str(format!(
|
|
|
|
"📦 Additional packages: {}",
|
|
|
|
conf.pkg.pkg.join(" ")
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
root_info.add_tree("📦 Packages", pkg_info);
|
|
|
|
|
|
|
|
let mut users_info = Tree::new();
|
|
|
|
|
2025-01-05 04:48:28 +01:00
|
|
|
let empty = Vec::new();
|
|
|
|
let user_conf = conf.user.as_ref().unwrap_or(&empty);
|
|
|
|
|
|
|
|
for user in user_conf {
|
2025-01-05 05:15:14 +01:00
|
|
|
let mut groups = Vec::new();
|
|
|
|
|
|
|
|
if user.doas_root.unwrap_or_default() {
|
|
|
|
groups.push("🔑");
|
|
|
|
}
|
|
|
|
|
|
|
|
if user.docker.unwrap_or_default() {
|
|
|
|
groups.push("🐋");
|
|
|
|
}
|
|
|
|
|
2025-01-05 04:33:47 +01:00
|
|
|
users_info.add_str(format!(
|
2025-01-05 05:15:14 +01:00
|
|
|
"👤 {}{}",
|
2025-01-05 04:33:47 +01:00
|
|
|
user.name,
|
2025-01-05 05:15:14 +01:00
|
|
|
if !groups.is_empty() {
|
|
|
|
format!(" [ {} ]", groups.join(" "))
|
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
}
|
2025-01-05 04:33:47 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
root_info.add_tree("🧛 Users", users_info);
|
|
|
|
|
|
|
|
if let Some(ssh_conf) = &conf.ssh {
|
|
|
|
let mut ssh_info = Tree::new();
|
|
|
|
|
|
|
|
if let Some(sshd_conf) = &ssh_conf.sshd_config {
|
|
|
|
ssh_info.add_str(format!("📖 Installing {sshd_conf} as sshd_config"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(keys) = &ssh_conf.key {
|
|
|
|
for key in keys {
|
|
|
|
let key_origin = key.key.split(" ").nth(2).unwrap_or_default();
|
|
|
|
|
|
|
|
ssh_info.add_str(format!(
|
|
|
|
"🔑 Key {} for {}",
|
|
|
|
key_origin.paint(Color::Blue),
|
|
|
|
key.users.join(", ").paint(Color::Yellow)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
root_info.add_tree("🌐 SSH", ssh_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(ai_conf) = &conf.ai {
|
|
|
|
let mut ai_info = Tree::new();
|
|
|
|
|
|
|
|
if ai_conf.gpu {
|
|
|
|
ai_info.add_str(format!("🟩 Use CUDA {}", "✔️".paint(Color::Green)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(models) = &ai_conf.models {
|
2025-01-09 18:17:55 +01:00
|
|
|
ai_info.add_str(format!("⬇️ Pull Models: {}", models.join(", ")));
|
2025-01-05 04:33:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
root_info.add_tree("🦙 Ollama", ai_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("{}", root_info.render(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Tree {
|
|
|
|
elements: Vec<TreeEntry>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum TreeEntry {
|
|
|
|
Tree(String, Tree),
|
|
|
|
Str(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Tree {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self { elements: vec![] }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_tree(&mut self, key: &str, item: Tree) {
|
|
|
|
self.elements.push(TreeEntry::Tree(key.to_string(), item));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_str(&mut self, item: String) {
|
|
|
|
self.elements.push(TreeEntry::Str(item));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render(&self, depth: i32) -> String {
|
|
|
|
const DEPTH_INCREASE: i32 = 3;
|
|
|
|
|
|
|
|
let mut ret = String::new();
|
|
|
|
|
|
|
|
let len = self.elements.len();
|
|
|
|
|
|
|
|
for (index, val) in self.elements.iter().enumerate() {
|
|
|
|
let padding = pad_with_bars(depth, DEPTH_INCREASE);
|
|
|
|
|
|
|
|
let path_repr = if (index + 1) == len {
|
|
|
|
if matches!(val, TreeEntry::Tree(_, _)) {
|
|
|
|
"├─"
|
|
|
|
} else {
|
|
|
|
"└─"
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
"├─"
|
|
|
|
};
|
|
|
|
|
|
|
|
match val {
|
|
|
|
TreeEntry::Tree(key, tree) => {
|
|
|
|
if !tree.elements.is_empty() {
|
|
|
|
ret.push_str(&format!("{padding}{path_repr} {key}\n"));
|
|
|
|
ret.push_str(&tree.render(depth + DEPTH_INCREASE))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TreeEntry::Str(str) => {
|
|
|
|
ret.push_str(&format!("{padding}{path_repr} {str}\n"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pad_with_bars(n: i32, depth_inc: i32) -> String {
|
|
|
|
let amount = n / depth_inc;
|
|
|
|
|
|
|
|
let mut ret = String::new();
|
|
|
|
|
|
|
|
if amount >= 1 {
|
|
|
|
ret.push_str("│");
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.push_str(&pad(n - amount));
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pad(n: i32) -> String {
|
|
|
|
let mut ret = String::new();
|
|
|
|
|
|
|
|
for _ in 0..n {
|
|
|
|
ret.push_str(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
ret
|
|
|
|
}
|