mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 07:43:39 +02:00
fix(parser): external argument with subexpressions (#16346)
Fixes: #16040 # Description TBH, I not a fan of this whole `parse_external_string` idea. Maybe I lack some of the background knowledge here, but I don't see why we choose not to 1. parse external arguments the same way as internal ones 2. treat them literally at runtime if necessary Tests: +1
This commit is contained in:
@ -264,6 +264,10 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre
|
|||||||
quote_char: u8,
|
quote_char: u8,
|
||||||
escaped: bool,
|
escaped: bool,
|
||||||
},
|
},
|
||||||
|
Parenthesized {
|
||||||
|
from: usize,
|
||||||
|
depth: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Find the spans of parts of the string that can be parsed as their own strings for
|
// Find the spans of parts of the string that can be parsed as their own strings for
|
||||||
// concatenation.
|
// concatenation.
|
||||||
@ -315,6 +319,15 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre
|
|||||||
}
|
}
|
||||||
state = State::BackTickQuote { from: index }
|
state = State::BackTickQuote { from: index }
|
||||||
}
|
}
|
||||||
|
b'(' => {
|
||||||
|
if index != *from {
|
||||||
|
spans.push(make_span(*from, index))
|
||||||
|
}
|
||||||
|
state = State::Parenthesized {
|
||||||
|
from: index,
|
||||||
|
depth: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
// Continue to consume
|
// Continue to consume
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
@ -343,6 +356,18 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre
|
|||||||
state = State::Bare { from: index + 1 };
|
state = State::Bare { from: index + 1 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
State::Parenthesized { from, depth } => {
|
||||||
|
if ch == b')' {
|
||||||
|
if *depth == 1 {
|
||||||
|
spans.push(make_span(*from, index + 1));
|
||||||
|
state = State::Bare { from: index + 1 };
|
||||||
|
} else {
|
||||||
|
*depth -= 1;
|
||||||
|
}
|
||||||
|
} else if ch == b'(' {
|
||||||
|
*depth += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
@ -351,6 +376,7 @@ fn parse_external_string(working_set: &mut StateWorkingSet, span: Span) -> Expre
|
|||||||
match state {
|
match state {
|
||||||
State::Bare { from }
|
State::Bare { from }
|
||||||
| State::Quote { from, .. }
|
| State::Quote { from, .. }
|
||||||
|
| State::Parenthesized { from, .. }
|
||||||
| State::BackTickQuote { from, .. } => {
|
| State::BackTickQuote { from, .. } => {
|
||||||
if from < contents.len() {
|
if from < contents.len() {
|
||||||
spans.push(make_span(from, contents.len()));
|
spans.push(make_span(from, contents.len()));
|
||||||
|
@ -1027,3 +1027,12 @@ fn not_panic_with_recursive_call() {
|
|||||||
);
|
);
|
||||||
assert!(result.status.success());
|
assert!(result.status.success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/nushell/nushell/issues/16040
|
||||||
|
#[test]
|
||||||
|
fn external_argument_with_subexpressions() -> TestResult {
|
||||||
|
run_test(r#"^echo foo( ('bar') | $in ++ 'baz' )"#, "foobarbaz")?;
|
||||||
|
run_test(r#"^echo foo( 'bar' )('baz')"#, "foobarbaz")?;
|
||||||
|
run_test(r#"^echo ")('foo')(""#, ")('foo')(")?;
|
||||||
|
fail_test(r#"^echo foo( 'bar'"#, "Unexpected end of code")
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user