mod choice;
mod confirm;
mod editor;
mod expand;
mod handler;
#[macro_use]
mod impl_macros;
mod input;
mod multi_select;
mod number;
mod order_select;
#[macro_use]
mod options;
mod custom_prompt;
mod password;
mod raw_select;
mod select;
pub use choice::Choice;
pub use confirm::ConfirmBuilder;
pub use custom_prompt::{CustomPromptBuilder, Prompt};
pub use editor::EditorBuilder;
pub use expand::ExpandBuilder;
pub use input::InputBuilder;
pub use multi_select::MultiSelectBuilder;
pub use number::{FloatBuilder, IntBuilder};
pub use order_select::{builder::OrderSelectBuilder, OrderSelectItem};
pub use password::PasswordBuilder;
pub use raw_select::RawSelectBuilder;
pub use select::SelectBuilder;
use ui::{backend::Backend, events::EventIterator};
use crate::{Answer, Answers};
use choice::{get_sep_str, ChoiceList};
use custom_prompt::CustomPromptInteral;
use handler::{
AutoComplete, Filter, Transform, TransformByVal, Validate, ValidateByVal, ValidateOnKey,
ValidateOnKeyByVal,
};
use options::Options;
#[derive(Debug)]
pub struct Question<'a> {
kind: QuestionKind<'a>,
opts: Options<'a>,
}
impl<'a> Question<'a> {
fn new(opts: Options<'a>, kind: QuestionKind<'a>) -> Self {
Self { kind, opts }
}
}
impl Question<'static> {
pub fn input<N: Into<String>>(name: N) -> InputBuilder<'static> {
InputBuilder::new(name.into())
}
pub fn password<N: Into<String>>(name: N) -> PasswordBuilder<'static> {
PasswordBuilder::new(name.into())
}
pub fn editor<N: Into<String>>(name: N) -> EditorBuilder<'static> {
EditorBuilder::new(name.into())
}
pub fn confirm<N: Into<String>>(name: N) -> ConfirmBuilder<'static> {
ConfirmBuilder::new(name.into())
}
pub fn int<N: Into<String>>(name: N) -> IntBuilder<'static> {
IntBuilder::new(name.into())
}
pub fn float<N: Into<String>>(name: N) -> FloatBuilder<'static> {
FloatBuilder::new(name.into())
}
pub fn expand<N: Into<String>>(name: N) -> ExpandBuilder<'static> {
ExpandBuilder::new(name.into())
}
pub fn select<N: Into<String>>(name: N) -> SelectBuilder<'static> {
SelectBuilder::new(name.into())
}
pub fn raw_select<N: Into<String>>(name: N) -> RawSelectBuilder<'static> {
RawSelectBuilder::new(name.into())
}
pub fn multi_select<N: Into<String>>(name: N) -> MultiSelectBuilder<'static> {
MultiSelectBuilder::new(name.into())
}
pub fn order_select<N: Into<String>>(name: N) -> OrderSelectBuilder<'static> {
OrderSelectBuilder::new(name.into())
}
pub fn custom<'a, N, P>(name: N, prompt: P) -> CustomPromptBuilder<'a>
where
N: Into<String>,
P: Prompt + 'a,
{
CustomPromptBuilder::new(name.into(), Box::new(Some(prompt)))
}
}
#[derive(Debug)]
enum QuestionKind<'a> {
Input(input::Input<'a>),
Int(number::Int<'a>),
Float(number::Float<'a>),
Confirm(confirm::Confirm<'a>),
Select(select::Select<'a>),
RawSelect(raw_select::RawSelect<'a>),
Expand(expand::Expand<'a>),
MultiSelect(multi_select::MultiSelect<'a>),
OrderSelect(order_select::OrderSelect<'a>),
Password(password::Password<'a>),
Editor(editor::Editor<'a>),
Custom(Box<dyn CustomPromptInteral + 'a>),
}
impl Question<'_> {
pub(crate) fn ask<B: Backend, I: EventIterator>(
self,
answers: &Answers,
b: &mut B,
events: &mut I,
) -> ui::Result<Option<(String, Answer)>> {
if !self.opts.ask_if_answered && answers.contains_key(&self.opts.name) {
return Ok(None);
}
if !self.opts.when.get(answers) {
return Ok(None);
}
let name = self.opts.name;
let message = self
.opts
.message
.map(|message| message.get(answers))
.unwrap_or_else(|| name.clone() + ":");
let on_esc = self.opts.on_esc.get(answers);
let res = match self.kind {
QuestionKind::Input(i) => i.ask(message, on_esc, answers, b, events)?,
QuestionKind::Int(i) => i.ask(message, on_esc, answers, b, events)?,
QuestionKind::Float(f) => f.ask(message, on_esc, answers, b, events)?,
QuestionKind::Confirm(c) => c.ask(message, on_esc, answers, b, events)?,
QuestionKind::Select(l) => l.ask(message, on_esc, answers, b, events)?,
QuestionKind::RawSelect(r) => r.ask(message, on_esc, answers, b, events)?,
QuestionKind::Expand(e) => e.ask(message, on_esc, answers, b, events)?,
QuestionKind::MultiSelect(c) => c.ask(message, on_esc, answers, b, events)?,
QuestionKind::OrderSelect(c) => c.ask(message, on_esc, answers, b, events)?,
QuestionKind::Password(p) => p.ask(message, on_esc, answers, b, events)?,
QuestionKind::Editor(e) => e.ask(message, on_esc, answers, b, events)?,
QuestionKind::Custom(mut o) => o.ask(message, answers, b, events)?,
};
Ok(res.map(|res| (name, res)))
}
}
#[cfg(feature = "smallvec")]
pub type Completions<T> = smallvec::SmallVec<[T; 1]>;
#[cfg(not(feature = "smallvec"))]
pub type Completions<T> = Vec<T>;
#[cfg(feature = "smallvec")]
pub use smallvec::smallvec as completions;
#[cfg(not(feature = "smallvec"))]
pub use std::vec as completions;