use std::{env, error::Error, io, path::PathBuf};
use crossterm::{
event::DisableMouseCapture,
execute,
terminal::{LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
pub enum CliAction {
Run(Option<PathBuf>),
Exit,
}
pub fn check_cli() -> Result<CliAction, Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
if args.len() > 1 {
match args[1].as_str() {
"--version" | "-v" => {
println!("gitwig {}", env!("CARGO_PKG_VERSION"));
return Ok(CliAction::Exit);
}
"--help" | "-h" => {
println!("Gitwig - A Rust-based terminal user interface (TUI) for Git");
println!();
println!("Usage:");
println!(" gitwig [config_path] Start Gitwig with the specified config file");
println!(" gitwig -v, --version Print version info and exit");
println!(" gitwig -h, --help Print help info and exit");
return Ok(CliAction::Exit);
}
_ => {}
}
}
if let Err(e) = std::process::Command::new("git").arg("--version").output() {
eprintln!("Error: 'git' command-line tool not found on PATH.");
eprintln!(
"Gitwig requires a system installation of 'git' for network operations, staging, and diffing."
);
eprintln!("Detailed error: {:?}", e);
std::process::exit(1);
}
let cli_path = env::args().nth(1).map(PathBuf::from);
Ok(CliAction::Run(cli_path))
}
pub fn setup_panic_hook() {
let default_panic = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = disable_raw_mode();
let mut stdout = io::stdout();
let _ = execute!(stdout, LeaveAlternateScreen, DisableMouseCapture);
let _ = execute!(std::io::stdout(), crossterm::cursor::Show);
let msg = if let Some(s) = info.payload().downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = info.payload().downcast_ref::<String>() {
s.clone()
} else {
"Unknown panic".to_string()
};
let location = info
.location()
.map(|l| format!("{}:{}:{}", l.file(), l.line(), l.column()))
.unwrap_or_else(|| "unknown".to_string());
let backtrace = std::backtrace::Backtrace::capture();
let panic_msg = format!("Panic at {}: {}\nBacktrace:\n{}", location, msg, backtrace);
for line in panic_msg.lines() {
crate::debug_log::log("PANIC_FATAL", line);
}
default_panic(info);
}));
}
pub struct TerminalGuard;
impl Drop for TerminalGuard {
fn drop(&mut self) {
let _ = disable_raw_mode();
let mut stdout = io::stdout();
let _ = execute!(stdout, LeaveAlternateScreen, DisableMouseCapture);
let _ = execute!(stdout, crossterm::cursor::Show);
print!("\x1b[23;0t");
let _ = io::Write::flush(&mut stdout);
}
}
pub fn init_terminal() -> Result<TerminalGuard, Box<dyn Error>> {
enable_raw_mode()?;
let guard = TerminalGuard;
let mut stdout = io::stdout();
print!("\x1b[22;0t");
let _ = io::Write::flush(&mut stdout);
execute!(
stdout,
crossterm::terminal::EnterAlternateScreen,
crossterm::event::EnableMouseCapture
)?;
Ok(guard)
}