mapm-cli 5.0.1

The command-line implementation of mapm
use dirs::{config_dir, home_dir};
use mapm::sty::MAPM_STY;
use std::fs;
use std::os::unix::fs::PermissionsExt;

const PREVIEW_TEX: &str = r#"\documentclass{article}
\usepackage{mapm}
\usepackage{pgffor}
\usepackage{asymptote}
\usepackage{tikz}
\usepackage{amsmath,amssymb}
\usepackage{float}

\newcommand\ansbold[1]{\mathbf{#1}}

\begin{document}
\section*{Problem (\probvar{1}{author})}

\probvar{1}{problem}

\ifnum\solcount{1}>0\relax
\foreach \i in {1,...,\solcount{1}} {
    \subsection*{Solution \i{} (\solvar{1}{\i}{author})}

        \solvar{1}{\i}{text}
    }
\fi
\end{document}
"#;

const PREVIEW_YML: &str = r#"vars: []
texfiles:
  preview.tex: preview.pdf
engine: pdflatex
problem_count: 1 
problemvars:
  - problem
solutionvars:
  - text
"#;

const PREVIEW_ALL_TEX: &str = r#"\documentclass{article}
\usepackage{mapm}
\usepackage{pgffor}
\usepackage{asymptote}
\usepackage{tikz}
\usepackage{amsmath,amssymb}
\usepackage{float}

\newcommand\ansbold[1]{\mathbf{#1}}

\begin{document}

\foreach \n in {1,...,\probcount} {

    \section{\probname{\n} (\probvar{\n}{author})}
    
    \probvar{\n}{problem}
    
    \ifnum\solcount{\n}>0\relax
        \foreach \i in {1,...,\solcount{\n}} {
            \subsection*{Solution \i{} (\solvar{\n}{\i}{author})}
    
            \solvar{\n}{\i}{text}
        }
    \fi

    \newpage

}

\end{document}
"#;

const PREVIEW_ALL_YML: &str = r#"vars: []
texfiles:
  preview-all.tex: preview-all.pdf
engine: pdflatex
problemvars:
  - problem
solutionvars:
  - text
"#;

fn makedir(dirname: &str) {
    let dir = config_dir().unwrap().join("mapm").join(dirname);
    if !dir.is_dir() {
        fs::create_dir_all(&dir).unwrap_or_else(|_| panic!("Could not create directory {:?}", dir));
    }
}

fn main() {
    // Make problem, template, and script directories
    makedir("problems");
    makedir("templates");
    makedir("scripts");
    println!("Copying default preview template...");
    let preview_dir = config_dir()
        .unwrap()
        .join("mapm")
        .join("templates")
        .join("preview");
    if !preview_dir.exists() {
        fs::create_dir_all(&preview_dir).expect("Could not create preview template directory");
    }
    let preview_all_dir = config_dir()
        .unwrap()
        .join("mapm")
        .join("templates")
        .join("preview-all");
    if !preview_all_dir.exists() {
        fs::create_dir_all(&preview_all_dir).expect("Could not create preview template directory");
    }
    let write_tmpl = |path: &str, contents: &str| {
        let path = config_dir()
            .unwrap()
            .join("mapm")
            .join("templates")
            .join(path);
        if path.exists() {
            println!("File {:?} already exists, skipping...", path);
        } else {
            fs::write(&path, contents).unwrap_or_else(|_| panic!("Could not write to {:?}", path));
        }
    };
    write_tmpl("preview/preview.tex", PREVIEW_TEX);
    write_tmpl("preview/config.yml", PREVIEW_YML);
    write_tmpl("preview-all/preview-all.tex", PREVIEW_ALL_TEX);
    write_tmpl("preview-all/config.yml", PREVIEW_ALL_YML);

    let script_dir = config_dir().unwrap().join("mapm").join("scripts");

    let write_script = |contents: &str| {
        let write_path = |template: &str| {
            let contents = &(String::from(contents) + " " + template + ".pdf");
            let path = script_dir.join(template);
            if path.exists() {
                println!("File {:?} already exists, skipping...", path);
            } else {
                fs::write(&path, contents)
                    .unwrap_or_else(|_| panic!("Could not write to {:?}", path));
            }
            // chmod u+x for non-Windows systems
            if !cfg!(windows) {
                fs::set_permissions(&path, fs::Permissions::from_mode(0o755)).unwrap();
            }
        };
        write_path("preview");
        write_path("preview-all");
    };

    if cfg!(windows) {
        // This is a security nightmare (it will EXECUTE this file if it's a binary) but Windows sucks, not my problem
        write_script("start");
    } else if cfg!(target_os = "macos") {
        write_script("open");
    } else {
        // Assume Linux
        write_script("xdg-open");
    }

    let mapm_sty_path = if cfg!(target_os = "macos") {
        home_dir()
            .unwrap()
            .join("Library")
            .join("texmf")
            .join("tex")
            .join("latex")
            .join("mapm.sty")
    } else {
        home_dir()
            .unwrap()
            .join("texmf")
            .join("tex")
            .join("latex")
            .join("mapm.sty")
    };

    fs::write(&mapm_sty_path, MAPM_STY).expect("Could not write to `mapm.sty`");
}