diff --git a/src/lib/parser/statement/splitter.rs b/src/lib/parser/statement/splitter.rs
index 687328ad6e6729f75e692de71a9723a3a2007d13..5a0e0aa64bd9677b4cf73e1f56f985ca7e4b70e7 100644
--- a/src/lib/parser/statement/splitter.rs
+++ b/src/lib/parser/statement/splitter.rs
@@ -11,13 +11,6 @@ enum LogicalOp {
     None,
 }
 
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-enum Quotes {
-    Single,
-    Double,
-    None,
-}
-
 #[derive(Debug, PartialEq)]
 pub enum StatementError {
     IllegalCommandName(String),
@@ -70,7 +63,6 @@ pub enum StatementVariant<'a> {
 pub struct StatementSplitter<'a> {
     data:             &'a str,
     read:             usize,
-    start:            usize,
     paren_level:      u8,
     brace_level:      u8,
     math_paren_level: i8,
@@ -78,7 +70,7 @@ pub struct StatementSplitter<'a> {
     skip:             bool,
     vbrace:           bool,
     variable:         bool,
-    quotes:           Quotes,
+    quotes:           bool,
 }
 
 impl<'a> StatementSplitter<'a> {
@@ -86,7 +78,6 @@ impl<'a> StatementSplitter<'a> {
         StatementSplitter {
             data,
             read: 0,
-            start: 0,
             paren_level: 0,
             brace_level: 0,
             math_paren_level: 0,
@@ -94,7 +85,7 @@ impl<'a> StatementSplitter<'a> {
             skip: false,
             vbrace: false,
             variable: false,
-            quotes: Quotes::None,
+            quotes: false,
         }
     }
 
@@ -137,16 +128,11 @@ impl<'a> Iterator for StatementSplitter<'a> {
                     last = None;
                     continue;
                 }
-                b'\\' => self.skip = true,
-                b'\'' => {
-                    if self.quotes == Quotes::Single {
-                        self.quotes = Quotes::None;
-                    } else if self.quotes == Quotes::None {
-                        self.variable = false;
-                        self.quotes = Quotes::Single;
-                    }
+                b'\'' if !self.quotes => {
+                    self.variable = false;
+                    bytes.find(|&(_, c)| c == b'\'');
                 }
-                _ if self.quotes == Quotes::Single => {}
+                b'\\' => self.skip = true,
                 // [^A-Za-z0-9_:,}]
                 0...43 | 45...47 | 59...64 | 91...94 | 96 | 123...124 | 126...127
                     if self.vbrace =>
@@ -157,70 +143,59 @@ impl<'a> Iterator for StatementSplitter<'a> {
                     }
                 }
                 // Toggle quotes and stop matching variables.
-                b'"' if self.quotes == Quotes::Double => self.quotes = Quotes::None,
+                b'"' if self.quotes && self.paren_level == 0 => self.quotes = false,
                 b'"' => {
-                    self.quotes = Quotes::Double;
+                    self.quotes = true;
                     self.variable = false;
                 }
                 // Array expansion
                 b'@' | b'$' => self.variable = true,
                 b'{' if [Some(b'$'), Some(b'@')].contains(&last) => self.vbrace = true,
-                b'{' if self.quotes == Quotes::None => self.brace_level += 1,
-                b'}' if self.vbrace => self.vbrace = false,
-                b'}' if self.quotes == Quotes::None => {
-                    if self.brace_level == 0 {
-                        if error.is_none() {
-                            error = Some(StatementError::InvalidCharacter(character as char, i + 1))
-                        }
-                    } else {
-                        self.brace_level -= 1;
-                    }
-                }
                 b'(' if self.math_paren_level > 0 => self.math_paren_level += 1,
-                b'(' if last == Some(b'$') => {
-                    self.variable = false;
-                    if let Some(&(_, b'(')) = bytes.peek() {
-                        bytes.next();
-                        self.read += 1;
-                        // The next character will always be a left paren in this branch;
-                        self.math_paren_level = 1;
-                    } else {
-                        self.paren_level += 1;
-                    }
+                b'(' if self.variable && last == Some(b'(') => {
+                    self.math_paren_level = 1;
+                    self.paren_level -= 1;
                 }
                 b'(' if self.variable => self.paren_level += 1,
-                b'(' if error.is_none() && self.quotes == Quotes::None => {
+                b'(' if error.is_none() && !self.quotes => {
                     error = Some(StatementError::InvalidCharacter(character as char, i + 1))
                 }
-                b')' if self.math_paren_level != 0 => {
-                    if self.math_paren_level == 1 {
-                        match bytes.peek() {
-                            Some(&(_, b')')) => {
-                                self.math_paren_level = 0;
-                                self.skip = true;
-                            }
-                            Some(&(_, next)) if error.is_none() => {
-                                error = Some(StatementError::InvalidCharacter(next as char, i + 1));
-                            }
-                            None if error.is_none() => {
-                                error = Some(StatementError::UnterminatedArithmetic)
-                            }
-                            _ => {}
-                        }
-                    } else {
-                        self.math_paren_level -= 1;
+                b')' if self.math_paren_level == 1 => match bytes.peek() {
+                    Some(&(_, b')')) => {
+                        self.math_paren_level = 0;
+                        self.skip = true;
                     }
-                }
-                b')' if self.variable && self.paren_level == 0 => {
-                    self.variable = false;
+                    Some(&(_, next)) if error.is_none() => {
+                        error = Some(StatementError::InvalidCharacter(next as char, i + 1));
+                    }
+                    None if error.is_none() => error = Some(StatementError::UnterminatedArithmetic),
+                    _ => {}
+                },
+                b'(' if self.math_paren_level != 0 => {
+                    self.math_paren_level -= 1;
                 }
                 b')' if self.paren_level == 0 => {
-                    if error.is_none() && self.quotes == Quotes::None {
+                    if !self.variable && error.is_none() && !self.quotes {
                         error = Some(StatementError::InvalidCharacter(character as char, i + 1))
                     }
+                    self.variable = false;
                 }
                 b')' => self.paren_level -= 1,
-                b';' if self.quotes == Quotes::None && self.paren_level == 0 => {
+                b'}' if self.vbrace => self.vbrace = false,
+                // [^A-Za-z0-9_]
+                0...37 | 39...47 | 58 | 60...64 | 91...94 | 96 | 126...127 => self.variable = false,
+                _ if self.quotes => {}
+                b'{' => self.brace_level += 1,
+                b'}' => {
+                    if self.brace_level == 0 {
+                        if error.is_none() {
+                            error = Some(StatementError::InvalidCharacter(character as char, i + 1))
+                        }
+                    } else {
+                        self.brace_level -= 1;
+                    }
+                }
+                b';' if self.paren_level == 0 => {
                     let statement = self.get_statement(start, i);
                     self.logical = LogicalOp::None;
 
@@ -230,11 +205,7 @@ impl<'a> Iterator for StatementSplitter<'a> {
                         None => Some(Ok(statement)),
                     };
                 }
-                b'&' | b'|'
-                    if self.quotes == Quotes::None
-                        && self.paren_level == 0
-                        && last == Some(character) =>
-                {
+                b'&' | b'|' if self.paren_level == 0 && last == Some(character) => {
                     // Detecting if there is a 2nd `&` character
                     let statement = self.get_statement(start, i - 1);
                     self.logical = if character == b'&' { LogicalOp::And } else { LogicalOp::Or };
@@ -244,8 +215,6 @@ impl<'a> Iterator for StatementSplitter<'a> {
                         None => Some(Ok(statement)),
                     };
                 }
-                // [^A-Za-z0-9_]
-                0...47 | 58...64 | 91...94 | 96 | 123...127 => self.variable = false,
                 _ => {}
             }
             last = Some(character);
diff --git a/src/lib/shell/binary/readln.rs b/src/lib/shell/binary/readln.rs
index 015ecc9f837d8032d78ff4ff84f8dbc0408c3f3d..205366f9186adbcf58c50dc7da3c1ffb33aa4e61 100644
--- a/src/lib/shell/binary/readln.rs
+++ b/src/lib/shell/binary/readln.rs
@@ -1,26 +1,11 @@
-use super::super::{completer::*, flags, Binary, DirectoryStack, Shell, Variables};
-use crate::{sys, types};
+use super::super::{completer::*, flags, Binary, Shell};
+use crate::sys;
 use liner::{BasicCompleter, CursorPosition, Event, EventKind};
 use std::{env, io::ErrorKind, mem, path::PathBuf};
 
 pub(crate) fn readln(shell: &mut Shell) -> Option<String> {
-    let vars_ptr = &shell.variables as *const Variables;
-    let dirs_ptr = &shell.directory_stack as *const DirectoryStack;
-
-    // Collects the current list of values from history for completion.
-    let history = shell
-        .context
-        .as_ref()
-        .unwrap()
-        .history
-        .buffers
-        .iter()
-        // Map each underlying `liner::Buffer` into a `String`.
-        .map(|x| x.chars().cloned().collect())
-        // Collect each result into a vector to avoid borrowing issues.
-        .collect::<Vec<types::Str>>();
-
     let prompt = shell.prompt();
+    let dirs = &shell.directory_stack;
     let vars = &shell.variables;
     let builtins = &shell.builtins;
 
@@ -37,13 +22,10 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> {
                     CursorPosition::InSpace(None, _) => false,
                     CursorPosition::OnWordLeftEdge(index) => index >= 1,
                     CursorPosition::OnWordRightEdge(index) => {
-                        match (words.into_iter().nth(index), env::current_dir()) {
-                            (Some((start, end)), Ok(file)) => {
-                                let filename = editor.current_buffer().range(start, end);
-                                complete_as_file(&file, &filename, index)
-                            }
-                            _ => false,
-                        }
+                        words.into_iter().nth(index).and_then(|(start, end)| {
+                            let filename = editor.current_buffer().range(start, end);
+                            Some(complete_as_file(&env::current_dir().ok()?, &filename, index))
+                        }) == Some(true)
                     }
                 };
 
@@ -51,13 +33,21 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> {
                     .ok()
                     .as_ref()
                     .and_then(|dir| dir.to_str())
-                    .map(|dir| IonFileCompleter::new(Some(dir), dirs_ptr, vars_ptr));
+                    .map(|dir| IonFileCompleter::new(Some(dir), dirs, vars));
 
                 if filename {
                     if let Some(completer) = dir_completer {
                         mem::replace(&mut editor.context().completer, Some(Box::new(completer)));
                     }
                 } else {
+                    // Collects the current list of values from history for completion.
+                    let history = editor
+                        .context()
+                        .history
+                        .buffers
+                        .iter()
+                        // Map each underlying `liner::Buffer` into a `String`.
+                        .map(|x| x.chars().cloned().collect());
                     // Creates a list of definitions from the shell environment that
                     // will be used
                     // in the creation of a custom completer.
@@ -67,7 +57,7 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> {
                         // Add built-in commands to the completer's definitions.
                         .map(|&s| s.to_string())
                         // Add the history list to the completer's definitions.
-                        .chain(history.iter().map(|s| s.to_string()))
+                        .chain(history)
                         // Add the aliases to the completer's definitions.
                         .chain(vars.aliases().map(|(key, _)| key.to_string()))
                         // Add the list of available functions to the completer's
@@ -89,7 +79,7 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> {
                     let mut file_completers: Vec<_> = env::var("PATH")
                         .unwrap_or_else(|_| "/bin/".to_string())
                         .split(sys::PATH_SEPARATOR)
-                        .map(|s| IonFileCompleter::new(Some(s), dirs_ptr, vars_ptr))
+                        .map(|s| IonFileCompleter::new(Some(s), dirs, vars))
                         .collect();
 
                     // Also add files/directories in the current directory to the