Fix raw strings as external argument (#12817)

# Description
As discovered by @YizhePKU in a
[comment](https://github.com/nushell/nushell/pull/9956#issuecomment-2103123797)
in #9956, raw strings are not parsed properly when they are used as an
argument to an external command. This PR fixes that.

# Tests + Formatting
Added a test.
This commit is contained in:
Ian Manske 2024-05-09 23:50:31 +00:00 committed by GitHub
parent 72d3860d05
commit 70c01bbb26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 1 deletions

View File

@ -228,6 +228,8 @@ fn parse_external_arg(working_set: &mut StateWorkingSet, span: Span) -> External
ExternalArgument::Regular(parse_dollar_expr(working_set, span))
} else if contents.starts_with(b"[") {
ExternalArgument::Regular(parse_list_expression(working_set, span, &SyntaxShape::Any))
} else if contents.starts_with(b"r#") {
ExternalArgument::Regular(parse_raw_string(working_set, span))
} else if contents.len() > 3
&& contents.starts_with(b"...")
&& (contents[3] == b'$' || contents[3] == b'[' || contents[3] == b'(')

View File

@ -1,6 +1,6 @@
use nu_parser::*;
use nu_protocol::{
ast::{Argument, Call, Expr, PathMember, Range},
ast::{Argument, Call, Expr, ExternalArgument, PathMember, Range},
engine::{Command, EngineState, Stack, StateWorkingSet},
ParseError, PipelineData, ShellError, Signature, Span, SyntaxShape,
};
@ -926,6 +926,28 @@ mod string {
assert!(working_set.parse_errors.is_empty());
}
}
#[test]
fn parse_raw_string_as_external_argument() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let block = parse(&mut working_set, None, b"^echo r#'text'#", true);
assert!(working_set.parse_errors.is_empty());
assert_eq!(block.len(), 1);
let pipeline = &block.pipelines[0];
assert_eq!(pipeline.len(), 1);
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::ExternalCall(_, args) = &element.expr.expr {
if let [ExternalArgument::Regular(expr)] = args.as_ref() {
assert_eq!(expr.expr, Expr::RawString("text".into()));
return;
}
}
panic!("wrong expression: {:?}", element.expr.expr)
}
}
#[rstest]

View File

@ -314,6 +314,7 @@ 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!("
@ -323,6 +324,12 @@ mod external_words {
assert_eq!(actual.out, "joturner@foo.bar.baz");
}
#[test]
fn raw_string_as_external_argument() {
let actual = nu!("nu --testbin cococo r#'asdf'#");
assert_eq!(actual.out, "asdf");
}
//FIXME: jt: limitation in testing - can't use single ticks currently
#[ignore]
#[test]