diff --git a/examples/nop-preprocessor.rs b/examples/nop-preprocessor.rs index 29b397ee..df8bd757 100644 --- a/examples/nop-preprocessor.rs +++ b/examples/nop-preprocessor.rs @@ -3,8 +3,9 @@ extern crate mdbook; extern crate clap; use clap::{App, Arg, ArgMatches, SubCommand}; -use mdbook::preprocess::{Preprocessor, PreprocessorContext}; +use mdbook::preprocess::{Preprocessor, PreprocessorContext, CmdPreprocessor}; use std::process; +use std::io; fn main() { let matches = app().get_matches(); @@ -17,7 +18,18 @@ fn main() { } fn handle_preprocessing(args: &ArgMatches) { - unimplemented!() + let (ctx, book) = CmdPreprocessor::parse_input(io::stdin()) + .expect("Couldn't parse the input"); + + // You can tell the preprocessor to blow up by setting a particular + // config value + if let Some(table) = ctx.config.get_preprocessor("nop-preprocessor") { + let should_blow_up = table.get("blow-up").is_some(); + + if should_blow_up { + panic!("Boom!!!1!"); + } + } } fn handle_supports(sub_args: &ArgMatches) { diff --git a/src/preprocess/cmd.rs b/src/preprocess/cmd.rs index 84a78e29..2fc14ffc 100644 --- a/src/preprocess/cmd.rs +++ b/src/preprocess/cmd.rs @@ -39,7 +39,7 @@ impl CmdPreprocessor { &self, child: &mut Child, book: Book, - ctx: PreprocessorContext, + ctx: &PreprocessorContext, ) { let mut stdin = child.stdin.take().expect("Child has stdin"); let input = (ctx, book); @@ -77,7 +77,25 @@ impl Preprocessor for CmdPreprocessor { } fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result { - unimplemented!() + let mut cmd = self.command()?; + + let mut child = cmd + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .chain_err(|| format!("Unable to start the \"{}\" preprocessor. Is it installed?", self.name()))?; + + self.write_input(&mut child, book, ctx); + + let output = child + .wait_with_output() + .chain_err(|| "Error waiting for the preprocessor to complete")?; + + trace!("{} exited with output: {:?}", self.cmd, output); + ensure!(output.status.success(), "The preprocessor exited unsuccessfully"); + + serde_json::from_slice(&output.stdout).chain_err(|| "Unable to parse the preprocessed book") } fn supports_renderer(&self, renderer: &str) -> bool { diff --git a/tests/custom_preprocessors.rs b/tests/custom_preprocessors.rs index 03d2689a..d0182e7e 100644 --- a/tests/custom_preprocessors.rs +++ b/tests/custom_preprocessors.rs @@ -1,6 +1,8 @@ extern crate mdbook; use mdbook::preprocess::{CmdPreprocessor, Preprocessor}; +use mdbook::MDBook; +use std::path::Path; fn example() -> CmdPreprocessor { CmdPreprocessor::new("nop-preprocessor".to_string(), "cargo run --example nop-preprocessor --".to_string()) @@ -23,3 +25,25 @@ fn example_doesnt_support_not_supported() { assert_eq!(got, false); } + +#[test] +fn ask_the_preprocessor_to_blow_up() { + let dummy_book = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests").join("dummy_book"); + let mut md = MDBook::load(&dummy_book).unwrap(); + md.with_preprecessor(example()); + + md.config.set("preprocess.nop-preprocessor.blow-up", true).unwrap(); + + let got = md.build(); + + assert!(got.is_err()); +} + +#[test] +fn process_the_dummy_book() { + let dummy_book = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests").join("dummy_book"); + let mut md = MDBook::load(&dummy_book).unwrap(); + md.with_preprecessor(example()); + + md.build().unwrap(); +}