Add support for Rust edition 2018 in playpens (#1086)

* Add support for Rust edition 2018 in playpens

* Add Rust edition support to rustdoc

* Run rustfmt

* Fix enum variant reference
This commit is contained in:
Gabriel Majeri 2019-11-11 13:42:24 +02:00 committed by Dylan DPC
parent a9160acd64
commit a7b3aa0444
6 changed files with 106 additions and 22 deletions

View File

@ -10,6 +10,7 @@ mathjax-support = true
[output.html.playpen] [output.html.playpen]
editable = true editable = true
line-numbers = true line-numbers = true
edition = "2018"
[output.html.search] [output.html.search]
limit-results = 20 limit-results = 20

View File

@ -178,7 +178,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.
@ -193,6 +193,7 @@ Available configuration options for the `[output.html.playpen]` table:
- **copy-js:** Copy JavaScript files for the editor to the output directory. - **copy-js:** Copy JavaScript files for the editor to the output directory.
Defaults to `true`. Defaults to `true`.
- **line-numbers** Display line numbers on editable sections of code. Requires both `editable` and `copy-js` to be `true`. Defaults to `false`. - **line-numbers** Display line numbers on editable sections of code. Requires both `editable` and `copy-js` to be `true`. Defaults to `false`.
- **edition**: Rust edition to use by default for the code snippets. Defaults to `2015`.
[Ace]: https://ace.c9.io/ [Ace]: https://ace.c9.io/

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,17 @@ 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)
.arg("--test") cmd.arg(&path).arg("--test").args(&library_args);
.args(&library_args)
.output()?; if let Some(html_cfg) = self.config.html_config() {
if html_cfg.playpen.edition == 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

@ -513,6 +513,8 @@ pub struct Playpen {
pub copy_js: bool, pub copy_js: bool,
/// Display line numbers on playpen snippets. Default: `false`. /// Display line numbers on playpen snippets. Default: `false`.
pub line_numbers: bool, pub line_numbers: bool,
/// Rust edition to use for the code. Default: `2015`.
pub edition: RustEdition,
} }
impl Default for Playpen { impl Default for Playpen {
@ -522,10 +524,66 @@ impl Default for Playpen {
copyable: true, copyable: true,
copy_js: true, copy_js: true,
line_numbers: false, line_numbers: false,
edition: RustEdition::E2015,
} }
} }
} }
#[derive(Debug, Clone, PartialEq)]
/// The edition of Rust used in a playpen code snippet
pub enum RustEdition {
/// The 2018 edition of Rust
E2018,
/// The 2015 edition of Rust
E2015,
}
impl Default for RustEdition {
fn default() -> Self {
RustEdition::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 of the search functionality of the HTML renderer. /// Configuration of the search functionality of the HTML renderer.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
@ -630,6 +688,7 @@ mod tests {
[output.html.playpen] [output.html.playpen]
editable = true editable = true
editor = "ace" editor = "ace"
edition = "2018"
[preprocessor.first] [preprocessor.first]
@ -658,6 +717,7 @@ mod tests {
copyable: true, copyable: true,
copy_js: true, copy_js: true,
line_numbers: false, line_numbers: false,
edition: RustEdition::E2018,
}; };
let html_should_be = HtmlConfig { let html_should_be = HtmlConfig {
curly_quotes: true, curly_quotes: true,

View File

@ -1,5 +1,5 @@
use crate::book::{Book, BookItem}; use crate::book::{Book, BookItem};
use crate::config::{Config, HtmlConfig, Playpen}; use crate::config::{Config, HtmlConfig, Playpen, RustEdition};
use crate::errors::*; use crate::errors::*;
use crate::renderer::html_handlebars::helpers; use crate::renderer::html_handlebars::helpers;
use crate::renderer::{RenderContext, Renderer}; use crate::renderer::{RenderContext, Renderer};
@ -608,14 +608,27 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
let classes = &caps[2]; let classes = &caps[2];
let code = &caps[3]; let code = &caps[3];
if classes.contains("language-rust") {
if (!classes.contains("ignore") && !classes.contains("noplaypen")) if (classes.contains("language-rust")
|| classes.contains("mdbook-runnable") && !classes.contains("ignore")
{ && !classes.contains("noplaypen"))
// wrap the contents in an external pre block || classes.contains("mdbook-runnable")
format!( {
"<pre class=\"playpen\"><code class=\"{}\">{}</code></pre>", let mut classes = classes.to_string();
classes, match playpen_config.edition {
RustEdition::E2018 => classes += " edition2018",
_ => (),
}
// wrap the contents in an external pre block
format!(
"<pre class=\"playpen\"><code class=\"{}\">{}</code></pre>",
classes,
{
let content: Cow<'_, str> = if playpen_config.editable
&& classes.contains("editable")
|| text.contains("fn main")
|| text.contains("quick_main!")
{ {
let content: Cow<'_, str> = if playpen_config.editable let content: Cow<'_, str> = if playpen_config.editable
&& classes.contains("editable") && classes.contains("editable")

View File

@ -490,12 +490,15 @@ fn markdown_options() {
"<td>bim</td>", "<td>bim</td>",
], ],
); );
assert_contains_strings(&path, &[ assert_contains_strings(
r##"<sup class="footnote-reference"><a href="#1">1</a></sup>"##, &path,
r##"<sup class="footnote-reference"><a href="#word">2</a></sup>"##, &[
r##"<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>"##, r##"<sup class="footnote-reference"><a href="#1">1</a></sup>"##,
r##"<div class="footnote-definition" id="word"><sup class="footnote-definition-label">2</sup>"##, r##"<sup class="footnote-reference"><a href="#word">2</a></sup>"##,
]); r##"<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>"##,
r##"<div class="footnote-definition" id="word"><sup class="footnote-definition-label">2</sup>"##,
],
);
assert_contains_strings(&path, &["<del>strikethrough example</del>"]); assert_contains_strings(&path, &["<del>strikethrough example</del>"]);
assert_contains_strings( assert_contains_strings(
&path, &path,