use anyhow::Result;
use clap::{Parser, Subcommand};
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture},
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
use ratatui::{Terminal, backend::CrosstermBackend};
use std::io;
mod app;
mod build_info;
mod format;
mod game;
mod i18n;
mod save;
mod self_cmd;
mod ui;
use app::App;
#[derive(Parser)]
#[command(
name = "cuqueclicker",
version,
about = "A TUI idle clicker where you finger an ASCII ass instead of clicking a cookie."
)]
struct Cli {
#[arg(long)]
no_debug: bool,
#[arg(long, num_args = 0..=1, default_missing_value = "30", hide = true, value_name = "SECONDS")]
demo_for_recording: Option<u32>,
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Subcommand)]
enum Command {
#[command(name = "self", subcommand)]
Self_(SelfAction),
}
#[derive(Subcommand)]
enum SelfAction {
Update,
}
fn main() -> Result<()> {
let cli = Cli::parse();
if let Some(Command::Self_(action)) = &cli.command {
return match action {
SelfAction::Update => self_cmd::update(),
};
}
install_panic_hook();
i18n::init();
let debug = build_info::is_dev_build() && !cli.no_debug;
let demo_seconds = cli
.demo_for_recording
.filter(|_| build_info::is_dev_build());
let _lock;
let state = if demo_seconds.is_some() {
app::build_demo_state()
} else {
_lock = match save::acquire_lock() {
Ok(l) => l,
Err(e) => {
eprintln!(
"CuqueClicker is already running (or the save directory is not writable)."
);
eprintln!("Close the other instance and try again.");
eprintln!("Details: {e}");
std::process::exit(1);
}
};
save::load()
};
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let result = App::new(state, debug, demo_seconds).run(&mut terminal);
disable_raw_mode()?;
execute!(
terminal.backend_mut(),
LeaveAlternateScreen,
DisableMouseCapture
)?;
terminal.show_cursor()?;
result
}
fn install_panic_hook() {
let original = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = disable_raw_mode();
let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
original(info);
}));
}