brochurise/src/main.rs

105 lines
3.6 KiB
Rust

use std::path::PathBuf;
use std::fs::read_to_string;
use std::hash::{Hash, Hasher};
use anyhow::{bail, Result};
use structopt::StructOpt;
mod frontmatter;
mod generate;
#[derive(Debug, StructOpt)]
//#[structopt(name = "brochurise", about = "Produce PDF zines (brochures) from your Markdown files")]
#[structopt(name = "brochurise")]
/// Produce PDF from your Markdown documents. Uses pandoc and pdfbook to produce linear A4
/// or A5 booklets (also called zines, brochures or books).
/// Multiple documents are generated to find the optimal font size (minimize free space without
/// requiring an additional A4 sheet, compared to the base size).
struct Cli {
// Positional arguments
#[structopt(parse(from_os_str))]
/// Path to the Markdown file to be brochurised
input: PathBuf,
/// Path to the PDF file to produce. When producing both linear and book output (default
/// behavior, unless -b or -l is set), `-book` will be appended to the book output path
/// eg. output.pdf and output-book.pdf
output: Option<PathBuf>,
// Additional arguments
#[structopt(short = "d", long = "debug")]
/// Enable debug output
debug: bool,
#[structopt(short = "l", long = "linear")]
/// Only produce a linear A4 output
linear: bool,
#[structopt(short = "b", long = "book", conflicts_with = "linear")]
/// Only produce an A5 booklet (4 pages per A4 sheet)
book: bool,
#[structopt(short = "s", long = "size", default_value = "11")]
/// The smallest size
size: u8,
}
fn main() -> Result<()> {
let cli = Cli::from_args();
if !cli.input.is_file() {
bail!("File does not exist: {:?}", &cli.input);
}
let source = read_to_string(&cli.input)?;
let (content, metadata) = frontmatter::extract(&source)?;
if cli.debug {
println!("{}", content);
}
let output = match cli.output {
Some(path) => path,
None => {
let mut path = PathBuf::from(cli.input.parent().unwrap());
path.push(cli.input.file_stem().unwrap());
path.set_extension("pdf");
path
}
};
match (cli.book, cli.linear) {
(true, false) => {
let mut tmp = std::env::temp_dir();
let mut hasher = std::collections::hash_map::DefaultHasher::new();
cli.input.hash(&mut hasher);
tmp.push(hasher.finish().to_string());
tmp.set_extension("pdf");
let pages_count = generate::linear(&content, tmp.clone(), &cli.size, metadata)?;
println!("Intermediary step: generated linear output to {:?} ({} pages)", &tmp, pages_count);
generate::book(&tmp, &output)?;
println!("Generated A5 booklet output to {:?}", output);
},
(false, true) => {
// Only linear output
let pages_count = generate::linear(&content, output.clone(), &cli.size, metadata)?;
println!("Generated linear A4 output to {:?} ({} pages)", output, pages_count);
},
(false, false) => {
// Both outputs
let pages_count = generate::linear(&content, output.clone(), &cli.size, metadata)?;
println!("Generated linear A4 output to {:?} ({} pages)", output, pages_count);
let mut book_output = output.clone();
book_output.set_extension("book.pdf");
generate::book(&output, &book_output)?;
println!("Generated A5 booklet output to {:?}", book_output);
},
(true, true) => {
unreachable!("-b conflicts with -l so this branch should never be reached");
}
}
Ok(())
}