diff --git a/crates/nu-command/src/commands/run_external.rs b/crates/nu-command/src/commands/run_external.rs index 14f881f1cc..fd80adfcd8 100644 --- a/crates/nu-command/src/commands/run_external.rs +++ b/crates/nu-command/src/commands/run_external.rs @@ -4,10 +4,13 @@ use crate::prelude::*; use derive_new::new; use std::path::PathBuf; -use nu_engine::shell::CdArgs; use nu_engine::WholeStreamCommand; +use nu_engine::{evaluate_baseline_expr, shell::CdArgs}; use nu_errors::ShellError; -use nu_protocol::hir::{Expression, ExternalArgs, ExternalCommand, Literal, SpannedExpression}; +use nu_protocol::{ + hir::{ExternalArgs, ExternalCommand, SpannedExpression}, + Primitive, UntaggedValue, +}; use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; @@ -17,12 +20,13 @@ pub struct RunExternalCommand { pub(crate) interactive: bool, } -fn spanned_expression_to_string(expr: SpannedExpression) -> Result { - if let SpannedExpression { - expr: Expression::Literal(Literal::String(s)), - .. - } = expr - { +fn spanned_expression_to_string( + expr: SpannedExpression, + ctx: &EvaluationContext, +) -> Result { + let value = evaluate_baseline_expr(&expr, ctx)?; + + if let UntaggedValue::Primitive(Primitive::String(s)) = value.value { Ok(s) } else { Err(ShellError::labeled_error( @@ -67,12 +71,11 @@ impl WholeStreamCommand for RunExternalCommand { let external_redirection = args.call_info.args.external_redirection; - let name = positionals - .next() - .ok_or_else(|| { - ShellError::untagged_runtime_error("run_external called with no arguments") - }) - .and_then(spanned_expression_to_string)?; + let expr = positionals.next().ok_or_else(|| { + ShellError::untagged_runtime_error("run_external called with no arguments") + })?; + + let name = spanned_expression_to_string(expr, &args.context)?; let mut external_context = args.context.clone(); diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 7c5480eb4b..efa8078c44 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -68,6 +68,18 @@ fn correctly_escape_external_arguments() { assert_eq!(actual.out, "$0"); } +#[test] +fn execute_binary_in_string() { + let actual = nu!( + cwd: ".", + r#" + let cmd = echo + ^$"($cmd)" '$0' + "#); + + assert_eq!(actual.out, "$0"); +} + #[test] fn redirects_custom_command_external() { let actual = nu!(cwd: ".", r#"def foo [] { nu --testbin cococo foo bar }; foo | str length "#);