Skip to main content

elicitation/containers/
option.rs

1//! Option<T> implementation for optional value elicitation.
2
3use crate::{ElicitClient, ElicitResult, Elicitation, Prompt};
4
5// For generic types, we create default-only style that ignores the type parameter
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
7pub enum OptionStyle {
8    #[default]
9    Default,
10}
11
12impl Prompt for OptionStyle {
13    fn prompt() -> Option<&'static str> {
14        None
15    }
16}
17
18impl Elicitation for OptionStyle {
19    type Style = OptionStyle;
20
21    #[tracing::instrument(skip(_client), level = "trace")]
22    async fn elicit(_client: &ElicitClient<'_>) -> ElicitResult<Self> {
23        Ok(Self::Default)
24    }
25}
26
27impl<T: Elicitation + Send> Prompt for Option<T> {
28    fn prompt() -> Option<&'static str> {
29        Some("Would you like to provide a value for this field?")
30    }
31}
32
33impl<T: Elicitation + Send> Elicitation for Option<T> {
34    type Style = OptionStyle;
35
36    #[tracing::instrument(skip(client), fields(inner_type = std::any::type_name::<T>()))]
37    async fn elicit(client: &ElicitClient<'_>) -> ElicitResult<Self> {
38        tracing::debug!("Eliciting optional value");
39
40        // First ask if they want to provide a value
41        let provide = bool::elicit(client).await?;
42
43        if provide {
44            tracing::debug!("User chose to provide value");
45            T::elicit(client).await.map(Some)
46        } else {
47            tracing::debug!("User chose to skip");
48            Ok(None)
49        }
50    }
51}