summaryrefslogtreecommitdiffstats
path: root/src/doc/rust-by-example
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/rust-by-example')
-rw-r--r--src/doc/rust-by-example/.github/workflows/rbe.yml35
-rw-r--r--src/doc/rust-by-example/README.md26
-rw-r--r--src/doc/rust-by-example/TRANSLATING.md85
-rw-r--r--src/doc/rust-by-example/book.toml9
-rw-r--r--src/doc/rust-by-example/src/attribute.md2
-rw-r--r--src/doc/rust-by-example/src/cargo/test.md6
-rw-r--r--src/doc/rust-by-example/src/conversion/string.md2
-rw-r--r--src/doc/rust-by-example/src/error/abort_unwind.md33
-rw-r--r--src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md2
-rw-r--r--src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md2
-rw-r--r--src/doc/rust-by-example/src/error/option_unwrap/defaults.md1
-rw-r--r--src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md9
-rw-r--r--src/doc/rust-by-example/src/flow_control/match/guard.md4
-rw-r--r--src/doc/rust-by-example/src/fn/closures.md2
-rw-r--r--src/doc/rust-by-example/src/fn/closures/capture.md2
-rw-r--r--src/doc/rust-by-example/src/index.md10
-rw-r--r--src/doc/rust-by-example/src/macros/dsl.md2
-rw-r--r--src/doc/rust-by-example/src/meta/doc.md4
-rw-r--r--src/doc/rust-by-example/src/meta/playground.md15
-rw-r--r--src/doc/rust-by-example/src/scope/lifetime/explicit.md4
-rw-r--r--src/doc/rust-by-example/src/std_misc/arg.md7
-rw-r--r--src/doc/rust-by-example/src/std_misc/ffi.md10
-rw-r--r--src/doc/rust-by-example/src/std_misc/fs.md10
-rw-r--r--src/doc/rust-by-example/src/std_misc/process/pipe.md11
-rw-r--r--src/doc/rust-by-example/src/testing/unit_testing.md2
-rw-r--r--src/doc/rust-by-example/src/trait/clone.md4
-rw-r--r--src/doc/rust-by-example/src/trait/disambiguating.md4
-rw-r--r--src/doc/rust-by-example/src/unsafe/asm.md11
-rw-r--r--src/doc/rust-by-example/theme/css/language-picker.css13
-rw-r--r--src/doc/rust-by-example/theme/index.hbs386
30 files changed, 657 insertions, 56 deletions
diff --git a/src/doc/rust-by-example/.github/workflows/rbe.yml b/src/doc/rust-by-example/.github/workflows/rbe.yml
index 76b127b96..e93054547 100644
--- a/src/doc/rust-by-example/.github/workflows/rbe.yml
+++ b/src/doc/rust-by-example/.github/workflows/rbe.yml
@@ -1,12 +1,19 @@
name: CI
on: [push, pull_request]
+env:
+ # Update the language picker in index.hbs to link new languages.
+ LANGUAGES:
+
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@master
+ - uses: actions/checkout@v4
+ with:
+ # We need the full history below.
+ fetch-depth: 0
- name: Update rustup
run: rustup self update
@@ -23,6 +30,10 @@ jobs:
curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin
echo "$(pwd)/bin" >> ${GITHUB_PATH}
+ - name: Install mdbook-i18n-helpers
+ run: |
+ cargo install mdbook-i18n-helpers --locked --version 0.3.0
+
- name: Report versions
run: |
rustup --version
@@ -41,6 +52,28 @@ jobs:
https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh
sh linkcheck.sh --all rust-by-example
+ - name: Build all translations
+ run: |
+ for po_lang in ${{ env.LANGUAGES }}; do
+ POT_CREATION_DATE=$(grep --max-count 1 '^"POT-Creation-Date:' po/$po_lang.po | sed -E 's/".*: (.*)\\n"/\1/')
+ if [[ $POT_CREATION_DATE == "" ]]; then
+ POT_CREATION_DATE=now
+ fi
+
+ echo "::group::Building $po_lang translation as of $POT_CREATION_DATE"
+ rm -r src/
+ git restore --source "$(git rev-list -n 1 --before "$POT_CREATION_DATE" @)" src/
+
+ # Set language and adjust site URL. Clear the redirects
+ # since they are in sync with the source files, not the
+ # translation.
+ MDBOOK_BOOK__LANGUAGE=$po_lang \
+ MDBOOK_OUTPUT__HTML__SITE_URL=/rust-by-example/$po_lang/ \
+ MDBOOK_OUTPUT__HTML__REDIRECT='{}' \
+ mdbook build -d book/$po_lang
+ echo "::endgroup::"
+ done
+
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md
index 2529a3fad..16b849f0b 100644
--- a/src/doc/rust-by-example/README.md
+++ b/src/doc/rust-by-example/README.md
@@ -27,14 +27,40 @@ mdbook serve
To be able to run the examples, you must be connected to the internet; you can
read all content offline, however!
+The following warnings can be ignored safely.
+
+```
+[WARN] (mdbook::preprocess::cmd): The command wasn't found, is the "gettext" preprocessor installed?
+[WARN] (mdbook::preprocess::cmd): Command: mdbook-gettext
+```
+
+### Using translated version
+
+If there is a translated resource in `po/` directory, it can be specified through `MDBOOK_BOOK__LANGUAGE` like below:
+
+```bash
+git clone https://github.com/rust-lang/rust-by-example
+cd rust-by-example
+cargo install mdbook
+MDBOOK_BOOK__LANGUAGE=ja mdbook build
+MDBOOK_BOOK__LANGUAGE=ja mdbook serve
+```
+
## Contributing
Please see the [CONTRIBUTING.md] file for more details.
[CONTRIBUTING.md]: https://github.com/rust-lang/rust-by-example/blob/master/CONTRIBUTING.md
+## Translating
+
+Please see the [TRANSLATING.md] file for more details.
+
+[TRANSLATING.md]: https://github.com/rust-lang/rust-by-example/blob/master/TRANSLATING.md
+
## Translations to other languages
+* [Bulgarian](https://github.com/kberov/rust-by-example-bg)
* [Chinese](https://github.com/rust-lang-cn/rust-by-example-cn)
* [Japanese](https://github.com/rust-lang-ja/rust-by-example-ja)
* [French](https://github.com/Songbird0/FR_RBE)
diff --git a/src/doc/rust-by-example/TRANSLATING.md b/src/doc/rust-by-example/TRANSLATING.md
new file mode 100644
index 000000000..c2a39f51b
--- /dev/null
+++ b/src/doc/rust-by-example/TRANSLATING.md
@@ -0,0 +1,85 @@
+# Rust by Example translation guidelines
+
+Please see the [CONTRIBUTING.md] file for general contribution guidelines.
+This file describes about the translation workflow.
+
+[CONTRIBUTING.md]: https://github.com/rust-lang/rust-by-example/blob/master/CONTRIBUTING.md
+
+## Translation workflow
+
+### Preparation
+
+RBE uses [mdbook-i18n-helpers](https://github.com/google/mdbook-i18n-helpers) as a translation framework.
+The following tools are required.
+
+* GNU gettext utilities ( `msgmerge` and `msgcat` )
+* mdbook-i18n-helpers ( `cargo install mdbook-i18n-helpers` )
+
+### Creating and Updating Translations
+
+Please see the [mdbook-i18n-helpers USAGE](https://github.com/google/mdbook-i18n-helpers/blob/main/i18n-helpers/USAGE.md) file for the detailed usage of mdbook-i18n-helpers.
+The summarized command list is below:
+
+#### Generating a message template
+
+The generated message templete `po/messages.pot` is required to create or update translations.
+
+```bash
+MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' \
+ mdbook build -d po
+```
+
+#### Creating a new translation resource
+
+`xx` is [ISO 639](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code.
+
+```bash
+msginit -i po/messages.pot -l xx -o po/xx.po
+```
+
+#### Updating the exising translation resource
+
+```bash
+msgmerge --update po/xx.po po/messages.pot
+```
+
+### Editing translation resources
+
+After generating a translation resource `po/xx.po`, you can write translation messages in `msgstr` entry of `po/xx.po`.
+To build a translated book, the following command can be used.
+
+```bash
+MDBOOK_BOOK__LANGUAGE=xx mdbook build
+MDBOOK_BOOK__LANGUAGE=xx mdbook serve
+```
+
+### Add a language entry
+
+Please add a language entry in `.github/workflows/rbe.yml` and `theme/index.hbs` like below:
+
+* `rbe.yml`
+
+```yml
+env:
+ # Update the language picker in index.hbs to link new languages.
+ LANGUAGES: xx yy zz
+```
+
+* `index.hbs`
+
+```html
+<ul id="language-list" class="theme-popup" aria-label="Languages" role="menu">
+ <li role="none"><button role="menuitem" class="theme">
+ <a id="en">English</a>
+ </button></li>
+ <li role="none"><button role="menuitem" class="theme">
+ <a id="xx">XX language</a>
+ </button></li>
+ <li role="none"><button role="menuitem" class="theme">
+ <a id="yy">YY language</a>
+ </button></li>
+ <li role="none"><button role="menuitem" class="theme">
+ <a id="zz">ZZ language</a>
+ </button></li>
+</ul>
+```
diff --git a/src/doc/rust-by-example/book.toml b/src/doc/rust-by-example/book.toml
index 61fb4057f..e8364161b 100644
--- a/src/doc/rust-by-example/book.toml
+++ b/src/doc/rust-by-example/book.toml
@@ -13,6 +13,15 @@ enable = true
[output.html]
git-repository-url = "https://github.com/rust-lang/rust-by-example"
+additional-css = [
+ "theme/css/language-picker.css",
+]
[rust]
edition = "2021"
+
+[build]
+extra-watch-dirs = ["po"]
+
+[preprocessor.gettext]
+after = ["links"]
diff --git a/src/doc/rust-by-example/src/attribute.md b/src/doc/rust-by-example/src/attribute.md
index d6a49dc01..870beb1ee 100644
--- a/src/doc/rust-by-example/src/attribute.md
+++ b/src/doc/rust-by-example/src/attribute.md
@@ -31,7 +31,7 @@ with the difference between them being where they apply.
```
- `#![inner_attribute]` applies to the enclosing [item][item] (typically a
- module or a crate). In other words, this attribute is intepreted as
+ module or a crate). In other words, this attribute is interpreted as
applying to the entire scope in which it's place. Here is an example
where `#![allow(unusude_variables)]` applies to the whole crate (if
placed in `main.rs`):
diff --git a/src/doc/rust-by-example/src/cargo/test.md b/src/doc/rust-by-example/src/cargo/test.md
index f2af48db5..a86b8f831 100644
--- a/src/doc/rust-by-example/src/cargo/test.md
+++ b/src/doc/rust-by-example/src/cargo/test.md
@@ -42,13 +42,13 @@ $ cargo test
Finished dev [unoptimized + debuginfo] target(s) in 0.89 secs
Running target/debug/deps/blah-d3b32b97275ec472
-running 3 tests
+running 4 tests
test test_bar ... ok
test test_baz ... ok
test test_foo_bar ... ok
test test_foo ... ok
-test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
You can also run tests whose name matches a pattern:
@@ -135,7 +135,7 @@ Corro
```
What actually gets put into `ferris.txt` is this:
```shell
-$ cargo test test_foo
+$ cargo test test_file && cat ferris.txt
Corro
Ferris
Corro
diff --git a/src/doc/rust-by-example/src/conversion/string.md b/src/doc/rust-by-example/src/conversion/string.md
index edadaaa51..9a17a2ce6 100644
--- a/src/doc/rust-by-example/src/conversion/string.md
+++ b/src/doc/rust-by-example/src/conversion/string.md
@@ -28,7 +28,7 @@ fn main() {
## Parsing a String
-One of the more common types to convert a string into a number. The idiomatic
+One of the more common types to convert a string into is a number. The idiomatic
approach to this is to use the [`parse`] function and either to arrange for
type inference or to specify the type to parse using the 'turbofish' syntax.
Both alternatives are shown in the following example.
diff --git a/src/doc/rust-by-example/src/error/abort_unwind.md b/src/doc/rust-by-example/src/error/abort_unwind.md
index d38af3ce1..2afae9882 100644
--- a/src/doc/rust-by-example/src/error/abort_unwind.md
+++ b/src/doc/rust-by-example/src/error/abort_unwind.md
@@ -6,14 +6,17 @@ The previous section illustrates the error handling mechanism `panic`. Differen
Building on the prior lemonade example, we explicitly use the panic strategy to exercise different lines of code.
```rust,editable,mdbook-runnable
-
fn drink(beverage: &str) {
- // You shouldn't drink too much sugary beverages.
+ // You shouldn't drink too much sugary beverages.
if beverage == "lemonade" {
- if cfg!(panic="abort"){ println!("This is not your party. Run!!!!");}
- else{ println!("Spit it out!!!!");}
+ if cfg!(panic = "abort") {
+ println!("This is not your party. Run!!!!");
+ } else {
+ println!("Spit it out!!!!");
+ }
+ } else {
+ println!("Some refreshing {} is all I need.", beverage);
}
- else{ println!("Some refreshing {} is all I need.", beverage); }
}
fn main() {
@@ -25,16 +28,22 @@ fn main() {
Here is another example focusing on rewriting `drink()` and explicitly use the `unwind` keyword.
```rust,editable
-
#[cfg(panic = "unwind")]
-fn ah(){ println!("Spit it out!!!!");}
+fn ah() {
+ println!("Spit it out!!!!");
+}
-#[cfg(not(panic="unwind"))]
-fn ah(){ println!("This is not your party. Run!!!!");}
+#[cfg(not(panic = "unwind"))]
+fn ah() {
+ println!("This is not your party. Run!!!!");
+}
-fn drink(beverage: &str){
- if beverage == "lemonade"{ ah();}
- else{println!("Some refreshing {} is all I need.", beverage);}
+fn drink(beverage: &str) {
+ if beverage == "lemonade" {
+ ah();
+ } else {
+ println!("Some refreshing {} is all I need.", beverage);
+ }
}
fn main() {
diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md b/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md
index 84b0c41e5..ca506d413 100644
--- a/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md
+++ b/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md
@@ -12,7 +12,7 @@ via [`From`][from].
use std::error;
use std::fmt;
-// Change the alias to `Box<error::Error>`.
+// Change the alias to use `Box<dyn error::Error>`.
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;
#[derive(Debug, Clone)]
diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
index 998b741e7..e00146462 100644
--- a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
+++ b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
@@ -26,7 +26,7 @@ Here, we rewrite the previous example using `?`. As a result, the
use std::error;
use std::fmt;
-// Change the alias to `Box<dyn error::Error>`.
+// Change the alias to use `Box<dyn error::Error>`.
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;
#[derive(Debug)]
diff --git a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
index 513bb1df7..e439f5cd4 100644
--- a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
+++ b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
@@ -38,7 +38,6 @@ Another alternative is to use `or_else`, which is also chainable, and evaluates
enum Fruit { Apple, Orange, Banana, Kiwi, Lemon }
fn main() {
- let apple = Some(Fruit::Apple);
let no_fruit: Option<Fruit> = None;
let get_kiwi_as_fallback = || {
println!("Providing kiwi as fallback");
diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md
index 252104fef..96b24368f 100644
--- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md
+++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md
@@ -30,6 +30,15 @@ fn main() {
// You do not need a match block to destructure structs:
let Foo { x : x0, y: y0 } = faa;
println!("Outside: x0 = {x0:?}, y0 = {y0}");
+
+ // Destructuring works with nested structs as well:
+ struct Bar {
+ foo: Foo,
+ }
+
+ let bar = Bar { foo: faa };
+ let Bar { foo: Foo { x: nested_x, y: nested_y } } = bar;
+ println!("Nested: nested_x = {nested_x:?}, nested_y = {nested_y:?}");
}
```
diff --git a/src/doc/rust-by-example/src/flow_control/match/guard.md b/src/doc/rust-by-example/src/flow_control/match/guard.md
index af81f64c9..df9fb2c9a 100644
--- a/src/doc/rust-by-example/src/flow_control/match/guard.md
+++ b/src/doc/rust-by-example/src/flow_control/match/guard.md
@@ -16,10 +16,10 @@ fn main() {
match temperature {
Temperature::Celsius(t) if t > 30 => println!("{}C is above 30 Celsius", t),
// The `if condition` part ^ is a guard
- Temperature::Celsius(t) => println!("{}C is below 30 Celsius", t),
+ Temperature::Celsius(t) => println!("{}C is equal to or below 30 Celsius", t),
Temperature::Fahrenheit(t) if t > 86 => println!("{}F is above 86 Fahrenheit", t),
- Temperature::Fahrenheit(t) => println!("{}F is below 86 Fahrenheit", t),
+ Temperature::Fahrenheit(t) => println!("{}F is equal to or below 86 Fahrenheit", t),
}
}
```
diff --git a/src/doc/rust-by-example/src/fn/closures.md b/src/doc/rust-by-example/src/fn/closures.md
index e7b8c9867..379a52e43 100644
--- a/src/doc/rust-by-example/src/fn/closures.md
+++ b/src/doc/rust-by-example/src/fn/closures.md
@@ -14,7 +14,7 @@ variable names *must* be specified.
Other characteristics of closures include:
* using `||` instead of `()` around input variables.
-* optional body delimitation (`{}`) for a single expression (mandatory otherwise).
+* optional body delimitation (`{}`) for a single line expression (mandatory otherwise).
* the ability to capture the outer environment variables.
```rust,editable
diff --git a/src/doc/rust-by-example/src/fn/closures/capture.md b/src/doc/rust-by-example/src/fn/closures/capture.md
index 061ef1c7b..c2f0c62ac 100644
--- a/src/doc/rust-by-example/src/fn/closures/capture.md
+++ b/src/doc/rust-by-example/src/fn/closures/capture.md
@@ -44,7 +44,7 @@ fn main() {
// borrows `count`.
//
// A `mut` is required on `inc` because a `&mut` is stored inside. Thus,
- // calling the closure mutates the closure which requires a `mut`.
+ // calling the closure mutates `count` which requires a `mut`.
let mut inc = || {
count += 1;
println!("`count`: {}", count);
diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md
index ecadff4cc..e42c196d1 100644
--- a/src/doc/rust-by-example/src/index.md
+++ b/src/doc/rust-by-example/src/index.md
@@ -21,9 +21,9 @@ Now let's begin!
- [Types](types.md) - Learn about changing and defining types.
-- [Conversion](conversion.md)
+- [Conversion](conversion.md) - Convert between different types, such as strings, integers, and floats.
-- [Expressions](expression.md)
+- [Expressions](expression.md) - Learn about Expressions & how to use them.
- [Flow of Control](flow_control.md) - `if`/`else`, `for`, and others.
@@ -43,7 +43,7 @@ Now let's begin!
- [Traits](trait.md) - A trait is a collection of methods defined for an unknown type: `Self`
-- [Macros](macros.md)
+- [Macros](macros.md) - Macros are a way of writing code that writes other code, which is known as metaprogramming.
- [Error handling](error.md) - Learn Rust way of handling failures.
@@ -53,9 +53,9 @@ Now let's begin!
- [Testing](testing.md) - All sorts of testing in Rust.
-- [Unsafe Operations](unsafe.md)
+- [Unsafe Operations](unsafe.md) - Learn about entering a block of unsafe operations.
-- [Compatibility](compatibility.md)
+- [Compatibility](compatibility.md) - Handling Rust's evolution and potential compatibility issues.
- [Meta](meta.md) - Documentation, Benchmarking.
diff --git a/src/doc/rust-by-example/src/macros/dsl.md b/src/doc/rust-by-example/src/macros/dsl.md
index 9aaeda34c..d83885a4d 100644
--- a/src/doc/rust-by-example/src/macros/dsl.md
+++ b/src/doc/rust-by-example/src/macros/dsl.md
@@ -12,7 +12,7 @@ an expression and have the output printed to console.
macro_rules! calculate {
(eval $e:expr) => {
{
- let val: usize = $e; // Force types to be integers
+ let val: usize = $e; // Force types to be unsigned integers
println!("{} = {}", stringify!{$e}, val);
}
};
diff --git a/src/doc/rust-by-example/src/meta/doc.md b/src/doc/rust-by-example/src/meta/doc.md
index b1732f837..f6978a9f4 100644
--- a/src/doc/rust-by-example/src/meta/doc.md
+++ b/src/doc/rust-by-example/src/meta/doc.md
@@ -46,7 +46,7 @@ impl Person {
/// Gives a friendly hello!
///
/// Says "Hello, [name](Person::name)" to the `Person` it is called on.
- pub fn hello(& self) {
+ pub fn hello(&self) {
println!("Hello, {}!", self.name);
}
}
@@ -80,7 +80,7 @@ Used to inline docs, instead of linking out to separate page.
pub use bar::Bar;
/// bar docs
-mod bar {
+pub mod bar {
/// the docs for Bar
pub struct Bar;
}
diff --git a/src/doc/rust-by-example/src/meta/playground.md b/src/doc/rust-by-example/src/meta/playground.md
index e78552d29..5fc488c78 100644
--- a/src/doc/rust-by-example/src/meta/playground.md
+++ b/src/doc/rust-by-example/src/meta/playground.md
@@ -14,7 +14,7 @@ fn main() {
```
This allows the reader to both run your code sample, but also modify and tweak
-it. The key here is the adding the word `editable` to your codefence block
+it. The key here is the adding of the word `editable` to your codefence block
separated by a comma.
````markdown
@@ -39,15 +39,22 @@ button that says "Run", which opens the code sample up in a new tab in Rust
Playground. This feature is enabled if you use the `#[doc]` attribute called
[`html_playground_url`][html-playground-url].
+```
+#![doc(html_playground_url = "https://play.rust-lang.org/")]
+//! ```
+//! println!("Hello Wolrd");
+//! ```
+```
+
### See also:
- [The Rust Playground][rust-playground]
-- [rust-playground][rust-playground]
+- [The Rust Playground On Github][rust-playground-github]
- [The rustdoc Book][rustdoc-book]
[rust-playground]: https://play.rust-lang.org/
-[rust-playground]: https://github.com/integer32llc/rust-playground/
+[rust-playground-github]: https://github.com/integer32llc/rust-playground/
[mdbook]: https://github.com/rust-lang/mdBook
[official-rust-docs]: https://doc.rust-lang.org/core/
[rustdoc-book]: https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html
-[html-playground-url]: https://doc.rust-lang.org/rustdoc/the-doc-attribute.html#html_playground_url
+[html-playground-url]: https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html#html_playground_url
diff --git a/src/doc/rust-by-example/src/scope/lifetime/explicit.md b/src/doc/rust-by-example/src/scope/lifetime/explicit.md
index f0ecdf5fc..68d144a82 100644
--- a/src/doc/rust-by-example/src/scope/lifetime/explicit.md
+++ b/src/doc/rust-by-example/src/scope/lifetime/explicit.md
@@ -40,10 +40,10 @@ fn failed_borrow<'a>() {
let _x = 12;
// ERROR: `_x` does not live long enough
- let y: &'a i32 = &_x;
+ let _y: &'a i32 = &_x;
// Attempting to use the lifetime `'a` as an explicit type annotation
// inside the function will fail because the lifetime of `&_x` is shorter
- // than that of `y`. A short lifetime cannot be coerced into a longer one.
+ // than that of `_y`. A short lifetime cannot be coerced into a longer one.
}
fn main() {
diff --git a/src/doc/rust-by-example/src/std_misc/arg.md b/src/doc/rust-by-example/src/std_misc/arg.md
index b5dd89ce6..1cf8cf7ef 100644
--- a/src/doc/rust-by-example/src/std_misc/arg.md
+++ b/src/doc/rust-by-example/src/std_misc/arg.md
@@ -30,8 +30,7 @@ I got 3 arguments: ["1", "2", "3"].
## Crates
Alternatively, there are numerous crates that can provide extra functionality
-when creating command-line applications. The [Rust Cookbook] exhibits best
-practices on how to use one of the more popular command line argument crates,
-`clap`.
+when creating command-line applications. One of the more popular command line
+argument crates being [`clap`].
-[Rust Cookbook]: https://rust-lang-nursery.github.io/rust-cookbook/cli/arguments.html
+[`clap`]: https://rust-cli.github.io/book/tutorial/cli-args.html#parsing-cli-arguments-with-clap
diff --git a/src/doc/rust-by-example/src/std_misc/ffi.md b/src/doc/rust-by-example/src/std_misc/ffi.md
index 71977e66f..272873600 100644
--- a/src/doc/rust-by-example/src/std_misc/ffi.md
+++ b/src/doc/rust-by-example/src/std_misc/ffi.md
@@ -8,6 +8,16 @@ attribute containing the name of the foreign library.
use std::fmt;
// this extern block links to the libm library
+#[cfg(target_family = "windows")]
+#[link(name = "msvcrt")]
+extern {
+ // this is a foreign function
+ // that computes the square root of a single precision complex number
+ fn csqrtf(z: Complex) -> Complex;
+
+ fn ccosf(z: Complex) -> Complex;
+}
+#[cfg(target_family = "unix")]
#[link(name = "m")]
extern {
// this is a foreign function
diff --git a/src/doc/rust-by-example/src/std_misc/fs.md b/src/doc/rust-by-example/src/std_misc/fs.md
index 48e4d4d66..ba2d4b4fa 100644
--- a/src/doc/rust-by-example/src/std_misc/fs.md
+++ b/src/doc/rust-by-example/src/std_misc/fs.md
@@ -7,7 +7,10 @@ use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
+#[cfg(target_family = "unix")]
use std::os::unix;
+#[cfg(target_family = "windows")]
+use std::os::windows;
use std::path::Path;
// A simple implementation of `% cat path`
@@ -62,11 +65,16 @@ fn main() {
println!("`ln -s ../b.txt a/c/b.txt`");
// Create a symbolic link, returns `io::Result<()>`
- if cfg!(target_family = "unix") {
+ #[cfg(target_family = "unix")] {
unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
}
+ #[cfg(target_family = "windows")] {
+ windows::fs::symlink_file("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
+ println!("! {:?}", why.to_string());
+ });
+ }
println!("`cat a/c/b.txt`");
match cat(&Path::new("a/c/b.txt")) {
diff --git a/src/doc/rust-by-example/src/std_misc/process/pipe.md b/src/doc/rust-by-example/src/std_misc/process/pipe.md
index fb0be0ea1..1b1973718 100644
--- a/src/doc/rust-by-example/src/std_misc/process/pipe.md
+++ b/src/doc/rust-by-example/src/std_misc/process/pipe.md
@@ -6,14 +6,21 @@ process via pipes.
```rust,ignore
use std::io::prelude::*;
-use std::process::{Command, Stdio};
+use std::process::Stdio;
static PANGRAM: &'static str =
"the quick brown fox jumped over the lazy dog\n";
fn main() {
// Spawn the `wc` command
- let process = match Command::new("wc")
+ let mut cmd = if cfg!(target_family = "windows") {
+ let mut cmd = Command::new("powershell");
+ cmd.arg("-Command").arg("$input | Measure-Object -Line -Word -Character");
+ cmd
+ } else {
+ Command::new("wc")
+ };
+ let process = match cmd
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn() {
diff --git a/src/doc/rust-by-example/src/testing/unit_testing.md b/src/doc/rust-by-example/src/testing/unit_testing.md
index cd8770664..bdce96334 100644
--- a/src/doc/rust-by-example/src/testing/unit_testing.md
+++ b/src/doc/rust-by-example/src/testing/unit_testing.md
@@ -199,7 +199,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Tests can be marked with the `#[ignore]` attribute to exclude some tests. Or to run
them with command `cargo test -- --ignored`
-```rust
+```rust,ignore
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
diff --git a/src/doc/rust-by-example/src/trait/clone.md b/src/doc/rust-by-example/src/trait/clone.md
index 5d6747a47..8e04f5a2a 100644
--- a/src/doc/rust-by-example/src/trait/clone.md
+++ b/src/doc/rust-by-example/src/trait/clone.md
@@ -40,11 +40,11 @@ fn main() {
// Clone `moved_pair` into `cloned_pair` (resources are included)
let cloned_pair = moved_pair.clone();
- // Drop the original pair using std::mem::drop
+ // Drop the moved original pair using std::mem::drop
drop(moved_pair);
// Error! `moved_pair` has been dropped
- //println!("copy: {:?}", moved_pair);
+ //println!("moved and dropped: {:?}", moved_pair);
// TODO ^ Try uncommenting this line
// The result from .clone() can still be used!
diff --git a/src/doc/rust-by-example/src/trait/disambiguating.md b/src/doc/rust-by-example/src/trait/disambiguating.md
index ae80d4acb..6fca4b032 100644
--- a/src/doc/rust-by-example/src/trait/disambiguating.md
+++ b/src/doc/rust-by-example/src/trait/disambiguating.md
@@ -1,8 +1,8 @@
# Disambiguating overlapping traits
A type can implement many different traits. What if two traits both require
-the same name? For example, many traits might have a method named `get()`.
-They might even have different return types!
+the same name for a function? For example, many traits might have a method
+named `get()`. They might even have different return types!
Good news: because each trait implementation gets its own `impl` block, it's
clear which trait's `get` method you're implementing.
diff --git a/src/doc/rust-by-example/src/unsafe/asm.md b/src/doc/rust-by-example/src/unsafe/asm.md
index cbe52c840..a2b5b079c 100644
--- a/src/doc/rust-by-example/src/unsafe/asm.md
+++ b/src/doc/rust-by-example/src/unsafe/asm.md
@@ -139,8 +139,8 @@ can be written at any time, and can therefore not share its location with any ot
However, to guarantee optimal performance it is important to use as few registers as possible,
so they won't have to be saved and reloaded around the inline assembly block.
To achieve this Rust provides a `lateout` specifier. This can be used on any output that is
-written only after all inputs have been consumed.
-There is also a `inlateout` variant of this specifier.
+written only after all inputs have been consumed. There is also an `inlateout` variant of this
+specifier.
Here is an example where `inlateout` *cannot* be used in `release` mode or other optimized cases:
@@ -163,11 +163,12 @@ unsafe {
assert_eq!(a, 12);
# }
```
-The above could work well in unoptimized cases (`Debug` mode), but if you want optimized performance (`release` mode or other optimized cases), it could not work.
-That is because in optimized cases, the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.
+In unoptimized cases (e.g. `Debug` mode), replacing `inout(reg) a` with `inlateout(reg) a` in the above example can continue to give the expected result. However, with `release` mode or other optimized cases, using `inlateout(reg) a` can instead lead to the final value `a = 16`, causing the assertion to fail.
-However the following example can use `inlateout` since the output is only modified after all input registers have been read:
+This is because in optimized cases, the compiler is free to allocate the same register for inputs `b` and `c` since it knows that they have the same value. Furthermore, when `inlateout` is used, `a` and `c` could be allocated to the same register, in which case the first `add` instruction would overwrite the initial load from variable `c`. This is in contrast to how using `inout(reg) a` ensures a separate register is allocated for `a`.
+
+However, the following example can use `inlateout` since the output is only modified after all input registers have been read:
```rust
# #[cfg(target_arch = "x86_64")] {
diff --git a/src/doc/rust-by-example/theme/css/language-picker.css b/src/doc/rust-by-example/theme/css/language-picker.css
new file mode 100644
index 000000000..1553ed68f
--- /dev/null
+++ b/src/doc/rust-by-example/theme/css/language-picker.css
@@ -0,0 +1,13 @@
+#language-list {
+ left: auto;
+ right: 10px;
+}
+
+[dir="rtl"] #language-list {
+ left: 10px;
+ right: auto;
+}
+
+#language-list a {
+ color: inherit;
+}
diff --git a/src/doc/rust-by-example/theme/index.hbs b/src/doc/rust-by-example/theme/index.hbs
new file mode 100644
index 000000000..1ae579f39
--- /dev/null
+++ b/src/doc/rust-by-example/theme/index.hbs
@@ -0,0 +1,386 @@
+<!DOCTYPE HTML>
+<html lang="{{ language }}" class="{{ default_theme }}" dir="{{ text_direction }}">
+ <head>
+ <!-- Book generated using mdBook -->
+ <meta charset="UTF-8">
+ <title>{{ title }}</title>
+ {{#if is_print }}
+ <meta name="robots" content="noindex">
+ {{/if}}
+ {{#if base_url}}
+ <base href="{{ base_url }}">
+ {{/if}}
+
+
+ <!-- Custom HTML head -->
+ {{> head}}
+
+ <meta name="description" content="{{ description }}">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#ffffff">
+
+ {{#if favicon_svg}}
+ <link rel="icon" href="{{ path_to_root }}favicon.svg">
+ {{/if}}
+ {{#if favicon_png}}
+ <link rel="shortcut icon" href="{{ path_to_root }}favicon.png">
+ {{/if}}
+ <link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
+ <link rel="stylesheet" href="{{ path_to_root }}css/general.css">
+ <link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
+ {{#if print_enable}}
+ <link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
+ {{/if}}
+
+ <!-- Fonts -->
+ <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
+ {{#if copy_fonts}}
+ <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
+ {{/if}}
+
+ <!-- Highlight.js Stylesheets -->
+ <link rel="stylesheet" href="{{ path_to_root }}highlight.css">
+ <link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
+ <link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
+
+ <!-- Custom theme stylesheets -->
+ {{#each additional_css}}
+ <link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">
+ {{/each}}
+
+ {{#if mathjax_support}}
+ <!-- MathJax -->
+ <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
+ {{/if}}
+ </head>
+ <body class="sidebar-visible no-js">
+ <div id="body-container">
+ <!-- Provide site root to javascript -->
+ <script>
+ var path_to_root = "{{ path_to_root }}";
+ var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
+ </script>
+
+ <!-- Work around some values being stored in localStorage wrapped in quotes -->
+ <script>
+ try {
+ var theme = localStorage.getItem('mdbook-theme');
+ var sidebar = localStorage.getItem('mdbook-sidebar');
+
+ if (theme.startsWith('"') && theme.endsWith('"')) {
+ localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
+ }
+
+ if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
+ localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
+ }
+ } catch (e) { }
+ </script>
+
+ <!-- Set the theme before any content is loaded, prevents flash -->
+ <script>
+ var theme;
+ try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
+ if (theme === null || theme === undefined) { theme = default_theme; }
+ var html = document.querySelector('html');
+ html.classList.remove('{{ default_theme }}')
+ html.classList.add(theme);
+ var body = document.querySelector('body');
+ body.classList.remove('no-js')
+ body.classList.add('js');
+ </script>
+
+ <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
+
+ <!-- Hide / unhide sidebar before it is displayed -->
+ <script>
+ var body = document.querySelector('body');
+ var sidebar = null;
+ var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
+ if (document.body.clientWidth >= 1080) {
+ try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
+ sidebar = sidebar || 'visible';
+ } else {
+ sidebar = 'hidden';
+ }
+ sidebar_toggle.checked = sidebar === 'visible';
+ body.classList.remove('sidebar-visible');
+ body.classList.add("sidebar-" + sidebar);
+ </script>
+
+ <nav id="sidebar" class="sidebar" aria-label="Table of contents">
+ <div class="sidebar-scrollbox">
+ {{#toc}}{{/toc}}
+ </div>
+ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
+ </nav>
+
+ <!-- Track and set sidebar scroll position -->
+ <script>
+ var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
+ sidebarScrollbox.addEventListener('click', function(e) {
+ if (e.target.tagName === 'A') {
+ sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
+ }
+ }, { passive: true });
+ var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
+ sessionStorage.removeItem('sidebar-scroll');
+ if (sidebarScrollTop) {
+ // preserve sidebar scroll position when navigating via links within sidebar
+ sidebarScrollbox.scrollTop = sidebarScrollTop;
+ } else {
+ // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
+ var activeSection = document.querySelector('#sidebar .active');
+ if (activeSection) {
+ activeSection.scrollIntoView({ block: 'center' });
+ }
+ }
+ </script>
+
+ <div id="page-wrapper" class="page-wrapper">
+
+ <div class="page">
+ {{> header}}
+ <div id="menu-bar-hover-placeholder"></div>
+ <div id="menu-bar" class="menu-bar sticky">
+ <div class="left-buttons">
+ <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
+ <i class="fa fa-bars"></i>
+ </label>
+ <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
+ <i class="fa fa-paint-brush"></i>
+ </button>
+ <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
+ <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
+ </ul>
+ {{#if search_enabled}}
+ <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
+ <i class="fa fa-search"></i>
+ </button>
+ {{/if}}
+ </div>
+
+ <h1 class="menu-title">{{ book_title }}</h1>
+
+ <div class="right-buttons">
+ <button id="language-toggle" class="icon-button" type="button"
+ title="Change language" aria-label="Change language"
+ aria-haspopup="true" aria-expanded="false"
+ aria-controls="language-list">
+ <i class="fa fa-globe"></i>
+ </button>
+ <ul id="language-list" class="theme-popup" aria-label="Languages" role="menu">
+ <li role="none"><button role="menuitem" class="theme">
+ <a id="en">English</a>
+ </button></li>
+ </ul>
+
+ <script>
+ let langToggle = document.getElementById("language-toggle");
+ let langList = document.getElementById("language-list");
+ langToggle.addEventListener("click", (event) => {
+ langList.style.display = langList.style.display == "block" ? "none" : "block";
+ });
+ let selectedLang = document.getElementById("{{ language }}");
+ if (selectedLang) {
+ selectedLang.parentNode.classList.add("theme-selected");
+ }
+
+ // The path to the root, taking the current
+ // language into account.
+ {{#if (eq language "en")}}
+ let full_path_to_root = "{{ path_to_root }}";
+ {{else}}
+ let full_path_to_root = "{{ path_to_root }}../";
+ {{/if}}
+ // The page path (mdbook only gives us
+ // access to the path to the Markdown file).
+ let path = "{{ path }}".replace(/\.md$/, ".html");
+ for (let lang of langList.querySelectorAll("a")) {
+ if (lang.id == "en") {
+ lang.href = `${full_path_to_root}${path}`;
+ } else {
+ lang.href = `${full_path_to_root}${lang.id}/${path}`;
+ }
+ }
+ </script>
+
+ {{#if print_enable}}
+ <a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
+ <i id="print-button" class="fa fa-print"></i>
+ </a>
+ {{/if}}
+ {{#if git_repository_url}}
+ <a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
+ <i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
+ </a>
+ {{/if}}
+ {{#if git_repository_edit_url}}
+ <a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
+ <i id="git-edit-button" class="fa fa-edit"></i>
+ </a>
+ {{/if}}
+
+ </div>
+ </div>
+
+ {{#if search_enabled}}
+ <div id="search-wrapper" class="hidden">
+ <form id="searchbar-outer" class="searchbar-outer">
+ <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
+ </form>
+ <div id="searchresults-outer" class="searchresults-outer hidden">
+ <div id="searchresults-header" class="searchresults-header"></div>
+ <ul id="searchresults">
+ </ul>
+ </div>
+ </div>
+ {{/if}}
+
+ <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
+ <script>
+ document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
+ document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
+ Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
+ link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
+ });
+ </script>
+
+ <div id="content" class="content">
+ <main>
+ {{{ content }}}
+ </main>
+
+ <nav class="nav-wrapper" aria-label="Page navigation">
+ <!-- Mobile navigation buttons -->
+ {{#previous}}
+ <a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
+ <i class="fa fa-angle-left"></i>
+ </a>
+ {{/previous}}
+
+ {{#next}}
+ <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
+ <i class="fa fa-angle-right"></i>
+ </a>
+ {{/next}}
+
+ <div style="clear: both"></div>
+ </nav>
+ </div>
+ </div>
+
+ <nav class="nav-wide-wrapper" aria-label="Page navigation">
+ {{#previous}}
+ <a rel="prev" href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
+ <i class="fa fa-angle-left"></i>
+ </a>
+ {{/previous}}
+
+ {{#next}}
+ <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
+ <i class="fa fa-angle-right"></i>
+ </a>
+ {{/next}}
+ </nav>
+
+ </div>
+
+ {{#if live_reload_endpoint}}
+ <!-- Livereload script (if served using the cli tool) -->
+ <script>
+ const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
+ const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
+ const socket = new WebSocket(wsAddress);
+ socket.onmessage = function (event) {
+ if (event.data === "reload") {
+ socket.close();
+ location.reload();
+ }
+ };
+
+ window.onbeforeunload = function() {
+ socket.close();
+ }
+ </script>
+ {{/if}}
+
+ {{#if google_analytics}}
+ <!-- Google Analytics Tag -->
+ <script>
+ var localAddrs = ["localhost", "127.0.0.1", ""];
+
+ // make sure we don't activate google analytics if the developer is
+ // inspecting the book locally...
+ if (localAddrs.indexOf(document.location.hostname) === -1) {
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+
+ ga('create', '{{google_analytics}}', 'auto');
+ ga('send', 'pageview');
+ }
+ </script>
+ {{/if}}
+
+ {{#if playground_line_numbers}}
+ <script>
+ window.playground_line_numbers = true;
+ </script>
+ {{/if}}
+
+ {{#if playground_copyable}}
+ <script>
+ window.playground_copyable = true;
+ </script>
+ {{/if}}
+
+ {{#if playground_js}}
+ <script src="{{ path_to_root }}ace.js"></script>
+ <script src="{{ path_to_root }}editor.js"></script>
+ <script src="{{ path_to_root }}mode-rust.js"></script>
+ <script src="{{ path_to_root }}theme-dawn.js"></script>
+ <script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
+ {{/if}}
+
+ {{#if search_js}}
+ <script src="{{ path_to_root }}elasticlunr.min.js"></script>
+ <script src="{{ path_to_root }}mark.min.js"></script>
+ <script src="{{ path_to_root }}searcher.js"></script>
+ {{/if}}
+
+ <script src="{{ path_to_root }}clipboard.min.js"></script>
+ <script src="{{ path_to_root }}highlight.js"></script>
+ <script src="{{ path_to_root }}book.js"></script>
+
+ <!-- Custom JS scripts -->
+ {{#each additional_js}}
+ <script src="{{ ../path_to_root }}{{this}}"></script>
+ {{/each}}
+
+ {{#if is_print}}
+ {{#if mathjax_support}}
+ <script>
+ window.addEventListener('load', function() {
+ MathJax.Hub.Register.StartupHook('End', function() {
+ window.setTimeout(window.print, 100);
+ });
+ });
+ </script>
+ {{else}}
+ <script>
+ window.addEventListener('load', function() {
+ window.setTimeout(window.print, 100);
+ });
+ </script>
+ {{/if}}
+ {{/if}}
+
+ </div>
+ </body>
+</html>