mirror of
https://github.com/nushell/nushell
synced 2024-12-28 22:13:10 +00:00
Allow bare words to interpolate (#5327)
* Allow bare words to interpolate * fix highlighting
This commit is contained in:
parent
190f379ff3
commit
3492d4015d
3 changed files with 49 additions and 23 deletions
|
@ -326,16 +326,24 @@ pub fn flatten_expression(
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
Expr::StringInterpolation(exprs) => {
|
Expr::StringInterpolation(exprs) => {
|
||||||
let mut output = vec![(
|
let mut output = vec![];
|
||||||
|
for expr in exprs {
|
||||||
|
output.extend(flatten_expression(working_set, expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
Span {
|
||||||
start: expr.span.start,
|
start: expr.span.start,
|
||||||
end: expr.span.start + 2,
|
end: expr.span.start + 2,
|
||||||
},
|
},
|
||||||
FlatShape::StringInterpolation,
|
FlatShape::StringInterpolation,
|
||||||
)];
|
),
|
||||||
for expr in exprs {
|
);
|
||||||
output.extend(flatten_expression(working_set, expr));
|
|
||||||
}
|
|
||||||
output.push((
|
output.push((
|
||||||
Span {
|
Span {
|
||||||
start: expr.span.end - 1,
|
start: expr.span.end - 1,
|
||||||
|
@ -343,6 +351,8 @@ pub fn flatten_expression(
|
||||||
},
|
},
|
||||||
FlatShape::StringInterpolation,
|
FlatShape::StringInterpolation,
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
Expr::Record(list) => {
|
Expr::Record(list) => {
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub fn parse_def_predecl(
|
||||||
};
|
};
|
||||||
|
|
||||||
if (name == b"def" || name == b"def-env") && spans.len() >= 4 {
|
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();
|
let name = name_expr.as_string();
|
||||||
|
|
||||||
working_set.enter_scope();
|
working_set.enter_scope();
|
||||||
|
@ -64,7 +64,7 @@ pub fn parse_def_predecl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if name == b"extern" && spans.len() == 3 {
|
} 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();
|
let name = name_expr.as_string();
|
||||||
|
|
||||||
working_set.enter_scope();
|
working_set.enter_scope();
|
||||||
|
@ -892,7 +892,8 @@ pub fn parse_export(
|
||||||
call.head = span(&spans[0..=1]);
|
call.head = span(&spans[0..=1]);
|
||||||
|
|
||||||
if let Some(name_span) = spans.get(2) {
|
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);
|
error = error.or(err);
|
||||||
call.add_positional(name_expr);
|
call.add_positional(name_expr);
|
||||||
|
|
||||||
|
@ -1132,7 +1133,7 @@ pub fn parse_module(
|
||||||
let bytes = working_set.get_span_contents(spans[0]);
|
let bytes = working_set.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if bytes == b"module" && spans.len() >= 3 {
|
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);
|
error = error.or(err);
|
||||||
|
|
||||||
let module_name = module_name_expr
|
let module_name = module_name_expr
|
||||||
|
@ -1524,7 +1525,7 @@ pub fn parse_hide(
|
||||||
|
|
||||||
if bytes == b"hide" && spans.len() >= 2 {
|
if bytes == b"hide" && spans.len() >= 2 {
|
||||||
for span in spans[1..].iter() {
|
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);
|
error = error.or(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1726,6 +1726,7 @@ pub fn parse_cell_path(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
tokens: impl Iterator<Item = Token>,
|
tokens: impl Iterator<Item = Token>,
|
||||||
mut expect_dot: bool,
|
mut expect_dot: bool,
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Vec<PathMember>, Option<ParseError>) {
|
) -> (Vec<PathMember>, Option<ParseError>) {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
@ -1755,7 +1756,8 @@ pub fn parse_cell_path(
|
||||||
span,
|
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);
|
error = error.or(err);
|
||||||
match result {
|
match result {
|
||||||
Expression {
|
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);
|
error = error.or(err);
|
||||||
|
|
||||||
if !tail.is_empty() {
|
if !tail.is_empty() {
|
||||||
|
@ -2475,11 +2483,17 @@ pub fn unescape_unquote_string(bytes: &[u8], span: Span) -> (String, Option<Pars
|
||||||
pub fn parse_string(
|
pub fn parse_string(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
trace!("parsing: string");
|
trace!("parsing: string");
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
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);
|
let (s, err) = unescape_unquote_string(bytes, span);
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3899,7 +3913,7 @@ pub fn parse_value(
|
||||||
SyntaxShape::Filepath => parse_filepath(working_set, span),
|
SyntaxShape::Filepath => parse_filepath(working_set, span),
|
||||||
SyntaxShape::Directory => parse_directory(working_set, span),
|
SyntaxShape::Directory => parse_directory(working_set, span),
|
||||||
SyntaxShape::GlobPattern => parse_glob_pattern(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::Binary => parse_binary(working_set, span),
|
||||||
SyntaxShape::Signature => {
|
SyntaxShape::Signature => {
|
||||||
if bytes.starts_with(b"[") {
|
if bytes.starts_with(b"[") {
|
||||||
|
@ -3940,7 +3954,8 @@ pub fn parse_value(
|
||||||
|
|
||||||
let tokens = tokens.into_iter().peekable();
|
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);
|
error = error.or(err);
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|
Loading…
Reference in a new issue