portablemc-cli 5.0.3

Cross platform command line utility for launching Minecraft quickly and reliably with included support for Mojang versions and popular mod loaders.

use std::process::ExitCode;
use std::path::Path;
use std::{fs, io};

use clap::{Command, CommandFactory};
use clap_mangen::Man;

use crate::parse::{CliArgs, GenArgs, GenCmd, GenManArgs};
use crate::cmd::Cli;

use super::log_any_error;


pub fn r#gen(cli: &mut Cli, args: &GenArgs) -> ExitCode {
    match &args.cmd {
        GenCmd::Man(gen_args) => gen_man(cli, gen_args),
    }
}

fn gen_man(cli: &mut Cli, args: &GenManArgs) -> ExitCode {
    
    cli.out.log("gen_man_dir")
        .arg(args.dir.display())
        .pending(format_args!("Generating man pages at {}", args.dir.display()));

    match gen_man_to(&args.dir) {
        Ok(()) => {

            cli.out.log("gen_man_success")
                .arg(args.dir.display())
                .success(format_args!("Generated man pages at {}", args.dir.display()));

            ExitCode::SUCCESS

        }
        Err(e) => {
            
            log_any_error(cli, &e, false, false);
            ExitCode::FAILURE

        }
    }

}

/// Internal function that generate the man page to given directory. This function 
/// applies a small patch to the syntax generated by clap_mangen.
fn gen_man_to(dir: &Path) -> io::Result<()> {
    
    fn generate(cmd: Command, dir: &Path) -> io::Result<()> {
        
        for cmd in cmd.get_subcommands().filter(|s| !s.is_hide_set()).cloned() {
            generate(cmd, dir)?;
        }

        let mut buf = Vec::new();
        let man = Man::new(cmd);
        man.render(&mut buf)?;
        let mut buf = String::from_utf8(buf).expect("Should be textual");

        const PATTERN: &str = ".RS\nMay also be specified with the";
        let mut cursor = 0usize;
        while let Some(index) = buf[cursor..].find(PATTERN) {
            buf.insert(cursor + index, '\n');
            cursor += index + PATTERN.len() + 1;
        }

        let man_file = dir.join(man.get_filename());
        fs::write(man_file, &buf)?;
        Ok(())

    }
    
    let mut cmd = CliArgs::command()
        .disable_help_subcommand(true);
    cmd.build();
    generate(cmd, dir)

}