From b54292ff4e69bee12e99b50124c653a4fd6421a9 Mon Sep 17 00:00:00 2001
From: MovingtoMars <definitelynotliam@gmail.com>
Date: Wed, 22 Mar 2017 16:41:58 +1300
Subject: [PATCH] Implement tilde expansion for other user's home directories.

This commit adds support only for non-Redox unix systems.
---
 Cargo.toml       |  3 +++
 src/main.rs      |  3 +++
 src/variables.rs | 48 +++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 77c1498a..2838578f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,3 +21,6 @@ glob = "0.2"
 liner = "0.1"
 peg-syntax-ext = "0.4"
 permutate = "0.2"
+
+[target.'cfg(all(unix, not(target_os = "redox")))'.dependencies]
+users = "0.5.1"
diff --git a/src/main.rs b/src/main.rs
index d8435f7c..0c0b990c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,6 +6,9 @@
 extern crate glob;
 extern crate liner;
 
+#[cfg(all(unix, not(target_os = "redox")))]
+extern crate users as users_unix;
+
 pub mod completer;
 pub mod pipe;
 pub mod directory_stack;
diff --git a/src/variables.rs b/src/variables.rs
index 6966674c..1f2d4dba 100644
--- a/src/variables.rs
+++ b/src/variables.rs
@@ -147,15 +147,22 @@ impl Variables {
                     neg = false;
                 }
 
-                if let Ok(num) = tilde_num.parse::<usize>() {
-                    let res = if neg {
-                        dir_stack.dir_from_top(num)
-                    } else {
-                        dir_stack.dir_from_bottom(num)
-                    };
-
-                    if let Some(path) = res {
-                        return Some(path.to_str().unwrap().to_string());
+                match tilde_num.parse() {
+                    Ok(num) => {
+                        let res = if neg {
+                            dir_stack.dir_from_top(num)
+                        } else {
+                            dir_stack.dir_from_bottom(num)
+                        };
+
+                        if let Some(path) = res {
+                            return Some(path.to_str().unwrap().to_string());
+                        }
+                    }
+                    Err(_) => {
+                        if let Some(home) = get_user_home(tilde_prefix) {
+                            return Some(home + remainder);
+                        }
                     }
                 }
             }
@@ -180,6 +187,29 @@ impl Variables {
     }
 }
 
+#[cfg(all(unix, not(target_os = "redox")))]
+fn get_user_home(username: &str) -> Option<String> {
+    use users_unix::get_user_by_name;
+    use users_unix::os::unix::UserExt;
+
+    match get_user_by_name(username) {
+        Some(user) => Some(user.home_dir().to_string_lossy().into_owned()),
+        None => None,
+    }
+}
+
+#[cfg(target_os = "redox")]
+fn get_user_home(_username: &str) -> Option<String> {
+    // TODO
+    None
+}
+
+#[cfg(not(any(unix, target_os = "redox")))]
+fn get_user_home(_username: &str) -> Option<String> {
+    // TODO
+    None
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
-- 
GitLab