Crates.io | ibuilder |
lib.rs | ibuilder |
version | 0.1.8 |
source | src |
created_at | 2020-04-03 19:33:04.805362 |
updated_at | 2021-08-22 12:27:49.670632 |
description | Interactive builder for Rust types |
homepage | https://github.com/edomora97/ibuilder |
repository | https://github.com/edomora97/ibuilder |
max_upload_size | |
id | 226027 |
size | 80,637 |
Interactive builders for structs.
This crate provides a way to construct structs interactively, prompting the user multiple choices and text inputs.
The builder provides the user with interactive menu-like interfaces, keeping the UI abstract and rust type-safeness.
When building an interactive application (e.g. a Telegram bot or a console application) it can be pretty cumbersome to come out with a decent interface without writing tons of code for the logic for handling the parsing and the validation of the input.
This crates provides a useful abstraction that allows an easy connection between the data and the user interface. Just by deriving the struct (or enum) that defines your data you can get a safe interface for building a UI.
The derive API is inspired by the great structopt
crate.
The API of this crate is very simple:
IBuilder
, including all the structs/enums that it depends
upon;builder()
method (from the Buildable
trait) to get an instance of Builder<T>
;get_options()
on the builder to get an object that contains a message to show the user,
a list of possible choices (i.e. buttons to press) and eventually the possibility to enter
some text (i.e. a text box);to_node()
on the builder to get a tree-like structure with the state of the builder,
highlighting the fields that still need actions;choose(input)
on the builder. This will apply the choice to the state of the structure if
it's valid, or return an error;choose
will return an instance of T
.A list of all the possible options for the ibuilder
attribute can be found here.
struct Foo(i64)
)bool
, String
, char
, Box<T>
,
Vec<T>
and Option<T>
NewBuildableValue
traitIn this example the data is stored inside a struct named Person
which has 3 fields, one of
which has a default value. Deriving from IBuilder
gives access to the builder()
method that
returns a Builder<Person>
.
Figure 1: main menu | Figure 2: AgeRange
menu | Figure 3: main menu again
use ibuilder::*;
#[derive(IBuilder)]
pub struct Person {
#[ibuilder(rename = "full name")]
full_name: String,
age: AgeRange,
#[ibuilder(default = 2, rename = "number of hands")]
num_hands: u64,
}
#[derive(IBuilder, Debug, Eq, PartialEq)]
#[ibuilder(prompt = "How old are you?")]
pub enum AgeRange {
#[ibuilder(rename = "Less than 13 years old")]
Child,
#[ibuilder(rename = "From 13 to 19 years old")]
Teen,
#[ibuilder(rename = "20 years or more")]
Adult,
#[ibuilder(rename = "I don't want to tell")]
Unknown,
}
let mut builder = Person::builder();
// * figure 1 *
let options = builder.get_options(); // main menu: select the field to edit
builder.choose(Input::choice("age")).unwrap(); // select the field
// * figure 2 *
let options = builder.get_options(); // age menu
builder.choose(Input::choice("Adult")).unwrap(); // insert the value
let options = builder.get_options(); // back to the main menu
builder.choose(Input::choice("full_name")).unwrap(); // select the field
let options = builder.get_options(); // full_name menu
assert!(options.text_input); // for inserting the string value
builder.choose(Input::text("edomora97")).unwrap(); // insert the value
// * figure 3 *
assert!(builder.is_done());
let options = builder.get_options(); // main menu again, but the "Done" option is available
// chose the "Done" option, the return value is Ok(Some(Person))
let value = builder.choose(Input::Choice(FINALIZE_ID.to_string())).unwrap().unwrap();
assert_eq!(value.full_name, "edomora97");
assert_eq!(value.age, AgeRange::Adult);
assert_eq!(value.num_hands, 2);
License: MIT