use bibsync::{ProviderChoice, SyncOptions, pre_commit_hook_manifest, sync_files};
use clap::{Parser, ValueEnum};
use std::path::PathBuf;
#[derive(Debug, Parser)]
#[command(version, about)]
#[allow(clippy::struct_excessive_bools)]
struct Cli {
#[arg(value_name = "FILE")]
files: Vec<PathBuf>,
#[arg(short, long, value_name = "BIB")]
output: Option<PathBuf>,
#[arg(short = 'r', long = "other", value_name = "BIB")]
other_bibliographies: Vec<PathBuf>,
#[arg(long, value_enum, default_value_t = CliProvider::Auto)]
provider: CliProvider,
#[arg(long = "no-update")]
no_update: bool,
#[arg(long)]
force_regenerate: bool,
#[arg(long)]
merge_other: bool,
#[arg(long = "no-backup")]
no_backup: bool,
#[arg(long)]
check: bool,
#[arg(long)]
print_pre_commit_hook: bool,
}
#[derive(Clone, Copy, Debug, ValueEnum)]
enum CliProvider {
Auto,
Ads,
Inspire,
}
impl From<CliProvider> for ProviderChoice {
fn from(value: CliProvider) -> Self {
match value {
CliProvider::Auto => Self::Auto,
CliProvider::Ads => Self::Ads,
CliProvider::Inspire => Self::Inspire,
}
}
}
fn main() {
let cli = Cli::parse();
if cli.print_pre_commit_hook {
print!("{manifest}", manifest = pre_commit_hook_manifest());
return;
}
if cli.files.is_empty() {
eprintln!("error: at least one TeX file or one BibTeX file is required");
std::process::exit(2);
}
let options = SyncOptions {
output: cli.output,
other_bibliographies: cli.other_bibliographies,
provider: cli.provider.into(),
update_existing: !cli.no_update,
force_regenerate: cli.force_regenerate,
merge_other: cli.merge_other,
backup: !cli.no_backup,
check: cli.check,
};
match sync_files(&cli.files, &options) {
Ok(report) => {
println!("output: {}", report.output.display());
if !report.added.is_empty() {
println!("added: {}", report.added.join(", "));
}
if !report.updated.is_empty() {
println!("updated: {}", report.updated.join(", "));
}
if !report.found_in_other.is_empty() {
println!(
"found in other bibliography: {}",
report.found_in_other.join(", ")
);
}
if !report.unresolved.is_empty() {
println!("unresolved: {}", report.unresolved.join(", "));
}
if report.changed {
if report.check_mode {
eprintln!("bibsync: bibliography is out of date");
std::process::exit(1);
}
println!("wrote updated bibliography");
} else {
println!("bibliography is up to date");
}
if !report.unresolved.is_empty() {
std::process::exit(1);
}
}
Err(error) => {
eprintln!("error: {error}");
std::process::exit(2);
}
}
}