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)) ExternalArgument::Regular(parse_dollar_expr(working_set, span))
} else if contents.starts_with(b"[") { } else if contents.starts_with(b"[") {
ExternalArgument::Regular(parse_list_expression(working_set, span, &SyntaxShape::Any)) 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 } else if contents.len() > 3
&& contents.starts_with(b"...") && contents.starts_with(b"...")
&& (contents[3] == b'$' || contents[3] == b'[' || contents[3] == b'(') && (contents[3] == b'$' || contents[3] == b'[' || contents[3] == b'(')

View File

@ -1,6 +1,6 @@
use nu_parser::*; use nu_parser::*;
use nu_protocol::{ use nu_protocol::{
ast::{Argument, Call, Expr, PathMember, Range}, ast::{Argument, Call, Expr, ExternalArgument, PathMember, Range},
engine::{Command, EngineState, Stack, StateWorkingSet}, engine::{Command, EngineState, Stack, StateWorkingSet},
ParseError, PipelineData, ShellError, Signature, Span, SyntaxShape, ParseError, PipelineData, ShellError, Signature, Span, SyntaxShape,
}; };
@ -926,6 +926,28 @@ mod string {
assert!(working_set.parse_errors.is_empty()); 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] #[rstest]

View File

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