Skip to content

Commit

Permalink
Rust Doc book improvements post-review
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyGauge committed Aug 22, 2020
1 parent b7a4bd9 commit 0f605b0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/doc/rustdoc/src/advanced-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ pub struct UnixToken;
```

Here, the respective tokens can only be used by dependent crates on their respective platforms, but
they will both appear in documentation.
they will both appear in documentation.
104 changes: 53 additions & 51 deletions src/doc/rustdoc/src/how-to-write-documentation.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# How to write documentation

Good documentation is not natural. There are opposing forces that make good
documentation difficult. It requires expertise in the subject but also
requires writing to a novice perspective. Documentation therefore often
glazes over implementation detail, or leaves an explain like I'm 5 response.
Good documentation is not natural. There are opposing goals that make writing
good documentation difficult. It requires expertise in the subject but also
writing to a novice perspective. Documentation therefore often glazes over
implementation detail, or leaves readers with unanswered questions.

There are tenants to Rust documentation that can help guide anyone through
the process of documenting libraries so everyone has ample opportunity to
use the code.
There are a few tenets to Rust documentation that can help guide anyone through
the process of documenting libraries so that everyone has an ample opportunity
to use the code.

This chapter covers not only how to write documentation but specifically
how to write **good** documentation. It is important to be as clear
Expand All @@ -18,38 +18,37 @@ then it should be documented.
## Getting Started

Documenting a crate should begin with front-page documentation. As an
example, [hashbrown] crate level documentation summarizes the role of
the crate, provides links to explain technical details, and gives the
reason why to use the crate.
example, the [`hashbrown`] crate level documentation summarizes the role of
the crate, provides links to explain technical details, and explains why you
would want to use the crate.

After introducing the crate, it is important that within the front-page
an example be given how to use the crate in a real world setting. The
example benefits from isolating the library's role from the implementation
details, but doing so without shortcuts also benefits users who may copy
and paste the example to get started.
After introducing the crate, it is important that the front-page gives
an example of how to use the crate in a real world setting. Stick to the
library's role in the example, but do so without shortcuts to benefit users who
may copy and paste the example to get started.

[futures] uses an approach of inline comments to explain line by line
the complexities of using a future, because often people's first exposure to
rust's future is this example.
[`futures`] uses inline comments to explain line by line
the complexities of using a [`Future`], because a person's first exposure to
rust's [`Future`] may be this example.

[backtrace] usage walks through the whole process, explaining changes made
to the `Cargo.toml` file, passing command line arguments to the compiler,
and shows a quick example of backtrace in the wild.
The [`backtrace`] documentation walks through the whole process, explaining
changes made to the `Cargo.toml` file, passing command line arguments to the
compiler, and shows a quick example of backtrace in the wild.

Finally, the front-page can eventually become a comprehensive reference
how to ues a crate, like the usage found in [regex]. In this front page, all
the requirements are outlined, the gotchas are taught, then practical examples
are provided. The front page goes on to show how to use regular expressions
how to use a crate, like [`regex`]. In this front page, all
requirements are outlined, the edge cases shown, and practical examples
provided. The front page goes on to show how to use regular expressions
then concludes with crate features.

Don't worry about comparing your crate that is just beginning to get
documentation to something more polished, just start incrementally and put
in an introduction, example, and features. Rome wasn't built in a day!
Don't worry about comparing your crate, which is just beginning. To get the
documentation to something more polished, start incrementally and put
in an introduction, example, and features. Rome was not built in a day!

The first lines within the `lib.rs` will compose the front-page, and they
use a different convention than the rest of the rustdocs. Lines should
start with `//!` which designate the code to refer to module-level or crate-
level documentation. Here's a quick example of the difference:
start with `//!` which indicate module-level or crate-level documentation.
Here's a quick example of the difference:

```rust
//! Fast and easy queue abstraction.
Expand All @@ -65,21 +64,21 @@ level documentation. Here's a quick example of the difference:
pub mod easy {

/// Use the abstract function to do this specific thing.
pub fn abstract {}
pub fn abstract() {}

}
```

Ideally, this first line of documentation is a sentence without highly
technical details, but very broadly descriptive of where this crate fits
within the rust ecosystem. Someone should know if this crate is qualified
for investigation in their use case by this line.
technical details, but descriptive of where this crate fits
within the rust ecosystem. Users should know whether this crate meets their use
case after reading this line.

## Documenting components

Whether documenting modules, structs, functions, or macros, the public
API of all code should have some documentation, and rarely does anyone
complain about too much documentation.
Whether it is modules, structs, functions, or macros: the public
API of all code should have documentation. Rarely does anyone
complain about too much documentation!

It is recommended that each item's documentation follows this basic structure:

Expand All @@ -98,7 +97,7 @@ documentation; while you might think that a code example is trivial,
the examples are really important because they can help users understand
what an item is, how it is used, and for what purpose it exists.

Let's see an example coming from the [standard library] by taking a look at the
Let us see an example coming from the [standard library] by taking a look at the
[`std::env::args()`][env::args] function:

``````text
Expand Down Expand Up @@ -133,17 +132,19 @@ for argument in env::args() {
[`args_os`]: ./fn.args_os.html
``````

The first line of description will be reused when describing the component in
a higher level of the documentation. For example, the function `std::env::args()`
above can be found within the [`std::env`] module documentation.
The first line of description will be reused to describe the component in
searches and module overviews. For example, the function `std::env::args()`
above will be shown on the [`std::env`] module documentation. Multi-line
summaries are also possible, however, concise writing is a goal of good
documentation.

Because the type system does a good job of defining what is passed to a function
and what is returned from one, there is not a benefit of explicitly writing those
things into the documentation. Rustdoc makes sure the links to the types included
in the signature are linked.
and what is returned from one, there is not a benefit of explicitly writing it
into the documentation. Rustdoc makes sure the links to the types included
in the function signature are linked.

In the example above, a Panics section explains when the code might abruptly exit
which can help the reader build guards if required. A panic section is recommended
In the example above, a 'Panics' section explains when the code might abruptly exit,
which can help the reader prevent reaching a panic. A panic section is recommended
every time edge cases in your code can be reached if known.

As you can see, it follows the structure detailed above: it starts with a short
Expand All @@ -154,17 +155,18 @@ and finally provides a code example.

`rustdoc` is using the [commonmark markdown specification]. You might be
interested into taking a look at their website to see what's possible to do.

[commonmark quick reference] is a very helpful resource for the majority of
use cases.
- [commonmark quick reference]
- [current spec]


[backtrace]: https://docs.rs/backtrace/0.3.50/backtrace/
[commonmark markdown specification]: https://commonmark.org/
[commonmark quick reference]: https://commonmark.org/help/
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
[futures]: https://docs.rs/futures/0.3.5/futures/
[hashbrown]: https://docs.rs/hashbrown/0.8.2/hashbrown/
[regex]: https://docs.rs/regex/1.3.9/regex/
[`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
[`futures`]: https://docs.rs/futures/0.3.5/futures/
[`hashbrown`]: https://docs.rs/hashbrown/0.8.2/hashbrown/
[`regex`]: https://docs.rs/regex/1.3.9/regex/
[standard library]: https://doc.rust-lang.org/stable/std/index.html
[current spec]: https://spec.commonmark.org/current/
[`std::env`]: https://doc.rust-lang.org/stable/std/env/index.html#functions
8 changes: 2 additions & 6 deletions src/doc/rustdoc/src/references.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# References

There are many great `rustdoc` references out there. This is a collection of
those documentation documents on the internet at the time of writing. If you
know of other great resources, please submit a pull request:

[Rust official Github]
There are many great `rustdoc` references out there.
If you know of other great resources, please submit a pull request

## Official

Expand All @@ -31,5 +28,4 @@ know of other great resources, please submit a pull request:
[RFC 1946: Intra Rustdoc Links]: https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html
[RFC (stalled) front page styleguide]: https://github.com/rust-lang/rfcs/pull/1687
[Rust By Example]: https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html
[Rust official Github]: https://github.com/rust-lang/rust/pulls
[Rust Reference]: https://doc.rust-lang.org/stable/reference/comments.html#doc-comments
22 changes: 11 additions & 11 deletions src/doc/rustdoc/src/what-is-rustdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ CSS, and JavaScript.

## Basic usage

Let's give it a try! Let's create a new project with Cargo:
Let us give it a try! Create a new project with Cargo:

```bash
$ cargo new docs
$ cd docs
```

In `src/lib.rs`, you'll find that Cargo has generated some sample code. Delete
In `src/lib.rs`, Cargo has generated some sample code. Delete
it and replace it with this:

```rust
/// foo is a function
fn foo() {}
```

Let's run `rustdoc` on our code. To do so, we can call it with the path to
Now, run `rustdoc` on our code. To do so, we can call it with the path to
our crate root like this:

```bash
Expand All @@ -31,12 +31,12 @@ $ rustdoc src/lib.rs

This will create a new directory, `doc`, with a website inside! In our case,
the main page is located in `doc/lib/index.html`. If you open that up in
a web browser, you'll see a page with a search bar, and "Crate lib" at the
a web browser, you will see a page with a search bar, and "Crate lib" at the
top, with no contents.

## Configuring rustdoc

There's two problems with this: first, why does it
There are two problems with this: first, why does it
think that our package is named "lib"? Second, why does it not have any
contents?

Expand All @@ -50,7 +50,7 @@ $ rustdoc src/lib.rs --crate-name docs

Now, `doc/docs/index.html` will be generated, and the page says "Crate docs."

For the second issue, it's because our function `foo` is not public; `rustdoc`
For the second issue, it is because our function `foo` is not public; `rustdoc`
defaults to generating documentation for only public functions. If we change
our code...

Expand All @@ -65,7 +65,7 @@ pub fn foo() {}
$ rustdoc src/lib.rs --crate-name docs
```

We'll have some generated documentation. Open up `doc/docs/index.html` and
We will have some generated documentation. Open up `doc/docs/index.html` and
check it out! It should show a link to the `foo` function's page, which
is located at `doc/docs/fn.foo.html`. On that page, you'll see the "foo is
a function" we put inside the documentation comment in our crate.
Expand All @@ -89,16 +89,16 @@ dependency=<path>/docs/target/debug/deps
You can see this with `cargo doc --verbose`.

It generates the correct `--crate-name` for us, as well as pointing to
`src/lib.rs` But what about those other arguments?
`src/lib.rs`. But what about those other arguments?
- `-o` controls the *o*utput of our docs. Instead of a top-level
`doc` directory, notice that Cargo puts generated documentation under
`target`. That is the idiomatic place for generated files in Cargo projects.
- `-L` flag helps rustdoc find the dependencies your code relies on.
If our project used dependencies, we'd get documentation for them as well!
If our project used dependencies, we would get documentation for them as well!

## Using standalone Markdown files

`rustdoc` can also generate HTML from standalone Markdown files. Let's
`rustdoc` can also generate HTML from standalone Markdown files. Let us
give it a try: create a `README.md` file with these contents:

````text
Expand All @@ -123,7 +123,7 @@ And call `rustdoc` on it:
$ rustdoc README.md
```

You'll find an HTML file in `docs/doc/README.html` generated from its
You will find an HTML file in `docs/doc/README.html` generated from its
Markdown contents.

Cargo currently does not understand standalone Markdown files, unfortunately.
Expand Down
72 changes: 39 additions & 33 deletions src/doc/rustdoc/src/what-to-include.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,38 +37,20 @@ warning: 1 warning emitted
```

As a library author, adding the lint `#![deny(missing_docs)]` is a great way to
ensure the project does not drift away from being documented well, and warn is
a good way to move towards comprehensive documentation.
ensure the project does not drift away from being documented well, and
`#![warn(missing_docs)]` is a good way to move towards comprehensive
documentation. In addition to docs, `#![deny(missing_doc_code_examples)]`
ensures each function contains a usage example. In our example above, the
warning is resolved by adding crate level documentation.

In our example above, the warning is resolved by adding crate level
documentation. The `main` method does not need documentation, but it is
present in the output. If your main method is doing anything special, like
returning a `Result`, it could use documentation!

```rust
#![warn(missing_docs)]

//! Run program to print Hello, world.

/// Allows unhandled errors to become program return values
fn main() -> std::io::Result<()> {
print_it();
Ok(())
}

/// Safely prints Hello, world!
fn print_it() {
println!("Hello, world!");
}
```
There are more lints in the upcoming chapter [Lints][rustdoc-lints].

## Examples

Of course this is contrived to be simple, but part of the power of documentation
is showing code that is easy to follow, rather than being realistic. Docs often
shortcut error handling because often examples become complicated to follow
with all the necessary set up required for a simple example.
take shortcuts with error handling because examples can become complicated to
follow with all the necessary set up required for a simple example.

`Async` is a good example of this. In order to execute an `async` example, an
executor needs to be available. Examples will often shortcut this, and leave
Expand All @@ -86,16 +68,16 @@ follow.
/// ```
``````

When rustdoc wraps that in a main function, it will panic due to the
`ParseIntError` trait not implemented. In order to help both your audience
and your test suite, this example needs to have additional work performed:
When rustdoc wraps that in a main function, it will fail to compile because the
`ParseIntError` trait is not implemented. In order to help both your audience
and your test suite, this example needs some additional code:

``````rust
/// Example
/// ```rust
/// # main() -> Result<(), std::num::ParseIntError> {
/// let fourtytwo = "42".parse::<u32>()?;
/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10);
/// let fortytwo = "42".parse::<u32>()?;
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
/// # Ok(())
/// # }
/// ```
Expand All @@ -108,12 +90,36 @@ upcoming [Documentation tests] chapter.
## What to Exclude

Certain parts of your public interface may be included by default in the output
of rustdoc. The attribute `#[doc(hidden)]` hides the non-public consumption
implementation details to facilitate idiomatic Rust.
of rustdoc. The attribute `#[doc(hidden)]` can hide implementation details
to encourage idiomatic use of the crate.

For example, an internal `macro!` that makes the crate easier to implement can
become a footgun for users when it appears in the public documentation. An
internal `Error` type may exist, and `impl` details should be hidden, as
detailed in the [API Guidelines].

## Customizing the output

Good examples are `impl From<Error>` for providing `?` usage, or `impl Display`.
It is possible to pass a custom css file to `rustdoc` and style the
documentation.

```bash
rustdoc --extend-css custom.css src/lib.rs
```

A good example of using this feature to create a dark theme is documented [on
this blog]. Just remember, dark theme is already included in the rustdoc output
by clicking on the paintbrush. Adding additional options to the themes are
as easy as creating a custom theme `.css` file and using the following syntax:

```bash
rustdoc --theme awesome.css src/lib.rs
```

Here is an example of a new theme, [Ayu].

[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/themes/ayu.css
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
[Documentation tests]: documentation-tests.md
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
[rustdoc-lints]: lints.md

0 comments on commit 0f605b0

Please sign in to comment.