diff --git a/socktop/src/main.rs b/socktop/src/main.rs index 98ab11d..5018d6c 100644 --- a/socktop/src/main.rs +++ b/socktop/src/main.rs @@ -98,7 +98,7 @@ async fn main() -> Result<(), Box> { // Determine final connection parameters (and maybe mutated profiles to persist) let mut profiles_mut = profiles_file.clone(); let (url, tls_ca): (String, Option) = match resolved { - ResolveProfile::Direct(u, t) => { + ResolveProfile::Direct(u, t) => { // Possibly save if profile specified and --save or new entry if let Some(name) = parsed.profile.as_ref() { let existing = profiles_mut.profiles.get(name); @@ -107,7 +107,10 @@ async fn main() -> Result<(), Box> { // New profile: auto-save immediately profiles_mut.profiles.insert( name.clone(), - ProfileEntry { url: u.clone(), tls_ca: t.clone() }, + ProfileEntry { + url: u.clone(), + tls_ca: t.clone(), + }, ); let _ = save_profiles(&profiles_mut); } @@ -117,7 +120,10 @@ async fn main() -> Result<(), Box> { if parsed.save { profiles_mut.profiles.insert( name.clone(), - ProfileEntry { url: u.clone(), tls_ca: t.clone() }, + ProfileEntry { + url: u.clone(), + tls_ca: t.clone(), + }, ); let _ = save_profiles(&profiles_mut); } else if prompt_yes_no(&format!( @@ -125,7 +131,10 @@ async fn main() -> Result<(), Box> { )) { profiles_mut.profiles.insert( name.clone(), - ProfileEntry { url: u.clone(), tls_ca: t.clone() }, + ProfileEntry { + url: u.clone(), + tls_ca: t.clone(), + }, ); let _ = save_profiles(&profiles_mut); } // else: do not overwrite, just connect with provided details @@ -163,6 +172,16 @@ async fn main() -> Result<(), Box> { return Ok(()); } } + ResolveProfile::PromptCreate(name) => { + eprintln!("Profile '{name}' does not exist yet."); + let url = prompt_string("Enter URL (ws://HOST:PORT/ws or wss://...): ")?; + if url.trim().is_empty() { return Ok(()); } + let ca = prompt_string("Enter TLS CA path (or leave blank): ")?; + let ca_opt = if ca.trim().is_empty() { None } else { Some(ca.trim().to_string()) }; + profiles_mut.profiles.insert(name.clone(), ProfileEntry { url: url.trim().to_string(), tls_ca: ca_opt.clone() }); + let _ = save_profiles(&profiles_mut); + (url.trim().to_string(), ca_opt) + } ResolveProfile::None => { eprintln!("No URL provided and no profiles to select."); return Ok(()); @@ -183,3 +202,11 @@ fn prompt_yes_no(prompt: &str) -> bool { false } } + +fn prompt_string(prompt: &str) -> io::Result { + eprint!("{prompt}"); + let _ = io::stderr().flush(); + let mut line = String::new(); + io::stdin().read_line(&mut line)?; + Ok(line) +} diff --git a/socktop/src/profiles.rs b/socktop/src/profiles.rs index 2a75c4d..8dcc682 100644 --- a/socktop/src/profiles.rs +++ b/socktop/src/profiles.rs @@ -57,6 +57,8 @@ pub enum ResolveProfile { Loaded(String, Option), /// Should prompt user to select among profile names PromptSelect(Vec), + /// Should prompt user to create a new profile (name) + PromptCreate(String), /// No profile could be resolved (e.g., missing arguments) None, } @@ -75,7 +77,7 @@ impl ProfileRequest { if let Some(entry) = pf.profiles.get(&name) { return ResolveProfile::Loaded(entry.url.clone(), entry.tls_ca.clone()); } else { - return ResolveProfile::None; + return ResolveProfile::PromptCreate(name); } } // Both provided -> direct (maybe later saved by caller)