From a021b99614d86f2e4434d3c2e7471e7c6fb8560a Mon Sep 17 00:00:00 2001 From: JT Date: Wed, 9 Jun 2021 08:59:53 +1200 Subject: [PATCH] Improve external quoting logic (#3579) * Add tests and improve quoting logic * fmt * Fix clippy ling * Fix clippy ling --- .../src/commands/classified/external.rs | 23 +++++++++++++++++- crates/nu-command/src/utils/test_bins.rs | 9 +++++++ crates/nu-protocol/src/value/column_path.rs | 1 - src/main.rs | 3 ++- tests/shell/pipeline/commands/external.rs | 24 ++++++++++++++++++- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/src/commands/classified/external.rs b/crates/nu-command/src/commands/classified/external.rs index c05c0a159..b99856430 100644 --- a/crates/nu-command/src/commands/classified/external.rs +++ b/crates/nu-command/src/commands/classified/external.rs @@ -38,6 +38,21 @@ pub(crate) fn run_external_command( run_with_stdin(command, context, input, external_redirection) } +#[allow(unused)] +fn trim_double_quotes(input: &str) -> String { + let mut chars = input.chars(); + + match (chars.next(), chars.next_back()) { + (Some('"'), Some('"')) => chars.collect(), + _ => input.to_string(), + } +} + +#[allow(unused)] +fn escape_where_needed(input: &str) -> String { + input.split(' ').join("\\ ").split('\'').join("\\'") +} + fn run_with_stdin( command: ExternalCommand, context: &mut EvaluationContext, @@ -81,6 +96,7 @@ fn run_with_stdin( } _ => { let trimmed_value_string = value.as_string()?.trim_end_matches('\n').to_string(); + //let trimmed_value_string = trim_quotes(&trimmed_value_string); command_args.push((trimmed_value_string, is_literal)); } } @@ -108,7 +124,12 @@ fn run_with_stdin( let escaped = escape_double_quotes(&arg); add_double_quotes(&escaped) } else { - arg.as_ref().to_string() + let trimmed = trim_double_quotes(&arg); + if trimmed != arg { + escape_where_needed(&trimmed) + } else { + trimmed + } } } #[cfg(windows)] diff --git a/crates/nu-command/src/utils/test_bins.rs b/crates/nu-command/src/utils/test_bins.rs index 8fb9cd185..b02f00e09 100644 --- a/crates/nu-command/src/utils/test_bins.rs +++ b/crates/nu-command/src/utils/test_bins.rs @@ -25,6 +25,15 @@ pub fn cococo() { } } +pub fn meow() { + let args: Vec = args(); + + for arg in args.iter().skip(1) { + let contents = std::fs::read_to_string(arg).expect("Expected a filepath"); + println!("{}", contents); + } +} + pub fn nonu() { args().iter().skip(1).for_each(|arg| print!("{}", arg)); } diff --git a/crates/nu-protocol/src/value/column_path.rs b/crates/nu-protocol/src/value/column_path.rs index c35a4c975..12464e39a 100644 --- a/crates/nu-protocol/src/value/column_path.rs +++ b/crates/nu-protocol/src/value/column_path.rs @@ -199,7 +199,6 @@ fn trim_quotes(input: &str) -> String { match (chars.next(), chars.next_back()) { (Some('\''), Some('\'')) => chars.collect(), (Some('"'), Some('"')) => chars.collect(), - (Some('`'), Some('`')) => chars.collect(), _ => input.to_string(), } } diff --git a/src/main.rs b/src/main.rs index 5f98ea6b4..cc97bfa73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,7 +44,7 @@ fn main() -> Result<(), Box> { .long("testbin") .value_name("TESTBIN") .possible_values(&[ - "echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", + "echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow", ]) .takes_value(true), ) @@ -90,6 +90,7 @@ fn main() -> Result<(), Box> { match bin { "echo_env" => binaries::echo_env(), "cococo" => binaries::cococo(), + "meow" => binaries::meow(), "iecho" => binaries::iecho(), "fail" => binaries::fail(), "nonu" => binaries::nonu(), diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 56e9102b7..7c5480eb4 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -199,7 +199,8 @@ mod stdin_evaluation { mod external_words { use super::nu; - + use nu_test_support::fs::Stub::FileWithContent; + use nu_test_support::{pipeline, playground::Playground}; #[test] fn relaxed_external_words() { let actual = nu!(cwd: ".", r#" @@ -217,6 +218,27 @@ mod external_words { assert_eq!(actual.out, "test \"things\""); } + + #[test] + fn external_arg_with_quotes() { + Playground::setup("external_arg_with_quotes", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContent( + "sample.toml", + r#" + nu_party_venue = "zion" + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + nu --testbin meow "sample.toml" | from toml | get nu_party_venue + "# + )); + + assert_eq!(actual.out, "zion"); + }) + } } mod nu_commands {