- [What is rustdoc?](what-is-rustdoc.md)
- [How to write documentation](how-to-write-documentation.md)
+- [What to include (and exclude)](what-to-include.md)
- [Command-line arguments](command-line-arguments.md)
- [The `#[doc]` attribute](the-doc-attribute.md)
- [Documentation tests](documentation-tests.md)
- [Passes](passes.md)
- [Advanced features](advanced-features.md)
- [Unstable features](unstable-features.md)
+- [References](references.md)
# How to write documentation
+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 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. Something to keep in mind when
-writing documentation is that your audience is not just yourself but others
-who simply don't have the context you do. It is important to be as clear
+how to write **good** documentation. It is important to be as clear
as you can, and as complete as possible. As a rule of thumb: the more
documentation you write for your crate the better. If an item is public
then it should be documented.
-## Basic structure
+## Getting Started
+
+Documenting a crate should begin with front-page documentation. As an
+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 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 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.
+
+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 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, which is just beginning, to other more
+developed crates. 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 indicate module-level or crate-level documentation.
+Here's a quick example of the difference:
+
+```rust,ignore
+//! Fast and easy queue abstraction.
+//!
+//! Provides an abstraction over a queue. When the abstraction is used
+//! there are these advantages:
+//! - Fast
+//! - [`Easy`]
+//!
+//! [`Easy`]: http://thatwaseasy.example.com
+
+/// This module makes it easy.
+pub mod easy {
+
+ /// Use the abstract function to do this specific thing.
+ pub fn abstract() {}
+
+}
+```
+
+Ideally, this first line of documentation is a sentence without highly
+technical details, but with a good description 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 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:
```
This basic structure should be straightforward to follow when writing your
-documentation and, while you might think that a code example is trivial,
-the examples are really important because they can help your users to
-understand what an item is, how it is used, and for what purpose it exists.
+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
[`std::env::args()`][env::args] function:
[`args_os`]: ./fn.args_os.html
``````
+Everything before the first empty line 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. It is good
+practice to keep the summary to one line: concise writing is a goal of good
+documentation.
+
+Because the type system does a good job of defining what types a function
+passes and returns, there is no benefit of explicitly writing it
+into the documentation, especially since `rustdoc` adds hyper links to all types in the function signature.
+
+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
sentence explaining what the functions does, then it provides more information
and finally provides a code example.
## Markdown
-`rustdoc` is using the [commonmark markdown specification]. You might be
+`rustdoc` uses 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]
+ - [current spec]
-## Lints
-
-To be sure that you didn't miss any item without documentation or code examples,
-you can take a look at the rustdoc lints [here][rustdoc-lints].
-[standard library]: https://doc.rust-lang.org/stable/std/index.html
-[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
+[`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
[commonmark markdown specification]: https://commonmark.org/
-[rustdoc-lints]: lints.md
+[commonmark quick reference]: https://commonmark.org/help/
+[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
+[`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
--- /dev/null
+# References
+
+There are many great `rustdoc` references out there.
+If you know of other great resources, please submit a pull request!
+
+## Official
+
+- [Learn Rust]
+- [Rust By Example]
+- [Rust Reference]
+- [RFC 1574: More API Documentation Conventions]
+- [RFC 1946: Intra Rustdoc Links]
+
+## Community
+- [API Guidelines]
+- [Github tagged RFCs]
+- [Github tagged issues]
+- [RFC (stalled) front page styleguide]
+- [Guide on how to write documenation for a Rust crate]
+
+
+[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html
+[Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
+[Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
+[Guide on how to write documenation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate
+[Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
+[RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html
+[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 Reference]: https://doc.rust-lang.org/stable/reference/comments.html#doc-comments
\ No newline at end of file
## Basic usage
-Let's give it a try! Let's create a new project with Cargo:
+Let's 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
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
-top, with no contents. There's two problems with this: first, why does it
+a web browser, you will see a page with a search bar, and "Crate lib" at the
+top, with no contents.
+
+## Configuring rustdoc
+
+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?
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...
$ rustdoc src/lib.rs --crate-name docs
```
-We'll have some generated documentation. Open up `doc/docs/index.html` and
+We now 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.
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? `-o` controls the
-*o*utput of our docs. Instead of a top-level `doc` directory, you'll
-notice that Cargo puts generated documentation under `target`. That's
-the idiomatic place for generated files in Cargo projects. Also, it
-passes `-L`, a flag that helps rustdoc find the dependencies
-your code relies on. If our project used dependencies, we'd get
-documentation for them as well!
+`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 would get documentation for them as well!
## Outer and inner documentation
## 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' s
give it a try: create a `README.md` file with these contents:
````text
[Here is a link!](https://www.rust-lang.org)
-## Subheading
+## Example
```rust
fn foo() -> i32 {
$ 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.
--- /dev/null
+# What to include (and exclude)
+
+It is easy to say everything must be documented in a project and often times
+that is correct, but how can we get there, and are there things that don't
+belong?
+
+At the top of the `src/lib.rs` or `main.rs` file in your binary project, include
+the following attribute:
+
+```rust
+#![warn(missing_docs)]
+```
+
+Now run `cargo doc` and examine the output. Here's a sample:
+
+```text
+ Documenting docdemo v0.1.0 (/Users/username/docdemo)
+warning: missing documentation for the crate
+ --> src/main.rs:1:1
+ |
+1 | / #![warn(missing_docs)]
+2 | |
+3 | | fn main() {
+4 | | println!("Hello, world!");
+5 | | }
+ | |_^
+ |
+note: the lint level is defined here
+ --> src/main.rs:1:9
+ |
+1 | #![warn(missing_docs)]
+ | ^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
+ Finished dev [unoptimized + debuginfo] target(s) in 2.96s
+```
+
+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(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.
+
+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
+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
+users to figure out how to put the `async` code into their own runtime.
+
+It is preferred that `unwrap()` not be used inside an example, and some of the
+error handling components be hidden if they make the example too difficult to
+follow.
+
+``````text
+/// Example
+/// ```rust
+/// let fourtytwo = "42".parse::<u32>()?;
+/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10);
+/// ```
+``````
+
+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:
+
+``````text
+/// Example
+/// ```rust
+/// # main() -> Result<(), std::num::ParseIntError> {
+/// let fortytwo = "42".parse::<u32>()?;
+/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
+/// # Ok(())
+/// # }
+/// ```
+``````
+
+The example is the same on the doc page, but has that extra information
+available to anyone trying to use your crate. More about tests in the
+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)]` 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
+
+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
\ No newline at end of file
(option.apply)(&mut options);
}
println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
+ println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
}
/// A result type used by several functions under `main()`.