summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWind <WindSoilder@outlook.com>2024-09-23 19:44:51 +0800
committerGitHub <noreply@github.com>2024-09-23 06:44:51 -0500
commit183c2221bbe7a997a7c7ff2638b584f3c2d39f58 (patch)
tree106d4b423120ba6bea0bdfa2377f3273233b3c19
parent03ee54a4df36889fa6accc52a8d33b1a21717732 (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.rs27
-rw-r--r--crates/nu-parser/tests/test_parser.rs25
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 {