reserve 0.2.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 lifecycle;
mod output;
mod plan;
mod progress;
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();
    install_logging(args.global.verbosity.tracing_level_filter());

    // @docgen Read here because the library refuses to determine a local offset once the process is multi-threaded.
    let clock = crate::lifecycle::Clock::start();

    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, clock));
    ExitCode::from(exit_class.code())
}

/// @docgen Logs go to stderr so a pipe reading stdout still receives only results, and RUST_LOG can widen what the flags set.
fn install_logging(level: tracing::level_filters::LevelFilter) {
    use tracing_subscriber::EnvFilter;

    let filter = EnvFilter::builder()
        .with_default_directive(level.into())
        .from_env_lossy();

    let _ = tracing_subscriber::fmt()
        .with_env_filter(filter)
        .with_writer(io::stderr)
        .with_target(false)
        .without_time()
        .try_init();
}

/// @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"));
        previous(info);
    }));
}