Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tutorial: Draft of Output chapter #52

Merged
merged 2 commits into from
Jul 31, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 127 additions & 2 deletions src/tutorial/output.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,140 @@
# 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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence is a bit clunky.

"It expects you to write a string literal as the first parameter, that contains placeholders that will be filled in [...]"

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

```console
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: `{:?}`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many more od these, maybe we want to link to the section in the book where they're explained?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a link to the std::fmt docs in the very next aside


For example,

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

will print

```console
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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we only want to mention one crate here or maybe also link to https://github.com/FGRibreau/spinners (it has a shark spinner! 🦈 )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to expand this with an example that uses indicatif to show progress as well as log messages. The spinners crate can't do that afaik

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?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to include several and compare? The book is supposed to be curated content, right? So maybe keeping a list of actively developed loggers isn't a bad idea

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but this is also the tutorial. I'll add a todo to link to ../in-depth/human-communication.html :)


</aside>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add TODO for escaping symbols in stdout/stderr?

Maybe it needs a tracking issue first, in particular I'm getting problems piping ssh to the stdout and stderr of my Rust program, it breaks the terminal (macOS standard Terminal.app) state quite often and I have to fix it like that:

$ stty sane

But ideally I need to figure what symbols cause that and how to escape them…

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I hadn't heard of that. Can you open an issue? One goal of the issue might be to add a section to the book :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, here we go #57

<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>