Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed some bugs + refectoring + tests added #73

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ object = "0.35.0"
pathdiff = "0.2.1"
pdb = "0.8.0"
ratatui = { version = "0.26.3", features = ["serde"] }
regex = "1.10.4"
russh = "0.43.0"
russh-keys = "0.43.0"
russh-sftp = "2.0.0"
Expand Down
14 changes: 7 additions & 7 deletions src/app/files/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ratatui::{backend::Backend, Terminal};

use crate::{app::{info_mode::InfoMode, notification::NotificationLevel, popup_state::PopupState, App}, headers::Header};

use super::{filesystem::FileSystem, path_result::PathResult, str_path::{path_diff, path_filename, path_is_absolute, path_join, path_parent}};
use super::{filesystem::FileSystem, path_result::PathResult, path};

impl App
{
Expand Down Expand Up @@ -47,24 +47,24 @@ impl App
}
else
{
path_parent(current_path).expect("A file should have a parent directory.").to_owned()
path::parent(current_path).expect("A file should have a parent directory.").to_owned()
}
}

pub(in crate::app) fn find_dir_contents(currently_open_path: &str, path: &str, filesystem: &FileSystem) -> Result<Vec<PathResult>, Box<dyn Error>>
{
let mut ret = Vec::new();
let (selected_dir, file_name) = if path_is_absolute(path)
let (selected_dir, file_name) = if path::is_absolute(path)
{
if filesystem.is_dir(path)
{
(filesystem.canonicalize(path)?, "".to_string())
}
else if let Some(parent) = path_parent(path)
else if let Some(parent) = path::parent(path)
{
if filesystem.is_dir(parent)
{
(filesystem.canonicalize(parent)?, path_filename(path).map_or("".into(), |name| name.to_string()))
(filesystem.canonicalize(parent)?, path::filename(path).map_or("".into(), |name| name.to_string()))
}
else
{
Expand All @@ -84,7 +84,7 @@ impl App
let entries = filesystem.ls(&selected_dir)?;
let entries = entries
.into_iter()
.map(|entry| path_diff(&entry, &selected_dir).to_string())
.map(|entry| path::diff(&entry, &selected_dir).to_string())
.collect::<Vec<_>>();

let entries = entries
Expand All @@ -93,7 +93,7 @@ impl App

for entry in entries
{
if let Ok(result) = PathResult::new(&path_join(&selected_dir, &entry, filesystem.separator()), filesystem)
if let Ok(result) = PathResult::new(&path::join(&selected_dir, &entry, filesystem.separator()), filesystem)
{
ret.push(result);
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/files/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{error::Error, path::Path};

use crate::app::ssh::connection::Connection;

use super::str_path::{path_join, path_parent};
use super::path;

pub enum FileSystem
{
Expand Down Expand Up @@ -71,9 +71,9 @@ impl FileSystem
}
Self::Remote { connection, .. } => connection.ls(path)
}?;
if path_parent(path).is_some()
if path::parent(path).is_some()
{
ret.insert(0,path_join(path,"..", self.separator()));
ret.insert(0,path::join(path,"..", self.separator()));
}
Ok(ret)
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/files/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod files;
pub mod path_result;
pub mod filesystem;
pub mod str_path;
pub mod path;
198 changes: 198 additions & 0 deletions src/app/files/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
use regex::Regex;

pub fn is_absolute(path: &str) -> bool
{
path.starts_with('/') ||
Regex::new(r"(^(\\\\\?\\)?[a-zA-Z]:)|(^\\\\\?\\[a-zA-Z]{1,})")
.expect("Invalid regex.")
.is_match(path)
}

pub fn is_root(path: &str) -> bool
{
path == "/" ||
Regex::new(r"(^(\\\\\?\\)?[a-zA-Z]:\\?$)|(^\\\\\?\\[a-zA-Z]{1,}\\?$)")
.expect("Invalid regex.")
.is_match(path)
}

pub fn parent(path: &str) -> Option<&str>
{
if is_root(path)
{
return None;
}
let path = path.trim_end_matches(|c| c == '/' || c == '\\');
let last_delimiter_index = path.rfind(|c| c == '/' || c == '\\');
Some(path.split_at(last_delimiter_index? + 1).0)
}

pub fn join(start: &str, end: &str, separator: char) -> String
{
let start = start.trim_end_matches(|c| c == separator);
let end = end.trim_start_matches(|c| c == separator);
if end == ".."
{
parent(start).unwrap_or(start).to_string()
}
else if end == "."
{
start.to_string()
}
else
{
format!("{}{}{}", start, separator, end)
}
}

pub fn filename(path: &str) -> Option<&str>
{
if is_root(path)
{
None
}
else
{
let path = path.trim_end_matches(|c| c == '/' || c == '\\');
let path = path.rsplit(|c| c == '/' || c == '\\').collect::<Vec<_>>();
Some(path[0])
}
}

pub fn diff<'a>(full_path: &'a str, prefix_path: &str) -> &'a str
{
if full_path == prefix_path
{
return ".";

Check warning

Code scanning / clippy

unneeded return statement Warning

unneeded return statement
}
else if let Some(unprefixed_path) = full_path.strip_prefix(prefix_path)
{
unprefixed_path.trim_start_matches(|c| c == '/' || c == '\\')
}
else if let Some(unprefixed_path_reverse_logic) = prefix_path.strip_prefix(full_path)
{
if unprefixed_path_reverse_logic.split(|c| c == '/' || c == '\\').filter(|s|!s.is_empty()).count() == 1
{
return "..";
}
else
{
full_path
}
}
else
{
full_path
}
}

#[cfg(test)]
mod test
{
use super::*;

#[test]
fn test_is_absolute()
{
assert!(is_absolute("/"));
assert!(!is_absolute("test"));
assert!(is_absolute("/home/user"));
assert!(!is_absolute("home/user"));

assert!(!is_absolute("\\\\?\\"));
assert!(is_absolute("\\\\?\\C:\\Users\\"));
assert!(is_absolute("\\\\?\\d:\\Users"));
assert!(is_absolute("C:\\Users"));
assert!(is_absolute("d:\\Users"));
assert!(!is_absolute("ASDF\\Users"));
assert!(is_absolute("\\\\?\\ASDF\\"));
assert!(!is_absolute(".\\Users"));
}

#[test]
fn test_is_root()
{
assert!(is_root("/"));
assert!(!is_root("test"));
assert!(!is_root("/home/user"));
assert!(!is_root("home/user"));

assert!(!is_root("\\\\?\\"));
assert!(is_root("\\\\?\\C:\\"));
assert!(is_root("\\\\?\\d:"));
assert!(is_root("C:\\"));
assert!(is_root("d:"));
assert!(!is_root("ASDF\\"));
assert!(is_root("\\\\?\\ASDF\\"));
assert!(!is_root(".\\Users"));
}

#[test]
fn test_parent()
{
assert_eq!(parent("/home/user"), Some("/home/"));
assert_eq!(parent("/home"), Some("/"));
assert_eq!(parent("/"), None);
assert_eq!(parent("C:\\Users\\user"), Some("C:\\Users\\"));
assert_eq!(parent("C:\\Users"), Some("C:\\"));
assert_eq!(parent("C:\\"), None);
assert_eq!(parent("\\\\?\\C:\\Users\\user"), Some("\\\\?\\C:\\Users\\"));
assert_eq!(parent("\\\\?\\C:\\Users"), Some("\\\\?\\C:\\"));
assert_eq!(parent("\\\\?\\C:\\"), None);
assert_eq!(parent("\\\\?\\ASDF\\Users\\user"), Some("\\\\?\\ASDF\\Users\\"));
assert_eq!(parent("\\\\?\\ASDF\\Users"), Some("\\\\?\\ASDF\\"));
assert_eq!(parent("\\\\?\\ASDF"), None);
}

#[test]
fn test_join()
{
assert_eq!(join("/home", "user", '/'), "/home/user");
assert_eq!(join("/home", "..", '/'), "/");
assert_eq!(join("/home", ".", '/'), "/home");

assert_eq!(join("C:\\Users", "user", '\\'), "C:\\Users\\user");
assert_eq!(join("C:\\Users", "..", '\\'), "C:\\");
assert_eq!(join("C:\\Users", ".", '\\'), "C:\\Users");
}

#[test]
fn test_filename()
{
assert_eq!(filename("/home/user"), Some("user"));
assert_eq!(filename("/home"), Some("home"));
assert_eq!(filename("/"), None);
assert_eq!(filename("C:\\Users\\user"), Some("user"));
assert_eq!(filename("C:\\Users"), Some("Users"));
assert_eq!(filename("C:\\"), None);
assert_eq!(filename("\\\\?\\C:\\Users\\user"), Some("user"));
assert_eq!(filename("\\\\?\\C:\\Users"), Some("Users"));
assert_eq!(filename("\\\\?\\C:\\"), None);
assert_eq!(filename("\\\\?\\ASDF\\Users\\user"), Some("user"));
assert_eq!(filename("\\\\?\\ASDF\\Users"), Some("Users"));
assert_eq!(filename("\\\\?\\ASDF"), None);
}

#[test]
fn test_diff()
{
assert_eq!(diff("/home/user", "/home"), "user");
assert_eq!(diff("/home", "/home/user"), "..");
assert_eq!(diff("/home", "/home"), ".");
assert_eq!(diff("/home", "/"), "home");
assert_eq!(diff("/", "/"), ".");
assert_eq!(diff("C:\\Users\\user", "C:\\Users"), "user");
assert_eq!(diff("C:\\Users", "C:\\Users\\user"), "..");
assert_eq!(diff("C:\\Users", "C:\\Users"), ".");
assert_eq!(diff("C:\\Users", "C:\\"), "Users");
assert_eq!(diff("C:\\", "C:\\"), ".");
assert_eq!(diff("\\\\?\\C:\\Users\\user", "\\\\?\\C:\\Users"), "user");
assert_eq!(diff("\\\\?\\C:\\Users", "\\\\?\\C:\\Users"), ".");
assert_eq!(diff("\\\\?\\C:\\Users", "\\\\?\\C:\\"), "Users");
assert_eq!(diff("\\\\?\\C:\\", "\\\\?\\C:\\"), ".");
assert_eq!(diff("\\\\?\\ASDF\\Users\\user", "\\\\?\\ASDF\\Users"), "user");
assert_eq!(diff("\\\\?\\ASDF\\Users", "\\\\?\\ASDF\\Users"), ".");
assert_eq!(diff("\\\\?\\ASDF\\Users", "\\\\?\\ASDF"), "Users");
assert_eq!(diff("\\\\?\\ASDF", "\\\\?\\ASDF"), ".");
}
}
4 changes: 2 additions & 2 deletions src/app/files/path_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use ratatui::text::{Line, Span};

use crate::app::settings::color_settings::ColorSettings;

use super::{filesystem::FileSystem, str_path::path_diff};
use super::{filesystem::FileSystem, path};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PathResult
Expand Down Expand Up @@ -51,7 +51,7 @@ impl PathResult
{
color_settings.path_file
};
let path = path_diff(&self.path, base_path);
let path = path::diff(&self.path, base_path);
ret.spans.push(Span::styled(path.to_string(), style));

ret.left_aligned()
Expand Down
79 changes: 0 additions & 79 deletions src/app/files/str_path.rs

This file was deleted.

Loading
Loading