diff --git a/src/main.rs b/src/main.rs index be33c1a..918299b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -127,13 +127,13 @@ fn main() { if let Some(remote) = extra_args.get(0) { // Parse address match utils::parser::parse_remote_opt(remote) { - Ok((addr, portn, proto, user, wrkdir)) => { + Ok(host_opts) => { // Set params - address = Some(addr); - port = portn; - protocol = proto; - username = user; - remote_wrkdir = wrkdir; + address = Some(host_opts.hostname); + port = host_opts.port; + protocol = host_opts.protocol; + username = host_opts.username; + remote_wrkdir = host_opts.wrkdir; } Err(err) => { eprintln!("Bad address option: {}", err); diff --git a/src/ui/activities/auth_activity/mod.rs b/src/ui/activities/auth_activity/mod.rs index 1f2d58b..effcad9 100644 --- a/src/ui/activities/auth_activity/mod.rs +++ b/src/ui/activities/auth_activity/mod.rs @@ -228,13 +228,11 @@ impl Activity for AuthActivity { return; } // Read one event - if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() { - if let Some(event) = event { - // Set redraw to true - self.redraw = true; - // Handle event - self.handle_input_event(&event); - } + if let Ok(Some(event)) = self.context.as_ref().unwrap().input_hnd.read_event() { + // Set redraw to true + self.redraw = true; + // Handle event + self.handle_input_event(&event); } // Redraw if necessary if self.redraw { diff --git a/src/ui/activities/filetransfer_activity/input.rs b/src/ui/activities/filetransfer_activity/input.rs index a3c560d..5aa4e9a 100644 --- a/src/ui/activities/filetransfer_activity/input.rs +++ b/src/ui/activities/filetransfer_activity/input.rs @@ -41,17 +41,11 @@ impl FileTransferActivity { /// Read one event. /// Returns whether at least one event has been handled pub(super) fn read_input_event(&mut self) -> bool { - if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() { - // Iterate over input events - if let Some(event) = event { - // Handle event - self.handle_input_event(&event); - // Return true - true - } else { - // No event - false - } + if let Ok(Some(event)) = self.context.as_ref().unwrap().input_hnd.read_event() { + // Handle event + self.handle_input_event(&event); + // Return true + true } else { // Error false @@ -103,7 +97,7 @@ impl FileTransferActivity { KeyCode::Esc => { // Handle quit event // Create quit prompt dialog - self.popup = self.create_disconnect_popup(); + self.popup = Some(self.create_disconnect_popup()); } KeyCode::Tab => self.switch_input_field(), // switch tab KeyCode::Right => self.tab = FileExplorerTab::Remote, // switch to right tab @@ -269,7 +263,7 @@ impl FileTransferActivity { } 'q' | 'Q' => { // Create quit prompt dialog - self.popup = self.create_quit_popup(); + self.popup = Some(self.create_quit_popup()); } 'r' | 'R' => { // Rename @@ -326,7 +320,7 @@ impl FileTransferActivity { KeyCode::Esc => { // Handle quit event // Create quit prompt dialog - self.popup = self.create_disconnect_popup(); + self.popup = Some(self.create_disconnect_popup()); } KeyCode::Tab => self.switch_input_field(), // switch tab KeyCode::Left => self.tab = FileExplorerTab::Local, // switch to local tab @@ -490,7 +484,7 @@ impl FileTransferActivity { } 'q' | 'Q' => { // Create quit prompt dialog - self.popup = self.create_quit_popup(); + self.popup = Some(self.create_quit_popup()); } 'r' | 'R' => { // Rename @@ -547,7 +541,7 @@ impl FileTransferActivity { KeyCode::Esc => { // Handle quit event // Create quit prompt dialog - self.popup = self.create_disconnect_popup(); + self.popup = Some(self.create_disconnect_popup()); } KeyCode::Tab => self.switch_input_field(), // switch tab KeyCode::Down => { @@ -586,7 +580,7 @@ impl FileTransferActivity { KeyCode::Char(ch) => match ch { 'q' | 'Q' => { // Create quit prompt dialog - self.popup = self.create_quit_popup(); + self.popup = Some(self.create_quit_popup()); } _ => { /* Nothing to do */ } }, diff --git a/src/ui/activities/filetransfer_activity/misc.rs b/src/ui/activities/filetransfer_activity/misc.rs index 04669d1..736ac22 100644 --- a/src/ui/activities/filetransfer_activity/misc.rs +++ b/src/ui/activities/filetransfer_activity/misc.rs @@ -62,23 +62,23 @@ impl FileTransferActivity { /// ### create_quit_popup /// /// Create quit popup input mode (since must be shared between different input handlers) - pub(super) fn create_disconnect_popup(&mut self) -> Option { - Some(Popup::YesNo( + pub(super) fn create_disconnect_popup(&mut self) -> Popup { + Popup::YesNo( String::from("Are you sure you want to disconnect?"), FileTransferActivity::disconnect, FileTransferActivity::callback_nothing_to_do, - )) + ) } /// ### create_quit_popup /// /// Create quit popup input mode (since must be shared between different input handlers) - pub(super) fn create_quit_popup(&mut self) -> Option { - Some(Popup::YesNo( + pub(super) fn create_quit_popup(&mut self) -> Popup { + Popup::YesNo( String::from("Are you sure you want to quit?"), FileTransferActivity::disconnect_and_quit, FileTransferActivity::callback_nothing_to_do, - )) + ) } /// ### switch_input_field diff --git a/src/ui/activities/setup_activity/layout.rs b/src/ui/activities/setup_activity/layout.rs index 5cedd85..f6eaa06 100644 --- a/src/ui/activities/setup_activity/layout.rs +++ b/src/ui/activities/setup_activity/layout.rs @@ -441,15 +441,11 @@ impl SetupActivity { // Iterate over ssh keys let mut ssh_keys: Vec = Vec::with_capacity(cli.iter_ssh_keys().count()); for key in cli.iter_ssh_keys() { - if let Ok(host) = cli.get_ssh_key(key) { - if let Some((addr, username, _)) = host { - ssh_keys.push(ListItem::new(Span::from(format!( - "{} at {}", - username, addr, - )))); - } else { - continue; - } + if let Ok(Some((addr, username, _))) = cli.get_ssh_key(key) { + ssh_keys.push(ListItem::new(Span::from(format!( + "{} at {}", + username, addr, + )))); } else { continue; } diff --git a/src/ui/activities/setup_activity/mod.rs b/src/ui/activities/setup_activity/mod.rs index b589f9c..7caa8f2 100644 --- a/src/ui/activities/setup_activity/mod.rs +++ b/src/ui/activities/setup_activity/mod.rs @@ -168,13 +168,11 @@ impl Activity for SetupActivity { return; } // Read one event - if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() { - if let Some(event) = event { - // Set redraw to true - self.redraw = true; - // Handle event - self.handle_input_event(&event); - } + if let Ok(Some(event)) = self.context.as_ref().unwrap().input_hnd.read_event() { + // Set redraw to true + self.redraw = true; + // Handle event + self.handle_input_event(&event); } // Redraw if necessary if self.redraw { diff --git a/src/utils/parser.rs b/src/utils/parser.rs index 674910d..ff90037 100644 --- a/src/utils/parser.rs +++ b/src/utils/parser.rs @@ -56,9 +56,17 @@ lazy_static! { static ref REMOTE_OPT_REGEX: Regex = Regex::new(r"(?:([a-z]+)://)?(?:([^@]+)@)?(?:([^:]+))(?::((?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])))?(?::([^:]+))?").ok().unwrap(); } +pub struct RemoteOptions { + pub hostname: String, + pub port: u16, + pub protocol: FileTransferProtocol, + pub username: Option, + pub wrkdir: Option, +} + /// ### parse_remote_opt /// -/// Parse remote option string. Returns in case of success a tuple made of (address, port, protocol, username, wrkdir) +/// Parse remote option string. Returns in case of success a RemoteOptions struct /// For ssh if username is not provided, current user will be used. /// In case of error, message is returned /// If port is missing default port will be used for each protocol @@ -75,18 +83,7 @@ lazy_static! { /// - sftp://172.26.104.1 /// - ... /// -pub fn parse_remote_opt( - remote: &str, -) -> Result< - ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ), - String, -> { +pub fn parse_remote_opt(remote: &str) -> Result { // Set protocol to default protocol #[cfg(not(test))] // NOTE: don't use configuration during tests let mut protocol: FileTransferProtocol = match environment::init_config_dir() { @@ -136,7 +133,7 @@ pub fn parse_remote_opt( }, }; // Get address - let address: String = match groups.get(3) { + let hostname: String = match groups.get(3) { Some(group) => group.as_str().to_string(), None => return Err(String::from("Missing address")), }; @@ -152,7 +149,13 @@ pub fn parse_remote_opt( Some(group) => Some(PathBuf::from(group.as_str())), None => None, }; - Ok((address, port, protocol, username, wrkdir)) + Ok(RemoteOptions { + hostname, + port, + protocol, + username, + wrkdir, + }) } None => Err(String::from("Bad remote host syntax!")), } @@ -217,168 +220,103 @@ mod tests { #[test] fn test_utils_parse_remote_opt() { // Base case - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("172.26.104.1")) + let result: RemoteOptions = parse_remote_opt(&String::from("172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 22); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert!(result.3.is_some()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 22); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert!(result.username.is_some()); // User case - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("root@172.26.104.1")) + let result: RemoteOptions = parse_remote_opt(&String::from("root@172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 22); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert_eq!(result.3.unwrap(), String::from("root")); - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 22); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert_eq!(result.username.unwrap(), String::from("root")); + assert!(result.wrkdir.is_none()); // User + port - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("root@172.26.104.1:8022")) + let result: RemoteOptions = parse_remote_opt(&String::from("root@172.26.104.1:8022")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 8022); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert_eq!(result.3.unwrap(), String::from("root")); - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 8022); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert_eq!(result.username.unwrap(), String::from("root")); + assert!(result.wrkdir.is_none()); // Port only - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("172.26.104.1:4022")) + let result: RemoteOptions = parse_remote_opt(&String::from("172.26.104.1:4022")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 4022); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert!(result.3.is_some()); - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 4022); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert!(result.username.is_some()); + assert!(result.wrkdir.is_none()); // Protocol - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("ftp://172.26.104.1")) + let result: RemoteOptions = parse_remote_opt(&String::from("ftp://172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 21); // Fallback to ftp default - assert_eq!(result.2, FileTransferProtocol::Ftp(false)); - assert!(result.3.is_none()); // Doesn't fall back - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 21); // Fallback to ftp default + assert_eq!(result.protocol, FileTransferProtocol::Ftp(false)); + assert!(result.username.is_none()); // Doesn't fall back + assert!(result.wrkdir.is_none()); // Protocol - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("sftp://172.26.104.1")) + let result: RemoteOptions = parse_remote_opt(&String::from("sftp://172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 22); // Fallback to sftp default - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert!(result.3.is_some()); // Doesn't fall back - assert!(result.4.is_none()); - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("scp://172.26.104.1")) + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 22); // Fallback to sftp default + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert!(result.username.is_some()); // Doesn't fall back + assert!(result.wrkdir.is_none()); + let result: RemoteOptions = parse_remote_opt(&String::from("scp://172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 22); // Fallback to scp default - assert_eq!(result.2, FileTransferProtocol::Scp); - assert!(result.3.is_some()); // Doesn't fall back - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 22); // Fallback to scp default + assert_eq!(result.protocol, FileTransferProtocol::Scp); + assert!(result.username.is_some()); // Doesn't fall back + assert!(result.wrkdir.is_none()); // Protocol + user - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("ftps://anon@172.26.104.1")) + let result: RemoteOptions = parse_remote_opt(&String::from("ftps://anon@172.26.104.1")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 21); // Fallback to ftp default - assert_eq!(result.2, FileTransferProtocol::Ftp(true)); - assert_eq!(result.3.unwrap(), String::from("anon")); - assert!(result.4.is_none()); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 21); // Fallback to ftp default + assert_eq!(result.protocol, FileTransferProtocol::Ftp(true)); + assert_eq!(result.username.unwrap(), String::from("anon")); + assert!(result.wrkdir.is_none()); // Path - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("root@172.26.104.1:8022:/var")) + let result: RemoteOptions = parse_remote_opt(&String::from("root@172.26.104.1:8022:/var")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 8022); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert_eq!(result.3.unwrap(), String::from("root")); - assert_eq!(result.4.unwrap(), PathBuf::from("/var")); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 8022); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert_eq!(result.username.unwrap(), String::from("root")); + assert_eq!(result.wrkdir.unwrap(), PathBuf::from("/var")); // Port only - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("172.26.104.1:home")) + let result: RemoteOptions = parse_remote_opt(&String::from("172.26.104.1:home")) .ok() .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 22); - assert_eq!(result.2, FileTransferProtocol::Sftp); - assert!(result.3.is_some()); - assert_eq!(result.4.unwrap(), PathBuf::from("home")); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 22); + assert_eq!(result.protocol, FileTransferProtocol::Sftp); + assert!(result.username.is_some()); + assert_eq!(result.wrkdir.unwrap(), PathBuf::from("home")); // All together now - let result: ( - String, - u16, - FileTransferProtocol, - Option, - Option, - ) = parse_remote_opt(&String::from("ftp://anon@172.26.104.1:8021:/tmp")) - .ok() - .unwrap(); - assert_eq!(result.0, String::from("172.26.104.1")); - assert_eq!(result.1, 8021); // Fallback to ftp default - assert_eq!(result.2, FileTransferProtocol::Ftp(false)); - assert_eq!(result.3.unwrap(), String::from("anon")); - assert_eq!(result.4.unwrap(), PathBuf::from("/tmp")); + let result: RemoteOptions = + parse_remote_opt(&String::from("ftp://anon@172.26.104.1:8021:/tmp")) + .ok() + .unwrap(); + assert_eq!(result.hostname, String::from("172.26.104.1")); + assert_eq!(result.port, 8021); // Fallback to ftp default + assert_eq!(result.protocol, FileTransferProtocol::Ftp(false)); + assert_eq!(result.username.unwrap(), String::from("anon")); + assert_eq!(result.wrkdir.unwrap(), PathBuf::from("/tmp")); // bad syntax assert!(parse_remote_opt(&String::from("omar://172.26.104.1")).is_err()); // Bad protocol assert!(parse_remote_opt(&String::from("omar://172.26.104.1:650000")).is_err());