GitXplorerGitXplorer
j

applause

public
0 stars
0 forks
3 issues

Commits

List of commits on branch main.
Verified
a573f6d656376844b6814d487cc34fb37f0dd298

docs: add examples and README detail

jjklong committed 3 years ago
Verified
899721d5b8bb3949bc04b95acbf1f58f98671f7c

doc: add attrs example

jjklong committed 3 years ago
Verified
4f92b2ac0b805c289b4d8bd42a973f739375fe88

doc: add simple example

jjklong committed 3 years ago
Verified
09292a4a692bf5110aeabc6857fc61e681876d39

refactor: re-export clap and update macros to reference it

jjklong committed 3 years ago
Verified
6fcc00df136ca337607511d17d74c7b878cdfe0f

doc: add DSL Syntax section to README

jjklong committed 3 years ago
Verified
70e5203b441a569216bd829002bee7cefc884840

doc: add README.md

jjklong committed 3 years ago

README

The README file for this repository.

applause

Applause is a basic DSL that allows for easy construction of Clap Apps that make use of subcommands.

It magicks away the endless matches and enums to define subcommands, arguments and handlers in favour of a simple dispatch system while passing as much as possible back to clap via its derive API.

DSL Syntax

The applause DSL is simple and aims to mimic normal Rust syntax.

The definition of the DSL syntax in Rust Reference Notation is as follows. Where syntactical items are as defined in the Reference, the appropriate page is linked.

See Examples for complete examples.

Syntax
Applause :
   ParserDef
   DispatchParams?
   Commands

ParserDef :
   IDENTIFIER  { StructFields? } ;

DispatchParams :
   dispatch_params ( FunctionParams ) ;

Commands :
   commands  { CommandDef + } ;

CommandDef :
   IDENTIFIER ( EnumItemTupleEnumItemStruct )
   DispatchExpr?
   ,

DispatchExpr :
   => BlockExpression

ParserDef

TODO

DispatchParams

TODO

Commands

TODO: Rewrite more to do with mapping to clap uses

The syntax of a CommandDef is Rust-like but does not behave like any of the Rust syntactical constructs it resembles.

The IDENTIFIER, EnumItemTuple and EnumItemStruct are used to generate an item in an enum. This enum is processed by the clap::Subcommand derive macro and may take the same form as accepted by clap, i.e. struct items are parsed as clap::Args and tuple items are use to refer to a separate clap::Args struct. Any attributes on the items or struct fields are passed through appropriately.

The optional DispatchExpr construct is used to populate the generated dispatcher function.

DispatchExpr

Each subcommand may also have an associated DispatchExpr. This is inserted into the dispatcher for that subcommand's match arm.

For example, a subcommand defined as

commands {
    Foo(Foo) => { handler.foo(); },
};

would produce a match arm like

match &self {
    Foo(handler) => { handler.foo(); },
}

Note that the enum variant is automatically destructured into handler, which can be referenced in the DispatchExpr. This is mainly useful for referring to clap structs defined outside applause.

Struct-like Enum Variants

A struct-like enum variant is automatically destructured to its named fields. A CommandDef of

Foo {name: String} => { println!("Saying foo to {}", name) },

would produce a match arm of

match &self {
    // SNIP
    Foo {name} => { println!("Saying foo to {}", name) }
    // SNIP
}

TODO: Talk about how clap treats these as args for the subcommand

Chaining Dispatches

As a shorthand, if no BlockExpression is specified for an enum variant with an unnamed field, for example Foo(commands::Foo),, applause will assume that the contained type is another applause generated Parser. It will then attempt to invoke its dispatch method with no other parameters.

This means a command line such as my_exe foo bar can be handled by

// main.rs - Top level
mod commands;
applause!{
    Cli{};

    commands {
        Foo(commands::Foo),
    };
}

fn main() {
    dispatch!(Cli);
}
// commands.rs - Subcommands
applause!{
    Foo{};

    commands {
        Bar(Bar) => { /* Do a bar */ },
    }
}

Helper Macros

applause ships several declarative macros to help with parsing and dispatch of commands.

dispatch

The dispatch!(T) macro parses the command line using the given type T and immediately dispatches to the subcommand handler.

    let subcmd_result = dispatch_args!(Cli);

dispatch_args

The dispatch_args!(T => args...) macro parses the command line using the type T and dispatches to the handler along with the additional list of arguments provided.

    let subcmd_result = dispatch_args!(Cli => "arg1", "arg2");

This can be used to call the run function when it has additional parameters defined by the dispatch_params {} block.

parse_args

The parse_args!(T) macro simply parses the command line with type T but does not perform any dispatch.

    let cli = parse_args!(Cli);