mirror of
https://github.com/nushell/nushell.git
synced 2024-11-25 01:43:47 +01:00
Making nushell works better with external args which surrounded by backtick quotes (#13910)
# Description Fixes: #13431 Fixes: #13578 The issue happened because nushell thinks external program name and external arg with totally same rule. But actually they are a little bit different. When parsing external program name, backtick is a thing and it should be keeped. But when parsing external args, backtick is just a mark that it's a **bareword which may contain space**. So in this context, it's already useless. # User-Facing Changes After the pr, the following command will work as intended. ```nushell > ^echo `"hello"` hello ``` # Tests + Formatting Added 3 test cases.
This commit is contained in:
parent
5002d87af4
commit
1d15bbc95b
@ -240,10 +240,26 @@ fn parse_unknown_arg(
|
|||||||
/// string, where each balanced pair of quotes is parsed as a separate part of the string, and then
|
/// string, where each balanced pair of quotes is parsed as a separate part of the string, and then
|
||||||
/// concatenated together.
|
/// concatenated together.
|
||||||
///
|
///
|
||||||
|
/// `keep_surround_backtick_quote` should be true when parsing it as command name. Or else it
|
||||||
|
/// should be false.
|
||||||
|
///
|
||||||
/// For example, `-foo="bar\nbaz"` becomes `$"-foo=bar\nbaz"`
|
/// For example, `-foo="bar\nbaz"` becomes `$"-foo=bar\nbaz"`
|
||||||
fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expression {
|
fn parse_external_string(
|
||||||
let contents = &working_set.get_span_contents(span);
|
working_set: &mut StateWorkingSet,
|
||||||
|
mut span: Span,
|
||||||
|
keep_surround_bakctick_quote: bool,
|
||||||
|
) -> Expression {
|
||||||
|
let mut contents = working_set.get_span_contents(span);
|
||||||
|
|
||||||
|
if !keep_surround_bakctick_quote
|
||||||
|
&& contents.len() > 1
|
||||||
|
&& contents.starts_with(b"`")
|
||||||
|
&& contents.ends_with(b"`")
|
||||||
|
{
|
||||||
|
contents = &contents[1..contents.len() - 1];
|
||||||
|
// backtick quote is useless in this case, so span is required to updated.
|
||||||
|
span = Span::new(span.start + 1, span.end - 1);
|
||||||
|
}
|
||||||
if contents.starts_with(b"r#") {
|
if contents.starts_with(b"r#") {
|
||||||
parse_raw_string(working_set, span)
|
parse_raw_string(working_set, span)
|
||||||
} else if contents
|
} else if contents
|
||||||
@ -441,7 +457,7 @@ fn parse_regular_external_arg(working_set: &mut StateWorkingSet, span: Span) ->
|
|||||||
} else if contents.starts_with(b"[") {
|
} else if contents.starts_with(b"[") {
|
||||||
parse_list_expression(working_set, span, &SyntaxShape::Any)
|
parse_list_expression(working_set, span, &SyntaxShape::Any)
|
||||||
} else {
|
} else {
|
||||||
parse_external_string(working_set, span)
|
parse_external_string(working_set, span, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +479,7 @@ pub fn parse_external_call(working_set: &mut StateWorkingSet, spans: &[Span]) ->
|
|||||||
let arg = parse_expression(working_set, &[head_span]);
|
let arg = parse_expression(working_set, &[head_span]);
|
||||||
Box::new(arg)
|
Box::new(arg)
|
||||||
} else {
|
} else {
|
||||||
Box::new(parse_external_string(working_set, head_span))
|
Box::new(parse_external_string(working_set, head_span, true))
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = spans[1..]
|
let args = spans[1..]
|
||||||
|
@ -1021,6 +1021,11 @@ pub fn test_external_call_head_interpolated_string(
|
|||||||
r#"{a:1,b:c,c:d}"#,
|
r#"{a:1,b:c,c:d}"#,
|
||||||
"value with single quote and double quote"
|
"value with single quote and double quote"
|
||||||
)]
|
)]
|
||||||
|
#[case(
|
||||||
|
r#"^foo `hello world`"#,
|
||||||
|
r#"hello world"#,
|
||||||
|
"value is surrounded by backtick quote"
|
||||||
|
)]
|
||||||
pub fn test_external_call_arg_glob(#[case] input: &str, #[case] expected: &str, #[case] tag: &str) {
|
pub fn test_external_call_arg_glob(#[case] input: &str, #[case] expected: &str, #[case] tag: &str) {
|
||||||
test_external_call(input, tag, |name, args| {
|
test_external_call(input, tag, |name, args| {
|
||||||
match &name.expr {
|
match &name.expr {
|
||||||
@ -1115,6 +1120,16 @@ pub fn test_external_call_arg_raw_string(
|
|||||||
r#"foo\external call"#,
|
r#"foo\external call"#,
|
||||||
"double quote with backslash"
|
"double quote with backslash"
|
||||||
)]
|
)]
|
||||||
|
#[case(
|
||||||
|
r#"^foo `"hello world"`"#,
|
||||||
|
r#"hello world"#,
|
||||||
|
"value is surrounded by backtick quote, with inner double quote"
|
||||||
|
)]
|
||||||
|
#[case(
|
||||||
|
r#"^foo `'hello world'`"#,
|
||||||
|
r#"hello world"#,
|
||||||
|
"value is surrounded by backtick quote, with inner single quote"
|
||||||
|
)]
|
||||||
pub fn test_external_call_arg_string(
|
pub fn test_external_call_arg_string(
|
||||||
#[case] input: &str,
|
#[case] input: &str,
|
||||||
#[case] expected: &str,
|
#[case] expected: &str,
|
||||||
|
Loading…
Reference in New Issue
Block a user