From dea9c1482bb13d2cab166196872aaebec8dbc338 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 9 Oct 2021 10:51:47 +1300 Subject: [PATCH] Allow vars and subexprs in extern args --- crates/nu-cli/src/syntax_highlight.rs | 8 ++++-- crates/nu-engine/src/eval.rs | 38 +++++++++++++++++---------- crates/nu-parser/src/flatten.rs | 14 +++++++++- crates/nu-parser/src/parser.rs | 22 +++++++++++++--- crates/nu-protocol/src/ast/expr.rs | 2 +- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index 161801e261..d0d5d06431 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -39,8 +39,12 @@ impl Highlighter for NuHighlighter { .to_string(); match shape.1 { FlatShape::Custom(..) => output.push((Style::new().bold(), next_token)), - FlatShape::External => output.push((Style::new().bold(), next_token)), - FlatShape::ExternalArg => output.push((Style::new().bold(), next_token)), + FlatShape::External => { + output.push((Style::new().fg(nu_ansi_term::Color::Green), next_token)) + } + FlatShape::ExternalArg => { + output.push((Style::new().fg(nu_ansi_term::Color::Green), next_token)) + } FlatShape::Garbage => output.push(( Style::new() .fg(nu_ansi_term::Color::White) diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index d59ff4b3e0..ca755c665f 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -2,6 +2,8 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; use nu_protocol::engine::EvaluationContext; use nu_protocol::{Range, ShellError, Span, Type, Unit, Value}; +use crate::FromValue; + pub fn eval_operator(op: &Expression) -> Result { match op { Expression { @@ -71,7 +73,7 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result Result { @@ -84,20 +86,28 @@ fn eval_external( let command = engine_state.get_decl(decl_id); let mut call = Call::new(); - call.positional = [*name] - .iter() - .chain(args.iter()) - .map(|span| { - let contents = engine_state.get_span_contents(span); - let val = String::from_utf8_lossy(contents); - Expression { - expr: Expr::String(val.into()), - span: *span, - ty: Type::String, - custom_completion: None, - } + + let name_span = name; + let name = engine_state.get_span_contents(name); + call.positional.push(Expression { + expr: Expr::String(String::from_utf8_lossy(name).to_string()), + span: *name_span, + ty: Type::String, + custom_completion: None, + }); + + for arg in args { + let span = arg.span; + let result = eval_expression(context, arg)?; + let result: String = FromValue::from_value(&result)?; + + call.positional.push(Expression { + expr: Expr::String(result), + span, + ty: Type::String, + custom_completion: None, }) - .collect(); + } if last_expression { call.named.push(("last_expression".into(), None)) diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index 90cfc5092d..26eae7e911 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -67,7 +67,19 @@ pub fn flatten_expression( let mut output = vec![(*name, FlatShape::External)]; for arg in args { - output.push((*arg, FlatShape::ExternalArg)); + //output.push((*arg, FlatShape::ExternalArg)); + match arg { + Expression { + expr: Expr::String(..), + span, + .. + } => { + output.push((*span, FlatShape::ExternalArg)); + } + _ => { + output.extend(flatten_expression(working_set, arg)); + } + } } output diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index f6f8ed2315..2f1ae7b508 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -104,14 +104,28 @@ pub fn check_name<'a>( } pub fn parse_external_call( - _working_set: &mut StateWorkingSet, + working_set: &mut StateWorkingSet, spans: &[Span], ) -> (Expression, Option) { - // TODO: add external parsing let mut args = vec![]; let name = spans[0]; + let mut error = None; + for span in &spans[1..] { - args.push(*span); + let contents = working_set.get_span_contents(*span); + + if contents.starts_with(b"$") || contents.starts_with(b"(") { + let (arg, err) = parse_expression(working_set, &[*span], true); + error = error.or(err); + args.push(arg); + } else { + args.push(Expression { + expr: Expr::String(String::from_utf8_lossy(contents).to_string()), + span: *span, + ty: Type::String, + custom_completion: None, + }) + } } ( Expression { @@ -120,7 +134,7 @@ pub fn parse_external_call( ty: Type::Unknown, custom_completion: None, }, - None, + error, ) } diff --git a/crates/nu-protocol/src/ast/expr.rs b/crates/nu-protocol/src/ast/expr.rs index 4a9b42527d..6eb0b539d5 100644 --- a/crates/nu-protocol/src/ast/expr.rs +++ b/crates/nu-protocol/src/ast/expr.rs @@ -14,7 +14,7 @@ pub enum Expr { ), Var(VarId), Call(Box), - ExternalCall(Span, Vec), + ExternalCall(Span, Vec), Operator(Operator), RowCondition(VarId, Box), BinaryOp(Box, Box, Box), //lhs, op, rhs