From c5b1d29a3ad1029d7b20140e3e4ffc781b44e1bc Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Mon, 7 Aug 2017 00:30:10 -0400
Subject: [PATCH] Implement env Variable Namespace

Try it out with the following:

    echo ${env::PATH}
---
 src/parser/statement/splitter.rs |  4 ++--
 src/shell/variables.rs           | 17 +++++++++++++----
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/src/parser/statement/splitter.rs b/src/parser/statement/splitter.rs
index 9aa54a1b..50218c42 100644
--- a/src/parser/statement/splitter.rs
+++ b/src/parser/statement/splitter.rs
@@ -94,8 +94,8 @@ impl<'a> Iterator for StatementSplitter<'a> {
                 _ if self.flags.contains(POST_MATHEXPR) => {
                     self.flags -= POST_MATHEXPR;
                 },
-                // [^A-Za-z0-9_}]
-                0...47 | 58...64 | 91...94 | 96 | 123...124 | 126...127 if self.flags.contains(VBRACE) => {
+                // [^A-Za-z0-9_:}]
+                0...47 | 59...64 | 91...94 | 96 | 123...124 | 126...127 if self.flags.contains(VBRACE) => {
                     // If we are just ending the braced section continue as normal
                     if error.is_none() {
                         error = Some(StatementError::InvalidCharacter(character as char, self.read))
diff --git a/src/shell/variables.rs b/src/shell/variables.rs
index 9d429524..61d14859 100644
--- a/src/shell/variables.rs
+++ b/src/shell/variables.rs
@@ -143,9 +143,19 @@ impl Variables {
     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()
-        })
+        if let Some((namespace, variable)) = name.find("::").map(|pos| (&name[..pos], &name[pos+2..])) {
+            match namespace {
+                "env" => env::var(variable).map(Into::into).ok(),
+                _ => {
+                    eprintln!("ion: unsupported namespace: '{}'", namespace);
+                    None
+                }
+            }
+        } else {
+            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() }
@@ -284,7 +294,6 @@ mod tests {
         }
     }
 
-
     #[test]
     fn undefined_variable_expands_to_empty_string() {
         let variables = Variables::default();
-- 
GitLab