Echo
Introduction
In this chapter, we're going to build an echo clone. The echo command on linux just
prints it's arguments to STDOUT. You can read about the echo command here:
You can also run man echo in your shell to see the documentation for echo.
Examples of echo
Here are some example usages:
-
Print a string to STDOUT
-
Printing multiple strings to STDOUT
This outputs
Hello Worldto STDOUT. -
Treatment of spaces between strings
- There are 4 spaces between
HelloandWorld
This still outputs
Hello Worldto STDOUT. This is becauseechotreatsHelloandWorldas separate arguments. (This is true at least for thebashandzshshells) - There are 4 spaces between
-
Getting spaces between parts to show
- Note the quotes surrounding the words.
This will output
Hello Worldas we intended it to. -
The
-nargumentThis will output
Hello Worldwithout a trailing newline. This is useful if you want to print something to STDOUT and then prompt the user for input on the same line.
Building the echo clone
We will create an echo clone named echo_ that supports the -n optional argument.
Note the _ at the end of our project. We do this to not mask the builtin echo
program.
Creating the project
Let's create a new project for this.
Directory structure
The directory structure looks like follows:
There's nothing interesting to see here, so let's move on to the code.
The code
Our clone must output whatever is passed as its arguments. This means that we need to be able to access the command-line arguments from within our program.
TODO: WIP
TODO: WIP
We can interact with the environment in rust using the std::env crate. It provides
an args function that returns the
arguments that the program was started with. It returns an struct of type
Args. So we can basically
get the command-line arguments to our program by calling std::env::args().
We can use the println! macro to
print text to the console, but trying to print the arguments directly as
println!(std::env::args()); will not work. This is becasue the println! macro
expects a string literal, but we're passing it an Args struct.
If you try to run the following program, the program will fail to compile:
It will give you the following error:
error: format argument must be a string literal
--> src/main.rs:2:14
|
2 | println!(std::env::args());
| ^^^^^^^^^^^^^^^^
|
help: you might be missing a string literal to format with
|
2 | println!("{}", std::env::args());
| +++++
error: could not compile `echo_` due to previous error
The compiler is pointing us in the right direction here. Let's try it's suggestion:
Running this will give us another error:
error[E0277]: `Args` doesn't implement `std::fmt::Display`
--> src/main.rs:2:20
|
2 | println!("{}", std::env::args());
| ^^^^^^^^^^^^^^^^ `Args` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Args`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
error: could not compile `echo_` due to previous error
The compiler is telling us that for a struct to be formatted as a string, it needs
to implement the std::fmt::Display