File size: 1,552 Bytes
c981f27 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | use anyhow::Result;
use forge_app::UserInfra;
use forge_select::ForgeWidget;
pub struct ForgeInquire;
impl Default for ForgeInquire {
fn default() -> Self {
Self::new()
}
}
impl ForgeInquire {
pub fn new() -> Self {
Self
}
async fn prompt<T, F>(&self, f: F) -> Result<Option<T>>
where
F: FnOnce() -> Result<Option<T>> + Send + 'static,
T: Send + 'static,
{
tokio::task::spawn_blocking(f).await?
}
}
#[async_trait::async_trait]
impl UserInfra for ForgeInquire {
async fn prompt_question(&self, question: &str) -> Result<Option<String>> {
let question = question.to_string();
self.prompt(move || ForgeWidget::input(&question).allow_empty(true).prompt())
.await
}
async fn select_one<T: Clone + std::fmt::Display + Send + 'static>(
&self,
message: &str,
options: Vec<T>,
) -> Result<Option<T>> {
if options.is_empty() {
return Ok(None);
}
let message = message.to_string();
self.prompt(move || ForgeWidget::select(&message, options).prompt())
.await
}
async fn select_many<T: std::fmt::Display + Clone + Send + 'static>(
&self,
message: &str,
options: Vec<T>,
) -> Result<Option<Vec<T>>> {
if options.is_empty() {
return Ok(None);
}
let message = message.to_string();
self.prompt(move || ForgeWidget::multi_select(&message, options).prompt())
.await
}
}
|