zim-studio 1.5.0

A Terminal-Based Audio Project Scaffold and Metadata System
Documentation
//! `zim pdf` — generate a PDF from the markdown tree under PATH.

use crate::config::Config;
use owo_colors::OwoColorize;
use std::error::Error;
use std::path::{Path, PathBuf};
use zim_studio::pdf::{self, GenerateOptions};
use zim_studio::utils::{progress::create_progress_spinner, validation::validate_path_exists};

pub fn handle_pdf(
    path: &str,
    output: Option<String>,
    title: Option<String>,
    author: Option<String>,
    keep_tex: bool,
) -> Result<(), Box<dyn Error>> {
    let root = Path::new(path);
    validate_path_exists(root)?;
    let root = root.canonicalize()?;

    let output = resolve_output(output, &root);
    let title = title.unwrap_or_else(|| default_title(&root));
    let author = author.or_else(|| Config::load().ok().map(|c| c.default_artist));

    println!(
        "{} {}",
        "Generating PDF for:".bright_black(),
        root.display().to_string().cyan()
    );

    let spinner = create_progress_spinner();
    spinner.set_message("Walking tree, rendering markdown, compiling LaTeX (2 passes)...");

    let stats = pdf::generate(&GenerateOptions {
        root,
        output,
        title,
        author,
        keep_tex,
    })?;

    spinner.finish_and_clear();

    println!(
        "{} {} {}",
        "".green().bold(),
        "Wrote".green(),
        stats.output.display().to_string().cyan()
    );
    println!(
        "  {} {} files across {} directories",
        "Included:".bright_black(),
        stats.num_files.to_string().cyan(),
        stats.num_dirs.to_string().cyan()
    );
    if let Some(tex) = stats.kept_tex {
        println!(
            "  {} {}",
            "Kept .tex:".bright_black(),
            tex.display().to_string().cyan()
        );
    }
    Ok(())
}

fn resolve_output(output: Option<String>, root: &Path) -> PathBuf {
    if let Some(o) = output {
        return PathBuf::from(o);
    }
    let stem = root
        .file_name()
        .map(|s| s.to_string_lossy().into_owned())
        .filter(|s| !s.is_empty())
        .unwrap_or_else(|| "zim".to_string());
    PathBuf::from(format!("{stem}.pdf"))
}

fn default_title(root: &Path) -> String {
    root.file_name()
        .map(|s| s.to_string_lossy().into_owned())
        .filter(|s| !s.is_empty())
        .unwrap_or_else(|| "ZIM Project".to_string())
}