From 3492d4015d93439d5492b3a663ac17b36432aadc Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Tue, 26 Apr 2022 11:44:44 +1200 Subject: [PATCH] Allow bare words to interpolate (#5327) * Allow bare words to interpolate * fix highlighting --- crates/nu-parser/src/flatten.rs | 38 ++++++++++++++++---------- crates/nu-parser/src/parse_keywords.rs | 11 ++++---- crates/nu-parser/src/parser.rs | 23 +++++++++++++--- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index 2584d18429..bdc8692e47 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -326,23 +326,33 @@ pub fn flatten_expression( output } Expr::StringInterpolation(exprs) => { - let mut output = vec![( - Span { - start: expr.span.start, - end: expr.span.start + 2, - }, - FlatShape::StringInterpolation, - )]; + let mut output = vec![]; for expr in exprs { output.extend(flatten_expression(working_set, expr)); } - output.push(( - Span { - start: expr.span.end - 1, - end: expr.span.end, - }, - FlatShape::StringInterpolation, - )); + + if let Some(first) = output.first() { + if first.0.start != expr.span.start { + // If we aren't a bare word interpolation, also highlight the outer quotes + output.insert( + 0, + ( + Span { + start: expr.span.start, + end: expr.span.start + 2, + }, + FlatShape::StringInterpolation, + ), + ); + output.push(( + Span { + start: expr.span.end - 1, + end: expr.span.end, + }, + FlatShape::StringInterpolation, + )); + } + } output } Expr::Record(list) => { diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 35dc0087d6..6f148b67c6 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -41,7 +41,7 @@ pub fn parse_def_predecl( }; if (name == b"def" || name == b"def-env") && spans.len() >= 4 { - let (name_expr, ..) = parse_string(working_set, spans[1]); + let (name_expr, ..) = parse_string(working_set, spans[1], expand_aliases_denylist); let name = name_expr.as_string(); working_set.enter_scope(); @@ -64,7 +64,7 @@ pub fn parse_def_predecl( } } } else if name == b"extern" && spans.len() == 3 { - let (name_expr, ..) = parse_string(working_set, spans[1]); + let (name_expr, ..) = parse_string(working_set, spans[1], expand_aliases_denylist); let name = name_expr.as_string(); working_set.enter_scope(); @@ -892,7 +892,8 @@ pub fn parse_export( call.head = span(&spans[0..=1]); if let Some(name_span) = spans.get(2) { - let (name_expr, err) = parse_string(working_set, *name_span); + let (name_expr, err) = + parse_string(working_set, *name_span, expand_aliases_denylist); error = error.or(err); call.add_positional(name_expr); @@ -1132,7 +1133,7 @@ pub fn parse_module( let bytes = working_set.get_span_contents(spans[0]); if bytes == b"module" && spans.len() >= 3 { - let (module_name_expr, err) = parse_string(working_set, spans[1]); + let (module_name_expr, err) = parse_string(working_set, spans[1], expand_aliases_denylist); error = error.or(err); let module_name = module_name_expr @@ -1524,7 +1525,7 @@ pub fn parse_hide( if bytes == b"hide" && spans.len() >= 2 { for span in spans[1..].iter() { - let (_, err) = parse_string(working_set, *span); + let (_, err) = parse_string(working_set, *span, expand_aliases_denylist); error = error.or(err); } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index ba4dc21cb6..853a0dacf8 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1726,6 +1726,7 @@ pub fn parse_cell_path( working_set: &mut StateWorkingSet, tokens: impl Iterator, mut expect_dot: bool, + expand_aliases_denylist: &[usize], span: Span, ) -> (Vec, Option) { let mut error = None; @@ -1755,7 +1756,8 @@ pub fn parse_cell_path( span, }), _ => { - let (result, err) = parse_string(working_set, path_element.span); + let (result, err) = + parse_string(working_set, path_element.span, expand_aliases_denylist); error = error.or(err); match result { Expression { @@ -1885,7 +1887,13 @@ pub fn parse_full_cell_path( ); }; - let (tail, err) = parse_cell_path(working_set, tokens, expect_dot, span); + let (tail, err) = parse_cell_path( + working_set, + tokens, + expect_dot, + expand_aliases_denylist, + span, + ); error = error.or(err); if !tail.is_empty() { @@ -2475,11 +2483,17 @@ pub fn unescape_unquote_string(bytes: &[u8], span: Span) -> (String, Option (Expression, Option) { trace!("parsing: string"); let bytes = working_set.get_span_contents(span); + // Check for bare word interpolation + if bytes[0] != b'\'' && bytes[0] != b'"' && bytes[0] != b'`' && bytes.contains(&b'(') { + return parse_string_interpolation(working_set, span, expand_aliases_denylist); + } + let (s, err) = unescape_unquote_string(bytes, span); ( @@ -3899,7 +3913,7 @@ pub fn parse_value( SyntaxShape::Filepath => parse_filepath(working_set, span), SyntaxShape::Directory => parse_directory(working_set, span), SyntaxShape::GlobPattern => parse_glob_pattern(working_set, span), - SyntaxShape::String => parse_string(working_set, span), + SyntaxShape::String => parse_string(working_set, span, expand_aliases_denylist), SyntaxShape::Binary => parse_binary(working_set, span), SyntaxShape::Signature => { if bytes.starts_with(b"[") { @@ -3940,7 +3954,8 @@ pub fn parse_value( let tokens = tokens.into_iter().peekable(); - let (cell_path, err) = parse_cell_path(working_set, tokens, false, span); + let (cell_path, err) = + parse_cell_path(working_set, tokens, false, expand_aliases_denylist, span); error = error.or(err); (