mod config;
mod diff;
mod ui;
use clap::Parser;
use std::error::Error;
#[derive(Parser)]
#[command(author="bahdotsh", version, about, long_about = None)]
struct Args {
#[arg(default_value = "")]
from: String,
#[arg(default_value = "")]
to: String,
#[arg(short, long)]
diff_args: Option<String>,
#[arg(short, long, help = "Auto-rebase if needed")]
auto_rebase: bool,
#[arg(short, long)]
theme: Option<String>,
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
if args.auto_rebase {
if let Some(rebase_msg) = diff::check_rebase_needed()? {
eprintln!("{}", rebase_msg);
if let Some(upstream) = diff::get_upstream_branch()? {
eprintln!("Auto-rebasing onto {}...", upstream);
if diff::perform_rebase(&upstream)? {
eprintln!("Rebase successful!");
} else {
eprintln!("Rebase failed. There might be conflicts to resolve.");
return Err("Rebase failed".into());
}
}
}
}
let (file_changes, left_label, right_label) = if let Some(diff_args) = &args.diff_args {
diff::get_changes_with_args(diff_args)?
} else if !args.from.is_empty() && !args.to.is_empty() {
diff::get_changes_between(&args.from, &args.to)?
} else if !args.from.is_empty() {
diff::get_changes_to_ref(&args.from)?
} else {
diff::get_uncommitted_changes()?
};
if file_changes.is_empty() {
println!("No changes.");
return Ok(());
}
let rebase_notification = diff::check_rebase_needed()?;
let cfg = config::load_config();
let theme = config::resolve_theme(&cfg, args.theme.as_deref());
if !ui::is_valid_syntax_theme(&theme.syntax_theme) {
eprintln!(
"Warning: syntax theme '{}' not found, using fallback",
theme.syntax_theme
);
}
ui::run_app(
file_changes,
&left_label,
&right_label,
theme,
rebase_notification,
)?;
Ok(())
}