oberst 0.1.1

A type-safe command parser and dispatcher inspired by Brigadier and written in Rust.
Documentation
# Oberst

A type-safe command parser & dispatcher inspired by [Brigadier](https://github.com/mojang/brigadier) and written in Rust.

## Usage

### Creating a command source

Oberst leverages Rust's procedural macros in order to generate a command's syntax from a set of ordinary functions. To use it, you first need a `CommandSource<C>`. Here, `C` can be any struct you want your commands to have access to:
```rust 
    use oberst::CommandSource;

    struct CommandContext {
        name: String
    }

    fn main() {
        let command_source = CommandSource::new(CommandContext {
            name: "Herbert".to_string()
        });
    }
```

### Defining a command

Commands are defined with the `define_command` macro : 
```rust
    use oberst::{ CommandResult, define_command}
    define_command!(hello: CommandContext /* Specify the type of context this command needs to run */ {
        fn simple(context: &CommandContext) -> CommandResult {
            println!("Hello, {}!", &context.name);
            Ok(0) // Commands can return a "status code" that is returned to the dispatcher
        }

        // Commands can take arguments as well
        fn with_arg(context: &CommandContext, from: String) {
            println!("Hello to {} from {}", &context.name, from)
        }

        #[args = "<times> times"]
        fn custom_syntax(context: &CommandContext, times: u64) {
            for _ in 0..times {
                println!("Hello, {}!", &context.name);
            }
        }
    })
```

Commands can accept whitespace-separated arguments of any type that implements Obersts' `Argument` trait. See the `oberst::parser` module for more info. While you can implement `Argument` for your custom types, Oberst comes with default implementation for built-in types such as integer types and `String`.

With the `args` attribute, it is possible to build a more sophisticated command syntax by allowing the command to parse both arguments and literals. However, arguments within an `args` attribute _must appear in the same order as they do in the function's signature._ 

Commands have to return either `()` or `oberst::CommandResult`. The latter supports returning any error values that implement `std::error::Error`.

### Registering a command
Commands can be registered to a source using the `register_command!` helper macro:
```rust
    fn main() {
        //...
        register_command!(command_source, hello);
        command_source.dispatch("hello \"John\""); // Prints "Hello to Herbert from John"
    }
```

## Roadmap
- [x] Command creation & dispatchment
- [x] Argument parsers for most std types
- [x] Add support for both `CommandResult` and `()` return values
- [x] Add support for custom syntax with `#[args = "..."]`
- [ ] Add support for multithreaded commands
- [ ] Make `CommandSource` clonable to avoid having to pass references around