Skip to content

Commit

Permalink
Tutorial: Draft of Output chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
killercup committed Jul 30, 2018
1 parent 3e69d56 commit e3f9d78
Showing 1 changed file with 123 additions and 2 deletions.
125 changes: 123 additions & 2 deletions src/tutorial/output.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,136 @@
# Output

## Printing "Hello World"

```rust
println!("Hello World");
```

Well, that was easy.
Great, onto the next topic.

## Using println

You can pretty much print all the things you like
with the `println!` macro.
This macro has some pretty amazing capabilities,
but also a special syntax.
It expects you to write,
as a first parameter,
a literal string that with placeholders,
followed by the data you want to put into these placeholders
as further arguments.

For example:

```rust
let x = 42;
println!("My lucky number is {}.", x);
```

will print

> My lucky number is 42.
The curly braces (`{}`) in the string above is one of these placeholders.
This is the default placeholder type
that tries to print the given in a human readable way.
For numbers and strings this works very well,
but not all types can do that.
This is why there is also a "debug representation",
that you can get by filling the braces of the placeholder like this: `{:?}`.

For example,

```rust
let xs = vec![1, 2, 3];
println!("The list is: {:?}", xs);
```

will print

> The list is: [1, 2, 3]
If you want your own data types to be printable for debugging and logging,
you can in most cases add a `#[derive(Debug)]` above their definition.

<aside>

**Aside:**
The human readable printing is done using the [`Display`] trait,
debug output uses the [`Debug`] trait.
You can find more information about the syntax you can use in `println!`
in the [documentation for the `std::fmt` module][std::fmt].

[`Display`]: https://doc.rust-lang.org/1.27.2/std/fmt/trait.Display.html
[`Debug`]: https://doc.rust-lang.org/1.27.2/std/fmt/trait.Debug.html
[std::fmt]: https://doc.rust-lang.org/1.27.2/std/fmt/index.html

</aside>

## Printing errors

<aside class="todo">

**TODO:**
`eprintln!` and stdout vs stderr

</aside>

## Showing a progress bar

Some CLI applications run less than a second,
others take minutes or hours.
If you are writing one of the latter types of programs,
you might want to show the user that something is happening.
For this, you should try to printing useful status updates,
ideally in a form that can be easily consumed.

Using the [indicatif] crate,
you can add progress bars
and little spinners to your program.

<aside class="todo">

**TODO:**
Show an example like
[this](https://github.com/mitsuhiko/indicatif/blob/950091d1b1683a88e01c4d4975f591009f56322b/examples/log.rs)
or [this](https://github.com/ashleygwilliams/cargo-generate/blob/c18cba0b33764012e25288d43c6a8545222b96f4/src/main.rs#L95).

</aside>

[indicatif]: https://crates.io/crates/indicatif

## Logging

To make it easier to understand what is happening in our program,
we might want to add some log statements.
This is usually easy while writing your application.
But it will become super helpful when running this program again in half a year.

<aside class="todo">

**TODO:**
`log` crate: macros with similar syntax to `println`

</aside>

<aside class="todo">

**TODO:**
crate for actual log output -- which one?
env_logger?

</aside>

<aside>

**Aside:** Experience has shown that even mildly useful CLI programs can end up being used for years to come.
Especially if they were meant as a temporary solution.
**Aside:**
Experience has shown that even mildly useful CLI programs can end up being used for years to come.
(Especially if they were meant as a temporary solution.)
If your application doesn't work
and someone (e.g., you, in the future) needs to figure out why,
being able to pass `--verbose` to get additional log output
can make the difference between minutes and hours of debugging.

</aside>

0 comments on commit e3f9d78

Please sign in to comment.