Add support for Rust edition

This commit is contained in:
Gabriel Majeri 2019-11-17 21:36:10 +03:00 committed by Eric Huss
parent bd0f434225
commit d39d4517aa
4 changed files with 126 additions and 7 deletions

View File

@ -3,6 +3,7 @@ title = "mdBook Documentation"
description = "Create book from markdown files. Like Gitbook but implemented in Rust" description = "Create book from markdown files. Like Gitbook but implemented in Rust"
authors = ["Mathieu David", "Michael-F-Bryan"] authors = ["Mathieu David", "Michael-F-Bryan"]
language = "en" language = "en"
edition = "2018"
[output.html] [output.html]
mathjax-support = true mathjax-support = true

View File

@ -9,6 +9,7 @@ Here is an example of what a ***book.toml*** file might look like:
title = "Example book" title = "Example book"
author = "John Doe" author = "John Doe"
description = "The example book covers examples." description = "The example book covers examples."
edition = "2018"
[build] [build]
build-dir = "my-example-book" 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` `src` directly under the root folder. But this is configurable with the `src`
key in the configuration file. key in the configuration file.
- **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example. - **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example.
- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015).
**book.toml** **book.toml**
```toml ```toml
@ -52,6 +54,7 @@ authors = ["John Doe", "Jane Doe"]
description = "The example book covers examples." description = "The example book covers examples."
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src` src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
language = "en" language = "en"
edition = "2018"
``` ```
### Build options ### 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. 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 - **git-repository-icon:** The FontAwesome icon class to use for the git
repository link. Defaults to `fa-github`. repository link. Defaults to `fa-github`.
Available configuration options for the `[output.html.fold]` table: Available configuration options for the `[output.html.fold]` table:
- **enable:** Enable section-folding. When off, all folds are open. - **enable:** Enable section-folding. When off, all folds are open.

View File

@ -27,7 +27,7 @@ use crate::preprocess::{
use crate::renderer::{CmdRenderer, HtmlHandlebars, MarkdownRenderer, RenderContext, Renderer}; use crate::renderer::{CmdRenderer, HtmlHandlebars, MarkdownRenderer, RenderContext, Renderer};
use crate::utils; use crate::utils;
use crate::config::Config; use crate::config::{Config, RustEdition};
/// The object used to manage and build a book. /// The object used to manage and build a book.
pub struct MDBook { pub struct MDBook {
@ -262,11 +262,21 @@ impl MDBook {
let mut tmpf = utils::fs::create_file(&path)?; let mut tmpf = utils::fs::create_file(&path)?;
tmpf.write_all(ch.content.as_bytes())?; tmpf.write_all(ch.content.as_bytes())?;
let output = Command::new("rustdoc") let mut cmd = Command::new("rustdoc");
.arg(&path) cmd.arg(&path).arg("--test").args(&library_args);
.arg("--test")
.args(&library_args) if let Some(edition) = self.config.book.edition {
.output()?; match edition {
RustEdition::E2015 => {
cmd.args(&["--edition", "2015"]);
}
RustEdition::E2018 => {
cmd.args(&["--edition", "2018"]);
}
}
}
let output = cmd.output()?;
if !output.status.success() { if !output.status.success() {
bail!(ErrorKind::Subprocess( bail!(ErrorKind::Subprocess(

View File

@ -393,6 +393,8 @@ pub struct BookConfig {
pub multilingual: bool, pub multilingual: bool,
/// The main language of the book. /// The main language of the book.
pub language: Option<String>, pub language: Option<String>,
/// Rust edition to use for the code.
pub edition: Option<RustEdition>,
} }
impl Default for BookConfig { impl Default for BookConfig {
@ -404,10 +406,60 @@ impl Default for BookConfig {
src: PathBuf::from("src"), src: PathBuf::from("src"),
multilingual: false, multilingual: false,
language: Some(String::from("en")), 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<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
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<D>(de: D) -> std::result::Result<Self, D::Error>
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. /// Configuration for the build procedure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
@ -647,6 +699,7 @@ mod tests {
multilingual: true, multilingual: true,
src: PathBuf::from("source"), src: PathBuf::from("source"),
language: Some(String::from("ja")), language: Some(String::from("ja")),
edition: None,
}; };
let build_should_be = BuildConfig { let build_should_be = BuildConfig {
build_dir: PathBuf::from("outputs"), build_dir: PathBuf::from("outputs"),
@ -678,6 +731,58 @@ mod tests {
assert_eq!(got.html_config().unwrap(), html_should_be); 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] #[test]
fn load_arbitrary_output_type() { fn load_arbitrary_output_type() {
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]