Expand description
A trait for objects which can be executed as commands in an application.
In larger applications with multiple (even nested) subcommands, it may be appropriate to make use of a structured design for implementing and executing those commands. This trait offers one way of doing so by defining the entry point and expected result of all subcommands. The trait implemented on the following principles:
- There is a context in which the subcommand must operate in.
- The result should only be used to indicate failure.
Providing context to subcommands
At minimum, the subcommand should have access to the input and output streams for the process.
However, we do not want to limit the information shared with all subcommands. To address these
concerns, the trait uses a generic type that implements io::Shared
for context. This allows
developers to use io::Streams
as the context, or a custom type.
Handling subcommand results
Ultimately, all results that are returned by subcommands should bubble up to the main function
of the application. Once a result reaches the main function, it should either be discarded or
used to determine if the subcommand has encountered an error and should exit with it. Since our
options are limited, [error::Result<()>
] is the preferred return type. Nothing is returned
other than an empty Ok
or the subcommand error, error::Error
in Err
which we can
exit with.
Example command
While this example demonstrates how it could be used with a single command, the trait is primarily intended to be used in an application with multiple subcommands. In cases where only a single command exists, it may be simpler skip the use of this trait and define the function to accept any arguments you may need.
use carli::io::Streams;
use carli::prelude::cmd::*;
use std::io::Write;
/// An example subcommand.
struct Subcommand {
/// A value specific to this subcommand.
name: String,
}
impl Execute<Streams> for Subcommand {
fn execute(&self, context: &Streams) -> Result<()> {
writeln!(context.output(), "Hello, {}!", self.name)?;
Ok(())
}
}
Required methods
Executes the command using the given context.
The command may mutably borrow any stream from the context in order to read input, or
write to the error or global output streams. When the command encounters an error, it
returns an Err
containing crate::error::Error
. If the command is successful,
then it will return Ok
.