Skip to content
Snippets Groups Projects
Commit 4d971dd4 authored by Michael Aaron Murphy's avatar Michael Aaron Murphy
Browse files

Implement !0, !^, and !*

parent 1147ac57
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ use std::process::{Command, Stdio}; ...@@ -4,6 +4,7 @@ use std::process::{Command, Stdio};
// use glob::glob; // use glob::glob;
use super::Shell; use super::Shell;
use parser::ArgumentSplitter;
use parser::expand_string; use parser::expand_string;
use parser::pipelines::RedirectFrom; use parser::pipelines::RedirectFrom;
use smallstring::SmallString; use smallstring::SmallString;
...@@ -41,41 +42,66 @@ impl Job { ...@@ -41,41 +42,66 @@ impl Job {
pub(crate) fn expand(&mut self, shell: &Shell) { pub(crate) fn expand(&mut self, shell: &Shell) {
let mut expanded = Array::new(); let mut expanded = Array::new();
expanded.grow(self.args.len()); expanded.grow(self.args.len());
expanded.extend(self.args.drain().flat_map(|arg| if arg == "!!" { expanded.extend(self.args.drain().flat_map(|arg| match arg.as_str() {
expand_last_command(shell, false) "!!" => expand_last_command(shell, Operation::All),
} else if arg == "!$" { "!$" => expand_last_command(shell, Operation::LastArg),
expand_last_command(shell, true) "!0" => expand_last_command(shell, Operation::Command),
} else { "!^" => expand_last_command(shell, Operation::FirstArg),
expand_arg(&arg, shell) "!*" => expand_last_command(shell, Operation::NoCommand),
_ => expand_arg(&arg, shell),
})); }));
self.args = expanded; self.args = expanded;
} }
} }
pub(crate) enum Operation {
LastArg,
FirstArg,
Command,
NoCommand,
All,
}
/// Expands the last command that was provided to the shell. /// Expands the last command that was provided to the shell.
/// ///
/// If `args_only` is set to `true`, then only the arguments of /// If `last_arg` is set to `true`, then only the last argument of
/// the last command will be expanded. /// the last command will be expanded.
fn expand_last_command(shell: &Shell, args_only: bool) -> Array { pub(crate) fn expand_last_command(shell: &Shell, operation: Operation) -> Array {
// Strips the command from the supplied buffer. fn get_last_arg(buffer: &str) -> &str { ArgumentSplitter::new(buffer).last().unwrap_or(buffer) }
fn get_args(buffer: &[u8]) -> &[u8] {
if let Some(pos) = buffer.iter().position(|&x| x == b' ') { fn get_first_arg(buffer: &str) -> &str {
let buffer = &buffer[pos + 1..]; ArgumentSplitter::new(buffer).skip(1).next().unwrap_or(buffer)
}
fn get_command(buffer: &str) -> &str { ArgumentSplitter::new(buffer).next().unwrap_or(buffer) }
fn get_args(buffer: &str) -> &str {
let bbuffer = buffer.as_bytes();
if let Some(pos) = bbuffer.iter().position(|&x| x == b' ') {
let buffer = &bbuffer[pos + 1..];
if let Some(pos) = buffer.iter().position(|&x| x != b' ') { if let Some(pos) = buffer.iter().position(|&x| x != b' ') {
return &buffer[pos..]; return unsafe { str::from_utf8_unchecked(&buffer[pos..]) };
} }
} }
&buffer buffer
}
fn expand_args(buffer: &str, shell: &Shell) -> Array {
ArgumentSplitter::new(buffer).flat_map(|b| expand_arg(b, shell)).collect::<Array>()
} }
if let Some(ref context) = shell.context { if let Some(ref context) = shell.context {
if let Some(buffer) = context.history.buffers.iter().last() { if let Some(buffer) = context.history.buffers.iter().last() {
let buffer = buffer.as_bytes(); let buffer = buffer.as_bytes();
let last_arg = unsafe { let buffer = unsafe { str::from_utf8_unchecked(&buffer) };
str::from_utf8_unchecked(if args_only { get_args(&buffer) } else { &buffer }) return match operation {
Operation::LastArg => expand_arg(get_last_arg(buffer), shell),
Operation::FirstArg => expand_arg(get_first_arg(buffer), shell),
Operation::Command => expand_arg(get_command(buffer), shell),
Operation::NoCommand => expand_args(get_args(buffer), shell),
Operation::All => expand_args(buffer, shell),
}; };
return expand_arg(&last_arg, shell);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment