diff options
author | Wind <WindSoilder@outlook.com> | 2024-09-23 19:44:51 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-23 06:44:51 -0500 |
commit | 183c2221bbe7a997a7c7ff2638b584f3c2d39f58 (patch) | |
tree | 106d4b423120ba6bea0bdfa2377f3273233b3c19 | |
parent | 03ee54a4df36889fa6accc52a8d33b1a21717732 (diff) |
Removes more quotes on external command arguments (#13883)
# Description
Fixes: #13662
I don't think nushell need to parse and keep nested quote on external
command arguments. Some nested quote is safe to removed. After the pr,
nushell will behave more likely to bash.
# User-Facing Changes
#### Before
```
> ^echo {a:1,b:'c',c:'d'}
{a:1,b:c',c:'d}
```
#### After
```
> ^echo {a:1,b:'c',c:'d'}
{a:1,b:c,c:d}
```
# Tests + Formatting
Added some tests to cover the behavior
-rw-r--r-- | crates/nu-parser/src/parser.rs | 27 | ||||
-rw-r--r-- | crates/nu-parser/tests/test_parser.rs | 25 |
2 files changed, 29 insertions, 23 deletions
diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 3a84defe9..57be8ec82 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -258,7 +258,6 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre from: usize, quote_char: u8, escaped: bool, - depth: i32, }, } // Find the spans of parts of the string that can be parsed as their own strings for @@ -287,7 +286,6 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre from: index, quote_char: ch, escaped: false, - depth: 1, }; } b'$' => { @@ -300,7 +298,6 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre from: index, quote_char, escaped: false, - depth: 1, }; // Skip over two chars (the dollar sign and the quote) index += 2; @@ -314,28 +311,12 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre from, quote_char, escaped, - depth, } => match ch { ch if ch == *quote_char && !*escaped => { - // Count if there are more than `depth` quotes remaining - if contents[index..] - .iter() - .filter(|b| *b == quote_char) - .count() as i32 - > *depth - { - // Increment depth to be greedy - *depth += 1; - } else { - // Decrement depth - *depth -= 1; - } - if *depth == 0 { - // End of string - spans.push(make_span(*from, index + 1)); - // go back to Bare state - state = State::Bare { from: index + 1 }; - } + // quoted string ended, just make a new span for it. + spans.push(make_span(*from, index + 1)); + // go back to Bare state. + state = State::Bare { from: index + 1 }; } b'\\' if !*escaped && *quote_char == b'"' => { // The next token is escaped so it doesn't count (only for double quote) diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 973ba1b68..86511bdca 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -996,6 +996,31 @@ pub fn test_external_call_head_interpolated_string( r"foo\external call", "backtick quote with backslash" )] +#[case( + r#"^foo --flag="value""#, + r#"--flag=value"#, + "flag value with double quote" +)] +#[case( + r#"^foo --flag='value'"#, + r#"--flag=value"#, + "flag value with single quote" +)] +#[case( + r#"^foo {a:1,b:'c',c:'d'}"#, + r#"{a:1,b:c,c:d}"#, + "value with many inner single quotes" +)] +#[case( + r#"^foo {a:1,b:"c",c:"d"}"#, + r#"{a:1,b:c,c:d}"#, + "value with many double quotes" +)] +#[case( + r#"^foo {a:1,b:'c',c:"d"}"#, + r#"{a:1,b:c,c:d}"#, + "value with single quote and double quote" +)] pub fn test_external_call_arg_glob(#[case] input: &str, #[case] expected: &str, #[case] tag: &str) { test_external_call(input, tag, |name, args| { match &name.expr { |