pub trait Execute<T> where
    T: Shared
{ fn execute(&self, context: &T) -> Result<()>; }
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:

  1. There is a context in which the subcommand must operate in.
  2. 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.

Implementors