cp437-tools 0.7.0

Small collection of tools to handle CP437 files
Documentation
use indoc::indoc;
use std::{
    env,
    ffi::{OsStr, OsString},
    fs::{self, create_dir_all, remove_dir_all, File},
    io::{self, Write},
    path::Path,
    process::{Command, Stdio},
};

fn main() -> Result<(), io::Error> {
    let man_dir = Path::new("res/man").canonicalize()?;
    let out_dir = Path::new(&env::var("OUT_DIR").unwrap()).join("man");
    if out_dir.exists() {
        remove_dir_all(out_dir.clone())?;
    }
    create_dir_all(out_dir.join("tmp"))?;

    let mut entries = man_dir
        .read_dir()?
        .map(|result| return result.map(|entry| return entry.path()))
        .collect::<Result<Vec<_>, io::Error>>()?;
    entries.sort();
    for raw_path in &entries {
        let man_path = out_dir.join(raw_path.strip_prefix(man_dir.clone()).unwrap());
        fs::copy(raw_path.clone(), man_path.clone())?;
        let mut man_file = File::options().append(true).open(man_path.clone())?;
        write!(
            &mut man_file,
            indoc! {"
                .\" -----------------------------------------------------------------------------
                .SH COPYRIGHT
                License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
                .PP
                This is free software: you are free to change and redistribute it. There is NO
                WARRANTY, to the extent permitted by law.
            "}
        )?;

        write!(
            &mut man_file,
            indoc! {"
                .\" -----------------------------------------------------------------------------
                .SH SEE ALSO
            "}
        )?;
        for (i, ref_path) in entries
            .iter()
            .filter(|ref_path| {
                return ref_path.file_name().unwrap() != raw_path.file_name().unwrap();
            })
            .enumerate()
        {
            writeln!(
                &mut man_file,
                ".BR {} ({}){}",
                ref_path.file_stem().unwrap().to_str().unwrap(),
                ref_path.extension().unwrap().to_str().unwrap(),
                if i + 2 < entries.len() { "," } else { "" }
            )?;
        }
        write!(
            &mut man_file,
            indoc! {"
                .\" -----------------------------------------------------------------------------
                .pl \\n[nl]u
            "}
        )?;

        let man_gz_file = File::create(man_path.with_extension({
            let mut old_extension = OsString::from(man_path.extension().unwrap_or(OsStr::new("")));
            old_extension.push(OsStr::new(".gz"));

            old_extension
        }))?;
        assert!(
            Command::new("gzip")
                .arg("-f9ck")
                .arg(man_path.clone())
                .stdout(Stdio::from(man_gz_file))
                .status()
                .expect("Failed to gzip manpage")
                .success(),
            "Failed to gzip manpage"
        );

        if raw_path.extension().unwrap_or(OsStr::new("")) == "1" {
            let tmp_path = out_dir
                .join("tmp")
                .join(raw_path.strip_prefix(man_dir.clone()).unwrap());
            let mut tmp_file = File::create(tmp_path.clone())?;
            write!(
                &mut tmp_file,
                indoc! {"
                    .de PT
                    ..
                    .de BT
                    ..
                "}
            )?;
            io::copy(&mut File::open(raw_path.clone())?, &mut tmp_file)?;
            write!(
                &mut tmp_file,
                indoc! {"
                    .\" -----------------------------------------------------------------------------
                    .pl \\n[nl]u
                "}
            )?;
            tmp_file.flush()?;
            let txt_path = out_dir
                .join(raw_path.strip_prefix(man_dir.clone()).unwrap())
                .with_extension(OsStr::new("txt"));
            let txt_file = File::create(txt_path)?;
            assert!(
                Command::new("groff")
                    .arg("-man")
                    .arg("-tTutf8")
                    .arg(tmp_path.clone())
                    .stdout(Stdio::from(txt_file))
                    .status()
                    .expect("Failed to render manpage")
                    .success(),
                "Failed to render manpage"
            );
        }
    }

    remove_dir_all(out_dir.join("tmp"))?;

    return Ok(());
}