We will be learning how to write a command and see what's required to do so in small steps. For this example we are interested writing a command named `take-two` that takes two lucky values coming in.
Let's generate a table with row literal syntax first, like so:
_Note: values are passed around in the stream. A generated table like the example above is three row values. See the [values chapter](https://www.nushell.sh/contributor-book/values.html) to learn more about row value types._
We want to `take-two` rows from the generated table. Here is what we would like to do:
See the `take-two` command in the pipeline above? That's what we want.
Before starting writing the command it's important to understand that everything in the stream are values. Sometimes you will see a table with no columns and the reason is that none of the values coming in are row value types. For this case we call it simply a _list_, like so:
When the pipeline finishes, as soon as Nu sees a value that is of type row it will try to display it as a table with columns. The reason is that a value of type row represents rows having column cell headers and cell values.
We appended the value 10 using `append`. Nu sees **four** values in the stream, **three** of them being row types and **one** being an int value type. Therefore we see a table printed (the three row values) and a list (one int value) from the **stream**. This matters because some commands expect and assume all values coming in are row types and some do not.
For the command `take-two` we are about to implement we don't care what kind of values are coming in since we just want to **take two** values.
## Command implementation steps
To guide us in our command implementation journey we will start registering the command, as we do so we will be driving out the command.
### Register the command
All the internal commands reside in `crates/nu-command`. For our command named `take-two` we can create the source file `take_two.rs` and place it in `src/commands/take_two.rs`. Go ahead and create it:
Before registering it to the context you need to make it available by declaring the module and re-export it in `crates/nu-command/src/commands.rs`. The commands we write are modules already (`take_two.rs` is the `take_two` module). In case you are not familiar with rust modules [read this refresher](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html). Let's go ahead and declare it and then re-export the command's `Command` struct as `TakeTwo`, like so:
_nu-command/src/commands.rs_
```rust
# ...
pub(crate) mod take_two;
# ...
# ...
pub(crate) use take_two::Command as TakeTwo;
# ...
```
We should be ready now to register it. You need to add the command (in this case the struct will be in scope named as `TakeTwo` from the previous snippet) where they are added one by one to the context.
_src/commands/default_context.rs_
```rust
context.add_commands(vec![
# ...
whole_stream_command(TakeTwo),
# ...
);
```
We will now resort to the rust compiler to make sure things are wired up correctly. Under `crates/nu-command` run:
| ------------------ required by this bound in `whole_stream_command`
error: aborting due to previous error
```
That's not certainly what we expected.
It happens that Nu needs to know more about the command, including it's name and signature. We didn't do any of that and the compiler is telling us so. We seem to be missing implementing the `WholeStreamCommand` trait. This is the trait that, when implemented, allows us to state it's name, signature, and the like.
## WholeStreamCommand
Every internal command must implement the `WholeStreamCommand` trait. Let's take a look at the required functions:
```rust
pub trait WholeStreamCommand: Send + Sync {
fn name(&self) -> &str;
fn signature(&self) -> Signature;
fn usage(&self) -> &str;
}
```
_Note: For simplicity, we've removed the default implementations of the trait. If you want to read more about the trait you [can read the code here](https://github.com/nushell/nushell/blob/e09e3b01d6523309b901fb396b416146b53c2b7f/crates/nu-engine/src/whole_stream_command.rs)_
We will need to implement the required functions `name` for telling Nu the name of the command, `signature` to tell the command's signature, and `usage`. Before we start, we will also write an example of the usage implementing `examples` (not shown above).
Ready? Go ahead and edit `crates/nu-command/src/commands/take_two.rs`:
Finished dev [unoptimized + debuginfo] target(s) in 10.56s
```
Great!
Since we have been working in `crates/nu-command` and building there to shorten the build time as we work on the command, you may want to run a full build now by doing `cargo build --all --features=extra`:
Let's try entering `help take-two`:
```
> help take-two
takes two values
Usage:
> take-two {flags}
Flags:
-h, --help: Display this help message
Examples:
Takes two values
> echo [11161984 500 200] | take-two
```
We get a help description of our newly implemented `take-two` command for free. This works because we implemented `examples`. It's good practice to do so for documentation (and as we will soon see, unit testing) purposes.
Now let's run `echo [11161984 500 200] | take-two`
```
> echo [11161984 500 200] | take-two
error: Error: Unimplemented: take-two does not implement run or run_with_actions
```
That was unexpected. What happened?
We did not implement `take-two`'s logic anywhere. Nu is telling us the command does not implement `run` or `run_with_actions`. These functions are in the `WholeStreamCommand` trait and the default implementation gives the error. Since our command won't be doing any actions we can go ahead and implement `run` for the logic, let's do that: