use anyhow::{Context, Result};
use clap::Parser;
use std::path::PathBuf;
mod display;
mod tui;
mod workbook;
#[derive(Parser)]
#[command(name = "xleak")]
#[command(author, version, about = "Expose Excel files in your terminal - no Microsoft Excel required", long_about = None)]
struct Cli {
#[arg(value_name = "FILE")]
file: PathBuf,
#[arg(short, long, value_name = "SHEET")]
sheet: Option<String>,
#[arg(short, long, value_name = "FORMAT")]
export: Option<String>,
#[arg(short = 'n', long, default_value = "50")]
max_rows: usize,
#[arg(short, long)]
formulas: bool,
#[arg(short = 'w', long, default_value = "30")]
max_width: usize,
#[arg(long)]
wrap: bool,
#[arg(short, long)]
interactive: bool,
}
fn main() -> Result<()> {
let cli = Cli::parse();
if !cli.file.exists() {
anyhow::bail!("File not found: {}", cli.file.display());
}
let mut wb = workbook::Workbook::open(&cli.file).context("Failed to open Excel file")?;
let sheet_names = wb.sheet_names();
if sheet_names.is_empty() {
anyhow::bail!("No sheets found in workbook");
}
let sheet_name = if let Some(ref name) = cli.sheet {
if sheet_names.iter().any(|s| s == name) {
name.clone()
} else {
if let Ok(idx) = name.parse::<usize>() {
if idx > 0 && idx <= sheet_names.len() {
sheet_names[idx - 1].clone()
} else {
anyhow::bail!("Sheet index {} out of range (1-{})", idx, sheet_names.len());
}
} else {
anyhow::bail!(
"Sheet '{}' not found. Available sheets: {}",
name,
sheet_names.join(", ")
);
}
}
} else {
sheet_names[0].clone()
};
if cli.interactive {
tui::run_tui(wb, &sheet_name)?;
} else {
let data = wb
.load_sheet(&sheet_name)
.with_context(|| format!("Failed to load sheet '{sheet_name}'"))?;
match cli.export.as_deref() {
Some("csv") => {
display::export_csv(&data)?;
}
Some("json") => {
display::export_json(&data, &sheet_name)?;
}
Some("text") => {
display::export_text(&data)?;
}
Some(format) => {
anyhow::bail!("Unknown export format: {format}. Use: csv, json, or text");
}
None => {
let sheet_names_refs: Vec<&str> = sheet_names.iter().map(|s| s.as_str()).collect();
display::display_table(
&data,
&sheet_name,
cli.max_rows,
&sheet_names_refs,
cli.max_width,
cli.wrap,
cli.formulas,
)?;
}
}
}
Ok(())
}