#![allow(dead_code)]
use clap::Parser;
mod app;
mod cli;
mod config;
mod event;
mod ssh;
mod ui;
mod utils;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = cli::Cli::parse();
let log_level = if cli.verbose { "debug" } else { "warn" };
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(log_level)),
)
.with_writer(std::io::stderr)
.init();
let default_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = crossterm::terminal::disable_raw_mode();
let _ = crossterm::execute!(
std::io::stdout(),
crossterm::terminal::LeaveAlternateScreen,
crossterm::event::DisableMouseCapture,
);
default_hook(info);
}));
let mut app_config = match config::app_config::load_app_config(cli.config.as_deref()) {
Ok(cfg) => {
if let Some(ref path) = cli.config {
tracing::info!("Loaded config from: {}", path.display());
}
cfg
}
Err(e) => {
tracing::warn!("Config load error (using defaults): {}", e);
config::app_config::AppConfig::default()
}
};
if let Some(ref theme) = cli.theme {
if config::app_config::UiConfig::is_valid_theme(theme) {
tracing::info!("Applying theme '{}' and saving to config", theme);
app_config.ui.theme = theme.clone();
if let Err(e) = config::app_config::save_theme_to_config(theme) {
eprintln!("Warning: Failed to save theme to config: {}", e);
eprintln!("Theme will be applied for this session only.");
} else {
eprintln!("✓ Theme '{}' saved to config", theme);
}
} else {
eprintln!(
"Error: Unknown theme '{}'. Available themes: {}",
theme,
config::app_config::UiConfig::available_themes().join(", ")
);
eprintln!(
"Falling back to theme from config: '{}'",
app_config.ui.theme
);
}
}
let mut app = app::App::new(app_config);
app.run().await
}