use crate::{DefaultValue, ResponsePath, ResponseValue};
#[derive(Debug, Clone, PartialEq)]
pub struct Question {
path: ResponsePath,
ask: String,
kind: QuestionKind,
default: DefaultValue,
}
impl Question {
pub fn new(path: impl Into<ResponsePath>, ask: impl Into<String>, kind: QuestionKind) -> Self {
Self {
path: path.into(),
ask: ask.into(),
kind,
default: DefaultValue::None,
}
}
pub fn path(&self) -> &ResponsePath {
&self.path
}
pub fn ask(&self) -> &str {
&self.ask
}
pub fn kind(&self) -> &QuestionKind {
&self.kind
}
pub fn kind_mut(&mut self) -> &mut QuestionKind {
&mut self.kind
}
pub fn default(&self) -> &DefaultValue {
&self.default
}
pub fn set_suggestion(&mut self, value: impl Into<ResponseValue>) {
self.default = DefaultValue::Suggested(value.into());
}
pub fn set_assumption(&mut self, value: impl Into<ResponseValue>) {
self.default = DefaultValue::Assumed(value.into());
}
pub fn clear_default(&mut self) {
self.default = DefaultValue::None;
}
pub fn is_assumed(&self) -> bool {
self.default.is_assumed()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum QuestionKind {
Unit,
Input(InputQuestion),
Multiline(MultilineQuestion),
Masked(MaskedQuestion),
Int(IntQuestion),
Float(FloatQuestion),
Confirm(ConfirmQuestion),
List(ListQuestion),
AnyOf(AnyOfQuestion),
AllOf(AllOfQuestion),
OneOf(OneOfQuestion),
}
impl QuestionKind {
pub fn is_unit(&self) -> bool {
self == &Self::Unit
}
pub fn is_basic(&self) -> bool {
matches!(
self,
Self::Input(_)
| Self::Multiline(_)
| Self::Masked(_)
| Self::Int(_)
| Self::Float(_)
| Self::Confirm(_)
| Self::List(_)
)
}
pub fn is_structural(&self) -> bool {
matches!(self, Self::AllOf(_) | Self::OneOf(_) | Self::AnyOf(_))
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Variant {
pub name: String,
pub kind: QuestionKind,
}
impl Variant {
pub fn new(name: impl Into<String>, kind: QuestionKind) -> Self {
Self {
name: name.into(),
kind,
}
}
pub fn unit(name: impl Into<String>) -> Self {
Self::new(name, QuestionKind::Unit)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AnyOfQuestion {
pub variants: Vec<Variant>,
pub defaults: Vec<usize>,
}
impl AnyOfQuestion {
pub fn new(variants: Vec<Variant>) -> Self {
Self {
variants,
defaults: Vec::new(),
}
}
pub fn with_defaults(variants: Vec<Variant>, defaults: Vec<usize>) -> Self {
Self { variants, defaults }
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AllOfQuestion {
pub questions: Vec<Question>,
}
impl AllOfQuestion {
pub fn new(questions: Vec<Question>) -> Self {
Self { questions }
}
pub fn empty() -> Self {
Self {
questions: Vec::new(),
}
}
pub fn questions(&self) -> &[Question] {
&self.questions
}
pub fn questions_mut(&mut self) -> &mut Vec<Question> {
&mut self.questions
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct OneOfQuestion {
pub variants: Vec<Variant>,
pub default: Option<usize>,
}
impl OneOfQuestion {
pub fn new(variants: Vec<Variant>) -> Self {
Self {
variants,
default: None,
}
}
pub fn with_default(variants: Vec<Variant>, default: usize) -> Self {
Self {
variants,
default: Some(default),
}
}
pub fn variants(&self) -> &[Variant] {
&self.variants
}
pub fn variants_mut(&mut self) -> &mut Vec<Variant> {
&mut self.variants
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct InputQuestion {
pub default: Option<String>,
pub validate: Option<String>,
}
impl InputQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_default(default: impl Into<String>) -> Self {
Self {
default: Some(default.into()),
validate: None,
}
}
pub fn with_validator(validate: Option<String>) -> Self {
Self {
default: None,
validate,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct MultilineQuestion {
pub default: Option<String>,
pub validate: Option<String>,
}
impl MultilineQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_validator(validate: Option<String>) -> Self {
Self {
default: None,
validate,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct MaskedQuestion {
pub mask: Option<char>,
pub validate: Option<String>,
}
impl MaskedQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_mask(mask: char) -> Self {
Self {
mask: Some(mask),
validate: None,
}
}
pub fn with_validator(validate: Option<String>) -> Self {
Self {
mask: None,
validate,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct IntQuestion {
pub default: Option<i64>,
pub min: Option<i64>,
pub max: Option<i64>,
pub validate: Option<String>,
}
impl IntQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_bounds(min: Option<i64>, max: Option<i64>) -> Self {
Self {
default: None,
min,
max,
validate: None,
}
}
pub fn with_bounds_and_validator(
min: Option<i64>,
max: Option<i64>,
validate: Option<String>,
) -> Self {
Self {
default: None,
min,
max,
validate,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct FloatQuestion {
pub default: Option<f64>,
pub min: Option<f64>,
pub max: Option<f64>,
pub validate: Option<String>,
}
impl FloatQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_bounds(min: Option<f64>, max: Option<f64>) -> Self {
Self {
default: None,
min,
max,
validate: None,
}
}
pub fn with_bounds_and_validator(
min: Option<f64>,
max: Option<f64>,
validate: Option<String>,
) -> Self {
Self {
default: None,
min,
max,
validate,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct ConfirmQuestion {
pub default: bool,
}
impl ConfirmQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn with_default(default: bool) -> Self {
Self { default }
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub enum ListElementKind {
#[default]
String,
Int { min: Option<i64>, max: Option<i64> },
Float { min: Option<f64>, max: Option<f64> },
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct ListQuestion {
pub element_kind: ListElementKind,
pub min_items: Option<usize>,
pub max_items: Option<usize>,
pub validate: Option<String>,
}
impl ListQuestion {
pub fn new() -> Self {
Self::default()
}
pub fn strings() -> Self {
Self {
element_kind: ListElementKind::String,
..Default::default()
}
}
pub fn ints() -> Self {
Self {
element_kind: ListElementKind::Int {
min: None,
max: None,
},
..Default::default()
}
}
pub fn ints_with_bounds(min: Option<i64>, max: Option<i64>) -> Self {
Self {
element_kind: ListElementKind::Int { min, max },
..Default::default()
}
}
pub fn floats() -> Self {
Self {
element_kind: ListElementKind::Float {
min: None,
max: None,
},
..Default::default()
}
}
pub fn floats_with_bounds(min: Option<f64>, max: Option<f64>) -> Self {
Self {
element_kind: ListElementKind::Float { min, max },
..Default::default()
}
}
pub fn with_item_bounds(mut self, min: Option<usize>, max: Option<usize>) -> Self {
self.min_items = min;
self.max_items = max;
self
}
pub fn with_validator(mut self, validate: impl Into<String>) -> Self {
self.validate = Some(validate.into());
self
}
}
pub const SELECTED_VARIANT_KEY: &str = "selected_variant";
pub const SELECTED_VARIANTS_KEY: &str = "selected_variants";