#![deny(unsafe_code)]
#![deny(unused_imports, unused_must_use, dead_code, unused_assignments)]
#![deny(clippy::all, clippy::perf)]
#![allow(
clippy::collapsible_if,
clippy::collapsible_else_if,
clippy::too_many_arguments,
clippy::needless_range_loop,
clippy::derivable_impls,
clippy::empty_line_after_doc_comments,
clippy::empty_line_after_outer_attr
)]
#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::panic))]
use std::{env, error::Error, io, path::PathBuf};
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture},
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
use ratatui::{Terminal, backend::CrosstermBackend};
mod app;
mod config;
mod debug_log;
mod input;
pub mod keybindings;
pub use gitwig_core as repo;
pub mod components;
mod keys;
pub mod popups;
mod queue;
pub mod tabs;
mod ui;
pub use crate::ui::ui_detail;
use crate::app::{App, run};
use crate::config::load_config;
fn main() -> Result<(), 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(());
}
"--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(());
}
_ => {}
}
}
let default_panic = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = disable_raw_mode();
let mut stdout = std::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);
}));
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let cli_path = env::args().nth(1).map(PathBuf::from);
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let (config, config_path) = load_config(cli_path)?;
let app = App::new(config, config_path);
let res = run(&mut terminal, app);
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?;
terminal.show_cursor()?;
if let Err(err) = res {
println!("{:?}", err);
}
Ok(())
}
pub mod mouse;