use crate::command_line::cli::{
Cli, Commands, CommonOptions, solve_and_report, solve_dir, solve_nonogram, solve_sudoku,
};
use crate::sat::dimacs::{parse_dimacs_text, parse_file};
use clap::{CommandFactory, Parser};
pub mod command_line;
pub mod nonogram;
pub mod sat;
pub mod sudoku;
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
fn main() {
let cli = Cli::parse();
if let Some(Commands::Completions { shell }) = &cli.command {
let mut cmd = <Cli as CommandFactory>::command();
let cmd_name = cmd.get_name().to_string();
clap_complete::generate(*shell, &mut cmd, cmd_name, &mut std::io::stdout());
return;
}
if let Some(path) = &cli.path {
if cli.command.is_none() {
if !path.exists() {
eprintln!("File does not exist: {}", path.display());
std::process::exit(1);
}
if path.is_dir() {
if let Err(e) = solve_dir(path, &cli.common) {
eprintln!("Error solving directory: {}", e);
std::process::exit(1);
}
return;
}
if path.extension().is_some_and(|ext| ext == "sudoku") {
if let Err(e) = solve_sudoku(path, false, &CommonOptions::default()) {
eprintln!("Error solving Sudoku: {}", e);
std::process::exit(1);
}
return;
}
if path.extension().is_some_and(|ext| ext == "nonogram") {
if let Err(e) = solve_nonogram(path, &CommonOptions::default()) {
eprintln!("Error solving Nonogram: {}", e);
std::process::exit(1);
}
return;
}
let time = std::time::Instant::now();
let cnf = parse_file(path)
.unwrap_or_else(|_| panic!("Failed to parse file: {}", path.display()));
let elapsed = time.elapsed();
solve_and_report(&cnf, &cli.common, Some(path), elapsed);
return;
}
}
match cli.command {
Some(Commands::File { path, common }) => {
if !path.exists() {
eprintln!("File does not exist: {}", path.display());
std::process::exit(1);
}
if path.is_dir() {
let result = solve_dir(&path, &common);
if let Err(e) = result {
eprintln!("Error solving directory: {}", e);
std::process::exit(1);
}
return;
}
if path.extension().is_some_and(|ext| ext == "sudoku") {
if let Err(e) = solve_sudoku(&path, false, &common) {
eprintln!("Error solving Sudoku: {}", e);
std::process::exit(1);
}
return;
}
if path.extension().is_some_and(|ext| ext == "nonogram") {
if let Err(e) = solve_nonogram(&path, &common) {
eprintln!("Error solving Nonogram: {}", e);
std::process::exit(1);
}
return;
}
let time = std::time::Instant::now();
let cnf = parse_file(&path)
.unwrap_or_else(|_| panic!("Failed to parse file: {}", path.display()));
let elapsed = time.elapsed();
solve_and_report(&cnf, &common, Some(&path), elapsed);
}
Some(Commands::Text { input, common }) => {
let time = std::time::Instant::now();
let result = parse_dimacs_text(&input);
let cnf = result.unwrap_or_else(|_| panic!("Failed to parse input text: {}", input));
let elapsed = time.elapsed();
solve_and_report(&cnf, &common, None, elapsed);
}
Some(Commands::Sudoku {
path,
common,
export_dimacs,
}) => {
if let Err(e) = solve_sudoku(&path, export_dimacs, &common) {
eprintln!("Error solving Sudoku: {}", e);
std::process::exit(1);
}
}
Some(Commands::Nonogram { path, common }) => {
if let Err(e) = solve_nonogram(&path, &common) {
eprintln!("Error solving Nonogram: {}", e);
std::process::exit(1);
}
}
None => {
if cli.path.is_none() {
eprintln!("No command provided. Use --help for more information.");
std::process::exit(1);
}
}
Some(Commands::Completions { .. }) => unreachable!(),
}
}
#[cfg(test)]
mod tests {}