upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/cli_helpers.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:18:29 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:18:29 +0000
commitfda0fdd81caab1ca92eb7ed601058e6c2fdc59f5 (patch)
treedd91fc1a7b41d02aead655ea2dc07463b3487d5d /src/cli_helpers.rs
parent0067804cc00e94ce2b7043e67f9ff50968525479 (diff)
helpers and utilities
Diffstat (limited to 'src/cli_helpers.rs')
-rw-r--r--src/cli_helpers.rs160
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 @@
1use confy::ConfyError;
2use dialoguer::{theme::ColorfulTheme, Input, MultiSelect, Confirm};
3use nostr::{EventId, prelude::{Nip19Event, FromBech32}};
4
5use crate::config::{MyConfig, save_conifg};
6/// Renders a dialoguer multi select prompt with a free-form option
7pub 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
67pub 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
123pub 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