use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use crate::error::{Error, Result};
#[derive(Debug)]
pub struct CompileOutcome {
pub success: bool,
pub stderr: String,
pub stdout: String,
pub pdf_path: PathBuf,
}
pub fn spawn(typ_path: &Path) -> Result<(Child, PathBuf)> {
let pdf_path = typ_path.with_extension("pdf");
let child = Command::new("typst")
.arg("compile")
.arg(typ_path)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
Error::Store(
"`typst` not found in PATH — install Typst from typst.app/docs/install/"
.into(),
)
} else {
Error::Store(format!("spawn `typst compile`: {e}"))
}
})?;
Ok((child, pdf_path))
}
pub fn finish(child: Child, pdf_path: PathBuf) -> Result<CompileOutcome> {
let output = child
.wait_with_output()
.map_err(|e| Error::Store(format!("wait_with_output on `typst compile`: {e}")))?;
Ok(CompileOutcome {
success: output.status.success(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
pdf_path,
})
}