From d29fe6f6dedcc58939df7c8441098610aeb46334 Mon Sep 17 00:00:00 2001 From: Koenraad Verheyden Date: Thu, 16 Jan 2020 01:38:16 +0100 Subject: [PATCH] External commands: wrap values that contain spaces in quotes (#1214) (#1220) * External commands: wrap values that contain spaces in quotes (#1214) * Add fn's argument_contains_whitespace & add_quotes (#1214) * Fix formatting with cargo fmt * Don't wrap argument in quotes when $it is already quoted (#1214) --- src/commands/classified/external.rs | 39 ++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/commands/classified/external.rs b/src/commands/classified/external.rs index a8e89a44d..f2de35729 100644 --- a/src/commands/classified/external.rs +++ b/src/commands/classified/external.rs @@ -113,6 +113,19 @@ async fn run_with_iterator_arg( } } }) + .map(|result| { + result.map(|value| { + if argument_contains_whitespace(&value) { + let arg = args.iter().find(|arg| arg.contains("$it")); + if let Some(arg) = arg { + if !argument_is_quoted(&arg) { + return add_quotes(&value); + } + } + } + value + }) + }) .collect::, ShellError>>()?; let home_dir = dirs::home_dir(); @@ -167,11 +180,19 @@ async fn run_with_iterator_arg( } } +pub fn argument_contains_whitespace(argument: &str) -> bool { + argument.chars().any(|c| c.is_whitespace()) +} + pub fn argument_is_quoted(argument: &str) -> bool { (argument.starts_with('"') && argument.ends_with('"') || (argument.starts_with('\'') && argument.ends_with('\''))) } +pub fn add_quotes(argument: &str) -> String { + format!("'{}'", argument) +} + pub fn remove_quotes(argument: &str) -> &str { let size = argument.len(); @@ -338,7 +359,10 @@ async fn run_with_stdin( #[cfg(test)] mod tests { - use super::{argument_is_quoted, remove_quotes, run_external_command, Context, OutputStream}; + use super::{ + add_quotes, argument_contains_whitespace, argument_is_quoted, remove_quotes, + run_external_command, Context, OutputStream, + }; use futures::executor::block_on; use futures::stream::TryStreamExt; use nu_errors::ShellError; @@ -419,6 +443,13 @@ mod tests { block_on(non_existent_run()) } + #[test] + fn checks_contains_whitespace_from_argument_to_be_passed_in() { + assert_eq!(argument_contains_whitespace("andrés"), false); + assert_eq!(argument_contains_whitespace("and rés"), true); + assert_eq!(argument_contains_whitespace(r#"and\ rés"#), true); + } + #[test] fn checks_quotes_from_argument_to_be_passed_in() { assert_eq!(argument_is_quoted("'andrés"), false); @@ -429,6 +460,12 @@ mod tests { assert_eq!(argument_is_quoted(r#""andrés""#), true); } + #[test] + fn adds_quotes_to_argument_to_be_passed_in() { + assert_eq!(add_quotes("andrés"), "'andrés'"); + assert_eq!(add_quotes("'andrés'"), "''andrés''"); + } + #[test] fn strips_quotes_from_argument_to_be_passed_in() { assert_eq!(remove_quotes(r#"'andrés'"#), "andrés");