reserve 0.1.0

Check domain name availability across grouped extensions, straight from the registry
//! The `reserve` binary: build the runtime context, run the application, return an exit code.

mod app;
mod cli;
mod context;
mod files;
mod output;
mod tui;

use std::io::{self, Write};
use std::process::ExitCode;

use clap::Parser;
use reserve_core::ExitClass;

use crate::cli::Cli;

fn main() -> ExitCode {
    install_panic_hook();

    let args = Cli::parse();
    let runtime = match tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
    {
        Ok(runtime) => runtime,
        Err(error) => {
            let _ = writeln!(io::stderr(), "reserve: could not start: {error}");
            return ExitCode::from(ExitClass::Io.code());
        }
    };

    let exit_class = runtime.block_on(app::run(args));
    ExitCode::from(exit_class.code())
}

/// @docgen The picker's hook stacks on top of this one, so the screen is restored before any panic message is printed.
fn install_panic_hook() {
    let previous = std::panic::take_hook();
    std::panic::set_hook(Box::new(move |info| {
        let mut stderr = io::stderr();
        let _ = writeln!(stderr, "reserve: stopped unexpectedly.");
        let _ = writeln!(
            stderr,
            "This is a bug. Please report it with the lines below at"
        );
        let _ = writeln!(
            stderr,
            "https://github.com/devops-infinity/reserve/issues/new"
        );
        let _ = writeln!(stderr, "  version: {}", env!("CARGO_PKG_VERSION"));
        if let Some(location) = info.location() {
            let _ = writeln!(stderr, "  where:   {}:{}", location.file(), location.line());
        }
        previous(info);
    }));
}