From e120af98c8af8fc2e7f2356cec3d5ac4b20ac45a Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Sun, 26 Mar 2017 14:21:15 -0400
Subject: [PATCH] Enable Autosuggestions & Clippy Fixes

---
 Cargo.toml                        |   2 +-
 README.md                         |   7 +-
 src/builtins/README.md            |   9 ++-
 src/parser/shell_expand/braces.rs |   6 +-
 src/parser/shell_expand/mod.rs    | 110 ++++++++++++++----------------
 src/parser/shell_expand/words.rs  |   6 +-
 src/shell/flow.rs                 |   2 +-
 7 files changed, 72 insertions(+), 70 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 2838578f..9eabcce6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,7 +18,7 @@ name = "ion"
 
 [dependencies]
 glob = "0.2"
-liner = "0.1"
+liner = { git = "https://github.com/redox-os/liner/", branch = "redox" }
 peg-syntax-ext = "0.4"
 permutate = "0.2"
 
diff --git a/README.md b/README.md
index 2f01c908..1991c59d 100644
--- a/README.md
+++ b/README.md
@@ -14,23 +14,28 @@ core functionality is complete. Features below:
 - [x] Variables
 - [x] Functions
 - [ ] Arrays
+- [ ] Array Process Expressions
 - [ ] Maps
+- [x] Process Expressions
 - [x] For Loops
 - [ ] Foreach Loops
 - [x] While Loops
 - [x] If Conditionals
 - [x] Piping Stdout/Stderr
 - [x] Redirecting Stdout/Stderr
+- [ ] Piping Builtins & Functions
 - [x] && and || Conditionals
 - [x] Background Jobs
 - [ ] Background Jobs Control
 - [ ] Signal Handling
-- [ ] Autosuggestions
+- [ ] Autosuggestions (90%)
 - [ ] Syntax Highlighting
 - [x] Multiline Comments and Commands
 - [ ] Multiline Editing
 - [x] Tab Completion (Needs Improvements)
 - [ ] Unescape sequences like '\n' and '\t'
+- [ ] Builtin Plugins
+- [ ] Prompt Plugins
 
 ## Shell Syntax
 
diff --git a/src/builtins/README.md b/src/builtins/README.md
index 88931bf7..8899c937 100644
--- a/src/builtins/README.md
+++ b/src/builtins/README.md
@@ -2,7 +2,11 @@
 
 This directory contains the source code of Ion's builtin commands and documentation for their usage.
 
-## Variables
+## source.rs
+
+Contains the source command
+
+## variables.rs
 
 The **variables.rs** module contains commands relating to setting and removing aliases, variables, and exports. The shell stores aliases and variables within two separate `BTreeMap` structures inside the same `Variables` structure, which is contained within the `Shell` structure.
 
@@ -27,8 +31,7 @@ unalias ls
 The `let` command sets a variable to the value of the expression that follows. These variables are stored as local values within the shell, so other processes many not access these values.
 
 ```ion
-// TODO: Ion Shell does not yet implement stderr redirection.
-let git_branch = $(git rev-parse --abbrev-ref HEAD 2> /dev/null)
+let git_branch = $(git rev-parse --abbrev-ref HEAD ^> /dev/null)
 ```
 
 If the command is executed without any arguments, it will simply list all available variables.
diff --git a/src/parser/shell_expand/braces.rs b/src/parser/shell_expand/braces.rs
index f7629032..7c7a12ad 100644
--- a/src/parser/shell_expand/braces.rs
+++ b/src/parser/shell_expand/braces.rs
@@ -4,17 +4,17 @@ use super::permutate::Permutator;
 /// A token primitive for the `expand_braces` function.
 pub enum BraceToken { Normal(String), Expander }
 
-pub fn expand_braces(tokens: Vec<BraceToken>, mut expanders: Vec<Vec<String>>) -> Vec<String> {
+pub fn expand_braces(tokens: &[BraceToken], mut expanders: Vec<Vec<String>>) -> Vec<String> {
     if expanders.len() > 1 {
         let tmp: Vec<Vec<&str>> = expanders.iter()
             .map(|list| list.iter().map(AsRef::as_ref).collect::<Vec<&str>>())
             .collect();
         let vector_of_arrays: Vec<&[&str]> = tmp.iter().map(AsRef::as_ref).collect();
-        multiple_brace_expand(&vector_of_arrays[..], &tokens)
+        multiple_brace_expand(&vector_of_arrays[..], tokens)
     } else if expanders.len() == 1 {
         let elements = expanders.drain(..).next().expect("there should be at least one value");
         let elements: Vec<&str> = elements.iter().map(AsRef::as_ref).collect();
-        single_brace_expand(&elements, &tokens)
+        single_brace_expand(&elements, tokens)
     } else {
         Vec::new()
     }
diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs
index c9c50028..9ac6e008 100644
--- a/src/parser/shell_expand/mod.rs
+++ b/src/parser/shell_expand/mod.rs
@@ -16,6 +16,52 @@ pub struct ExpanderFunctions<'f> {
     pub command:  &'f Fn(&str, bool) -> Option<String>
 }
 
+fn expand_process(current: &mut String, command: &str, quoted: bool,
+    expand_func: &ExpanderFunctions)
+{
+    let mut expanded = String::with_capacity(command.len());
+    for token in CommandExpander::new(command) {
+        match token {
+            CommandToken::Normal(string) => expanded.push_str(string),
+            CommandToken::Variable(var) => {
+                if let Some(result) = (expand_func.variable)(var, quoted) {
+                    expanded.push_str(&result);
+                }
+            }
+        }
+    }
+
+    if let Some(result) = (expand_func.command)(&expanded, quoted) {
+        current.push_str(&result);
+    }
+}
+
+fn expand_brace(current: &mut String, expanders: &mut Vec<Vec<String>>,
+    tokens: &mut Vec<BraceToken>, nodes: Vec<&str>, expand_func: &ExpanderFunctions,
+    reverse_quoting: bool)
+{
+    let mut temp = Vec::new();
+    for word in nodes.into_iter()
+        .flat_map(|node| expand_string(node, expand_func, reverse_quoting))
+    {
+        match parse_range(&word) {
+            Some(elements) => for word in elements { temp.push(word) },
+            None           => temp.push(word),
+        }
+    }
+
+    if !temp.is_empty() {
+        if !current.is_empty() {
+            tokens.push(BraceToken::Normal(current.clone()));
+            current.clear();
+        }
+        tokens.push(BraceToken::Expander);
+        expanders.push(temp);
+    } else {
+        current.push_str("{}");
+    }
+}
+
 /// Performs shell expansions to an input string, efficiently returning the final expanded form.
 /// Shells must provide their own batteries for expanding tilde and variable words.
 pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_quoting: bool) -> Vec<String> {
@@ -37,30 +83,8 @@ pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_qu
 
             for word in token_buffer.drain(..) {
                 match word {
-                    WordToken::Brace(nodes) => {
-                        let mut temp = Vec::new();
-                        for word in nodes.into_iter()
-                            .flat_map(|node| expand_string(node, expand_func, reverse_quoting))
-                        {
-                            match parse_range(&word) {
-                                Some(elements) => for word in elements {
-                                    temp.push(word)
-                                },
-                                None => temp.push(word),
-                            }
-                        }
-
-                        if temp.len() > 0 {
-                            if !current.is_empty() {
-                                tokens.push(BraceToken::Normal(current.clone()));
-                                current.clear();
-                            }
-                            tokens.push(BraceToken::Expander);
-                            expanders.push(temp);
-                        } else {
-                            current.push_str("{}");
-                        }
-                    },
+                    WordToken::Brace(nodes) =>
+                        expand_brace(&mut current, &mut expanders, &mut tokens, nodes, expand_func, reverse_quoting),
                     WordToken::Normal(text) => current.push_str(text),
                     WordToken::Whitespace(_) => unreachable!(),
                     WordToken::Tilde(text) => current.push_str(match (expand_func.tilde)(text) {
@@ -69,21 +93,7 @@ pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_qu
                     }),
                     WordToken::Process(command, quoted) => {
                         let quoted = if reverse_quoting { !quoted } else { quoted };
-                        let mut expanded = String::with_capacity(command.len());
-                        for token in CommandExpander::new(&command) {
-                            match token {
-                                CommandToken::Normal(string) => expanded.push_str(string),
-                                CommandToken::Variable(var) => {
-                                    if let Some(result) = (expand_func.variable)(var, quoted) {
-                                        expanded.push_str(&result);
-                                    }
-                                }
-                            }
-                        }
-
-                        if let Some(result) = (expand_func.command)(&expanded, quoted) {
-                            current.push_str(&result);
-                        }
+                        expand_process(&mut current, command, quoted, expand_func);
                     },
                     WordToken::Variable(text, quoted) => {
                         let quoted = if reverse_quoting { !quoted } else { quoted };
@@ -95,15 +105,13 @@ pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_qu
                 }
             }
 
-
-
-            if expanders.len() == 0 {
+            if expanders.is_empty() {
                 expanded_words.push(current);
             } else {
                 if !current.is_empty() {
                     tokens.push(BraceToken::Normal(current));
                 }
-                for word in braces::expand_braces(tokens, expanders) {
+                for word in braces::expand_braces(&tokens, expanders) {
                     expanded_words.push(word);
                 }
             }
@@ -120,21 +128,7 @@ pub fn expand_string(original: &str, expand_func: &ExpanderFunctions, reverse_qu
                     }),
                     WordToken::Process(command, quoted) => {
                         let quoted = if reverse_quoting { !quoted } else { quoted };
-                        let mut expanded = String::with_capacity(command.len());
-                        for token in CommandExpander::new(&command) {
-                            match token {
-                                CommandToken::Normal(string) => expanded.push_str(string),
-                                CommandToken::Variable(var) => {
-                                    if let Some(result) = (expand_func.variable)(var, quoted) {
-                                        expanded.push_str(&result);
-                                    }
-                                }
-                            }
-                        }
-
-                        if let Some(result) = (expand_func.command)(&expanded, quoted) {
-                            output.push_str(&result);
-                        }
+                        expand_process(&mut output, command, quoted, expand_func);
                     },
                     WordToken::Variable(text, quoted) => {
                         let quoted = if reverse_quoting { !quoted } else { quoted };
diff --git a/src/parser/shell_expand/words.rs b/src/parser/shell_expand/words.rs
index 2d16478e..c5cbad60 100644
--- a/src/parser/shell_expand/words.rs
+++ b/src/parser/shell_expand/words.rs
@@ -95,9 +95,9 @@ impl<'a> WordIterator<'a> {
         while let Some(character) = iterator.next() {
             match character {
                 // If found, this is not a `Variable` but an `ArrayToString`
-                b'(' => {
-                    unimplemented!()
-                },
+                // b'(' => {
+                //     unimplemented!()
+                // },
                 // Only alphanumerical and underscores are allowed in variable names
                 0...47 | 58...64 | 91...94 | 96 | 123...127 => {
                     return WordToken::Variable(&self.data[start..self.read], self.flags & DQUOTE != 0);
diff --git a/src/shell/flow.rs b/src/shell/flow.rs
index 60f82120..4732ace7 100644
--- a/src/shell/flow.rs
+++ b/src/shell/flow.rs
@@ -177,7 +177,7 @@ impl<'a> FlowLogic for Shell<'a> {
         fn glob_expand(arg: &str) -> Vec<String> {
             let mut expanded = Vec::new();
             if arg.contains(|chr| chr == '?' || chr == '*' || chr == '[') {
-                if let Ok(glob) = glob(&arg) {
+                if let Ok(glob) = glob(arg) {
                     for path in glob.filter_map(Result::ok) {
                         expanded.push(path.to_string_lossy().into_owned());
                     }
-- 
GitLab