From d39d4517aa1e30bfdfefaf5b07235bd522eab9d1 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Sun, 17 Nov 2019 21:36:10 +0300 Subject: [PATCH] Add support for Rust edition --- book-example/book.toml | 1 + book-example/src/format/config.md | 5 +- src/book/mod.rs | 22 +++++-- src/config.rs | 105 ++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 7 deletions(-) diff --git a/book-example/book.toml b/book-example/book.toml index 100247fa..0c5ece6b 100644 --- a/book-example/book.toml +++ b/book-example/book.toml @@ -3,6 +3,7 @@ title = "mdBook Documentation" description = "Create book from markdown files. Like Gitbook but implemented in Rust" authors = ["Mathieu David", "Michael-F-Bryan"] language = "en" +edition = "2018" [output.html] mathjax-support = true diff --git a/book-example/src/format/config.md b/book-example/src/format/config.md index e1145aa8..0b671557 100644 --- a/book-example/src/format/config.md +++ b/book-example/src/format/config.md @@ -9,6 +9,7 @@ Here is an example of what a ***book.toml*** file might look like: title = "Example book" author = "John Doe" description = "The example book covers examples." +edition = "2018" [build] build-dir = "my-example-book" @@ -43,6 +44,7 @@ This is general information about your book. `src` directly under the root folder. But this is configurable with the `src` key in the configuration file. - **language:** The main language of the book, which is used as a language attribute `` for example. +- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015). **book.toml** ```toml @@ -52,6 +54,7 @@ authors = ["John Doe", "Jane Doe"] description = "The example book covers examples." src = "my-src" # the source files will be found in `root/my-src` instead of `root/src` language = "en" +edition = "2018" ``` ### Build options @@ -178,7 +181,7 @@ The following configuration options are available: an icon link will be output in the menu bar of the book. - **git-repository-icon:** The FontAwesome icon class to use for the git repository link. Defaults to `fa-github`. - + Available configuration options for the `[output.html.fold]` table: - **enable:** Enable section-folding. When off, all folds are open. diff --git a/src/book/mod.rs b/src/book/mod.rs index 2015801c..959800ed 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -27,7 +27,7 @@ use crate::preprocess::{ use crate::renderer::{CmdRenderer, HtmlHandlebars, MarkdownRenderer, RenderContext, Renderer}; use crate::utils; -use crate::config::Config; +use crate::config::{Config, RustEdition}; /// The object used to manage and build a book. pub struct MDBook { @@ -262,11 +262,21 @@ impl MDBook { let mut tmpf = utils::fs::create_file(&path)?; tmpf.write_all(ch.content.as_bytes())?; - let output = Command::new("rustdoc") - .arg(&path) - .arg("--test") - .args(&library_args) - .output()?; + let mut cmd = Command::new("rustdoc"); + cmd.arg(&path).arg("--test").args(&library_args); + + if let Some(edition) = self.config.book.edition { + match edition { + RustEdition::E2015 => { + cmd.args(&["--edition", "2015"]); + } + RustEdition::E2018 => { + cmd.args(&["--edition", "2018"]); + } + } + } + + let output = cmd.output()?; if !output.status.success() { bail!(ErrorKind::Subprocess( diff --git a/src/config.rs b/src/config.rs index 18d70ed7..2c4e12d3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -393,6 +393,8 @@ pub struct BookConfig { pub multilingual: bool, /// The main language of the book. pub language: Option, + /// Rust edition to use for the code. + pub edition: Option, } impl Default for BookConfig { @@ -404,10 +406,60 @@ impl Default for BookConfig { src: PathBuf::from("src"), multilingual: false, language: Some(String::from("en")), + edition: None, } } } +#[derive(Debug, Copy, Clone, PartialEq)] +/// Rust edition to use for the code. +pub enum RustEdition { + /// The 2018 edition of Rust + E2018, + /// The 2015 edition of Rust + E2015, +} + +impl Serialize for RustEdition { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + match self { + RustEdition::E2015 => serializer.serialize_str("2015"), + RustEdition::E2018 => serializer.serialize_str("2018"), + } + } +} + +impl<'de> Deserialize<'de> for RustEdition { + fn deserialize(de: D) -> std::result::Result + where + D: Deserializer<'de>, + { + use serde::de::Error; + + let raw = Value::deserialize(de)?; + + let edition = match raw { + Value::String(s) => s, + _ => { + return Err(D::Error::custom("Rust edition should be a string")); + } + }; + + let edition = match edition.as_str() { + "2018" => RustEdition::E2018, + "2015" => RustEdition::E2015, + _ => { + return Err(D::Error::custom("Unknown Rust edition")); + } + }; + + Ok(edition) + } +} + /// Configuration for the build procedure. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] @@ -647,6 +699,7 @@ mod tests { multilingual: true, src: PathBuf::from("source"), language: Some(String::from("ja")), + edition: None, }; let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), @@ -678,6 +731,58 @@ mod tests { assert_eq!(got.html_config().unwrap(), html_should_be); } + #[test] + fn edition_2015() { + let src = r#" + [book] + title = "mdBook Documentation" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + edition = "2015" + "#; + + let book_should_be = BookConfig { + title: Some(String::from("mdBook Documentation")), + description: Some(String::from( + "Create book from markdown files. Like Gitbook but implemented in Rust", + )), + authors: vec![String::from("Mathieu David")], + src: PathBuf::from("./source"), + edition: Some(RustEdition::E2015), + ..Default::default() + }; + + let got = Config::from_str(src).unwrap(); + assert_eq!(got.book, book_should_be); + } + + #[test] + fn edition_2018() { + let src = r#" + [book] + title = "mdBook Documentation" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + edition = "2018" + "#; + + let book_should_be = BookConfig { + title: Some(String::from("mdBook Documentation")), + description: Some(String::from( + "Create book from markdown files. Like Gitbook but implemented in Rust", + )), + authors: vec![String::from("Mathieu David")], + src: PathBuf::from("./source"), + edition: Some(RustEdition::E2018), + ..Default::default() + }; + + let got = Config::from_str(src).unwrap(); + assert_eq!(got.book, book_should_be); + } + #[test] fn load_arbitrary_output_type() { #[derive(Debug, Deserialize, PartialEq)]