From 304234c122ec15051a2ed4379bd3a21b2dccb4fa Mon Sep 17 00:00:00 2001 From: Michael Bryan Date: Sun, 16 Sep 2018 23:00:19 +0800 Subject: [PATCH] The example can now tell mdbook if renderers are supported --- examples/nop-preprocessor.rs | 19 +++++++---- src/preprocess/cmd.rs | 60 +++++++++++++++++++---------------- tests/custom_preprocessors.rs | 11 ++++++- 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/examples/nop-preprocessor.rs b/examples/nop-preprocessor.rs index 1349a591..29b397ee 100644 --- a/examples/nop-preprocessor.rs +++ b/examples/nop-preprocessor.rs @@ -2,8 +2,9 @@ extern crate mdbook; #[macro_use] extern crate clap; -use clap::{App, Arg, SubCommand, ArgMatches}; +use clap::{App, Arg, ArgMatches, SubCommand}; use mdbook::preprocess::{Preprocessor, PreprocessorContext}; +use std::process; fn main() { let matches = app().get_matches(); @@ -16,16 +17,23 @@ fn main() { } fn handle_preprocessing(args: &ArgMatches) { - + unimplemented!() } fn handle_supports(sub_args: &ArgMatches) { - let renderer = sub_args.value_of("renderer").expect("Required argument"); - let supported = renderer_is_supported(&renderer); + let renderer = sub_args.value_of("renderer").expect("Required argument"); + let supported = renderer_is_supported(&renderer); + + if supported { + process::exit(0); + } else { + process::exit(1); + } } fn renderer_is_supported(renderer: &str) -> bool { - true + // We support everything except the `not-supported` renderer + renderer != "not-supported" } fn app() -> App<'static, 'static> { @@ -37,4 +45,3 @@ fn app() -> App<'static, 'static> { ), ) } - diff --git a/src/preprocess/cmd.rs b/src/preprocess/cmd.rs index 2047cc43..84a78e29 100644 --- a/src/preprocess/cmd.rs +++ b/src/preprocess/cmd.rs @@ -1,10 +1,10 @@ use super::{Preprocessor, PreprocessorContext}; use book::Book; use errors::*; +use serde_json; use shlex::Shlex; use std::io::{self, Read}; -use serde_json; -use std::process::{Command, Stdio, Child}; +use std::process::{Child, Command, Stdio}; /// A custom preprocessor which will shell out to a 3rd-party program. /// @@ -31,21 +31,27 @@ impl CmdPreprocessor { pub fn parse_input( reader: R, ) -> Result<(PreprocessorContext, Book)> { - serde_json::from_reader(reader).chain_err(|| "Unable to parse the input") + serde_json::from_reader(reader) + .chain_err(|| "Unable to parse the input") } - fn write_input(&self, child: &mut Child, book: Book, ctx: PreprocessorContext) { - let mut stdin = child.stdin.take().expect("Child has stdin"); - let input = (ctx, book); + fn write_input( + &self, + child: &mut Child, + book: Book, + ctx: PreprocessorContext, + ) { + let mut stdin = child.stdin.take().expect("Child has stdin"); + let input = (ctx, book); - if let Err(e) = serde_json::to_writer(&mut stdin, &input) { - // Looks like the backend hung up before we could finish - // sending it the render context. Log the error and keep going - warn!("Error writing the RenderContext to the backend, {}", e); - } + if let Err(e) = serde_json::to_writer(&mut stdin, &input) { + // Looks like the backend hung up before we could finish + // sending it the render context. Log the error and keep going + warn!("Error writing the RenderContext to the backend, {}", e); + } - // explicitly close the `stdin` file handle - drop(stdin); + // explicitly close the `stdin` file handle + drop(stdin); } fn command(&self) -> Result { @@ -75,6 +81,8 @@ impl Preprocessor for CmdPreprocessor { } fn supports_renderer(&self, renderer: &str) -> bool { + debug!("Checking if the \"{}\" preprocessor supports \"{}\"", self.name(), renderer); + let mut cmd = match self.command() { Ok(c) => c, Err(e) => { @@ -83,29 +91,25 @@ impl Preprocessor for CmdPreprocessor { } }; - cmd + let outcome = cmd .arg("supports") .arg(renderer) - .stdin(Stdio::piped()) + .stdin(Stdio::null()) .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()); + .stderr(Stdio::inherit()) + .status() + .map(|status| status.code() == Some(0)); - let child = match cmd.spawn() { - Ok(c) => c, - Err(e) => { - if e.kind() == io::ErrorKind::NotFound { - warn!( + if let Err(ref e) = outcome { + if e.kind() == io::ErrorKind::NotFound { + warn!( "The command wasn't found, is the \"{}\" preprocessor installed?", self.name ); - warn!("\tCommand: {}", self.cmd); - } - - // give it the benefit of the doubt - return true; + warn!("\tCommand: {}", self.cmd); } - }; + } - unimplemented!() + outcome.unwrap_or(false) } } diff --git a/tests/custom_preprocessors.rs b/tests/custom_preprocessors.rs index bad64f98..03d2689a 100644 --- a/tests/custom_preprocessors.rs +++ b/tests/custom_preprocessors.rs @@ -7,10 +7,19 @@ fn example() -> CmdPreprocessor { } #[test] -fn check_if_renderer_is_supported() { +fn example_supports_whatever() { let cmd = example(); let got = cmd.supports_renderer("whatever"); assert_eq!(got, true); } + +#[test] +fn example_doesnt_support_not_supported() { + let cmd = example(); + + let got = cmd.supports_renderer("not-supported"); + + assert_eq!(got, false); +}