From b38f90d4c709b5dfc043e7b8ff4848c27742ddc9 Mon Sep 17 00:00:00 2001 From: merelymyself <88221256+merelymyself@users.noreply.github.com> Date: Mon, 25 Apr 2022 06:12:57 +0800 Subject: [PATCH] Adding ~user tilde recognition in file paths (#5251) * Added search terms to math commands * Attempts to add ~user. From: // Extend this to work with "~user" style of home paths * Clippy recommendation * clippy suggestions, again. * fixing non-compilation on windows and macos * fmt apparently does not like my imports * even more clippy issues. * less expect(), single conversion, match. Should work for MacOS too. * Attempted to add functionality for windows: all it does is take the home path of current user, and replace the username. * silly mistake in Windows version of user_home_dir() * Update tilde.rs * user_home_dir now returns a path instead of a string - should be smoother with no conversions to string * clippy warnings * clippy warnings 2 * Changed user_home_dir to return PathBuf now. * Changed user_home_dir to return PathBuf now. * forgot to fmt * fixed windows build errors from modifying pathbuf but not returning it * fixed windows clippy errors from returning () instead of pathbuf * forgot to fmt * borrowed path did not live long enough. * previously, path.push did not work because rest_of_path started with "/" - it was not relative. Removing the / makes it a relative path again. * Issue fixed. * Update tilde.rs * fmt. * There is now a zero chance of panic. All expect()s have been removed. --- Cargo.lock | 45 +++++++++++++++ crates/nu-path/Cargo.toml | 3 + crates/nu-path/src/tilde.rs | 107 +++++++++++++++++++++++++++++++++++- 3 files changed, 154 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 64d3736cea..29215ff052 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,6 +988,28 @@ dependencies = [ "libc", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -2436,6 +2458,7 @@ version = "0.61.1" dependencies = [ "dirs-next", "dunce", + "pwd", ] [[package]] @@ -3282,6 +3305,16 @@ dependencies = [ "libc", ] +[[package]] +name = "pwd" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ca0304857594109dca88140120427c7a65027be6b77d86a5938588e79cb07b" +dependencies = [ + "failure", + "libc", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4237,6 +4270,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "sys-locale" version = "0.2.0" diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index b925f213a1..c0e5007a65 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -9,3 +9,6 @@ version = "0.61.1" [dependencies] dirs-next = "2.0.0" dunce = "1.0.1" + +[target.'cfg(target_os = "linux")'.dependencies] +pwd = "1.3.1" \ No newline at end of file diff --git a/crates/nu-path/src/tilde.rs b/crates/nu-path/src/tilde.rs index 5b16805c65..c51ea52d03 100644 --- a/crates/nu-path/src/tilde.rs +++ b/crates/nu-path/src/tilde.rs @@ -1,10 +1,17 @@ +#[cfg(target_os = "linux")] +use pwd::Passwd; use std::path::{Path, PathBuf}; fn expand_tilde_with_home(path: impl AsRef, home: Option) -> PathBuf { let path = path.as_ref(); if !path.starts_with("~") { - return path.into(); + let string = path.to_string_lossy(); + let mut path_as_string = string.as_ref().chars(); + return match path_as_string.next() { + Some('~') => expand_tilde_with_another_user_home(path), + _ => path.into(), + }; } match home { @@ -31,6 +38,104 @@ fn expand_tilde_with_home(path: impl AsRef, home: Option) -> Path } } +#[cfg(target_os = "linux")] +fn user_home_dir(username: &str) -> PathBuf { + let passwd = Passwd::from_name(username); + match &passwd.ok() { + Some(Some(dir)) => PathBuf::from(&dir.dir), + _ => { + let mut file = String::from("/home/"); + file.push_str(username); + PathBuf::from(file) + } + } + // PathBuf::from(concat!("/home/", username)), + // Returns home dir of user. +} + +#[cfg(target_os = "macos")] +fn user_home_dir(username: &str) -> PathBuf { + match dirs_next::home_dir() { + None => { + let mut expected_path = String::from("/Users/"); + expected_path.push_str(username); + let path = Path::new(&expected_path); + let mut home = PathBuf::new(); + home.push(path); + home + } + Some(user) => { + let mut expected_path = user; + expected_path.pop(); + expected_path.push(Path::new(username)); + if expected_path.is_dir() { + expected_path + } else { + let mut expected_path_as_string = String::from("/Users/"); + expected_path_as_string.push_str(username); + let path = Path::new(&expected_path_as_string); + let mut home = PathBuf::new(); + home.push(path); + home + } + } + } +} + +#[cfg(target_os = "windows")] +fn user_home_dir(username: &str) -> PathBuf { + match dirs_next::home_dir() { + None => { + let mut expected_path = String::from("C:\\Users\\"); + expected_path.push_str(username); + let path = Path::new(&expected_path); + let mut home = PathBuf::new(); + home.push(path); + home + } + Some(user) => { + let mut expected_path = user; + expected_path.pop(); + expected_path.push(Path::new(username)); + if expected_path.is_dir() { + expected_path + } else { + let mut expected_path_as_string = String::from("C:\\Users\\"); + expected_path_as_string.push_str(username); + let path = Path::new(&expected_path_as_string); + let mut home = PathBuf::new(); + home.push(path); + home + } + } + } +} + +fn expand_tilde_with_another_user_home(path: &Path) -> PathBuf { + return match path.to_str() { + Some(file_path) => { + let mut file = file_path.to_string(); + match file_path.chars().position(|c| c == '/' || c == '\\') { + None => { + file.remove(0); + user_home_dir(&file) + } + Some(i) => { + let (pre_name, rest_of_path) = file.split_at(i); + let mut name = pre_name.to_string(); + let mut rest_path = rest_of_path.to_string(); + rest_path.remove(0); + name.remove(0); + let mut path = user_home_dir(&name); + path.push(Path::new(&rest_path)); + path + } + } + } + None => path.to_path_buf(), + }; +} + /// Expand tilde ("~") into a home directory if it is the first path component pub fn expand_tilde(path: impl AsRef) -> PathBuf { // TODO: Extend this to work with "~user" style of home paths