summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-04-24 13:34:55 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-04-24 13:34:55 +0200
commit2784016116c85decb24feb837c36a9ac4eb9758d (patch)
tree1e65f4617b0a40e9338de99a7bcc37993c02cbe8
parent2987c24a46f3895afd85edd5f3c262776e7fa47e (diff)
parentddaa455a66bb33299ea67e744f95c92b23715f32 (diff)
Merge branch 'option-support'
-rw-r--r--examples/option.rs15
-rw-r--r--src/backend/dialoguer.rs26
-rw-r--r--src/backend/mod.rs7
-rw-r--r--src/buildable.rs16
-rw-r--r--src/lib.rs7
5 files changed, 64 insertions, 7 deletions
diff --git a/examples/option.rs b/examples/option.rs
new file mode 100644
index 0000000..937733a
--- /dev/null
+++ b/examples/option.rs
@@ -0,0 +1,15 @@
+use interactive_object_builder::*;
+use interactive_object_builder::backend::dialoguer::DialoguerBackend;
+
+fn main() -> Result<(), ()> {
+ let v = Option::<bool>::builder(DialoguerBackend).build_collection("optional yes/no")
+ .map_err(|_| ())?;
+
+ println!("{:?}", v);
+
+ let v = Option::<u64>::builder(DialoguerBackend).build_collection("optional u64")
+ .map_err(|_| ())?;
+
+ println!("{:?}", v);
+ Ok(())
+}
diff --git a/src/backend/dialoguer.rs b/src/backend/dialoguer.rs
index 11d5349..5bdebd6 100644
--- a/src/backend/dialoguer.rs
+++ b/src/backend/dialoguer.rs
@@ -1,7 +1,7 @@
use crate::Backend;
-use crate::ValueBuilder;
use crate::BuildableValue;
use crate::CollectionBuilder;
+use crate::ValueBuilder;
pub struct DialoguerBackend;
@@ -88,6 +88,9 @@ impl Backend for DialoguerBackend {
Box::new(DialoguerVecBuilder::<T>(std::marker::PhantomData))
}
+ fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>, Error = Self::Error>> {
+ Box::new(DialoguerOptionValueBuilder::<T>(std::marker::PhantomData))
+ }
}
pub struct DialoguerValueBuilder<T: Sized>(std::marker::PhantomData<T>);
@@ -106,6 +109,27 @@ impl<T> ValueBuilder for DialoguerValueBuilder<T>
}
}
+pub struct DialoguerOptionValueBuilder<T: BuildableValue>(std::marker::PhantomData<T>);
+impl<T: BuildableValue> CollectionBuilder for DialoguerOptionValueBuilder<T> {
+ type Output = Option<T>;
+ type Error = DialoguerBackendError;
+
+ fn build_collection(&self, value_desc: &str) -> Result<Self::Output, Self::Error> {
+ let q = format!("Do you want to provide a Value for {}", value_desc);
+ let b = dialoguer::Input::<bool>::new()
+ .with_prompt(q)
+ .interact_text()?;
+
+ if b {
+ T::builder(DialoguerBackend)
+ .build_value(value_desc)
+ .map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+}
+
pub struct DialoguerVecBuilder<T: 'static + BuildableValue>(std::marker::PhantomData<T>);
impl<T> CollectionBuilder for DialoguerVecBuilder<T>
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index 1353a6d..3f72d66 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,8 +1,8 @@
pub mod dialoguer;
-use crate::ValueBuilder;
use crate::BuildableValue;
use crate::CollectionBuilder;
+use crate::ValueBuilder;
/// A backend can be used to get builders for specific types
pub trait Backend {
@@ -26,9 +26,10 @@ pub trait Backend {
fn char_builder(&self) -> Box<dyn ValueBuilder<Output = char, Error = Self::Error>>;
fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String, Error = Self::Error>>;
+ fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>, Error = Self::Error>>;
+
fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
- where T: 'static + BuildableValue
- ;
+ where T: 'static + BuildableValue;
}
diff --git a/src/buildable.rs b/src/buildable.rs
index 95382e7..37bfc3c 100644
--- a/src/buildable.rs
+++ b/src/buildable.rs
@@ -1,6 +1,6 @@
-use crate::ValueBuilder;
-use crate::CollectionBuilder;
use crate::Backend;
+use crate::CollectionBuilder;
+use crate::ValueBuilder;
// A value that can be built interactively, using a Backend
pub trait BuildableValue: Sized {
@@ -164,7 +164,6 @@ impl BuildableValue for String {
}
-
pub trait BuildableCollection {
fn builder<E, B>(backend: B) -> Box<dyn CollectionBuilder<Output = Self, Error = E>>
where E: Sized,
@@ -183,3 +182,14 @@ impl<T> BuildableCollection for Vec<T>
}
}
+impl<T> BuildableCollection for Option<T>
+ where T: 'static + BuildableValue + Sized
+{
+ fn builder<E, B>(backend: B) -> Box<dyn CollectionBuilder<Output = Option<T>, Error = E>>
+ where E: Sized,
+ B: Backend<Error = E>
+ {
+ backend.option_builder()
+ }
+}
+
diff --git a/src/lib.rs b/src/lib.rs
index 21d5ab4..f7ef93b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -71,6 +71,10 @@ mod dummy_bool_test {
unimplemented!()
}
+ fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>, Error = Self::Error>> {
+ unimplemented!()
+ }
+
fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
where T: 'static + BuildableValue
{
@@ -155,6 +159,9 @@ mod vec_test {
fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String, Error = Self::Error>> {
unimplemented!()
}
+ fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>, Error = Self::Error>> {
+ unimplemented!()
+ }
fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
where T: 'static + BuildableValue
{