diff options
Diffstat (limited to 'src/cli_helpers.rs')
| -rw-r--r-- | src/cli_helpers.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/cli_helpers.rs b/src/cli_helpers.rs new file mode 100644 index 0000000..91f6dde --- /dev/null +++ b/src/cli_helpers.rs | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | use confy::ConfyError; | ||
| 2 | use dialoguer::{theme::ColorfulTheme, Input, MultiSelect, Confirm}; | ||
| 3 | use nostr::{EventId, prelude::{Nip19Event, FromBech32}}; | ||
| 4 | |||
| 5 | use crate::config::{MyConfig, save_conifg}; | ||
| 6 | /// Renders a dialoguer multi select prompt with a free-form option | ||
| 7 | pub fn multi_select_with_add( | ||
| 8 | proposed:Vec<String>, | ||
| 9 | selected:Vec<bool>, | ||
| 10 | prompt: &str, | ||
| 11 | add_prompt: &str, | ||
| 12 | ) -> Vec<String> { | ||
| 13 | // add option with add_prompt | ||
| 14 | let mut options:Vec<String> = proposed.clone(); | ||
| 15 | options.push(add_prompt.to_string()); | ||
| 16 | let mut options_selected = selected.clone(); | ||
| 17 | options_selected.push(false); | ||
| 18 | // present options | ||
| 19 | let chosen : Vec<usize> = MultiSelect::new() | ||
| 20 | .with_prompt(prompt) | ||
| 21 | .items(&options) | ||
| 22 | .defaults(&options_selected) | ||
| 23 | .report(false) | ||
| 24 | .interact() | ||
| 25 | .unwrap(); | ||
| 26 | // reduce options list | ||
| 27 | let mut new_proposed: Vec<String> = [].to_vec(); | ||
| 28 | for (i, _el) in proposed.iter().enumerate() { | ||
| 29 | if chosen.contains(&i) { | ||
| 30 | new_proposed.push(proposed[i].clone()) | ||
| 31 | } | ||
| 32 | } | ||
| 33 | let mut new_selected: Vec<bool> = vec![true;new_proposed.len()]; | ||
| 34 | // if add_prompt selected | ||
| 35 | let last = chosen.last(); | ||
| 36 | if last == None || *last.unwrap() == options.len() - 1 { | ||
| 37 | // get user to input new item | ||
| 38 | let new_relay: String = Input::with_theme(&ColorfulTheme::default()) | ||
| 39 | .with_prompt(add_prompt) | ||
| 40 | .report(false) | ||
| 41 | .interact_text() | ||
| 42 | .unwrap(); | ||
| 43 | // prepare new proposed options | ||
| 44 | // if new item is not blank add it as a selected option | ||
| 45 | if new_relay.len() > 0 { | ||
| 46 | new_proposed.push(new_relay); | ||
| 47 | new_selected.push(true); | ||
| 48 | } | ||
| 49 | // re run selection | ||
| 50 | return multi_select_with_add( | ||
| 51 | new_proposed, | ||
| 52 | new_selected, | ||
| 53 | prompt, | ||
| 54 | add_prompt, | ||
| 55 | ) | ||
| 56 | } | ||
| 57 | else { | ||
| 58 | let mut items: Vec<String> = [].to_vec(); | ||
| 59 | for i in chosen { | ||
| 60 | items.push(options[i].clone()); | ||
| 61 | } | ||
| 62 | println!("{}: {:?}",prompt,items); | ||
| 63 | return items; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | pub fn select_relays(cfg:&mut MyConfig, selected_defaults:&Vec<String>) -> Result<Vec<String>,ConfyError> { | ||
| 68 | // set default relays (selected by default) | ||
| 69 | let default_relays = | ||
| 70 | if selected_defaults.is_empty() { cfg.default_relays.clone() } | ||
| 71 | else { selected_defaults.clone() }; | ||
| 72 | // set full proposed list | ||
| 73 | let mut proposed_relays = default_relays.clone(); | ||
| 74 | // add config defaults to proposed unless duplicate | ||
| 75 | for s in &cfg.default_relays { | ||
| 76 | if !(proposed_relays.iter().any(|df| s.eq(df))) { | ||
| 77 | proposed_relays.push(s.clone()); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | // add example options to proposed list unless duplicate | ||
| 81 | for s in vec![ | ||
| 82 | String::from("wss://relay.damus.io"), | ||
| 83 | String::from("wss://nostr.wine"), | ||
| 84 | String::from("wss://nos.lol"), | ||
| 85 | ] { | ||
| 86 | if !(proposed_relays.iter().any(|df| s.eq(df))) { | ||
| 87 | proposed_relays.push(s.clone()); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | // select only cli attribute relays or thie first in the proposed list | ||
| 91 | // this does the same thing but which is more idiumatic? | ||
| 92 | // let mut selected: Vec<bool> = vec![]; | ||
| 93 | // for i in 0..proposed_relays.len() { | ||
| 94 | // selected.push(i < relays.len()); | ||
| 95 | // } | ||
| 96 | let selected: Vec<bool> = proposed_relays | ||
| 97 | .iter() | ||
| 98 | .enumerate() | ||
| 99 | .map(|r| r.0 < default_relays.len() ).collect(); | ||
| 100 | |||
| 101 | // get user relay selection | ||
| 102 | let relay_selection: Vec<String> = crate::cli_helpers::multi_select_with_add( | ||
| 103 | proposed_relays, | ||
| 104 | selected, | ||
| 105 | "Relays", | ||
| 106 | "Other Relay" | ||
| 107 | ); | ||
| 108 | |||
| 109 | // offer to save as default config | ||
| 110 | if relay_selection.ne(&cfg.default_relays) { | ||
| 111 | if Confirm::with_theme(&ColorfulTheme::default()) | ||
| 112 | .with_prompt("Save relays as ngit default?") | ||
| 113 | .default(true) | ||
| 114 | .interact() | ||
| 115 | .unwrap() { | ||
| 116 | cfg.default_relays = relay_selection.clone(); | ||
| 117 | save_conifg(&cfg); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | Ok(relay_selection) | ||
| 121 | } | ||
| 122 | |||
| 123 | pub fn valid_event_id_from_input( | ||
| 124 | proposed_event_id: Option<String>, | ||
| 125 | prompt:&String, | ||
| 126 | ) -> EventId { | ||
| 127 | let mut string_param = proposed_event_id.clone(); | ||
| 128 | loop { | ||
| 129 | string_param = match string_param { | ||
| 130 | None => { | ||
| 131 | let response: String = Input::with_theme(&ColorfulTheme::default()) | ||
| 132 | .with_prompt(prompt.clone()) | ||
| 133 | .report(true) | ||
| 134 | .interact_text() | ||
| 135 | .unwrap(); | ||
| 136 | Some(response) | ||
| 137 | } | ||
| 138 | Some(ref s) => { Some(s.clone()) }, | ||
| 139 | }; | ||
| 140 | |||
| 141 | let _valid_id = match Nip19Event::from_bech32(&string_param.clone().unwrap()) { | ||
| 142 | Ok(n19) => { break n19.event_id } | ||
| 143 | Err(_) => { | ||
| 144 | match EventId::from_bech32(&string_param.clone().unwrap()) { | ||
| 145 | Ok(id) => { break id } | ||
| 146 | Err(_) => { | ||
| 147 | match EventId::from_hex(&string_param.clone().unwrap()) { | ||
| 148 | Ok(id) => { break id } | ||
| 149 | Err(_) => { | ||
| 150 | println!("not a valid nevent, note or hex string. try again."); | ||
| 151 | string_param = None; | ||
| 152 | continue; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | }; | ||
| 159 | } | ||
| 160 | } \ No newline at end of file | ||