From c97f543cf2356e8cf420646f566fcfb3b29f07d4 Mon Sep 17 00:00:00 2001
From: stratact <stratact1@gmail.com>
Date: Thu, 28 Jan 2016 07:32:20 -0800
Subject: [PATCH] Move rogue functions to methods and cleanup

---
 src/builtin.rs |  10 +-
 src/main.rs    | 354 ++++++++++++++++++++++++-------------------------
 2 files changed, 182 insertions(+), 182 deletions(-)

diff --git a/src/builtin.rs b/src/builtin.rs
index 0e1e2934..797a9ec5 100644
--- a/src/builtin.rs
+++ b/src/builtin.rs
@@ -2,7 +2,7 @@ use std::io::{stdout, Write};
 use std::env;
 use std::process;
 
-use super::{set_var, Variables};
+use super::{Shell, Variables};
 use super::input_editor::readln;
 
 pub fn cd(args: &[String]) {
@@ -16,7 +16,7 @@ pub fn cd(args: &[String]) {
     }
 }
 
-pub fn read(args: &[String], variables: &mut Variables) {
+pub fn read(args: &[String], shell: &mut Shell) {
     let mut out = stdout();
     for i in 1..args.len() {
         if let Some(arg_original) = args.get(i) {
@@ -27,13 +27,13 @@ pub fn read(args: &[String], variables: &mut Variables) {
             }
             if let Some(value_original) = readln() {
                 let value = value_original.trim();
-                set_var(variables, arg, value);
+                shell.set_var(arg, value);
             }
         }
     }
 }
 
-pub fn run(args: &[String], variables: &mut Variables) {
+pub fn run(args: &[String], shell: &mut Shell) {
     let path = "/apps/shell/main.bin";
 
     let mut command = process::Command::new(path);
@@ -48,7 +48,7 @@ pub fn run(args: &[String], variables: &mut Variables) {
             match child.wait() {
                 Ok(status) => {
                     if let Some(code) = status.code() {
-                        set_var(variables, "?", &format!("{}", code));
+                        shell.set_var("?", &format!("{}", code));
                     } else {
                         println!("{}: No child exit code", path);
                     }
diff --git a/src/main.rs b/src/main.rs
index 5cb84a21..bce7745e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,10 +26,10 @@ pub type Variables = BTreeMap<String, String>;
 /// This struct will contain all of the data structures related to this
 /// instance of the shell.
 pub struct Shell {
-    pub variables: Variables,
-    pub modes: Vec<Mode>,
-    pub directory_stack: DirectoryStack,
-    pub history: VecDeque<String>,
+    variables: Variables,
+    modes: Vec<Mode>,
+    directory_stack: DirectoryStack,
+    history: VecDeque<String>,
 }
 
 impl Shell {
@@ -42,6 +42,174 @@ impl Shell {
             history: VecDeque::new(),
         }
     }
+
+    pub fn print_prompt(&self) {
+        let prompt_prefix = self.modes.iter().rev().fold(String::new(), |acc, mode| {
+            acc +
+            if mode.value {
+                "+ "
+            } else {
+                "- "
+            }
+        });
+        print!("{}", prompt_prefix);
+
+        let cwd = env::current_dir().ok().map_or("?".to_string(),
+                                                 |ref p| p.to_str().unwrap_or("?").to_string());
+
+        print!("ion:{}# ", cwd);
+        if let Err(message) = stdout().flush() {
+            println!("{}: failed to flush prompt to stdout", message);
+        }
+    }
+
+    fn on_command(&mut self, command_string: &str, commands: &HashMap<&str, Command>) {
+        let max_history: usize = 1000; // TODO temporary, make this configurable
+        if self.history.len() > max_history {
+            self.history.pop_front();
+        }
+        self.history.push_back(command_string.to_string());
+
+        // Show variables
+        if command_string == "$" {
+            for (key, value) in self.variables.iter() {
+                println!("{}={}", key, value);
+            }
+            return;
+        }
+
+        let mut jobs = parse(command_string);
+        expand_variables(&mut jobs, &self.variables);
+
+        // Execute commands
+        for job in jobs.iter() {
+            if job.command == "if" {
+                let mut value = false;
+
+                if let Some(left) = job.args.get(0) {
+                    if let Some(cmp) = job.args.get(1) {
+                        if let Some(right) = job.args.get(2) {
+                            if cmp == "==" {
+                                value = *left == *right;
+                            } else if cmp == "!=" {
+                                value = *left != *right;
+                            } else if cmp == ">" {
+                                value = left.to_num_signed() > right.to_num_signed();
+                            } else if cmp == ">=" {
+                                value = left.to_num_signed() >= right.to_num_signed();
+                            } else if cmp == "<" {
+                                value = left.to_num_signed() < right.to_num_signed();
+                            } else if cmp == "<=" {
+                                value = left.to_num_signed() <= right.to_num_signed();
+                            } else {
+                                println!("Unknown comparison: {}", cmp);
+                            }
+                        } else {
+                            println!("No right hand side");
+                        }
+                    } else {
+                        println!("No comparison operator");
+                    }
+                } else {
+                    println!("No left hand side");
+                }
+
+                self.modes.insert(0, Mode { value: value });
+                continue;
+            }
+
+            if job.command == "else" {
+                if let Some(mode) = self.modes.get_mut(0) {
+                    mode.value = !mode.value;
+                } else {
+                    println!("Syntax error: else found with no previous if");
+                }
+                continue;
+            }
+
+            if job.command == "fi" {
+                if !self.modes.is_empty() {
+                    self.modes.remove(0);
+                } else {
+                    println!("Syntax error: fi found with no previous if");
+                }
+                continue;
+            }
+
+            let mut skipped: bool = false;
+            for mode in self.modes.iter() {
+                if !mode.value {
+                    skipped = true;
+                    break;
+                }
+            }
+            if skipped {
+                continue;
+            }
+
+            // Set variables
+            if let Some(i) = job.command.find('=') {
+                let name = job.command[0..i].trim();
+                let mut value = job.command[i + 1..job.command.len()].trim().to_string();
+
+                for i in 0..job.args.len() {
+                    if let Some(arg) = job.args.get(i) {
+                        value = value + " " + &arg;
+                    }
+                }
+
+                self.set_var(name, &value);
+                continue;
+            }
+
+            // Commands
+            let mut args = job.args.clone();
+            args.insert(0, job.command.clone());
+            if let Some(command) = commands.get(&job.command.as_str()) {
+                (*command.main)(&args, self);
+            } else {
+                self.run_external_commmand(args);
+            }
+        }
+    }
+
+    fn run_external_commmand(&mut self, args: Vec<String>) {
+        if let Some(path) = args.get(0) {
+            let mut command = process::Command::new(path);
+            for i in 1..args.len() {
+                if let Some(arg) = args.get(i) {
+                    command.arg(arg);
+                }
+            }
+            match command.spawn() {
+                Ok(mut child) => {
+                    match child.wait() {
+                        Ok(status) => {
+                            if let Some(code) = status.code() {
+                                self.set_var("?", &code.to_string());
+                            } else {
+                                println!("{}: No child exit code", path);
+                            }
+                        }
+                        Err(err) => println!("{}: Failed to wait: {}", path, err),
+                    }
+                }
+                Err(err) => println!("{}: Failed to execute: {}", path, err),
+            }
+        }
+    }
+
+    pub fn set_var(&mut self, name: &str, value: &str) {
+        if name.is_empty() {
+            return;
+        }
+
+        if value.is_empty() {
+            self.variables.remove(&name.to_string());
+        } else {
+            self.variables.insert(name.to_string(), value.to_string());
+        }
+    }
 }
 
 /// Structure which represents a Terminal's command.
@@ -99,7 +267,7 @@ impl Command {
                             name: "read",
                             help: "To read some variables\n    read <my_variable>",
                             main: box |args: &[String], shell: &mut Shell| {
-                                builtin::read(args, &mut shell.variables);
+                                builtin::read(args, shell);
                             },
                         });
 
@@ -108,7 +276,7 @@ impl Command {
                             name: "run",
                             help: "Run a script\n    run <script>",
                             main: box |args: &[String], shell: &mut Shell| {
-                                builtin::run(args, &mut shell.variables);
+                                builtin::run(args, shell);
                             },
                         });
 
@@ -182,174 +350,6 @@ pub struct Mode {
     value: bool,
 }
 
-fn on_command(command_string: &str, commands: &HashMap<&str, Command>, shell: &mut Shell) {
-    let max_history: usize = 1000; // TODO temporary, make this configurable
-    if shell.history.len() > max_history {
-        shell.history.pop_front();
-    }
-    shell.history.push_back(command_string.to_string());
-
-    // Show variables
-    if command_string == "$" {
-        for (key, value) in shell.variables.iter() {
-            println!("{}={}", key, value);
-        }
-        return;
-    }
-
-    let mut jobs = parse(command_string);
-    expand_variables(&mut jobs, &shell.variables);
-
-    // Execute commands
-    for job in jobs.iter() {
-        if job.command == "if" {
-            let mut value = false;
-
-            if let Some(left) = job.args.get(0) {
-                if let Some(cmp) = job.args.get(1) {
-                    if let Some(right) = job.args.get(2) {
-                        if cmp == "==" {
-                            value = *left == *right;
-                        } else if cmp == "!=" {
-                            value = *left != *right;
-                        } else if cmp == ">" {
-                            value = left.to_num_signed() > right.to_num_signed();
-                        } else if cmp == ">=" {
-                            value = left.to_num_signed() >= right.to_num_signed();
-                        } else if cmp == "<" {
-                            value = left.to_num_signed() < right.to_num_signed();
-                        } else if cmp == "<=" {
-                            value = left.to_num_signed() <= right.to_num_signed();
-                        } else {
-                            println!("Unknown comparison: {}", cmp);
-                        }
-                    } else {
-                        println!("No right hand side");
-                    }
-                } else {
-                    println!("No comparison operator");
-                }
-            } else {
-                println!("No left hand side");
-            }
-
-            shell.modes.insert(0, Mode { value: value });
-            continue;
-        }
-
-        if job.command == "else" {
-            if let Some(mode) = shell.modes.get_mut(0) {
-                mode.value = !mode.value;
-            } else {
-                println!("Syntax error: else found with no previous if");
-            }
-            continue;
-        }
-
-        if job.command == "fi" {
-            if !shell.modes.is_empty() {
-                shell.modes.remove(0);
-            } else {
-                println!("Syntax error: fi found with no previous if");
-            }
-            continue;
-        }
-
-        let mut skipped: bool = false;
-        for mode in shell.modes.iter() {
-            if !mode.value {
-                skipped = true;
-                break;
-            }
-        }
-        if skipped {
-            continue;
-        }
-
-        // Set variables
-        if let Some(i) = job.command.find('=') {
-            let name = job.command[0..i].trim();
-            let mut value = job.command[i + 1..job.command.len()].trim().to_string();
-
-            for i in 0..job.args.len() {
-                if let Some(arg) = job.args.get(i) {
-                    value = value + " " + &arg;
-                }
-            }
-
-            set_var(&mut shell.variables, name, &value);
-            continue;
-        }
-
-        // Commands
-        let mut args = job.args.clone();
-        args.insert(0, job.command.clone());
-        if let Some(command) = commands.get(&job.command.as_str()) {
-            (*command.main)(&args, shell);
-        } else {
-            run_external_commmand(args, &mut shell.variables);
-        }
-    }
-}
-
-
-pub fn set_var(variables: &mut Variables, name: &str, value: &str) {
-    if name.is_empty() {
-        return;
-    }
-
-    if value.is_empty() {
-        variables.remove(&name.to_string());
-    } else {
-        variables.insert(name.to_string(), value.to_string());
-    }
-}
-
-fn print_prompt(modes: &[Mode]) {
-    let prompt_prefix = modes.iter().rev().fold(String::new(), |acc, mode| {
-        acc +
-        if mode.value {
-            "+ "
-        } else {
-            "- "
-        }
-    });
-    print!("{}", prompt_prefix);
-
-    let cwd = env::current_dir().ok().map_or("?".to_string(),
-                                             |ref p| p.to_str().unwrap_or("?").to_string());
-
-    print!("ion:{}# ", cwd);
-    if let Err(message) = stdout().flush() {
-        println!("{}: failed to flush prompt to stdout", message);
-    }
-}
-
-fn run_external_commmand(args: Vec<String>, variables: &mut Variables) {
-    if let Some(path) = args.get(0) {
-        let mut command = process::Command::new(path);
-        for i in 1..args.len() {
-            if let Some(arg) = args.get(i) {
-                command.arg(arg);
-            }
-        }
-        match command.spawn() {
-            Ok(mut child) => {
-                match child.wait() {
-                    Ok(status) => {
-                        if let Some(code) = status.code() {
-                            set_var(variables, "?", &code.to_string());
-                        } else {
-                            println!("{}: No child exit code", path);
-                        }
-                    }
-                    Err(err) => println!("{}: Failed to wait: {}", path, err),
-                }
-            }
-            Err(err) => println!("{}: Failed to execute: {}", path, err),
-        }
-    }
-}
 
 fn main() {
     let commands = Command::map();
@@ -362,20 +362,20 @@ fn main() {
                 println!("{}: Failed to read {}", message, arg);
             }
         }
-        on_command(&command_list, &commands, &mut shell);
+        shell.on_command(&command_list, &commands);
         return;
     }
 
     loop {
 
-        print_prompt(&shell.modes);
+        shell.print_prompt();
 
         if let Some(command_original) = readln() {
             let command = command_original.trim();
             if command == "exit" {
                 break;
             } else if !command.is_empty() {
-                on_command(&command, &commands, &mut shell);
+                shell.on_command(&command, &commands);
             }
         } else {
             break;
-- 
GitLab