+++ /dev/null
-## Subcommands
-
-The top-level `cargo` command delegates to sub-commands named
-`cargo-foo`.
-
-```
-$ cargo compile
-# delegates to cargo-compile
-```
-
-By default, Cargo will come with a set of built-in commands that don't
-need to be on the `$PATH`, but additional commands can be added to the
-`$PATH`.
-
-There will also be an additional configuration for locating Cargo
-subcommands that are not on the `$PATH`.
-
-### Input/Output
-
-By default, Cargo subcommands are built by implementing the
-`CargoCommand` trait. This trait will pass structured data to the
-command.
-
-By default, commands will communicate with each other via JSON data, and
-the `CargoCommand` trait will convert the JSON data into the structured
-data needed by the command. All commands must implement JSON data
-output.
-
-Commands must also implement human-readable output, and may implement
-additional output forms (such as tab- or space-separated output) for use
-in other scripting languages.
-
-```rs
-// The main entry point for new commands to implement
-trait CargoCommand<T, U> {
- fn execute<L: CargoLogger>(input: T, logger: L) -> Result<U, CargoErr>;
-}
-
-// For now, the raw IPC communication is represented as JSON primitive
-// values. The ConvertToRaw trait below converts a string protocol into the
-// Raw format. Obviously, the JSON string protocol can trivially be
-// converted, but other line protocols need to be defined on a
-// case-by-case basis.
-type Raw = serialize::json::Json;
-type Flags = Map<~str, serialize::json::Json>
-
-// This is a list of available IPC String protocols. To start, we'll
-// support JSON and an (optional) arbitrary type-defined line protocol.
-enum Input {
- JSONString(~str),
- LineOrientedString(~str)
-}
-
-// This trait supports converting any supported input form into Raw.
-trait ConvertToRaw<Input> {
- fn convert(input: Input) -> Raw;
-}
-
-// This is the runner implementation. It will not need to be implemented
-// by individual commands.
-fn execute_command<Config, Output, C: CargoCommand, L: Logger>(command: C, config: Config, logger: L) -> Output {
- match command.execute(input, logger) {
- Ok(success) => {
- // serialize success
- },
- Err(failure) => {
- // error handling/output
- }
- }
-}
-
-// This is an example configuration. It is the combination of the Raw
-// input from a previous command and any flags passed to this command.
-// Top-level commands will mostly be configured via flags -- plumbing
-// commands will be mostly configured via Raw.
-//
-// Note that because configurations serve as both input and output, and
-// the ConvertToRaw trait handles both sides of the pipe, these definitions
-// are not part of an individual command. Some configuration structures
-// may even be used by multiple different commands.
-struct CompileConfig {
- flags: ~[~str],
- path: ~[~str],
- lib_path: ~str
-}
-
-struct CompileConfigBuilder {
- flags: Option<~[~str]>,
- path: Option<~[~str]>,
- lib_path: Option<~str>
-}
-
-// For now, configurations manually convert the Flags and Raw into a
-// single configuration object. This is the main point where a failure
-// can occur that is not type-checked. All other functions receive the
-// structured type and will get compiler help.
-impl CompileConfig {
- pub fn deserialize(flags: Flags, raw: Raw) -> CompileConfig {
- CompileConfig{ flags: raw.at("flags"), path: raw.at("path"), lib_path: flags.at("lib_path") }
- }
-}
-
-// Configurations must implement ConvertIntoRaw<JSONString> and may
-// implement other ConvertIntoRaw converters.
-impl ConvertToRaw<JSONString> for CompileConfig {
- fn convert(input: JSONString) -> Raw {
-
- }
-}
-
-impl ConvertToRaw<LineOrientedString> for CompileConfig {
- fn convert(input: LineOrientedString) -> Raw {
-
- }
-}
-
-impl ConvertFlags for CompileConfig {
- fn convert(input: FlagDefinition) -> Flags {
-
- }
-}
-
-// Commands are simple objects that implement CargoCommand for a given
-struct CompileCommand;
-
-impl CompileCommand {
- fn new() -> CompileCommand { CompileCommand }
-}
-
-impl CargoCommand<CompileConfig, CompileOutput> for CompileCommand {
- fn execute<L: CargoLogger>(input: CompileConfig, logger: L) -> Result<CompileOutput, CargoErr>;
-
- }
-}
-
-fn main() {
- let args = parse_arguments(f);
- let config = process_args_and_stdin(args); // { "flags": [ ... ] }
- let command = CompileCommand::new()
- let logger = CargoLogger::for(config);
- let result = execute_command(command, config, logger);
-
- // deal with serialized output or error
-}
-
-fn process_args_and_stdin(args: Flags) -> CompileConfig {
- // delegate to other generic function; Flags tells us which serializer
- // to use
-}
-```
-
-## Configuration