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
use std::str::FromStr;

use dialoguer::{theme::ColorfulTheme, Select};
use serde_derive::{Deserialize, Serialize};
use serde_variant::to_variant_name;
use strum::{EnumIter, EnumString, IntoEnumIterator};

#[derive(clap::ValueEnum, Clone, Serialize, Deserialize, Debug, EnumIter, EnumString)]
pub enum Starter {
    #[serde(rename = "Saas")]
    #[strum(serialize = "Saas")]
    Saas,
    #[serde(rename = "Stateless (not db)")]
    #[strum(serialize = "Stateless (not db)")]
    Stateless,
}

impl std::fmt::Display for Starter {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        to_variant_name(self).expect("only enum supported").fmt(f)
    }
}

impl Starter {
    #[must_use]
    pub fn to_list() -> Vec<String> {
        Self::iter().map(|provider| provider.to_string()).collect()
    }

    /// Show interactive starter selection
    ///
    /// # Errors
    /// When could not show the prompt or could not convert selection the
    /// [`Starter`]
    pub fn prompt_selection() -> eyre::Result<Self> {
        let selections = Self::to_list();
        let selection = Select::with_theme(&ColorfulTheme::default())
            .with_prompt("Choose starter template")
            .default(0)
            .items(&selections[..])
            .interact()?;

        println!("{}", &selections[selection]);
        Ok(Self::from_str(&selections[selection])?)
    }

    #[must_use]
    pub fn git_url(&self) -> String {
        match self {
            Self::Saas => "https://github.com/loco-rs/saas-starter-template".to_string(),
            Self::Stateless => "https://github.com/loco-rs/stateless-starter-template".to_string(),
        }
    }
}