Skip to content
This repository has been archived by the owner on Dec 29, 2021. It is now read-only.

Commit

Permalink
Introduce a glorious new cli arg splitter
Browse files Browse the repository at this point in the history
Allow &str and &[&str] as input for `command`

Fixes #25
  • Loading branch information
killercup committed Mar 23, 2017
1 parent b386d23 commit a04a0e1
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ pub use macros::flatten_escaped_string;
mod output;
use output::{OutputAssertion, StdErr, StdOut};

mod parse_cmd;
use parse_cmd::ToCmd;

mod diff;

/// Assertions for a specific command.
Expand Down Expand Up @@ -178,9 +181,16 @@ impl Assert {
/// assert_cli::Assert::command(&["echo", "1337"])
/// .unwrap();
/// ```
pub fn command(cmd: &[&str]) -> Self {
///
/// ```rust
/// extern crate assert_cli;
///
/// assert_cli::Assert::command("echo 1337")
/// .unwrap();
/// ```
pub fn command<'a, T: ToCmd<'a> + ?Sized>(cmd: &'a T) -> Self {
Assert {
cmd: cmd.into_iter().cloned().map(String::from).collect(),
cmd: cmd.to_cmd(),
..Self::default()
}
}
Expand Down
98 changes: 98 additions & 0 deletions src/parse_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
pub trait ToCmd<'a> {
fn to_cmd(&'a self) -> Vec<String>;
}

impl<'a> ToCmd<'a> for str {
fn to_cmd(&'a self) -> Vec<String> {
let mut args = Vec::new();
let mut current_arg = String::new();
let mut in_quote = Vec::new();

for c in self.chars() {
if in_quote.is_empty() && c.is_whitespace() {
args.push(current_arg);
current_arg = String::new();
continue;
}

current_arg.push(c);

if c == '"' || c == '\'' {
if in_quote.last() == Some(&c) {
in_quote.pop();
} else {
in_quote.push(c);
}
}
}

if !current_arg.is_empty() {
args.push(current_arg);
}

args
}
}

impl<'a, 'b, T> ToCmd<'a> for T where
&'a T: AsRef<[&'b str]>,
T: 'a,
{
fn to_cmd(&'a self) -> Vec<String> {
self.as_ref().into_iter().map(|x| x.to_string()).collect()
}
}

#[cfg(test)]
mod test {
use super::ToCmd;

#[test]
fn slices() {
assert_eq!(
ToCmd::to_cmd(&["echo", "42"]),
vec!["echo", "42"]
);
}

#[test]
fn simple() {
assert_eq!(
"echo 42".to_cmd(),
vec!["echo", "42"]
);
assert_eq!(
r#"echo "42""#.to_cmd(),
vec!["echo", "\"42\""]
);
assert_eq!(
r#"echo '42'"#.to_cmd(),
vec!["echo", "\'42\'"]
);
assert_eq!(
r#"echo '42 is the answer'"#.to_cmd(),
vec!["echo", "\'42 is the answer\'"]
);
}

#[test]
fn real_world() {
assert_eq!(
r#"cargo run --bin whatever -- --input="Lorem ipsum" -f"#.to_cmd(),
vec!["cargo", "run", "--bin", "whatever", "--", "--input=\"Lorem ipsum\"", "-f"]
);
}

#[test]
fn nested_quotes() {
assert_eq!(
r#"echo "lorem ipsum 'dolor' sit amet""#.to_cmd(),
vec!["echo", "\"lorem ipsum 'dolor' sit amet\""]
);

assert_eq!(
r#"echo "lorem ipsum ('dolor "doloris" septetur') sit amet""#.to_cmd(),
vec!["echo", "\"lorem ipsum ('dolor \"doloris\" septetur') sit amet\""]
);
}
}

0 comments on commit a04a0e1

Please sign in to comment.