use clap::Parser;
use tr300::{
cli::{Action, Cli},
collectors::{CollectMode, SystemInfo},
config::{Config, OutputFormat},
error::Result,
install, report, update,
};
fn main() -> Result<()> {
let cli = Cli::parse();
let action = cli.action;
let mut config = Config::new().with_colors(!cli.no_color);
if cli.ascii || !is_utf8_locale() {
config = config.with_ascii();
}
if cli.json {
config = config.with_json();
}
if cli.no_elevation_hint {
config = config.with_no_elevation_hint(true);
}
if let Some(title) = cli.title {
config = config.with_title(title);
}
#[cfg(windows)]
{
enable_utf8_console();
}
if cli.update || action == Some(Action::Update) {
let exit_code = update::run(&config);
std::process::exit(exit_code);
}
if cli.install || action == Some(Action::Install) {
return run_install();
}
if cli.uninstall || action == Some(Action::Uninstall) {
return run_uninstall();
}
let mode = if cli.fast {
CollectMode::Fast
} else {
CollectMode::Full
};
run_report(&config, mode)
}
fn run_report(config: &Config, mode: CollectMode) -> Result<()> {
let info = SystemInfo::collect_with_mode(mode)?;
let output = report::generate(&info, config);
print!("{}", output);
if mode == CollectMode::Full && config.format == OutputFormat::Table {
match report::save_markdown_report(&info) {
Some(path) => eprintln!("Report saved: {}", path.display()),
None => eprintln!("Warning: Could not save markdown report"),
}
}
Ok(())
}
fn run_install() -> Result<()> {
println!("Installing TR-300...");
install::install()?;
println!("Installation complete!");
println!();
println!("The following changes were made:");
println!(" - Added 'report' alias for tr300");
println!(" - Added auto-run on new interactive shells");
println!();
println!("Please restart your shell or run 'source ~/.bashrc' (or equivalent)");
println!("to activate the changes.");
Ok(())
}
fn run_uninstall() -> Result<()> {
use install::{
confirm_complete_uninstall, find_binary_location, get_binary_parent_dir,
prompt_uninstall_option, UninstallOption,
};
let option = prompt_uninstall_option();
match option {
UninstallOption::Cancel => {
println!();
println!("Uninstall cancelled.");
Ok(())
}
UninstallOption::ProfileOnly => {
println!();
println!("Removing shell profile modifications...");
install::uninstall()?;
println!();
println!("TR-300 auto-run has been removed from your shell profile.");
println!("The tr300 binary remains installed and can be run manually.");
Ok(())
}
UninstallOption::Complete => {
let binary_path = find_binary_location();
let parent_dir = binary_path
.as_ref()
.and_then(|p| get_binary_parent_dir(p.as_path()));
if let Some(ref path) = binary_path {
if !confirm_complete_uninstall(path, parent_dir.as_deref()) {
println!();
println!("Uninstall cancelled.");
return Ok(());
}
}
println!();
println!("Performing complete uninstall...");
install::uninstall_complete()?;
println!();
println!("TR-300 has been completely removed from your system.");
Ok(())
}
}
}
fn is_utf8_locale() -> bool {
#[cfg(windows)]
{
true
}
#[cfg(not(windows))]
{
for var in ["LC_ALL", "LC_CTYPE", "LANG"] {
if let Ok(val) = std::env::var(var) {
if !val.is_empty() && val != "C" && val != "POSIX" {
let upper = val.to_uppercase();
return upper.contains("UTF-8") || upper.contains("UTF8");
}
}
}
false
}
}
#[cfg(windows)]
fn enable_utf8_console() {
use std::io::IsTerminal;
if std::io::stdout().is_terminal() {
unsafe {
winapi::um::wincon::SetConsoleOutputCP(65001);
}
}
}