diff --git a/Cargo.toml b/Cargo.toml index 24b399b..3851184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ regex = "1.4.2" lazy_static = "1.4.0" hostname = "0.3.1" -[target.'cfg(any(unix, macos, linux))'.dependencies] +[target.'cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))'.dependencies] users = "0.11.0" [dev-dependencies] diff --git a/src/activity_manager.rs b/src/activity_manager.rs index b21721a..68133c3 100644 --- a/src/activity_manager.rs +++ b/src/activity_manager.rs @@ -73,7 +73,7 @@ impl ActivityManager { Ok(ActivityManager { context: Some(ctx), ftparams: None, - interval: interval, + interval, }) } @@ -89,11 +89,11 @@ impl ActivityManager { password: Option, ) { self.ftparams = Some(FileTransferParams { - address: address, - port: port, - protocol: protocol, - username: username, - password: password, + address, + port, + protocol, + username, + password, }); } diff --git a/src/filetransfer/ftp_transfer.rs b/src/filetransfer/ftp_transfer.rs index 16809d5..78e3991 100644 --- a/src/filetransfer/ftp_transfer.rs +++ b/src/filetransfer/ftp_transfer.rs @@ -53,10 +53,7 @@ impl FtpFileTransfer { /// /// Instantiates a new `FtpFileTransfer` pub fn new(ftps: bool) -> FtpFileTransfer { - FtpFileTransfer { - stream: None, - ftps: ftps, - } + FtpFileTransfer { stream: None, ftps } } /// ### parse_list_line @@ -97,13 +94,12 @@ impl FtpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -115,13 +111,12 @@ impl FtpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -133,13 +128,12 @@ impl FtpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -174,7 +168,7 @@ impl FtpFileTransfer { let file_name: String = String::from(metadata.get(8).unwrap().as_str()); // Check if file_name is '.' or '..' if file_name.as_str() == "." || file_name.as_str() == ".." { - return Err(()) + return Err(()); } let mut abs_path: PathBuf = PathBuf::from(path); let extension: Option = match abs_path.as_path().extension() { @@ -187,7 +181,7 @@ impl FtpFileTransfer { Ok(match is_dir { true => FsEntry::Directory(FsDirectory { name: file_name, - abs_path: abs_path, + abs_path, last_change_time: mtime, last_access_time: mtime, creation_time: mtime, @@ -199,7 +193,7 @@ impl FtpFileTransfer { }), false => FsEntry::File(FsFile { name: file_name, - abs_path: abs_path, + abs_path, last_change_time: mtime, last_access_time: mtime, creation_time: mtime, @@ -267,11 +261,11 @@ impl FileTransfer for FtpFileTransfer { } // Login (use anonymous if credentials are unspecified) let username: String = match username { - Some(u) => u.clone(), + Some(u) => u, None => String::from("anonymous"), }; let password: String = match password { - Some(pwd) => String::from(pwd), + Some(pwd) => pwd, None => String::new(), }; if let Err(err) = stream.login(username.as_str(), password.as_str()) { @@ -309,10 +303,7 @@ impl FileTransfer for FtpFileTransfer { /// /// Indicates whether the client is connected to remote fn is_connected(&self) -> bool { - match self.stream { - Some(_) => true, - None => false, - } + self.stream.is_some() } /// ### pwd diff --git a/src/filetransfer/mod.rs b/src/filetransfer/mod.rs index dda5f04..82af420 100644 --- a/src/filetransfer/mod.rs +++ b/src/filetransfer/mod.rs @@ -79,7 +79,7 @@ impl FileTransferError { /// Instantiates a new FileTransferError pub fn new(code: FileTransferErrorType) -> FileTransferError { FileTransferError { - code: code, + code, msg: None, } } diff --git a/src/filetransfer/scp_transfer.rs b/src/filetransfer/scp_transfer.rs index 7fcb5b0..5da59a8 100644 --- a/src/filetransfer/scp_transfer.rs +++ b/src/filetransfer/scp_transfer.rs @@ -48,6 +48,12 @@ pub struct ScpFileTransfer { wrkdir: PathBuf, } +impl Default for ScpFileTransfer { + fn default() -> Self { + Self::new() + } +} + impl ScpFileTransfer { /// ### new /// @@ -97,13 +103,12 @@ impl ScpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -115,13 +120,12 @@ impl ScpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -133,13 +137,12 @@ impl ScpFileTransfer { match c { '-' => {} _ => { - count = count - + match i { - 0 => 4, - 1 => 2, - 2 => 1, - _ => 0, - } + count += match i { + 0 => 4, + 1 => 2, + 2 => 1, + _ => 0, + } } } } @@ -178,7 +181,7 @@ impl ScpFileTransfer { }; // Check if file_name is '.' or '..' if file_name.as_str() == "." || file_name.as_str() == ".." { - return Err(()) + return Err(()); } let mut abs_path: PathBuf = PathBuf::from(path); let extension: Option = match abs_path.as_path().extension() { @@ -191,7 +194,7 @@ impl ScpFileTransfer { Ok(match is_dir { true => FsEntry::Directory(FsDirectory { name: file_name, - abs_path: abs_path, + abs_path, last_change_time: mtime, last_access_time: mtime, creation_time: mtime, @@ -203,7 +206,7 @@ impl ScpFileTransfer { }), false => FsEntry::File(FsFile { name: file_name, - abs_path: abs_path, + abs_path, last_change_time: mtime, last_access_time: mtime, creation_time: mtime, @@ -331,15 +334,15 @@ impl FileTransfer for ScpFileTransfer { )); } let username: String = match username { - Some(u) => u.clone(), + Some(u) => u, None => String::from(""), }; // Try authenticating with user agent - if let Err(_) = session.userauth_agent(username.as_str()) { + if session.userauth_agent(username.as_str()).is_err() { // Try authentication with password then if let Err(err) = session.userauth_password( username.as_str(), - password.unwrap_or(String::from("")).as_str(), + password.unwrap_or_else(|| String::from("")).as_str(), ) { return Err(FileTransferError::new_ex( FileTransferErrorType::AuthenticationFailed, @@ -391,10 +394,7 @@ impl FileTransfer for ScpFileTransfer { /// /// Indicates whether the client is connected to remote fn is_connected(&self) -> bool { - match self.session.as_ref() { - Some(_) => true, - None => false, - } + self.session.as_ref().is_some() } /// ### pwd @@ -435,7 +435,7 @@ impl FileTransfer for ScpFileTransfer { // Trim let output: String = String::from(output.as_str().trim()); // Check if output starts with 0; should be 0{PWD} - match output.as_str().starts_with("0") { + match output.as_str().starts_with('0') { true => { // Set working directory self.wrkdir = PathBuf::from(&output.as_str()[1..].trim()); @@ -857,7 +857,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_filetransfer_scp_cwd() { let mut client: ScpFileTransfer = ScpFileTransfer::new(); assert!(client diff --git a/src/filetransfer/sftp_transfer.rs b/src/filetransfer/sftp_transfer.rs index 94d3aa0..35611ab 100644 --- a/src/filetransfer/sftp_transfer.rs +++ b/src/filetransfer/sftp_transfer.rs @@ -46,6 +46,12 @@ pub struct SftpFileTransfer { wrkdir: PathBuf, } +impl Default for SftpFileTransfer { + fn default() -> Self { + Self::new() + } +} + impl SftpFileTransfer { /// ### new /// @@ -68,7 +74,7 @@ impl SftpFileTransfer { root.push(p); match self.sftp.as_ref().unwrap().realpath(root.as_path()) { Ok(p) => match self.sftp.as_ref().unwrap().stat(p.as_path()) { - Ok(_) => Ok(PathBuf::from(p)), + Ok(_) => Ok(p), Err(err) => Err(FileTransferError::new_ex( FileTransferErrorType::NoSuchFileOrDirectory, format!("{}", err), @@ -82,7 +88,7 @@ impl SftpFileTransfer { } false => match self.sftp.as_ref().unwrap().realpath(p) { Ok(p) => match self.sftp.as_ref().unwrap().stat(p.as_path()) { - Ok(_) => Ok(PathBuf::from(p)), + Ok(_) => Ok(p), Err(err) => Err(FileTransferError::new_ex( FileTransferErrorType::NoSuchFileOrDirectory, format!("{}", err), @@ -162,7 +168,7 @@ impl SftpFileTransfer { last_access_time: atime, creation_time: SystemTime::UNIX_EPOCH, readonly: false, - symlink: symlink, + symlink, user: uid, group: gid, unix_pex: pex, @@ -176,7 +182,7 @@ impl SftpFileTransfer { last_access_time: atime, creation_time: SystemTime::UNIX_EPOCH, readonly: false, - symlink: symlink, + symlink, user: uid, group: gid, unix_pex: pex, @@ -226,15 +232,15 @@ impl FileTransfer for SftpFileTransfer { )); } let username: String = match username { - Some(u) => u.clone(), + Some(u) => u, None => String::from(""), }; // Try authenticating with user agent - if let Err(_) = session.userauth_agent(username.as_str()) { + if session.userauth_agent(username.as_str()).is_err() { // Try authentication with password then if let Err(err) = session.userauth_password( username.as_str(), - password.unwrap_or(String::from("")).as_str(), + password.unwrap_or_else(|| String::from("")).as_str(), ) { return Err(FileTransferError::new_ex( FileTransferErrorType::AuthenticationFailed, @@ -352,12 +358,10 @@ impl FileTransfer for SftpFileTransfer { }; // Get files match sftp.readdir(dir.as_path()) { - Err(err) => { - return Err(FileTransferError::new_ex( - FileTransferErrorType::DirStatFailed, - format!("{}", err), - )) - } + Err(err) => Err(FileTransferError::new_ex( + FileTransferErrorType::DirStatFailed, + format!("{}", err), + )), Ok(files) => { // Allocate vector let mut entries: Vec = Vec::with_capacity(files.len()); diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 3f0c927..5b20f84 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -24,7 +24,7 @@ */ extern crate bytesize; -#[cfg(any(unix, macos, linux))] +#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] extern crate users; use crate::utils::{fmt_pex, time_to_str}; @@ -32,7 +32,7 @@ use crate::utils::{fmt_pex, time_to_str}; use bytesize::ByteSize; use std::path::PathBuf; use std::time::SystemTime; -#[cfg(any(unix, macos, linux))] +#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use users::get_user_by_uid; /// ## FsEntry @@ -87,7 +87,7 @@ impl std::fmt::Display for FsEntry { /// ### fmt_ls /// /// Format File Entry as `ls` does - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { FsEntry::Directory(dir) => { diff --git a/src/host/mod.rs b/src/host/mod.rs index a04a3d0..03391ca 100644 --- a/src/host/mod.rs +++ b/src/host/mod.rs @@ -27,7 +27,7 @@ use std::fs::{self, File, Metadata, OpenOptions}; use std::path::{Path, PathBuf}; use std::time::SystemTime; // Metadata ext -#[cfg(any(unix, macos, linux))] +#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use std::os::unix::fs::MetadataExt; // Locals @@ -62,7 +62,7 @@ impl HostError { /// Instantiates a new HostError pub(crate) fn new(error: HostErrorType, errno: Option) -> HostError { HostError { - error: error, + error, ioerr: errno, } } @@ -101,7 +101,7 @@ impl Localhost { /// Instantiates a new Localhost struct pub fn new(wrkdir: PathBuf) -> Result { let mut host: Localhost = Localhost { - wrkdir: wrkdir, + wrkdir, files: Vec::new(), }; // Check if dir exists @@ -264,9 +264,9 @@ impl Localhost { /// ### stat /// /// Stat file and create a FsEntry - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] pub fn stat(&self, path: &Path) -> Result { - let attr: Metadata = match fs::metadata(path.clone()) { + let attr: Metadata = match fs::metadata(path) { Ok(metadata) => metadata, Err(err) => return Err(HostError::new(HostErrorType::FileNotAccessible, Some(err))), }; @@ -436,7 +436,7 @@ impl Localhost { /// ### u32_to_mode /// /// Return string with format xxxxxx to tuple of permissions (user, group, others) - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn u32_to_mode(&self, mode: u32) -> (u8, u8, u8) { let user: u8 = ((mode >> 6) & 0x7) as u8; let group: u8 = ((mode >> 3) & 0x7) as u8; @@ -449,12 +449,12 @@ impl Localhost { mod tests { use super::*; - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use std::fs::File; - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use std::io::Write; - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use std::os::unix::fs::{symlink, PermissionsExt}; #[test] @@ -465,7 +465,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_new() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); assert_eq!(host.wrkdir, PathBuf::from("/bin")); @@ -501,14 +501,14 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_pwd() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); assert_eq!(host.pwd(), PathBuf::from("/bin")); } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_list_files() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); // Scan dir @@ -521,7 +521,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_change_dir() { let mut host: Localhost = Localhost::new(PathBuf::from("/dev")).ok().unwrap(); let new_dir: PathBuf = PathBuf::from("/dev"); @@ -537,7 +537,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] #[should_panic] fn test_host_localhost_change_dir_failed() { let mut host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); @@ -546,7 +546,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_open_read() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); // Create temp file @@ -555,7 +555,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] #[should_panic] fn test_host_localhost_open_read_err_no_such_file() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); @@ -565,7 +565,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_open_read_err_not_accessible() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); let file: tempfile::NamedTempFile = create_sample_file(); @@ -576,7 +576,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_open_write() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); // Create temp file @@ -585,7 +585,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_open_write_err() { let host: Localhost = Localhost::new(PathBuf::from("/bin")).ok().unwrap(); let file: tempfile::NamedTempFile = create_sample_file(); @@ -594,7 +594,7 @@ mod tests { //fs::set_permissions(file.path(), perms)?; assert!(host.open_file_write(file.path()).is_err()); } - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] #[test] fn test_host_localhost_symlinks() { let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap(); @@ -643,7 +643,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_mkdir() { let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap(); let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap(); @@ -661,7 +661,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_remove() { let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap(); // Create sample file @@ -683,7 +683,7 @@ mod tests { } #[test] - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn test_host_localhost_rename() { let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap(); // Create sample file @@ -714,7 +714,7 @@ mod tests { /// ### create_sample_file /// /// Create a sample file - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn create_sample_file() -> tempfile::NamedTempFile { // Write let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap(); @@ -726,7 +726,7 @@ mod tests { tmpfile } - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] fn get_filename(entry: &FsEntry) -> String { match entry { FsEntry::Directory(d) => d.name.clone(), diff --git a/src/main.rs b/src/main.rs index 49d7e26..fa0f29c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,12 +19,13 @@ * */ -const TERMSCP_VERSION: &'static str = env!("CARGO_PKG_VERSION"); -const TERMSCP_AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS"); +const TERMSCP_VERSION: &str = env!("CARGO_PKG_VERSION"); +const TERMSCP_AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); // Crates extern crate getopts; -#[macro_use] extern crate lazy_static; +#[macro_use] +extern crate lazy_static; extern crate rpassword; // External libs @@ -50,7 +51,7 @@ use filetransfer::FileTransferProtocol; /// Print usage fn print_usage(opts: Options) { - let brief = format!("Usage: termscp [options]... [protocol://user@address:port]"); + let brief = String::from("Usage: termscp [options]... [protocol://user@address:port]"); print!("{}", opts.usage(&brief)); println!("\nPlease, report issues to "); } @@ -97,7 +98,7 @@ fn main() { } // Match password if let Some(passwd) = matches.opt_str("P") { - password = Some(String::from(passwd)); + password = Some(passwd); } // Match ticks if let Some(val) = matches.opt_str("T") { @@ -111,7 +112,7 @@ fn main() { } } // Check free args - let extra_args: Vec = matches.free.clone(); + let extra_args: Vec = matches.free; if let Some(remote) = extra_args.get(0) { // Parse address match utils::parse_remote_opt(remote) { @@ -141,10 +142,10 @@ fn main() { // Ask password if unspecified password = match rpassword::read_password_from_tty(Some("Password: ")) { Ok(p) => { - if p.len() > 0 { - Some(p) - } else { + if p.is_empty() { None + } else { + Some(p) } } Err(_) => { diff --git a/src/ui/activities/auth_activity.rs b/src/ui/activities/auth_activity.rs index 4e6958b..6ba23f1 100644 --- a/src/ui/activities/auth_activity.rs +++ b/src/ui/activities/auth_activity.rs @@ -85,6 +85,12 @@ pub struct AuthActivity { redraw: bool, // Should ui actually be redrawned? } +impl Default for AuthActivity { + fn default() -> Self { + Self::new() + } +} + impl AuthActivity { /// ### new /// @@ -132,129 +138,125 @@ impl AuthActivity { /// /// Handler for input event when in textmode fn handle_input_event_mode_text(&mut self, ev: &InputEvent) { - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Esc => { - self.quit = true; + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Esc => { + self.quit = true; + } + KeyCode::Enter => { + // Handle submit + // Check form + // Check address + if self.address.is_empty() { + self.popup_message = Some(String::from("Invalid address")); + return; } - KeyCode::Enter => { - // Handle submit - // Check form - // Check address - if self.address.len() == 0 { - self.popup_message = Some(String::from("Invalid address")); - return; - } - // Check port - // Convert port to number - match self.port.parse::() { - Ok(val) => { - if val > 65535 { - self.popup_message = Some(String::from( - "Specified port must be in range 0-65535", - )); - return; - } - } - Err(_) => { + // Check port + // Convert port to number + match self.port.parse::() { + Ok(val) => { + if val > 65535 { self.popup_message = - Some(String::from("Specified port is not a number")); + Some(String::from("Specified port must be in range 0-65535")); return; } } - // Check username - //if self.username.len() == 0 { - // self.popup_message = Some(String::from("Invalid username")); - // return; - //} - // Everything OK, set enter - self.submit = true; - self.popup_message = - Some(format!("Connecting to {}:{}...", self.address, self.port)); + Err(_) => { + self.popup_message = + Some(String::from("Specified port is not a number")); + return; + } } - KeyCode::Backspace => { - // Pop last char - match self.selected_field { - InputField::Address => { - let _ = self.address.pop(); + // Check username + //if self.username.len() == 0 { + // self.popup_message = Some(String::from("Invalid username")); + // return; + //} + // Everything OK, set enter + self.submit = true; + self.popup_message = + Some(format!("Connecting to {}:{}...", self.address, self.port)); + } + KeyCode::Backspace => { + // Pop last char + match self.selected_field { + InputField::Address => { + let _ = self.address.pop(); + } + InputField::Password => { + let _ = self.password.pop(); + } + InputField::Username => { + let _ = self.username.pop(); + } + InputField::Port => { + let _ = self.port.pop(); + } + _ => { /* Nothing to do */ } + }; + } + KeyCode::Up => { + // Move item up + self.selected_field = match self.selected_field { + InputField::Address => InputField::Password, // End of list (wrap) + InputField::Port => InputField::Address, + InputField::Protocol => InputField::Port, + InputField::Username => InputField::Protocol, + InputField::Password => InputField::Username, + } + } + KeyCode::Down | KeyCode::Tab => { + // Move item down + self.selected_field = match self.selected_field { + InputField::Address => InputField::Port, + InputField::Port => InputField::Protocol, + InputField::Protocol => InputField::Username, + InputField::Username => InputField::Password, + InputField::Password => InputField::Address, // End of list (wrap) + } + } + KeyCode::Char(ch) => { + match self.selected_field { + InputField::Address => self.address.push(ch), + InputField::Password => self.password.push(ch), + InputField::Username => self.username.push(ch), + InputField::Port => { + // Value must be numeric + if ch.is_numeric() { + self.port.push(ch); } - InputField::Password => { - let _ = self.password.pop(); - } - InputField::Username => { - let _ = self.username.pop(); - } - InputField::Port => { - let _ = self.port.pop(); - } - _ => { /* Nothing to do */ } + } + _ => { /* Nothing to do */ } + } + } + KeyCode::Left => { + // If current field is Protocol handle event... (move element left) + if self.selected_field == InputField::Protocol { + self.protocol = match self.protocol { + FileTransferProtocol::Sftp => FileTransferProtocol::Ftp(true), // End of list (wrap) + FileTransferProtocol::Scp => FileTransferProtocol::Sftp, + FileTransferProtocol::Ftp(ftps) => match ftps { + false => FileTransferProtocol::Scp, + true => FileTransferProtocol::Ftp(false), + }, }; } - KeyCode::Up => { - // Move item up - self.selected_field = match self.selected_field { - InputField::Address => InputField::Password, // End of list (wrap) - InputField::Port => InputField::Address, - InputField::Protocol => InputField::Port, - InputField::Username => InputField::Protocol, - InputField::Password => InputField::Username, - } - } - KeyCode::Down | KeyCode::Tab => { - // Move item down - self.selected_field = match self.selected_field { - InputField::Address => InputField::Port, - InputField::Port => InputField::Protocol, - InputField::Protocol => InputField::Username, - InputField::Username => InputField::Password, - InputField::Password => InputField::Address, // End of list (wrap) - } - } - KeyCode::Char(ch) => { - match self.selected_field { - InputField::Address => self.address.push(ch), - InputField::Password => self.password.push(ch), - InputField::Username => self.username.push(ch), - InputField::Port => { - // Value must be numeric - if ch.is_numeric() { - self.port.push(ch); - } - } - _ => { /* Nothing to do */ } - } - } - KeyCode::Left => { - // If current field is Protocol handle event... (move element left) - if self.selected_field == InputField::Protocol { - self.protocol = match self.protocol { - FileTransferProtocol::Sftp => FileTransferProtocol::Ftp(true), // End of list (wrap) - FileTransferProtocol::Scp => FileTransferProtocol::Sftp, - FileTransferProtocol::Ftp(ftps) => match ftps { - false => FileTransferProtocol::Scp, - true => FileTransferProtocol::Ftp(false), - }, - }; - } - } - KeyCode::Right => { - // If current field is Protocol handle event... ( move element right ) - if self.selected_field == InputField::Protocol { - self.protocol = match self.protocol { - FileTransferProtocol::Sftp => FileTransferProtocol::Scp, - FileTransferProtocol::Scp => FileTransferProtocol::Ftp(false), - FileTransferProtocol::Ftp(ftps) => match ftps { - false => FileTransferProtocol::Ftp(true), - true => FileTransferProtocol::Sftp, // End of list (wrap) - }, - }; - } - } - _ => { /* Nothing to do */ } } + KeyCode::Right => { + // If current field is Protocol handle event... ( move element right ) + if self.selected_field == InputField::Protocol { + self.protocol = match self.protocol { + FileTransferProtocol::Sftp => FileTransferProtocol::Scp, + FileTransferProtocol::Scp => FileTransferProtocol::Ftp(false), + FileTransferProtocol::Ftp(ftps) => match ftps { + false => FileTransferProtocol::Ftp(true), + true => FileTransferProtocol::Sftp, // End of list (wrap) + }, + }; + } + } + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -263,16 +265,10 @@ impl AuthActivity { /// Handler for input event when in popup mode fn handle_input_event_mode_popup(&mut self, ev: &InputEvent) { // Only enter should be allowed here - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter => { - self.popup_message = None; // Hide popup - } - _ => { /* Nothing to do */ } - } + if let InputEvent::Key(key) = ev { + if let KeyCode::Enter = key.code { + self.popup_message = None; // Hide popup } - _ => { /* Nothing to do */ } } } @@ -452,7 +448,7 @@ impl Activity for AuthActivity { } // Start catching Input Events if let Ok(input_events) = self.context.as_ref().unwrap().input_hnd.fetch_events() { - if input_events.len() > 0 { + if !input_events.is_empty() { self.redraw = true; // Set redraw to true if there is at least one event } // Iterate over input events @@ -533,9 +529,7 @@ impl Activity for AuthActivity { fn on_destroy(&mut self) -> Option { // Disable raw mode let _ = disable_raw_mode(); - if self.context.is_none() { - return None; - } + self.context.as_ref()?; // Clear terminal and return match self.context.take() { Some(mut ctx) => { diff --git a/src/ui/activities/filetransfer_activity/input.rs b/src/ui/activities/filetransfer_activity/input.rs index 8ff7394..e574ebe 100644 --- a/src/ui/activities/filetransfer_activity/input.rs +++ b/src/ui/activities/filetransfer_activity/input.rs @@ -69,204 +69,199 @@ impl FileTransferActivity { /// Input event handler for explorer mode when localhost tab is selected pub(super) fn handle_input_event_mode_explorer_tab_local(&mut self, ev: &InputEvent) { // Match events - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Esc => { - // Handle quit event - // Create quit prompt dialog - self.input_mode = self.create_disconnect_popup(); + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Esc => { + // Handle quit event + // Create quit prompt dialog + self.input_mode = self.create_disconnect_popup(); + } + KeyCode::Tab => self.switch_input_field(), // switch tab + KeyCode::Right => self.tab = FileExplorerTab::Remote, // switch to right tab + KeyCode::Up => { + // Move index up + if self.local.index > 0 { + self.local.index -= 1; } - KeyCode::Tab => self.switch_input_field(), // switch tab - KeyCode::Right => self.tab = FileExplorerTab::Remote, // switch to right tab - KeyCode::Up => { - // Move index up - if self.local.index > 0 { - self.local.index -= 1; - } + } + KeyCode::Down => { + // Move index down + if self.local.index + 1 < self.local.files.len() { + self.local.index += 1; } - KeyCode::Down => { - // Move index down - if self.local.index + 1 < self.local.files.len() { - self.local.index += 1; - } + } + KeyCode::PageUp => { + // Move index up (fast) + if self.local.index > 8 { + self.local.index -= 8; // Decrease by `8` if possible + } else { + self.local.index = 0; // Set to 0 otherwise } - KeyCode::PageUp => { - // Move index up (fast) - if self.local.index > 8 { - self.local.index = self.local.index - 8; // Decrease by `8` if possible - } else { - self.local.index = 0; // Set to 0 otherwise - } + } + KeyCode::PageDown => { + // Move index down (fast) + if self.local.index + 8 >= self.local.files.len() { + // If overflows, set to size + self.local.index = self.local.files.len() - 1; + } else { + self.local.index += 8; // Increase by `8` } - KeyCode::PageDown => { - // Move index down (fast) - if self.local.index + 8 >= self.local.files.len() { - // If overflows, set to size - self.local.index = self.local.files.len() - 1; - } else { - self.local.index = self.local.index + 8; // Increase by `8` - } - } - KeyCode::Enter => { - // Match selected file - let local_files: Vec = self.local.files.clone(); - if let Some(entry) = local_files.get(self.local.index) { - // If directory, enter directory, otherwise check if symlink - match entry { - FsEntry::Directory(dir) => { - self.local_changedir(dir.abs_path.as_path(), true) - } - FsEntry::File(file) => { - // Check if symlink - if let Some(realpath) = &file.symlink { - // Stat realpath - match self - .context - .as_ref() - .unwrap() - .local - .stat(realpath.as_path()) - { - Ok(real_file) => { - // If real file is a directory, enter directory - if let FsEntry::Directory(real_dir) = real_file { - self.local_changedir( - real_dir.abs_path.as_path(), - true, - ) - } - } - Err(err) => { - self.log( - LogLevel::Error, - format!( - "Failed to stat file \"{}\": {}", - realpath.display(), - err - ) - .as_ref(), - ); - self.input_mode = - InputMode::Popup(PopupType::Alert( - Color::Red, - format!( - "Failed to stat file \"{}\": {}", - realpath.display(), - err - ), - )); + } + KeyCode::Enter => { + // Match selected file + let local_files: Vec = self.local.files.clone(); + if let Some(entry) = local_files.get(self.local.index) { + // If directory, enter directory, otherwise check if symlink + match entry { + FsEntry::Directory(dir) => { + self.local_changedir(dir.abs_path.as_path(), true) + } + FsEntry::File(file) => { + // Check if symlink + if let Some(realpath) = &file.symlink { + // Stat realpath + match self + .context + .as_ref() + .unwrap() + .local + .stat(realpath.as_path()) + { + Ok(real_file) => { + // If real file is a directory, enter directory + if let FsEntry::Directory(real_dir) = real_file { + self.local_changedir( + real_dir.abs_path.as_path(), + true, + ) } } + Err(err) => { + self.log( + LogLevel::Error, + format!( + "Failed to stat file \"{}\": {}", + realpath.display(), + err + ) + .as_ref(), + ); + self.input_mode = InputMode::Popup(PopupType::Alert( + Color::Red, + format!( + "Failed to stat file \"{}\": {}", + realpath.display(), + err + ), + )); + } } } } } } - KeyCode::Backspace => { - // Go to previous directory - if let Some(d) = self.local.popd() { - self.local_changedir(d.as_path(), false); - } - } - KeyCode::Delete => { - // Get file at index - if let Some(entry) = self.local.files.get(self.local.index) { - // Get file name - let file_name: String = match entry { - FsEntry::Directory(dir) => dir.name.clone(), - FsEntry::File(file) => file.name.clone(), - }; - // Show delete prompt - self.input_mode = InputMode::Popup(PopupType::YesNo( - format!("Delete file \"{}\"", file_name), - FileTransferActivity::callback_delete_fsentry, - FileTransferActivity::callback_nothing_to_do, - )) - } - } - KeyCode::Char(ch) => match ch { - 'q' | 'Q' => { - // Create quit prompt dialog - self.input_mode = self.create_quit_popup(); - } - 'g' | 'G' => { - // Goto - // Show input popup - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Change working directory"), - FileTransferActivity::callback_change_directory, - )); - } - 'd' | 'D' => { - // Make directory - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Insert directory name"), - FileTransferActivity::callback_mkdir, - )); - } - 'h' | 'H' => { - // Show help - self.input_mode = InputMode::Popup(PopupType::Help); - } - 'i' | 'I' => { - // Show file info - self.input_mode = InputMode::Popup(PopupType::FileInfo); - } - 'r' | 'R' => { - // Rename - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Insert new name"), - FileTransferActivity::callback_rename, - )); - } - 's' | 'S' => { - // Save as... - // Ask for input - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Save as..."), - FileTransferActivity::callback_save_as, - )); - } - 'u' | 'U' => { - // Go to parent directory - // Get pwd - let path: PathBuf = self.context.as_ref().unwrap().local.pwd(); - if let Some(parent) = path.as_path().parent() { - self.local_changedir(parent, true); - } - } - ' ' => { - // Get pwd - let wrkdir: PathBuf = match self.client.pwd() { - Ok(p) => p, - Err(err) => { - self.log( - LogLevel::Error, - format!("Could not get current remote path: {}", err) - .as_ref(), - ); - self.input_mode = InputMode::Popup(PopupType::Alert( - Color::Red, - format!("Could not get current remote path: {}", err), - )); - return; - } - }; - // Get files - let files: Vec = self.local.files.clone(); // Otherwise self is borrowed both as mutable and immutable... - // Get file at index - if let Some(entry) = files.get(self.local.index) { - // Call upload - self.filetransfer_send(entry, wrkdir.as_path(), None); - } - } - _ => { /* Nothing to do */ } - }, - _ => { /* Nothing to do */ } } + KeyCode::Backspace => { + // Go to previous directory + if let Some(d) = self.local.popd() { + self.local_changedir(d.as_path(), false); + } + } + KeyCode::Delete => { + // Get file at index + if let Some(entry) = self.local.files.get(self.local.index) { + // Get file name + let file_name: String = match entry { + FsEntry::Directory(dir) => dir.name.clone(), + FsEntry::File(file) => file.name.clone(), + }; + // Show delete prompt + self.input_mode = InputMode::Popup(PopupType::YesNo( + format!("Delete file \"{}\"", file_name), + FileTransferActivity::callback_delete_fsentry, + FileTransferActivity::callback_nothing_to_do, + )) + } + } + KeyCode::Char(ch) => match ch { + 'q' | 'Q' => { + // Create quit prompt dialog + self.input_mode = self.create_quit_popup(); + } + 'g' | 'G' => { + // Goto + // Show input popup + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Change working directory"), + FileTransferActivity::callback_change_directory, + )); + } + 'd' | 'D' => { + // Make directory + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Insert directory name"), + FileTransferActivity::callback_mkdir, + )); + } + 'h' | 'H' => { + // Show help + self.input_mode = InputMode::Popup(PopupType::Help); + } + 'i' | 'I' => { + // Show file info + self.input_mode = InputMode::Popup(PopupType::FileInfo); + } + 'r' | 'R' => { + // Rename + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Insert new name"), + FileTransferActivity::callback_rename, + )); + } + 's' | 'S' => { + // Save as... + // Ask for input + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Save as..."), + FileTransferActivity::callback_save_as, + )); + } + 'u' | 'U' => { + // Go to parent directory + // Get pwd + let path: PathBuf = self.context.as_ref().unwrap().local.pwd(); + if let Some(parent) = path.as_path().parent() { + self.local_changedir(parent, true); + } + } + ' ' => { + // Get pwd + let wrkdir: PathBuf = match self.client.pwd() { + Ok(p) => p, + Err(err) => { + self.log( + LogLevel::Error, + format!("Could not get current remote path: {}", err).as_ref(), + ); + self.input_mode = InputMode::Popup(PopupType::Alert( + Color::Red, + format!("Could not get current remote path: {}", err), + )); + return; + } + }; + // Get files + let files: Vec = self.local.files.clone(); // Otherwise self is borrowed both as mutable and immutable... + // Get file at index + if let Some(entry) = files.get(self.local.index) { + // Call upload + self.filetransfer_send(entry, wrkdir.as_path(), None); + } + } + _ => { /* Nothing to do */ } + }, + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -275,195 +270,191 @@ impl FileTransferActivity { /// Input event handler for explorer mode when remote tab is selected pub(super) fn handle_input_event_mode_explorer_tab_remote(&mut self, ev: &InputEvent) { // Match events - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Esc => { - // Handle quit event - // Create quit prompt dialog - self.input_mode = self.create_disconnect_popup(); + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Esc => { + // Handle quit event + // Create quit prompt dialog + self.input_mode = self.create_disconnect_popup(); + } + KeyCode::Tab => self.switch_input_field(), // switch tab + KeyCode::Left => self.tab = FileExplorerTab::Local, // switch to local tab + KeyCode::Up => { + // Move index up + if self.remote.index > 0 { + self.remote.index -= 1; } - KeyCode::Tab => self.switch_input_field(), // switch tab - KeyCode::Left => self.tab = FileExplorerTab::Local, // switch to local tab - KeyCode::Up => { - // Move index up - if self.remote.index > 0 { - self.remote.index -= 1; - } + } + KeyCode::Down => { + // Move index down + if self.remote.index + 1 < self.remote.files.len() { + self.remote.index += 1; } - KeyCode::Down => { - // Move index down - if self.remote.index + 1 < self.remote.files.len() { - self.remote.index += 1; - } + } + KeyCode::PageUp => { + // Move index up (fast) + if self.remote.index > 8 { + self.remote.index -= 8; // Decrease by `8` if possible + } else { + self.remote.index = 0; // Set to 0 otherwise } - KeyCode::PageUp => { - // Move index up (fast) - if self.remote.index > 8 { - self.remote.index = self.remote.index - 8; // Decrease by `8` if possible - } else { - self.remote.index = 0; // Set to 0 otherwise - } + } + KeyCode::PageDown => { + // Move index down (fast) + if self.remote.index + 8 >= self.remote.files.len() { + // If overflows, set to size + self.remote.index = self.remote.files.len() - 1; + } else { + self.remote.index += 8; // Increase by `8` } - KeyCode::PageDown => { - // Move index down (fast) - if self.remote.index + 8 >= self.remote.files.len() { - // If overflows, set to size - self.remote.index = self.remote.files.len() - 1; - } else { - self.remote.index = self.remote.index + 8; // Increase by `8` - } - } - KeyCode::Enter => { - // Match selected file - let files: Vec = self.remote.files.clone(); - if let Some(entry) = files.get(self.remote.index) { - // If directory, enter directory; if file, check if is symlink - match entry { - FsEntry::Directory(dir) => { - self.remote_changedir(dir.abs_path.as_path(), true) - } - FsEntry::File(file) => { - // Check if symlink - if let Some(realpath) = &file.symlink { - // Stat realpath - match self.client.stat(realpath.as_path()) { - Ok(real_file) => { - // If real file is a directory, enter directory - if let FsEntry::Directory(real_dir) = real_file { - self.remote_changedir( - real_dir.abs_path.as_path(), - true, - ) - } - } - Err(err) => { - self.log( - LogLevel::Error, - format!( - "Failed to stat file \"{}\": {}", - realpath.display(), - err - ) - .as_ref(), - ); - self.input_mode = - InputMode::Popup(PopupType::Alert( - Color::Red, - format!( - "Failed to stat file \"{}\": {}", - realpath.display(), - err - ), - )); + } + KeyCode::Enter => { + // Match selected file + let files: Vec = self.remote.files.clone(); + if let Some(entry) = files.get(self.remote.index) { + // If directory, enter directory; if file, check if is symlink + match entry { + FsEntry::Directory(dir) => { + self.remote_changedir(dir.abs_path.as_path(), true) + } + FsEntry::File(file) => { + // Check if symlink + if let Some(realpath) = &file.symlink { + // Stat realpath + match self.client.stat(realpath.as_path()) { + Ok(real_file) => { + // If real file is a directory, enter directory + if let FsEntry::Directory(real_dir) = real_file { + self.remote_changedir( + real_dir.abs_path.as_path(), + true, + ) } } + Err(err) => { + self.log( + LogLevel::Error, + format!( + "Failed to stat file \"{}\": {}", + realpath.display(), + err + ) + .as_ref(), + ); + self.input_mode = InputMode::Popup(PopupType::Alert( + Color::Red, + format!( + "Failed to stat file \"{}\": {}", + realpath.display(), + err + ), + )); + } } } } } } - KeyCode::Backspace => { - // Go to previous directory - if let Some(d) = self.remote.popd() { - self.remote_changedir(d.as_path(), false); - } - } - KeyCode::Delete => { - // Get file at index - if let Some(entry) = self.remote.files.get(self.remote.index) { - // Get file name - let file_name: String = match entry { - FsEntry::Directory(dir) => dir.name.clone(), - FsEntry::File(file) => file.name.clone(), - }; - // Show delete prompt - self.input_mode = InputMode::Popup(PopupType::YesNo( - format!("Delete file \"{}\"", file_name), - FileTransferActivity::callback_delete_fsentry, - FileTransferActivity::callback_nothing_to_do, - )) - } - } - KeyCode::Char(ch) => match ch { - 'q' | 'Q' => { - // Create quit prompt dialog - self.input_mode = self.create_quit_popup(); - } - 'g' | 'G' => { - // Goto - // Show input popup - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Change working directory"), - FileTransferActivity::callback_change_directory, - )); - } - 'd' | 'D' => { - // Make directory - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Insert directory name"), - FileTransferActivity::callback_mkdir, - )); - } - 'h' | 'H' => { - // Show help - self.input_mode = InputMode::Popup(PopupType::Help); - } - 'i' | 'I' => { - // Show file info - self.input_mode = InputMode::Popup(PopupType::FileInfo); - } - 'r' | 'R' => { - // Rename - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Insert new name"), - FileTransferActivity::callback_rename, - )); - } - 's' | 'S' => { - // Save as... - // Ask for input - self.input_mode = InputMode::Popup(PopupType::Input( - String::from("Save as..."), - FileTransferActivity::callback_save_as, - )); - } - 'u' | 'U' => { - // Go to parent directory - // Get pwd - match self.client.pwd() { - Ok(path) => { - if let Some(parent) = path.as_path().parent() { - self.remote_changedir(parent, true); - } - } - Err(err) => { - self.input_mode = InputMode::Popup(PopupType::Alert( - Color::Red, - format!("Could not change working directory: {}", err), - )) - } - } - } - ' ' => { - // Get files - let files: Vec = self.remote.files.clone(); // Otherwise self is borrowed both as mutable and immutable... - // Get file at index - if let Some(entry) = files.get(self.remote.index) { - // Call upload - self.filetransfer_recv( - entry, - self.context.as_ref().unwrap().local.pwd().as_path(), - None, - ); - } - } - _ => { /* Nothing to do */ } - }, - _ => { /* Nothing to do */ } } + KeyCode::Backspace => { + // Go to previous directory + if let Some(d) = self.remote.popd() { + self.remote_changedir(d.as_path(), false); + } + } + KeyCode::Delete => { + // Get file at index + if let Some(entry) = self.remote.files.get(self.remote.index) { + // Get file name + let file_name: String = match entry { + FsEntry::Directory(dir) => dir.name.clone(), + FsEntry::File(file) => file.name.clone(), + }; + // Show delete prompt + self.input_mode = InputMode::Popup(PopupType::YesNo( + format!("Delete file \"{}\"", file_name), + FileTransferActivity::callback_delete_fsentry, + FileTransferActivity::callback_nothing_to_do, + )) + } + } + KeyCode::Char(ch) => match ch { + 'q' | 'Q' => { + // Create quit prompt dialog + self.input_mode = self.create_quit_popup(); + } + 'g' | 'G' => { + // Goto + // Show input popup + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Change working directory"), + FileTransferActivity::callback_change_directory, + )); + } + 'd' | 'D' => { + // Make directory + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Insert directory name"), + FileTransferActivity::callback_mkdir, + )); + } + 'h' | 'H' => { + // Show help + self.input_mode = InputMode::Popup(PopupType::Help); + } + 'i' | 'I' => { + // Show file info + self.input_mode = InputMode::Popup(PopupType::FileInfo); + } + 'r' | 'R' => { + // Rename + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Insert new name"), + FileTransferActivity::callback_rename, + )); + } + 's' | 'S' => { + // Save as... + // Ask for input + self.input_mode = InputMode::Popup(PopupType::Input( + String::from("Save as..."), + FileTransferActivity::callback_save_as, + )); + } + 'u' | 'U' => { + // Go to parent directory + // Get pwd + match self.client.pwd() { + Ok(path) => { + if let Some(parent) = path.as_path().parent() { + self.remote_changedir(parent, true); + } + } + Err(err) => { + self.input_mode = InputMode::Popup(PopupType::Alert( + Color::Red, + format!("Could not change working directory: {}", err), + )) + } + } + } + ' ' => { + // Get files + let files: Vec = self.remote.files.clone(); // Otherwise self is borrowed both as mutable and immutable... + // Get file at index + if let Some(entry) = files.get(self.remote.index) { + // Call upload + self.filetransfer_recv( + entry, + self.context.as_ref().unwrap().local.pwd().as_path(), + None, + ); + } + } + _ => { /* Nothing to do */ } + }, + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -473,59 +464,56 @@ impl FileTransferActivity { pub(super) fn handle_input_event_mode_explorer_log(&mut self, ev: &InputEvent) { // Match event let records_block: usize = 16; - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Esc => { - // Handle quit event - // Create quit prompt dialog - self.input_mode = self.create_disconnect_popup(); - } - KeyCode::Tab => self.switch_input_field(), // switch tab - KeyCode::Down => { - // NOTE: Twisted logic - // Decrease log index - if self.log_index > 0 { - self.log_index = self.log_index - 1; - } - } - KeyCode::Up => { - // NOTE: Twisted logic - // Increase log index - if self.log_index + 1 < self.log_records.len() { - self.log_index = self.log_index + 1; - } - } - KeyCode::PageDown => { - // NOTE: Twisted logic - // Fast decreasing of log index - if self.log_index >= records_block { - self.log_index = self.log_index - records_block; // Decrease by `records_block` if possible - } else { - self.log_index = 0; // Set to 0 otherwise - } - } - KeyCode::PageUp => { - // NOTE: Twisted logic - // Fast increasing of log index - if self.log_index + records_block >= self.log_records.len() { - // If overflows, set to size - self.log_index = self.log_records.len() - 1; - } else { - self.log_index = self.log_index + records_block; // Increase by `records_block` - } - } - KeyCode::Char(ch) => match ch { - 'q' | 'Q' => { - // Create quit prompt dialog - self.input_mode = self.create_quit_popup(); - } - _ => { /* Nothing to do */ } - }, - _ => { /* Nothing to do */ } + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Esc => { + // Handle quit event + // Create quit prompt dialog + self.input_mode = self.create_disconnect_popup(); } + KeyCode::Tab => self.switch_input_field(), // switch tab + KeyCode::Down => { + // NOTE: Twisted logic + // Decrease log index + if self.log_index > 0 { + self.log_index -= 1; + } + } + KeyCode::Up => { + // NOTE: Twisted logic + // Increase log index + if self.log_index + 1 < self.log_records.len() { + self.log_index += 1; + } + } + KeyCode::PageDown => { + // NOTE: Twisted logic + // Fast decreasing of log index + if self.log_index >= records_block { + self.log_index -= records_block; // Decrease by `records_block` if possible + } else { + self.log_index = 0; // Set to 0 otherwise + } + } + KeyCode::PageUp => { + // NOTE: Twisted logic + // Fast increasing of log index + if self.log_index + records_block >= self.log_records.len() { + // If overflows, set to size + self.log_index = self.log_records.len() - 1; + } else { + self.log_index += records_block; // Increase by `records_block` + } + } + KeyCode::Char(ch) => match ch { + 'q' | 'Q' => { + // Create quit prompt dialog + self.input_mode = self.create_quit_popup(); + } + _ => { /* Nothing to do */ } + }, + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -552,17 +540,11 @@ impl FileTransferActivity { /// Input event handler for popup alert pub(super) fn handle_input_event_mode_popup_alert(&mut self, ev: &InputEvent) { // If enter, close popup - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter => { - // Set input mode back to explorer - self.input_mode = InputMode::Explorer; - } - _ => { /* Nothing to do */ } - } + if let InputEvent::Key(key) = ev { + if let KeyCode::Enter = key.code { + // Set input mode back to explorer + self.input_mode = InputMode::Explorer; } - _ => { /* Nothing to do */ } } } @@ -571,17 +553,14 @@ impl FileTransferActivity { /// Input event handler for popup fileinfo pub(super) fn handle_input_event_mode_popup_fileinfo(&mut self, ev: &InputEvent) { // If enter, close popup - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter | KeyCode::Esc => { - // Set input mode back to explorer - self.input_mode = InputMode::Explorer; - } - _ => { /* Nothing to do */ } + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Enter | KeyCode::Esc => { + // Set input mode back to explorer + self.input_mode = InputMode::Explorer; } + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -590,17 +569,14 @@ impl FileTransferActivity { /// Input event handler for popup help pub(super) fn handle_input_event_mode_popup_help(&mut self, ev: &InputEvent) { // If enter, close popup - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter | KeyCode::Esc => { - // Set input mode back to explorer - self.input_mode = InputMode::Explorer; - } - _ => { /* Nothing to do */ } + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Enter | KeyCode::Esc => { + // Set input mode back to explorer + self.input_mode = InputMode::Explorer; } + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } @@ -609,17 +585,11 @@ impl FileTransferActivity { /// Input event handler for popup alert pub(super) fn handle_input_event_mode_popup_fatal(&mut self, ev: &InputEvent) { // If enter, close popup - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter => { - // Set quit to true; since a fatal error happened - self.disconnect(); - } - _ => { /* Nothing to do */ } - } + if let InputEvent::Key(key) = ev { + if let KeyCode::Enter = key.code { + // Set quit to true; since a fatal error happened + self.disconnect(); } - _ => { /* Nothing to do */ } } } @@ -632,55 +602,46 @@ impl FileTransferActivity { cb: OnInputSubmitCallback, ) { // If enter, close popup, otherwise push chars to input - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Esc => { - // Abort input - // Clear current input text - self.input_txt.clear(); - // Set mode back to explorer - self.input_mode = InputMode::Explorer; - } - KeyCode::Enter => { - // Submit - let input_text: String = self.input_txt.clone(); - // Clear current input text - self.input_txt.clear(); - // Set mode back to explorer BEFORE CALLBACKS!!! Callback can then overwrite this, clever uh? - self.input_mode = InputMode::Explorer; - // Call cb - cb(self, input_text); - } - KeyCode::Char(ch) => self.input_txt.push(ch), - KeyCode::Backspace => { - let _ = self.input_txt.pop(); - } - _ => { /* Nothing to do */ } + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Esc => { + // Abort input + // Clear current input text + self.input_txt.clear(); + // Set mode back to explorer + self.input_mode = InputMode::Explorer; } + KeyCode::Enter => { + // Submit + let input_text: String = self.input_txt.clone(); + // Clear current input text + self.input_txt.clear(); + // Set mode back to explorer BEFORE CALLBACKS!!! Callback can then overwrite this, clever uh? + self.input_mode = InputMode::Explorer; + // Call cb + cb(self, input_text); + } + KeyCode::Char(ch) => self.input_txt.push(ch), + KeyCode::Backspace => { + let _ = self.input_txt.pop(); + } + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } /// ### handle_input_event_mode_explorer_alert /// /// Input event handler for popup alert - pub(super) fn handle_input_event_mode_popup_progress(&mut self, ev: &InputEvent) { + pub(super) fn handle_input_event_mode_popup_progress(&mut self, _ev: &InputEvent) { // There's nothing you can do here I guess... maybe ctrl+c in the future idk - match ev { - _ => { /* Nothing to do */ } - } } /// ### handle_input_event_mode_explorer_alert /// /// Input event handler for popup alert - pub(super) fn handle_input_event_mode_popup_wait(&mut self, ev: &InputEvent) { + pub(super) fn handle_input_event_mode_popup_wait(&mut self, _ev: &InputEvent) { // There's nothing you can do here I guess... maybe ctrl+c in the future idk - match ev { - _ => { /* Nothing to do */ } - } } /// ### handle_input_event_mode_explorer_alert @@ -693,26 +654,23 @@ impl FileTransferActivity { no_cb: DialogCallback, ) { // If enter, close popup, otherwise move dialog option - match ev { - InputEvent::Key(key) => { - match key.code { - KeyCode::Enter => { - // @! Set input mode to Explorer BEFORE CALLBACKS!!! Callback can then overwrite this, clever uh? - self.input_mode = InputMode::Explorer; - // Check if user selected yes or not - match self.choice_opt { - DialogYesNoOption::No => no_cb(self), - DialogYesNoOption::Yes => yes_cb(self), - } - // Reset choice option to yes - self.choice_opt = DialogYesNoOption::Yes; + if let InputEvent::Key(key) = ev { + match key.code { + KeyCode::Enter => { + // @! Set input mode to Explorer BEFORE CALLBACKS!!! Callback can then overwrite this, clever uh? + self.input_mode = InputMode::Explorer; + // Check if user selected yes or not + match self.choice_opt { + DialogYesNoOption::No => no_cb(self), + DialogYesNoOption::Yes => yes_cb(self), } - KeyCode::Right => self.choice_opt = DialogYesNoOption::No, // Set to NO - KeyCode::Left => self.choice_opt = DialogYesNoOption::Yes, // Set to YES - _ => { /* Nothing to do */ } + // Reset choice option to yes + self.choice_opt = DialogYesNoOption::Yes; } + KeyCode::Right => self.choice_opt = DialogYesNoOption::No, // Set to NO + KeyCode::Left => self.choice_opt = DialogYesNoOption::Yes, // Set to YES + _ => { /* Nothing to do */ } } - _ => { /* Nothing to do */ } } } } diff --git a/src/ui/activities/filetransfer_activity/layout.rs b/src/ui/activities/filetransfer_activity/layout.rs index 343905b..84b4594 100644 --- a/src/ui/activities/filetransfer_activity/layout.rs +++ b/src/ui/activities/filetransfer_activity/layout.rs @@ -21,7 +21,7 @@ extern crate bytesize; extern crate hostname; -#[cfg(any(unix, macos, linux))] +#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] extern crate users; use super::{ @@ -39,7 +39,7 @@ use tui::{ widgets::{Block, Borders, Clear, Gauge, List, ListItem, ListState, Paragraph, Tabs}, }; use unicode_width::UnicodeWidthStr; -#[cfg(any(unix, macos, linux))] +#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] use users::{get_group_by_gid, get_user_by_uid}; impl FileTransferActivity { @@ -115,7 +115,7 @@ impl FileTransferActivity { f.render_widget(Clear, popup_area); //this clears out the background match popup { PopupType::Alert(color, txt) => f.render_widget( - self.draw_popup_alert(color.clone(), txt.clone(), popup_area.width), + self.draw_popup_alert(*color, txt.clone(), popup_area.width), popup_area, ), PopupType::Fatal(txt) => f.render_widget( @@ -511,7 +511,7 @@ impl FileTransferActivity { ), ]))); // User - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] let username: String = match dir.user { Some(uid) => match get_user_by_uid(uid) { Some(user) => user.name().to_string_lossy().to_string(), @@ -531,7 +531,7 @@ impl FileTransferActivity { ), ]))); // Group - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] let group: String = match dir.group { Some(gid) => match get_group_by_gid(gid) { Some(group) => group.name().to_string_lossy().to_string(), @@ -608,7 +608,7 @@ impl FileTransferActivity { ), ]))); // User - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] let username: String = match file.user { Some(uid) => match get_user_by_uid(uid) { Some(user) => user.name().to_string_lossy().to_string(), @@ -628,7 +628,7 @@ impl FileTransferActivity { ), ]))); // Group - #[cfg(any(unix, macos, linux))] + #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] let group: String = match file.group { Some(gid) => match get_group_by_gid(gid) { Some(group) => group.name().to_string_lossy().to_string(), diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs index 772c3aa..37f10c7 100644 --- a/src/ui/activities/filetransfer_activity/mod.rs +++ b/src/ui/activities/filetransfer_activity/mod.rs @@ -199,7 +199,7 @@ impl LogRecord { pub fn new(level: LogLevel, msg: &str) -> LogRecord { LogRecord { time: Local::now(), - level: level, + level, msg: String::from(msg), } } @@ -243,7 +243,7 @@ impl FileTransferActivity { FileTransferProtocol::Ftp(ftps) => Box::new(FtpFileTransfer::new(ftps)), FileTransferProtocol::Scp => Box::new(ScpFileTransfer::new()), }, - params: params, + params, local: FileExplorer::new(), remote: FileExplorer::new(), tab: FileExplorerTab::Local, @@ -292,10 +292,7 @@ impl Activity for FileTransferActivity { if self.context.is_none() { return; } - let is_explorer_mode: bool = match self.input_mode { - InputMode::Explorer => true, - _ => false, - }; + let is_explorer_mode: bool = matches!(self.input_mode, InputMode::Explorer); // Check if connected if !self.client.is_connected() && is_explorer_mode { // Set init state to connecting popup diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs index 545cb86..a048d1b 100644 --- a/src/ui/activities/filetransfer_activity/session.rs +++ b/src/ui/activities/filetransfer_activity/session.rs @@ -385,7 +385,7 @@ impl FileTransferActivity { // Get local file let mut local_file_path: PathBuf = PathBuf::from(local_path); let local_file_name: String = match dst_name { - Some(n) => n.clone(), + Some(n) => n, None => file.name.clone(), }; local_file_path.push(local_file_name.as_str()); diff --git a/src/ui/context.rs b/src/ui/context.rs index 907b46f..75b38b7 100644 --- a/src/ui/context.rs +++ b/src/ui/context.rs @@ -57,7 +57,7 @@ impl Context { let mut stdout = stdout(); assert!(execute!(stdout, EnterAlternateScreen).is_ok()); Context { - local: local, + local, input_hnd: InputHandler::new(), terminal: Terminal::new(CrosstermBackend::new(stdout)).unwrap() } @@ -72,7 +72,6 @@ impl Drop for Context { LeaveAlternateScreen, DisableMouseCapture ); - drop(self); } } @@ -107,4 +106,4 @@ mod tests { Box::new(sftp_client) } } -*/ \ No newline at end of file +*/ diff --git a/src/utils.rs b/src/utils.rs index b3e17fb..24e6c6b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -53,9 +53,9 @@ use std::time::{Duration, SystemTime}; /// - ... /// pub fn parse_remote_opt( - remote: &String, + remote: &str, ) -> Result<(String, u16, FileTransferProtocol, Option), String> { - let mut wrkstr: String = remote.clone(); + let mut wrkstr: String = remote.to_string(); let address: String; let mut port: u16 = 22; let mut protocol: FileTransferProtocol = FileTransferProtocol::Sftp; @@ -104,7 +104,7 @@ pub fn parse_remote_opt( username = Some(whoami::username()); } // Split wrkstring by '@' - let tokens: Vec<&str> = wrkstr.split("@").collect(); + let tokens: Vec<&str> = wrkstr.split('@').collect(); match tokens.len() { 1 => {} 2 => { @@ -116,7 +116,7 @@ pub fn parse_remote_opt( _ => return Err(String::from("Bad syntax")), // Too many tokens... } // Split wrkstring by ':' - let tokens: Vec<&str> = wrkstr.split(":").collect(); + let tokens: Vec<&str> = wrkstr.split(':').collect(); match tokens.len() { 1 => { // Address is wrkstr