diff --git a/Cargo.lock b/Cargo.lock index 9c4509d77..82b308616 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -471,6 +471,11 @@ dependencies = [ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "path-slash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "percent-encoding" version = "2.0.0" @@ -719,6 +724,7 @@ dependencies = [ "git2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -986,6 +992,7 @@ dependencies = [ "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" +"checksum path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0858af4d9136275541f4eac7be1af70add84cf356d901799b065ac1b8ff6e2f" "checksum percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" diff --git a/Cargo.toml b/Cargo.toml index fb167f6b3..f690d0ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ pretty_env_logger = "0.3.0" log = "0.4.7" battery = "0.7.4" lazy_static = "1.3.0" +path-slash = "0.1.1" [dev-dependencies] tempfile = "3.1.0" diff --git a/src/modules/directory.rs b/src/modules/directory.rs index bd9d8333b..61937e751 100644 --- a/src/modules/directory.rs +++ b/src/modules/directory.rs @@ -1,4 +1,5 @@ use ansi_term::Color; +use path_slash::PathExt; use std::path::Path; use super::{Context, Module}; @@ -51,25 +52,43 @@ pub fn module<'a>(context: &'a Context) -> Option> { /// `top_level_replacement`. fn contract_path(full_path: &Path, top_level_path: &Path, top_level_replacement: &str) -> String { if !full_path.starts_with(top_level_path) { - return full_path.to_str().unwrap().to_string(); + return replace_c_dir(full_path.to_slash().unwrap()); } if full_path == top_level_path { - return top_level_replacement.to_string(); + return replace_c_dir(top_level_replacement.to_string()); } format!( "{replacement}{separator}{path}", replacement = top_level_replacement, separator = "/", - path = full_path - .strip_prefix(top_level_path) - .unwrap() - .to_str() - .unwrap() + path = replace_c_dir( + full_path + .strip_prefix(top_level_path) + .unwrap() + .to_slash() + .unwrap() + ) ) } +/// Replaces "C://" with "/c/" within a Windows path +/// +/// On non-Windows OS, does nothing +#[cfg(target_os = "windows")] +fn replace_c_dir(path: String) -> String { + return path.replace("C:/", "/c"); +} + +/// Replaces "C://" with "/c/" within a Windows path +/// +/// On non-Windows OS, does nothing +#[cfg(not(target_os = "windows"))] +fn replace_c_dir(path: String) -> String { + return path; +} + /// Truncate a path to only have a set number of path components /// /// Will truncate a path to only show the last `length` components in a path. @@ -110,6 +129,46 @@ mod tests { assert_eq!(output, "rocket-controls/src"); } + #[test] + #[cfg(target_os = "windows")] + fn contract_windows_style_home_directory() { + let full_path = Path::new("C:\\Users\\astronaut\\schematics\\rocket"); + let home = Path::new("C:\\Users\\astronaut"); + + let output = contract_path(full_path, home, "~"); + assert_eq!(output, "~/schematics/rocket"); + } + + #[test] + #[cfg(target_os = "windows")] + fn contract_windows_style_repo_directory() { + let full_path = Path::new("C:\\Users\\astronaut\\dev\\rocket-controls\\src"); + let repo_root = Path::new("C:\\Users\\astronaut\\dev\\rocket-controls"); + + let output = contract_path(full_path, repo_root, "rocket-controls"); + assert_eq!(output, "rocket-controls/src"); + } + + #[test] + #[cfg(target_os = "windows")] + fn contract_windows_style_no_top_level_directory() { + let full_path = Path::new("C:\\Some\\Other\\Path"); + let top_level_path = Path::new("C:\\Users\\astronaut"); + + let output = contract_path(full_path, top_level_path, "~"); + assert_eq!(output, "/c/Some/Other/Path"); + } + + #[test] + #[cfg(target_os = "windows")] + fn contract_windows_style_root_directory() { + let full_path = Path::new("C:\\"); + let top_level_path = Path::new("C:\\Users\\astronaut"); + + let output = contract_path(full_path, top_level_path, "~"); + assert_eq!(output, "/c"); + } + #[test] fn truncate_smaller_path_than_provided_length() { let path = "~/starship";