terminal_magic/
prompts.rs1use async_std::task;
2use indexmap::IndexMap;
3use mustache::MapBuilder;
4use prompts::{confirm::ConfirmPrompt, Prompt, text::TextPrompt};
5
6use crate::models::EntryType;
7
8pub fn boolean_prompt(prompt_string: &str) -> bool {
15 let mut prompt = ConfirmPrompt::new(prompt_string);
16 match task::block_on(async { prompt.run().await }) {
17 Ok(Some(val)) => val,
18 _ => std::process::exit(1),
19 }
20}
21pub fn text_prompt(prompt_string: &str) -> Option<String> {
22 let mut prompt = TextPrompt::new(prompt_string);
23 match task::block_on(async { prompt.run().await }) {
24 Ok(val) => val,
25 _ => None,
26 }
27}
28pub fn password_prompt(prompt_string: &str) -> Option<String> {
29 let mut prompt = TextPrompt::new(prompt_string).with_style(prompts::text::Style::Password);
30 match task::block_on(async { prompt.run().await }) {
31 Ok(val) => val,
32 _ => None,
33 }
34}
35
36
37pub fn read(key: &str, entry_type: &EntryType, map_builder: MapBuilder) -> (MapBuilder, EntryType) {
38 match entry_type {
39 EntryType::Value(str) => (map_builder, read_value(key, str)),
40 EntryType::Array(array) => read_array(key, &array[0], map_builder),
41 EntryType::Object(obj) => read_object(obj, map_builder),
42 }
43}
44
45pub fn read_value(key: &str, str: &str) -> EntryType {
46 let mut prompt = TextPrompt::new(format!("{} [{}]? ", key, str));
47 match task::block_on(async { prompt.run().await }) {
48 Ok(Some(s)) => {
49 if !s.is_empty() {
50 EntryType::Value(shellexpand::tilde(&s).to_string())
51 } else {
52 EntryType::Value(shellexpand::tilde(&str).to_string())
53 }
54 }
55 _ => std::process::exit(1),
56 }
57}
58
59pub fn get_short_names(array: &[EntryType]) -> String {
60 let mut short_names: Vec<String> = vec![];
61 for entry in array {
62 if let EntryType::Object(obj) = entry {
63 if obj.contains_key("shortName") {
64 if let Some(EntryType::Value(short_name)) = obj.get("shortName") {
65 short_names.push(short_name.clone());
66 }
67 }
68 }
69 }
70 short_names.join(" ")
71}
72
73pub fn read_array(
74 key: &str,
75 proto_type: &EntryType,
76 mut map_builder: MapBuilder,
77) -> (MapBuilder, EntryType) {
78 let mut new_array = vec![];
79 loop {
80 let object = proto_type.clone();
81 let (new_map_builder, object_to_insert) = read(key, &object, map_builder);
82 map_builder = new_map_builder;
83 new_array.push(object_to_insert);
84 let mut prompt = ConfirmPrompt::new("Another one? ");
85 match task::block_on(async { prompt.run().await }) {
86 Ok(Some(true)) => continue,
87 _ => break,
88 }
89 }
90 let name = get_short_names(&new_array);
91 map_builder = map_builder.insert_str(format!("{}_shortNames", key), name);
92 (map_builder, EntryType::Array(new_array))
93}
94
95pub fn read_object(
96 obj: &IndexMap<String, EntryType>,
97 mut map_builder: MapBuilder,
98) -> (MapBuilder, EntryType) {
99 let mut new_obj = IndexMap::new();
100 for keys in obj.iter() {
101 let (new_map_builder, object) = read(keys.0, keys.1, map_builder);
102 map_builder = new_map_builder;
103 new_obj.insert(keys.0.to_string(), object);
104 }
105 (map_builder, EntryType::Object(new_obj))
106}