diff --git a/src/parser/pipelines/mod.rs b/src/parser/pipelines/mod.rs
index cb28fbacd2fc207699310c0a19d5daec4a073420..76d12083777391900f7e408ea5523faa6f343594 100644
--- a/src/parser/pipelines/mod.rs
+++ b/src/parser/pipelines/mod.rs
@@ -2,8 +2,8 @@ mod collector;
 
 pub(crate) use self::collector::*;
 
-use super::{expand_string, Expander};
-use shell::{Job, JobKind};
+use super::expand_string;
+use shell::{Job, JobKind, Shell};
 use std::fmt;
 
 #[derive(Debug, PartialEq, Clone, Copy)]
@@ -52,22 +52,20 @@ impl PipeItem {
         }
     }
 
-    pub(crate) fn expand<E: Expander>(&mut self, expanders: &E) {
-        self.job.expand(expanders);
+    pub(crate) fn expand(&mut self, shell: &Shell) {
+        self.job.expand(shell);
 
         for input in self.inputs.iter_mut() {
             *input = match input {
-                &mut Input::File(ref s) => {
-                    Input::File(expand_string(s, expanders, false).join(" "))
-                }
+                &mut Input::File(ref s) => Input::File(expand_string(s, shell, false).join(" ")),
                 &mut Input::HereString(ref s) => {
-                    Input::HereString(expand_string(s, expanders, true).join(" "))
+                    Input::HereString(expand_string(s, shell, true).join(" "))
                 }
             };
         }
 
         for output in self.outputs.iter_mut() {
-            output.file = expand_string(output.file.as_str(), expanders, false).join(" ");
+            output.file = expand_string(output.file.as_str(), shell, false).join(" ");
         }
     }
 }
@@ -75,8 +73,8 @@ impl PipeItem {
 impl Pipeline {
     pub(crate) fn new() -> Self { Pipeline { items: Vec::new() } }
 
-    pub(crate) fn expand<E: Expander>(&mut self, expanders: &E) {
-        self.items.iter_mut().for_each(|i| i.expand(expanders));
+    pub(crate) fn expand(&mut self, shell: &Shell) {
+        self.items.iter_mut().for_each(|i| i.expand(shell));
     }
 
     pub(crate) fn requires_piping(&self) -> bool {
diff --git a/src/parser/shell_expand/words/mod.rs b/src/parser/shell_expand/words/mod.rs
index 2176f773dc7cef453297ba62d7f84e2b9801a91b..b44e4ebd79d4e5aa645471d84de77ac860b0551f 100644
--- a/src/parser/shell_expand/words/mod.rs
+++ b/src/parser/shell_expand/words/mod.rs
@@ -686,6 +686,11 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> {
                             self.read += 2;
                             return Some(self.braced_array_variable(&mut iterator));
                         }
+                        Some(b' ') | None => {
+                            self.read += 1;
+                            let output = &self.data[start..self.read];
+                            return Some(WordToken::Normal(output, glob, tilde));
+                        }
                         _ => {
                             self.read += 1;
                             return Some(self.array_variable(&mut iterator));
@@ -714,6 +719,11 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> {
                                 self.read += 2;
                                 return Some(self.braced_variable(&mut iterator));
                             }
+                            Some(b' ') | None => {
+                                self.read += 1;
+                                let output = &self.data[start..self.read];
+                                return Some(WordToken::Normal(output, glob, tilde));
+                            }
                             _ => {
                                 self.read += 1;
                                 return Some(self.variable(&mut iterator));
@@ -781,6 +791,13 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> {
                     return Some(WordToken::Normal(&self.data[start..self.read], glob, tilde))
                 }
                 b'$' | b'@' if !self.flags.contains(SQUOTE) => {
+                    if let Some(&character) = self.data.as_bytes().get(self.read) {
+                        if character == b' ' {
+                            self.read += 1;
+                            let output = &self.data[start..self.read];
+                            return Some(WordToken::Normal(output, glob, tilde));
+                        }
+                    }
                     let output = &self.data[start..self.read];
                     if output != "" {
                         return Some(WordToken::Normal(output, glob, tilde));
diff --git a/src/shell/job.rs b/src/shell/job.rs
index b0916b0fd73ba38bfbca8e06699720be81b24099..89858e9299b7007ef7ec6efd796b18041875fcef 100644
--- a/src/shell/job.rs
+++ b/src/shell/job.rs
@@ -3,9 +3,11 @@ use std::process::{Command, Stdio};
 
 // use glob::glob;
 
-use parser::{expand_string, Expander};
+use super::Shell;
+use parser::expand_string;
 use parser::pipelines::RedirectFrom;
 use smallstring::SmallString;
+use std::str;
 use types::*;
 
 #[derive(Debug, PartialEq, Clone, Copy)]
@@ -36,21 +38,60 @@ impl Job {
 
     /// Takes the current job's arguments and expands them, one argument at a
     /// time, returning a new `Job` with the expanded arguments.
-    pub(crate) fn expand<E: Expander>(&mut self, expanders: &E) {
+    pub(crate) fn expand(&mut self, shell: &Shell) {
         let mut expanded = Array::new();
         expanded.grow(self.args.len());
-        expanded.extend(self.args.drain().flat_map(|arg| {
-            let res = expand_string(&arg, expanders, false);
-            if res.is_empty() {
-                array![""]
-            } else {
-                res
-            }
+        expanded.extend(self.args.drain().flat_map(|arg| if arg == "!!" {
+            expand_last_command(shell, false)
+        } else if arg == "!$" {
+            expand_last_command(shell, true)
+        } else {
+            expand_arg(&arg, shell)
         }));
         self.args = expanded;
     }
 }
 
+/// Expands the last command that was provided to the shell.
+///
+/// If `args_only` is set to `true`, then only the arguments of
+/// the last command will be expanded.
+fn expand_last_command(shell: &Shell, args_only: bool) -> Array {
+    // Strips the command from the supplied buffer.
+    fn get_args(buffer: &[u8]) -> &[u8] {
+        if let Some(pos) = buffer.iter().position(|&x| x == b' ') {
+            let buffer = &buffer[pos + 1..];
+            if let Some(pos) = buffer.iter().position(|&x| x != b' ') {
+                return &buffer[pos..];
+            }
+        }
+
+        &buffer
+    }
+
+    if let Some(ref context) = shell.context {
+        if let Some(buffer) = context.history.buffers.iter().last() {
+            let buffer = buffer.as_bytes();
+            let last_arg = unsafe {
+                str::from_utf8_unchecked(if args_only { get_args(&buffer) } else { &buffer })
+            };
+            return expand_arg(&last_arg, shell);
+        }
+    }
+
+    array![""]
+}
+
+/// Expands a given argument and returns it as an `Array`.
+fn expand_arg(arg: &str, shell: &Shell) -> Array {
+    let res = expand_string(&arg, shell, false);
+    if res.is_empty() {
+        array![""]
+    } else {
+        res
+    }
+}
+
 /// This represents a job that has been processed and expanded to be run
 /// as part of some pipeline
 pub(crate) enum RefinedJob {
@@ -288,9 +329,10 @@ mod tests {
 
     #[test]
     fn preserve_empty_arg() {
+        let shell = Shell::new();
         let job = Job::new(array!("rename", "", "0", "a"), JobKind::Last);
         let mut expanded = job.clone();
-        expanded.expand(&Empty);
+        expanded.expand(&shell);
         assert_eq!(job, expanded);
     }
 
diff --git a/src/sys/redox.rs b/src/sys/redox.rs
index cd1145c864b67e9ead5bd8863b5365b2ece61057..ba903b5e60499abe2a7107bc2ecbc8b414c8e027 100644
--- a/src/sys/redox.rs
+++ b/src/sys/redox.rs
@@ -83,12 +83,7 @@ pub(crate) fn dup2(old: RawFd, new: RawFd) -> io::Result<RawFd> {
 
 pub(crate) fn close(fd: RawFd) -> io::Result<()> { cvt(syscall::close(fd)).and(Ok(())) }
 
-pub(crate) fn close_stdin()
-// fn close_stdin() // fn close_stdin() // fn close_stdin() // fn
-// close_stdin()
-{
-    syscall::close(STDIN_FILENO);
-}
+pub(crate) fn close_stdin() { syscall::close(STDIN_FILENO); }
 
 pub(crate) fn isatty(fd: RawFd) -> bool {
     if let Ok(tfd) = syscall::dup(fd, b"termios") {
@@ -106,16 +101,12 @@ fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
 
 // TODO
 pub mod signals {
-    pub(crate) fn block() // fn block() // fn block() // fn block() // fn block()
-    {
-    }
+    pub(crate) fn block() {}
 
     /// Unblocks the SIGTSTP/SIGTTOU/SIGTTIN/SIGCHLD signals so children processes can be
     /// controlled
     /// by the shell.
-    pub(crate) fn unblock() // fn unblock() // fn unblock() // fn unblock() // fn unblock()
-    {
-    }
+    pub(crate) fn unblock() {}
 }
 
 pub mod job_control {
diff --git a/src/sys/unix/mod.rs b/src/sys/unix/mod.rs
index cb70ecf6595d86e4c1b867ccb13a573b46e9b815..2da1f77b073215ba85189f5ff13ab9fcf3ed5eae 100644
--- a/src/sys/unix/mod.rs
+++ b/src/sys/unix/mod.rs
@@ -80,10 +80,7 @@ pub(crate) fn dup2(old: RawFd, new: RawFd) -> io::Result<RawFd> {
 
 pub(crate) fn close(fd: RawFd) -> io::Result<()> { cvt(unsafe { libc::close(fd) }).and(Ok(())) }
 
-pub(crate) fn close_stdin()
-// fn close_stdin() // fn close_stdin() // fn close_stdin() // fn
-// close_stdin()
-{
+pub(crate) fn close_stdin() {
     unsafe {
         libc::close(STDIN_FILENO);
     }