Improve external quoting logic (#3579)

* Add tests and improve quoting logic

* fmt

* Fix clippy ling

* Fix clippy ling
This commit is contained in:
JT 2021-06-09 08:59:53 +12:00 committed by GitHub
parent e9de4c08b0
commit a021b99614
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 4 deletions

View File

@ -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)]

View File

@ -25,6 +25,15 @@ pub fn cococo() {
}
}
pub fn meow() {
let args: Vec<String> = 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));
}

View File

@ -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(),
}
}

View File

@ -44,7 +44,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.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<dyn Error>> {
match bin {
"echo_env" => binaries::echo_env(),
"cococo" => binaries::cococo(),
"meow" => binaries::meow(),
"iecho" => binaries::iecho(),
"fail" => binaries::fail(),
"nonu" => binaries::nonu(),

View File

@ -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 {