Interactive builders for structs.
This crate provides a way to construct structs interactively, starting from an "empty" state and filling the values of the fields of the struct prompting the user with multiple choices and text inputs. After each choice the internal state of the builder changes.
The builder provides the user with interactive menu-like interfaces, keeping the UI abstract and rust type-safeness.
The API of this crate is very simple, you start with a struct derived from ibuilder
and call
the auto-generated function builder()
. This will construct a new custom-built Builder
to
use for the communication. The Builder
provides two main functions: get_options()
for
getting the current state of the builder and the list of possible options the user can choose,
and choose(input)
that validates and inserts the choice of the user.
When building an interactive application (e.g. a Telegram Bot, a Console application) which needs loads of configurations it can be pretty hard to come out with a decent interface without writing loads of code for handling all the corner cases.
This crates provides a useful abstraction that takes care of the management of the abstract interface while keeping the API clean. The struct where you needs the data is the actual output of this crate, keeping all the type-safeness.
The derive API is inspired by the great structopt
crate.
struct Foo(i64)
)bool
, String
, char
and Vec<T>
NewBuildableValue
trait.Option<T>
```rust extern crate ibuilderderive; use ibuilderderive::ibuilder; use ibuilder::{FINALIZE_ID, Input};
struct Example { /// This message is used as the help message of the field. intfield: i64, stringfield: String, #[ibuilder(default = 123)] defaulted: i64, }
let mut builder = Example::builder();
let options = builder.getoptions(); // main menu: select the field to edit builder.choose(Input::Choice("intfield".into())).unwrap(); // select the field
let options = builder.getoptions(); // intfield menu assert!(options.text_input); // for inserting the integer value builder.choose(Input::Text("42".into())).unwrap(); // insert the value
let options = builder.getoptions(); // back to the main menu builder.choose(Input::Choice("stringfield".into())).unwrap(); // select the second field
let options = builder.getoptions(); // stringfield menu assert!(options.text_input); // for inserting the string value builder.choose(Input::Text("hello world!".into())).unwrap(); // insert the value
assert!(builder.isdone()); let options = builder.getoptions(); // main menu again, but the "Done" option is available // chose the "Done" option, the return value is Ok(Some(Example)) let value = builder.choose(Input::Choice(FINALIZEID.tostring())).unwrap().unwrap();
asserteq!(value.intfield, 42); asserteq!(value.stringfield, "hello world!"); assert_eq!(value.defaulted, 123); ```