use anyhow::{Context, Result};
use colored::*;
use std::fmt::Display;
use std::fs;
use std::path::Path;
pub struct Io {
verbose: bool,
}
impl Io {
pub fn new(verbose: bool) -> Self {
Self { verbose }
}
pub fn header<D: Display>(&self, text: D) {
println!("\n{}", text.to_string().bold().bright_cyan());
}
pub fn success<D: Display>(&self, text: D) {
println!("{} {}", "✔".green(), text);
}
pub fn error<D: Display>(&self, text: D) {
eprintln!("{} {}", "✘".red(), text);
}
pub fn warning<D: Display>(&self, text: D) {
println!("{} {}", "!".yellow(), text);
}
pub fn info<D: Display>(&self, text: D) {
if self.verbose {
println!("{} {}", "ℹ".blue(), text);
}
}
pub fn read_file<P: AsRef<Path>>(&self, path: P) -> Result<String> {
let path = path.as_ref();
self.info(format!("Reading file: {}", path.display()));
fs::read_to_string(path).with_context(|| format!("Failed to read file: {}", path.display()))
}
pub fn write_file<P: AsRef<Path>>(&self, path: P, content: &str) -> Result<()> {
let path = path.as_ref();
self.info(format!("Writing file: {}", path.display()));
if let Some(parent) = path.parent() {
if !parent.exists() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory: {}", parent.display()))?;
}
}
fs::write(path, content)
.with_context(|| format!("Failed to write file: {}", path.display()))
}
}
pub struct Table {
headers: Vec<String>,
rows: Vec<Vec<String>>,
}
impl Table {
pub fn new(headers: Vec<&str>) -> Self {
Self {
headers: headers.into_iter().map(|s| s.to_string()).collect(),
rows: Vec::new(),
}
}
pub fn add_row(&mut self, row: Vec<String>) {
self.rows.push(row);
}
pub fn print(&self) {
if self.headers.is_empty() && self.rows.is_empty() {
return;
}
let mut col_widths = self.headers.iter().map(|h| h.len()).collect::<Vec<_>>();
for row in &self.rows {
for (i, cell) in row.iter().enumerate() {
if i < col_widths.len() {
col_widths[i] = col_widths[i].max(cell.len());
}
}
}
println!();
for (i, header) in self.headers.iter().enumerate() {
print!(
"{:<width$} ",
header.bold().underline(),
width = col_widths[i]
);
}
println!();
for row in &self.rows {
for (i, cell) in row.iter().enumerate() {
if i < col_widths.len() {
print!("{:<width$} ", cell, width = col_widths[i]);
}
}
println!();
}
println!();
}
}