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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use crate::config::{Catalog, CatalogEntry, CatalogError}; use crate::util::{Source, SourceError}; use crate::Archetect; use crate::vendor::read_input::shortcut::input; use crate::vendor::read_input::InputBuild; use std::collections::{HashMap, HashSet}; #[derive(Debug)] pub enum CatalogSelectError { EmptyCatalog, SourceError(SourceError), UnsupportedCatalogSource(String), } impl From<SourceError> for CatalogSelectError { fn from(cause: SourceError) -> Self { CatalogSelectError::SourceError(cause) } } pub fn you_are_sure(message: &str) -> bool { input::<bool>() .prompting_on_stderr() .msg(format!("{} [false]: ", message)) .default(false) .get() } pub fn select_from_catalog( archetect: &Archetect, catalog: &Catalog, current_source: &Source, ) -> Result<CatalogEntry, CatalogError> { let mut catalog = catalog.clone(); let mut current_source = current_source.clone(); loop { if catalog.entries().is_empty() { return Err(CatalogError::EmptyCatalog); } let choice = select_from_entries(archetect, catalog.entries_owned())?; match choice { CatalogEntry::Catalog { description: _, source } => { let source = Source::detect(archetect, &source, Some(current_source))?; current_source = source.clone(); catalog = Catalog::load(source)?; } CatalogEntry::Archetype { description: _, source: _, } => { return Ok(choice); } CatalogEntry::Group { description: _, entries: _, } => unreachable!(), } } } pub fn select_from_entries( _archetect: &Archetect, mut entry_items: Vec<CatalogEntry>, ) -> Result<CatalogEntry, CatalogError> { if entry_items.is_empty() { return Err(CatalogError::EmptyGroup); } loop { let mut choices = entry_items .iter() .enumerate() .map(|(id, entry)| (id + 1, entry.clone())) .collect::<HashMap<_, _>>(); for (id, entry) in entry_items.iter().enumerate() { eprintln!("{:>2}) {}", id + 1, entry.description()); } let test_values = choices.keys().map(|v| *v).collect::<HashSet<_>>(); let result = input::<usize>() .prompting_on_stderr() .msg("\nSelect an entry: ") .add_test(move |value| test_values.contains(value)) .err("Please enter the number of a selection from the list.") .repeat_msg("Select an entry: ") .get(); let choice = choices.remove(&result).unwrap(); match choice { CatalogEntry::Group { description: _, entries, } => { entry_items = entries; } CatalogEntry::Catalog { description: _, source: _, } => return Ok(choice), CatalogEntry::Archetype { description: _, source: _, } => return Ok(choice), } } }