diff --git a/src/lib/parser/quotes.rs b/src/lib/parser/quotes.rs
index 1f2690f59ae70447f2b17fec3a903b753e08e590..43773b60bf3f9dbc9ca18324af46abd92808fbfb 100644
--- a/src/lib/parser/quotes.rs
+++ b/src/lib/parser/quotes.rs
@@ -1,14 +1,11 @@
-use std::str;
+use itertools::Itertools;
+use std::{iter::Peekable, mem, str};
 
 bitflags! {
     pub struct Flags : u8 {
         const SQUOTE = 1;
         const DQUOTE = 2;
         const TRIM   = 4;
-        const ARRAY  = 8;
-        const COMM   = 16;
-        const EOF    = 32;
-        const ERROR  = 64;
     }
 }
 
@@ -36,140 +33,176 @@ impl From<String> for Terminator {
     fn from(string: String) -> Terminator { Terminator::new(string) }
 }
 
+#[derive(Debug)]
+enum NotTerminatedErr {
+    StartEof,
+    Eof,
+    Comment,
+    UnclosedArray,
+    UnclosedString,
+    EscapedNewline,
+    AndOrClause,
+}
+
+#[derive(Clone, Debug)]
+pub struct RearPeekable<I: Iterator> {
+    iter: Peekable<I>,
+    now:  Option<I::Item>,
+    last: Option<I::Item>,
+}
+
+impl<I> Iterator for RearPeekable<I>
+where
+    I: Iterator,
+    I::Item: Copy,
+{
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<I::Item> {
+        let next = self.iter.next();
+        if next.is_some() {
+            self.last = mem::replace(&mut self.now, next);
+        }
+        next
+    }
+}
+
+impl<I: Iterator> RearPeekable<I> {
+    #[inline]
+    pub fn peek(&mut self) -> Option<&I::Item> { self.iter.peek() }
+
+    #[inline]
+    pub fn prev(&self) -> Option<&I::Item> { self.last.as_ref() }
+
+    #[inline]
+    pub fn now(&self) -> Option<&I::Item> { self.now.as_ref() }
+}
+
 impl Terminator {
     /// Consumes the `Terminator`, and returns the underlying `String`.
     pub fn consume(self) -> String { self.buffer }
 
-    pub fn is_terminated(&mut self) -> bool {
-        let mut eof_line = None;
-        let eof = self.eof.clone();
-        let status = if let Some(ref eof) = eof {
-            let line = &self.eof_buffer;
-            eof_line = Some([&line, "\n"].concat());
-            line.trim() == eof
-        } else {
-            {
-                let mut instance = Flags::empty();
-                {
-                    let mut bytes = self.buffer.bytes().skip(self.read);
-                    while let Some(character) = bytes.next() {
-                        self.read += 1;
-                        match character {
-                            b'\\' => {
-                                let _ = bytes.next();
-                            }
-                            b'\'' if !self.flags.intersects(Flags::DQUOTE) => {
-                                self.flags ^= Flags::SQUOTE
-                            }
-                            b'"' if !self.flags.intersects(Flags::SQUOTE) => {
-                                self.flags ^= Flags::DQUOTE
-                            }
-                            b'<' if !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => {
-                                let as_bytes = self.buffer.as_bytes();
-                                if Some(&b'<') == as_bytes.get(self.read) {
-                                    self.read += 1;
-                                    if Some(&b'<') != as_bytes.get(self.read) {
-                                        let eof_phrase = unsafe {
-                                            str::from_utf8_unchecked(&as_bytes[self.read..])
-                                        };
-                                        self.eof = Some(eof_phrase.trim().to_owned());
-                                        instance |= Flags::EOF;
-                                        break;
-                                    }
-                                }
-                            }
-                            b'[' if !self.flags.intersects(Flags::DQUOTE | Flags::SQUOTE) => {
-                                self.flags |= Flags::ARRAY;
-                                self.array += 1;
-                            }
-                            b']' if !self.flags.intersects(Flags::DQUOTE | Flags::SQUOTE) => {
-                                if self.array > 0 {
-                                    self.array -= 1;
-                                } else if self.array == 0 && self.flags.contains(Flags::ARRAY) {
-                                    instance |= Flags::ERROR;
-                                    break;
-                                }
-
-                                if self.array == 0 {
-                                    self.flags -= Flags::ARRAY
-                                }
-                            }
-                            b'#' if !self.flags.intersects(Flags::DQUOTE | Flags::SQUOTE) => {
-                                if self.read > 1 {
-                                    let character =
-                                        self.buffer.as_bytes().get(self.read - 2).unwrap();
-                                    if [b' ', b'\n'].contains(character) {
-                                        instance |= Flags::COMM;
-                                        break;
-                                    }
-                                } else {
-                                    instance |= Flags::COMM;
-                                    break;
-                                }
-                            }
-                            _ => (),
-                        }
+    fn pair_components(&mut self) -> Result<(), NotTerminatedErr> {
+        if self.eof.as_ref() == Some(&self.eof_buffer) {
+            return Err(NotTerminatedErr::StartEof);
+        } else if self.eof.is_some() {
+            return Err(NotTerminatedErr::Eof);
+        }
+
+        let bytes = self
+            .buffer
+            .bytes()
+            .enumerate()
+            .skip(self.read)
+            .coalesce(|prev, next| {
+                if prev.1 == b'\\' {
+                    Ok((next.0, 0))
+                } else {
+                    Err((prev, next))
+                }
+            })
+            .filter(|&(_, c)| c != 0)
+            .peekable();
+
+        let mut bytes = RearPeekable {
+            iter: bytes,
+            now:  None,
+            last: None,
+        };
+
+        while let Some((i, character)) = bytes.next() {
+            self.read = i + 1;
+
+            match character {
+                b'\'' if !self.flags.intersects(Flags::DQUOTE) => {
+                    if bytes.find(|&(_, c)| c == b'\'').is_none() {
+                        self.flags ^= Flags::SQUOTE;
                     }
                 }
-                if instance.contains(Flags::ERROR) {
-                    self.buffer.clear();
-                    self.buffer.push('\n');
-                    return true;
-                } else if instance.contains(Flags::EOF) {
-                    self.buffer.push('\n');
-                    return false;
-                } else if instance.contains(Flags::COMM) {
-                    self.buffer.truncate(self.read - 1);
-                    return !self
-                        .flags
-                        .intersects(Flags::SQUOTE | Flags::DQUOTE | Flags::ARRAY);
+                b'"' if !self.flags.intersects(Flags::SQUOTE) => {
+                    if bytes.find(|&(_, c)| c == b'"').is_none() {
+                        self.flags ^= Flags::DQUOTE;
+                    }
                 }
-            }
-
-            if self
-                .flags
-                .intersects(Flags::SQUOTE | Flags::DQUOTE | Flags::ARRAY)
-            {
-                if let Some(b'\\') = self.buffer.bytes().last() {
-                    let _ = self.buffer.pop();
-                    self.read -= 1;
-                    self.flags |= Flags::TRIM;
-                } else {
-                    self.read += 1;
-                    self.buffer.push(if self.flags.contains(Flags::ARRAY) {
-                        ' '
+                b'<' if bytes.prev() == Some(&(i - 1, b'<')) => {
+                    if bytes.peek() == Some(&(i + 1, b'<')) {
+                        bytes.next();
                     } else {
-                        '\n'
-                    });
+                        let bytes = &self.buffer.as_bytes()[self.read..];
+                        let eof_phrase = unsafe { str::from_utf8_unchecked(bytes) };
+                        self.eof = Some(eof_phrase.trim().to_owned());
+                        return Err(NotTerminatedErr::Eof);
+                    }
                 }
-                false
-            } else if let Some(b'\\') = self.buffer.bytes().last() {
-                let _ = self.buffer.pop();
-                self.read -= 1;
-                self.flags |= Flags::TRIM;
-                false
-            } else {
-                // If the last two bytes are either '&&' or '||', we aren't terminated yet.
-                let bytes = self.buffer.as_bytes();
-                if bytes.len() >= 2 {
-                    let bytes = &bytes[bytes.len() - 2..];
-                    bytes != [b'&', b'&'] && bytes != [b'|', b'|']
-                } else {
-                    true
+                b'[' => {
+                    self.array += 1;
                 }
+                b']' => {
+                    if self.array > 0 {
+                        self.array -= 1;
+                    }
+                }
+                b'#' if bytes
+                    .prev()
+                    .filter(|&(j, c)| !(*j == i - 1 && [b' ', b'\n'].contains(c)))
+                    .is_none() =>
+                {
+                    return Err(NotTerminatedErr::Comment);
+                }
+                _ => (),
             }
-        };
+        }
 
-        if let Some(line) = eof_line {
-            self.buffer.push_str(&line);
+        if let Some((_, b'\\')) = bytes.now() {
+            Err(NotTerminatedErr::EscapedNewline)
+        } else if self.array > 0 {
+            Err(NotTerminatedErr::UnclosedArray)
+        } else if self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) {
+            Err(NotTerminatedErr::UnclosedString)
+        } else if bytes
+            .now()
+            .filter(|&&(_, now)| now == b'&' || now == b'|')
+            .and_then(|&(_, now)| bytes.prev().filter(|&&(_, prev)| prev == now))
+            .is_some()
+        {
+            Err(NotTerminatedErr::AndOrClause)
+        } else {
+            Ok(())
         }
-        if self.eof.is_some() {
-            self.eof_buffer.clear();
-            if status {
+    }
+
+    pub fn is_terminated(&mut self) -> bool {
+        match self.pair_components() {
+            Err(NotTerminatedErr::StartEof) => {
                 self.eof = None;
+                self.buffer.push('\n');
+                true
+            }
+            Err(NotTerminatedErr::Eof) => false,
+            Err(NotTerminatedErr::Comment) => {
+                self.buffer.truncate(self.read - 1);
+                self.array == 0 && !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE)
+            }
+            Err(NotTerminatedErr::EscapedNewline) => {
+                self.buffer.pop();
+                self.read -= 1;
+                self.flags |= Flags::TRIM;
+                false
+            }
+            Err(NotTerminatedErr::UnclosedString) => {
+                self.read += 1;
+                self.buffer.push('\n');
+                false
             }
+            Err(NotTerminatedErr::UnclosedArray) => {
+                self.read += 1;
+                self.buffer.push(' ');
+                false
+            }
+            Err(NotTerminatedErr::AndOrClause) => false,
+            Ok(()) => true,
         }
-        status
     }
 
     /// Appends a string to the internal buffer.
@@ -181,7 +214,10 @@ impl Terminator {
                 input
             });
         } else {
-            self.eof_buffer.push_str(input);
+            self.eof_buffer.clear();
+            self.eof_buffer.push_str(input.trim());
+            self.buffer.push('\n');
+            self.buffer.push_str(input);
         }
     }
 
diff --git a/src/lib/shell/binary/terminate.rs b/src/lib/shell/binary/terminate.rs
index 47b742992ac82e8c498a7ffc4d570cbdfde55b78..0b2900c354fe0860cb698e94f7d4cc2dd2c53783 100644
--- a/src/lib/shell/binary/terminate.rs
+++ b/src/lib/shell/binary/terminate.rs
@@ -8,30 +8,11 @@ pub(crate) fn terminate_script_quotes<I: Iterator<Item = String>>(
     while let Some(command) = lines.next() {
         let mut buffer = Terminator::new(command);
         while !buffer.is_terminated() {
-            loop {
-                if let Some(command) = lines.next() {
-                    if !command.starts_with('#') {
-                        let mut start = 0;
-                        let cmd: &str = loop {
-                            if start >= command.len() {
-                                break &command;
-                            }
-
-                            match command[start..].find('#').map(|x| x + start) {
-                                Some(pos) if command.as_bytes()[pos - 1] != b' ' => {
-                                    start = pos + 1;
-                                }
-                                Some(pos) => break &command[..pos],
-                                None => break &command,
-                            }
-                        };
-                        buffer.append(cmd);
-                        break;
-                    }
-                } else {
-                    eprintln!("ion: unterminated quote in script");
-                    return FAILURE;
-                }
+            if let Some(command) = lines.find(|cmd| !cmd.starts_with('#')) {
+                buffer.append(command.split(" #").next().unwrap_or(&command));
+            } else {
+                eprintln!("ion: unterminated quote in script");
+                return FAILURE;
             }
         }
         shell.on_command(&buffer.consume());
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index a098e672b1cc2ae9921c849e313f11ce8fff8cfb..a79ba0d81205daf1d894b80239c07ca774029073 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -124,9 +124,9 @@ pub struct Shell {
 pub struct ShellBuilder;
 
 impl ShellBuilder {
-    pub fn as_binary(self) -> Shell { Shell::new(false) }
+    pub fn as_binary(&self) -> Shell { Shell::new(false) }
 
-    pub fn as_library(self) -> Shell { Shell::new(true) }
+    pub fn as_library(&self) -> Shell { Shell::new(true) }
 
     pub fn set_unique_pid(self) -> ShellBuilder {
         if let Ok(pid) = sys::getpid() {