From 4cea5782acbedeebee768b6b4b3eafddb4f1ce7b Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Thu, 27 Jul 2017 11:49:51 -0400
Subject: [PATCH] Create PID Variable To Store Shell's PID

---
 src/shell/variables.rs | 149 ++++++++++++++++++-----------------------
 1 file changed, 65 insertions(+), 84 deletions(-)

diff --git a/src/shell/variables.rs b/src/shell/variables.rs
index 8d8f32f4..959b278c 100644
--- a/src/shell/variables.rs
+++ b/src/shell/variables.rs
@@ -2,68 +2,76 @@ use fnv::FnvHashMap;
 use std::env;
 use std::process;
 
-use app_dirs::{AppDataType, AppInfo, app_root};
 use super::directory_stack::DirectoryStack;
+use super::status::{FAILURE, SUCCESS};
+use app_dirs::{AppDataType, AppInfo, app_root};
 use liner::Context;
-use super::status::{SUCCESS, FAILURE};
-use types::{
-    HashMapVariableContext,
-    ArrayVariableContext,
-    VariableContext,
-    Identifier,
-    Key,
-    Value,
-    Array,
-    HashMap,
-};
-
-use ::sys::variables as self_sys;
+use types::{Array, ArrayVariableContext, HashMap, HashMapVariableContext, Identifier, Key, Value, VariableContext};
+
+#[cfg(target_os = "redox")]
+use sys::getpid;
+
+#[cfg(all(unix, not(target_os = "unix")))]
+use sys::getpid;
+
+use sys::variables as self_sys;
 
 #[derive(Debug)]
 pub struct Variables {
-    pub hashmaps:  HashMapVariableContext,
-    pub arrays:    ArrayVariableContext,
+    pub hashmaps: HashMapVariableContext,
+    pub arrays: ArrayVariableContext,
     pub variables: VariableContext,
-    pub aliases:   VariableContext,
+    pub aliases: VariableContext,
 }
 
 impl Default for Variables {
     fn default() -> Variables {
-        let mut map = FnvHashMap::with_capacity_and_hasher(
-            64,
-            Default::default(),
-        );
+        let mut map = FnvHashMap::with_capacity_and_hasher(64, Default::default());
         map.insert("DIRECTORY_STACK_SIZE".into(), "1000".into());
         map.insert("HISTORY_SIZE".into(), "1000".into());
         map.insert("HISTORY_FILE_SIZE".into(), "1000".into());
         map.insert("PROMPT".into(), "\x1B\']\'0;${USER}: ${PWD}\x07\x1B\'[\'0m\x1B\'[\'1;38;5;85m${USER}\x1B\'[\'37m:\x1B\'[\'38;5;75m${PWD}\x1B\'[\'37m#\x1B\'[\'0m ".into());
+        // Set the PID variable to the PID of the shell
+        let pid = getpid().map(|p| p.to_string()).unwrap_or_else(
+            |e| e.to_string(),
+        );
+        map.insert("PID".into(), pid.into());
 
         // Initialize the HISTORY_FILE variable
-        if let Ok(mut home_path) = app_root(AppDataType::UserData, &AppInfo{ name: "ion", author: "Redox OS Developers" }) {
+        if let Ok(mut home_path) =
+            app_root(
+                AppDataType::UserData,
+                &AppInfo {
+                    name: "ion",
+                    author: "Redox OS Developers",
+                },
+            )
+        {
             home_path.push("history");
             map.insert("HISTORY_FILE".into(), home_path.to_str().unwrap_or("?").into());
             map.insert("HISTORY_FILE_ENABLED".into(), "1".into());
         }
 
         // Initialize the PWD (Present Working Directory) variable
-        env::current_dir().ok().map_or_else(|| env::set_var("PWD", "?"), |path| env::set_var("PWD", path.to_str().unwrap_or("?")));
+        env::current_dir().ok().map_or_else(
+            || env::set_var("PWD", "?"),
+            |path| {
+                env::set_var("PWD", path.to_str().unwrap_or("?"))
+            },
+        );
 
         // Initialize the HOME variable
-        env::home_dir().map_or_else(|| env::set_var("HOME", "?"), |path| env::set_var("HOME", path.to_str().unwrap_or("?")));
+        env::home_dir().map_or_else(
+            || env::set_var("HOME", "?"),
+            |path| {
+                env::set_var("HOME", path.to_str().unwrap_or("?"))
+            },
+        );
         Variables {
-            hashmaps: FnvHashMap::with_capacity_and_hasher(
-                64,
-                Default::default(),
-            ),
-            arrays: FnvHashMap::with_capacity_and_hasher(
-                64,
-                Default::default(),
-            ),
+            hashmaps: FnvHashMap::with_capacity_and_hasher(64, Default::default()),
+            arrays: FnvHashMap::with_capacity_and_hasher(64, Default::default()),
             variables: map,
-            aliases: FnvHashMap::with_capacity_and_hasher(
-                64,
-                Default::default(),
-            )
+            aliases: FnvHashMap::with_capacity_and_hasher(64, Default::default()),
         }
     }
 }
@@ -87,10 +95,7 @@ impl Variables {
             if value.is_empty() {
                 self.variables.remove(name);
             } else {
-                self.variables.insert(
-                    name.into(),
-                    value.into(),
-                );
+                self.variables.insert(name.into(), value.into());
             }
         }
     }
@@ -109,56 +114,42 @@ impl Variables {
         if !name.is_empty() {
             if let Some(map) = self.hashmaps.get_mut(name) {
                 map.insert(key.into(), value.into());
-                return
+                return;
             }
 
-            let mut map = HashMap::with_capacity_and_hasher(
-                4,
-                Default::default()
-            );
+            let mut map = HashMap::with_capacity_and_hasher(4, Default::default());
             map.insert(key.into(), value.into());
             self.hashmaps.insert(name.into(), map);
         }
     }
 
-    pub fn get_map(&self, name: &str) -> Option<&HashMap>{
-        self.hashmaps.get(name)
-    }
+    pub fn get_map(&self, name: &str) -> Option<&HashMap> { self.hashmaps.get(name) }
 
-    pub fn get_array(&self, name: &str) -> Option<&Array> {
-        self.arrays.get(name)
-    }
+    pub fn get_array(&self, name: &str) -> Option<&Array> { self.arrays.get(name) }
 
-    pub fn unset_array(&mut self, name: &str) -> Option<Array> {
-        self.arrays.remove(name)
-    }
+    pub fn unset_array(&mut self, name: &str) -> Option<Array> { self.arrays.remove(name) }
 
     pub fn get_var(&self, name: &str) -> Option<Value> {
-        self.variables.get(name).cloned()
-            .or_else(|| env::var(name).map(Into::into).ok())
+        self.variables.get(name).cloned().or_else(|| {
+            env::var(name).map(Into::into).ok()
+        })
     }
 
-    pub fn get_var_or_empty(&self, name: &str) -> Value {
-        self.get_var(name).unwrap_or_default()
-    }
+    pub fn get_var_or_empty(&self, name: &str) -> Value { self.get_var(name).unwrap_or_default() }
 
-    pub fn unset_var(&mut self, name: &str) -> Option<Value> {
-        self.variables.remove(name)
-    }
+    pub fn unset_var(&mut self, name: &str) -> Option<Value> { self.variables.remove(name) }
 
     pub fn get_vars(&self) -> Vec<Identifier> {
-        self.variables.keys().cloned()
+        self.variables
+            .keys()
+            .cloned()
             .chain(env::vars().map(|(k, _)| k.into()))
             .collect()
     }
 
-    pub fn is_valid_variable_character(c: char) -> bool {
-        c.is_alphanumeric() || c == '_' || c == '?'
-    }
+    pub fn is_valid_variable_character(c: char) -> bool { c.is_alphanumeric() || c == '_' || c == '?' }
 
-    pub fn is_valid_variable_name(name: &str) -> bool {
-        name.chars().all(Variables::is_valid_variable_character)
-    }
+    pub fn is_valid_variable_name(name: &str) -> bool { name.chars().all(Variables::is_valid_variable_character) }
 
     pub fn tilde_expansion(&self, word: &str, dir_stack: &DirectoryStack) -> Option<String> {
         let mut chars = word.char_indices();
@@ -215,11 +206,7 @@ impl Variables {
 
                 match tilde_num.parse() {
                     Ok(num) => {
-                        let res = if neg {
-                            dir_stack.dir_from_top(num)
-                        } else {
-                            dir_stack.dir_from_bottom(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());
@@ -261,7 +248,7 @@ impl Variables {
                     if inner_key.ends_with(']') {
                         inner_key = inner_key.split(']').next().unwrap_or("");
                         inner_key = inner_key.trim_matches(|c| c == '\'' || c == '\"');
-                        return Some((map_name.into(), inner_key.into()))
+                        return Some((map_name.into(), inner_key.into()));
                     }
                 }
             }
@@ -273,12 +260,10 @@ impl Variables {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use parser::{ExpanderFunctions, Select, expand_string};
     use shell::directory_stack::DirectoryStack;
-    use parser::{expand_string, ExpanderFunctions, Select};
 
-    fn new_dir_stack() -> DirectoryStack {
-        DirectoryStack::new()
-    }
+    fn new_dir_stack() -> DirectoryStack { DirectoryStack::new() }
 
     #[test]
     fn undefined_variable_expands_to_empty_string() {
@@ -291,11 +276,7 @@ mod tests {
     fn set_var_and_expand_a_variable() {
         let mut variables = Variables::default();
         variables.set_var("FOO", "BAR");
-        let expanded = expand_string(
-            "$FOO",
-            &get_expanders!(&variables, &new_dir_stack()),
-            false
-        ).join("");
+        let expanded = expand_string("$FOO", &get_expanders!(&variables, &new_dir_stack()), false).join("");
         assert_eq!("BAR", &expanded);
     }
 
-- 
GitLab