mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
Allow aliasing parser keywords (#8250)
This commit is contained in:
parent
baddc86d9d
commit
af1ab39851
5 changed files with 313 additions and 400 deletions
|
@ -74,8 +74,19 @@ fn alias_fails_with_invalid_name() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
alias ^foo = "bar"
|
alias ^foo = echo "bar"
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
assert!(actual.err.contains(err_msg));
|
assert!(actual.err.contains(err_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cant_alias_keyword() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"
|
||||||
|
alias ou = let
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
assert!(actual.err.contains("cant_alias_keyword"));
|
||||||
|
}
|
||||||
|
|
|
@ -95,6 +95,13 @@ pub enum ParseError {
|
||||||
)]
|
)]
|
||||||
UnexpectedKeyword(String, #[label("unexpected {0}")] Span),
|
UnexpectedKeyword(String, #[label("unexpected {0}")] Span),
|
||||||
|
|
||||||
|
#[error("Can't create alias to parser keyword.")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::parser::cant_alias_keyword),
|
||||||
|
help("Only the following keywords can be aliased: {0}.")
|
||||||
|
)]
|
||||||
|
CantAliasKeyword(String, #[label("not supported in alias")] Span),
|
||||||
|
|
||||||
#[error("Unknown operator")]
|
#[error("Unknown operator")]
|
||||||
#[diagnostic(code(nu::parser::unknown_operator), help("{1}"))]
|
#[diagnostic(code(nu::parser::unknown_operator), help("{1}"))]
|
||||||
UnknownOperator(
|
UnknownOperator(
|
||||||
|
@ -419,6 +426,7 @@ impl ParseError {
|
||||||
ParseError::UnsupportedOperation(_, _, _, s, _) => *s,
|
ParseError::UnsupportedOperation(_, _, _, s, _) => *s,
|
||||||
ParseError::ExpectedKeyword(_, s) => *s,
|
ParseError::ExpectedKeyword(_, s) => *s,
|
||||||
ParseError::UnexpectedKeyword(_, s) => *s,
|
ParseError::UnexpectedKeyword(_, s) => *s,
|
||||||
|
ParseError::CantAliasKeyword(_, s) => *s,
|
||||||
ParseError::BuiltinCommandInPipeline(_, s) => *s,
|
ParseError::BuiltinCommandInPipeline(_, s) => *s,
|
||||||
ParseError::AssignInPipeline(_, _, _, s) => *s,
|
ParseError::AssignInPipeline(_, _, _, s) => *s,
|
||||||
ParseError::LetBuiltinVar(_, s) => *s,
|
ParseError::LetBuiltinVar(_, s) => *s,
|
||||||
|
|
|
@ -28,6 +28,92 @@ use crate::{
|
||||||
unescape_unquote_string, ParseError, Token, TokenContents,
|
unescape_unquote_string, ParseError, Token, TokenContents,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// These parser keywords can be aliased
|
||||||
|
pub const ALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[b"overlay hide", b"overlay new", b"overlay use"];
|
||||||
|
|
||||||
|
/// These parser keywords cannot be aliased (either not possible, or support not yet added)
|
||||||
|
pub const UNALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[
|
||||||
|
b"export",
|
||||||
|
b"def",
|
||||||
|
b"export def",
|
||||||
|
b"for",
|
||||||
|
b"extern",
|
||||||
|
b"export extern",
|
||||||
|
b"alias",
|
||||||
|
b"export alias",
|
||||||
|
b"export-env",
|
||||||
|
b"module",
|
||||||
|
b"use",
|
||||||
|
b"export use",
|
||||||
|
b"hide",
|
||||||
|
// b"overlay",
|
||||||
|
// b"overlay hide",
|
||||||
|
// b"overlay new",
|
||||||
|
// b"overlay use",
|
||||||
|
b"let",
|
||||||
|
b"const",
|
||||||
|
b"mut",
|
||||||
|
b"source",
|
||||||
|
b"where",
|
||||||
|
b"register",
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Check whether spans start with a parser keyword that can be aliased
|
||||||
|
pub fn is_unaliasable_parser_keyword(working_set: &StateWorkingSet, spans: &[Span]) -> bool {
|
||||||
|
// try two words
|
||||||
|
if let (Some(span1), Some(span2)) = (spans.get(0), spans.get(1)) {
|
||||||
|
let cmd_name = working_set.get_span_contents(span(&[*span1, *span2]));
|
||||||
|
return UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try one word
|
||||||
|
if let Some(span1) = spans.get(0) {
|
||||||
|
let cmd_name = working_set.get_span_contents(*span1);
|
||||||
|
UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is a new more compact method of calling parse_xxx() functions without repeating the
|
||||||
|
/// parse_call() in each function. Remaining keywords can be moved here.
|
||||||
|
pub fn parse_keyword(
|
||||||
|
working_set: &mut StateWorkingSet,
|
||||||
|
lite_command: &LiteCommand,
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
|
is_subexpression: bool,
|
||||||
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
|
let (call_expr, err) = parse_call(
|
||||||
|
working_set,
|
||||||
|
&lite_command.parts,
|
||||||
|
lite_command.parts[0],
|
||||||
|
expand_aliases_denylist,
|
||||||
|
is_subexpression,
|
||||||
|
);
|
||||||
|
|
||||||
|
if err.is_some() {
|
||||||
|
return (Pipeline::from_vec(vec![call_expr]), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
..
|
||||||
|
} = call_expr.clone()
|
||||||
|
{
|
||||||
|
// Apply parse keyword side effects
|
||||||
|
let cmd = working_set.get_decl(call.decl_id);
|
||||||
|
|
||||||
|
match cmd.name() {
|
||||||
|
"overlay hide" => parse_overlay_hide(working_set, call),
|
||||||
|
"overlay new" => parse_overlay_new(working_set, call),
|
||||||
|
"overlay use" => parse_overlay_use(working_set, call, expand_aliases_denylist),
|
||||||
|
_ => (Pipeline::from_vec(vec![call_expr]), err),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(Pipeline::from_vec(vec![call_expr]), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_def_predecl(
|
pub fn parse_def_predecl(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
|
@ -657,7 +743,11 @@ pub fn parse_alias(
|
||||||
if let Some(decl_id) = working_set.find_decl(b"alias", &Type::Any) {
|
if let Some(decl_id) = working_set.find_decl(b"alias", &Type::Any) {
|
||||||
let (command_spans, rest_spans) = spans.split_at(split_id);
|
let (command_spans, rest_spans) = spans.split_at(split_id);
|
||||||
|
|
||||||
let ParsedInternalCall { call, output, .. } = parse_internal_call(
|
let ParsedInternalCall {
|
||||||
|
call: alias_call,
|
||||||
|
output,
|
||||||
|
..
|
||||||
|
} = parse_internal_call(
|
||||||
working_set,
|
working_set,
|
||||||
span(command_spans),
|
span(command_spans),
|
||||||
rest_spans,
|
rest_spans,
|
||||||
|
@ -665,16 +755,17 @@ pub fn parse_alias(
|
||||||
expand_aliases_denylist,
|
expand_aliases_denylist,
|
||||||
);
|
);
|
||||||
|
|
||||||
if call.has_flag("help") {
|
let has_help_flag = alias_call.has_flag("help");
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
let alias_pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(alias_call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: output,
|
ty: output,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}]),
|
}]);
|
||||||
None,
|
|
||||||
);
|
if has_help_flag {
|
||||||
|
return (alias_pipeline, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if spans.len() >= split_id + 3 {
|
if spans.len() >= split_id + 3 {
|
||||||
|
@ -692,12 +783,7 @@ pub fn parse_alias(
|
||||||
if let Some(mod_name) = module_name {
|
if let Some(mod_name) = module_name {
|
||||||
if alias_name == mod_name {
|
if alias_name == mod_name {
|
||||||
return (
|
return (
|
||||||
Pipeline::from_vec(vec![Expression {
|
alias_pipeline,
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
Some(ParseError::NamedAsModule(
|
Some(ParseError::NamedAsModule(
|
||||||
"alias".to_string(),
|
"alias".to_string(),
|
||||||
String::from_utf8_lossy(&alias_name).to_string(),
|
String::from_utf8_lossy(&alias_name).to_string(),
|
||||||
|
@ -708,12 +794,7 @@ pub fn parse_alias(
|
||||||
|
|
||||||
if &alias_name == b"main" {
|
if &alias_name == b"main" {
|
||||||
return (
|
return (
|
||||||
Pipeline::from_vec(vec![Expression {
|
alias_pipeline,
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
Some(ParseError::ExportMainAliasNotAllowed(spans[split_id])),
|
Some(ParseError::ExportMainAliasNotAllowed(spans[split_id])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -741,21 +822,36 @@ pub fn parse_alias(
|
||||||
|
|
||||||
let (command, wrapped_call) = match expr {
|
let (command, wrapped_call) = match expr {
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Call(ref call),
|
expr: Expr::Call(ref rhs_call),
|
||||||
..
|
..
|
||||||
} => (Some(working_set.get_decl(call.decl_id).clone_box()), expr),
|
} => {
|
||||||
|
let cmd = working_set.get_decl(rhs_call.decl_id);
|
||||||
|
|
||||||
|
if cmd.is_parser_keyword()
|
||||||
|
&& !ALIASABLE_PARSER_KEYWORDS.contains(&cmd.name().as_bytes())
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
alias_pipeline,
|
||||||
|
Some(ParseError::CantAliasKeyword(
|
||||||
|
ALIASABLE_PARSER_KEYWORDS
|
||||||
|
.iter()
|
||||||
|
.map(|bytes| String::from_utf8_lossy(bytes).to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(", "),
|
||||||
|
rhs_call.head,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(Some(cmd.clone_box()), expr)
|
||||||
|
}
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::ExternalCall(..),
|
expr: Expr::ExternalCall(..),
|
||||||
..
|
..
|
||||||
} => (None, expr),
|
} => (None, expr),
|
||||||
_ => {
|
_ => {
|
||||||
return (
|
return (
|
||||||
Pipeline::from_vec(vec![Expression {
|
alias_pipeline,
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"Parsed call not a call".into(),
|
"Parsed call not a call".into(),
|
||||||
expr.span,
|
expr.span,
|
||||||
|
@ -798,15 +894,7 @@ pub fn parse_alias(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (alias_pipeline, err);
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: Type::Any,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2582,220 +2670,27 @@ pub fn parse_hide(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_overlay(
|
|
||||||
working_set: &mut StateWorkingSet,
|
|
||||||
spans: &[Span],
|
|
||||||
expand_aliases_denylist: &[usize],
|
|
||||||
) -> (Pipeline, Option<ParseError>) {
|
|
||||||
if working_set.get_span_contents(spans[0]) != b"overlay" {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: Wrong call name for 'overlay' command".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if spans.len() > 1 {
|
|
||||||
let subcommand = working_set.get_span_contents(spans[1]);
|
|
||||||
|
|
||||||
match subcommand {
|
|
||||||
b"use" => {
|
|
||||||
return parse_overlay_use(working_set, spans, expand_aliases_denylist);
|
|
||||||
}
|
|
||||||
b"list" => {
|
|
||||||
// TODO: Abstract this code blob, it's repeated all over the place:
|
|
||||||
let call = match working_set.find_decl(b"overlay list", &Type::Any) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let ParsedInternalCall {
|
|
||||||
call,
|
|
||||||
error: mut err,
|
|
||||||
output,
|
|
||||||
} = parse_internal_call(
|
|
||||||
working_set,
|
|
||||||
span(&spans[..2]),
|
|
||||||
if spans.len() > 2 { &spans[2..] } else { &[] },
|
|
||||||
decl_id,
|
|
||||||
expand_aliases_denylist,
|
|
||||||
);
|
|
||||||
let decl = working_set.get_decl(decl_id);
|
|
||||||
|
|
||||||
let call_span = span(spans);
|
|
||||||
|
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
|
||||||
if err.is_some() || call.has_flag("help") {
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: call_span,
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
call
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: 'overlay' declaration not found".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: Type::Any,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
b"new" => {
|
|
||||||
return parse_overlay_new(working_set, spans, expand_aliases_denylist);
|
|
||||||
}
|
|
||||||
b"hide" => {
|
|
||||||
return parse_overlay_hide(working_set, spans, expand_aliases_denylist);
|
|
||||||
}
|
|
||||||
_ => { /* continue parsing overlay */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let call = match working_set.find_decl(b"overlay", &Type::Any) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let ParsedInternalCall {
|
|
||||||
call,
|
|
||||||
error: mut err,
|
|
||||||
output,
|
|
||||||
} = parse_internal_call(
|
|
||||||
working_set,
|
|
||||||
spans[0],
|
|
||||||
&spans[1..],
|
|
||||||
decl_id,
|
|
||||||
expand_aliases_denylist,
|
|
||||||
);
|
|
||||||
let decl = working_set.get_decl(decl_id);
|
|
||||||
|
|
||||||
let call_span = span(spans);
|
|
||||||
|
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
|
||||||
if err.is_some() || call.has_flag("help") {
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: call_span,
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
call
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: 'overlay' declaration not found".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: span(spans),
|
|
||||||
ty: Type::Any,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_overlay_new(
|
pub fn parse_overlay_new(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
call: Box<Call>,
|
||||||
expand_aliases_denylist: &[usize],
|
|
||||||
) -> (Pipeline, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
if spans.len() > 1 && working_set.get_span_contents(span(&spans[0..2])) != b"overlay new" {
|
let call_span = call.span();
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: Wrong call name for 'overlay new' command".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (call, call_span) = match working_set.find_decl(b"overlay new", &Type::Any) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let ParsedInternalCall {
|
|
||||||
call,
|
|
||||||
error: mut err,
|
|
||||||
output,
|
|
||||||
} = parse_internal_call(
|
|
||||||
working_set,
|
|
||||||
span(&spans[0..2]),
|
|
||||||
&spans[2..],
|
|
||||||
decl_id,
|
|
||||||
expand_aliases_denylist,
|
|
||||||
);
|
|
||||||
let decl = working_set.get_decl(decl_id);
|
|
||||||
|
|
||||||
let call_span = span(spans);
|
|
||||||
|
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
|
||||||
if err.is_some() || call.has_flag("help") {
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: call_span,
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
(call, call_span)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: 'overlay new' declaration not found".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
|
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
|
||||||
match eval_constant(working_set, expr) {
|
match eval_constant(working_set, expr) {
|
||||||
Ok(val) => match value_as_string(val, expr.span) {
|
Ok(val) => match value_as_string(val, expr.span) {
|
||||||
Ok(s) => (s, expr.span),
|
Ok(s) => (s, expr.span),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_pipeline(spans),
|
garbage_pipeline(&[call_span]),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Missing required positional after call parsing".into(),
|
"internal error: Missing required positional after call parsing".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -2805,7 +2700,7 @@ pub fn parse_overlay_new(
|
||||||
|
|
||||||
let pipeline = Pipeline::from_vec(vec![Expression {
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: call_span,
|
||||||
ty: Type::Any,
|
ty: Type::Any,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}]);
|
}]);
|
||||||
|
@ -2829,78 +2724,26 @@ pub fn parse_overlay_new(
|
||||||
|
|
||||||
pub fn parse_overlay_use(
|
pub fn parse_overlay_use(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
call: Box<Call>,
|
||||||
expand_aliases_denylist: &[usize],
|
expand_aliases_denylist: &[usize],
|
||||||
) -> (Pipeline, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
if spans.len() > 1 && working_set.get_span_contents(span(&spans[0..2])) != b"overlay use" {
|
let call_span = call.span();
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: Wrong call name for 'overlay use' command".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Allow full import pattern as argument (requires custom naming of module/overlay)
|
|
||||||
let (call, call_span) = match working_set.find_decl(b"overlay use", &Type::Any) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let ParsedInternalCall {
|
|
||||||
call,
|
|
||||||
error: mut err,
|
|
||||||
output,
|
|
||||||
} = parse_internal_call(
|
|
||||||
working_set,
|
|
||||||
span(&spans[0..2]),
|
|
||||||
&spans[2..],
|
|
||||||
decl_id,
|
|
||||||
expand_aliases_denylist,
|
|
||||||
);
|
|
||||||
let decl = working_set.get_decl(decl_id);
|
|
||||||
|
|
||||||
let call_span = span(spans);
|
|
||||||
|
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
|
||||||
if err.is_some() || call.has_flag("help") {
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: call_span,
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
(call, call_span)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: 'overlay use' declaration not found".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
|
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
|
||||||
match eval_constant(working_set, expr) {
|
match eval_constant(working_set, expr) {
|
||||||
Ok(val) => match value_as_string(val, expr.span) {
|
Ok(val) => match value_as_string(val, expr.span) {
|
||||||
Ok(s) => (s, expr.span),
|
Ok(s) => (s, expr.span),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_pipeline(spans),
|
garbage_pipeline(&[call_span]),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Missing required positional after call parsing".into(),
|
"internal error: Missing required positional after call parsing".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -2916,13 +2759,13 @@ pub fn parse_overlay_use(
|
||||||
item: s,
|
item: s,
|
||||||
span: new_name_expression.span,
|
span: new_name_expression.span,
|
||||||
}),
|
}),
|
||||||
Err(err) => return (garbage_pipeline(spans), Some(err)),
|
Err(err) => return (garbage_pipeline(&[call_span]), Some(err)),
|
||||||
},
|
},
|
||||||
Err(err) => return (garbage_pipeline(spans), Some(err)),
|
Err(err) => return (garbage_pipeline(&[call_span]), Some(err)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_pipeline(spans),
|
garbage_pipeline(&[call_span]),
|
||||||
Some(ParseError::ExpectedKeyword(
|
Some(ParseError::ExpectedKeyword(
|
||||||
"as keyword".to_string(),
|
"as keyword".to_string(),
|
||||||
kw_expression.span,
|
kw_expression.span,
|
||||||
|
@ -2938,7 +2781,7 @@ pub fn parse_overlay_use(
|
||||||
|
|
||||||
let pipeline = Pipeline::from_vec(vec![Expression {
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call.clone()),
|
expr: Expr::Call(call.clone()),
|
||||||
span: span(spans),
|
span: call_span,
|
||||||
ty: Type::Any,
|
ty: Type::Any,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}]);
|
}]);
|
||||||
|
@ -3037,7 +2880,7 @@ pub fn parse_overlay_use(
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
pipeline,
|
pipeline,
|
||||||
Some(ParseError::ModuleOrOverlayNotFound(spans[1])),
|
Some(ParseError::ModuleOrOverlayNotFound(overlay_name_span)),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3081,7 +2924,7 @@ pub fn parse_overlay_use(
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
pipeline,
|
pipeline,
|
||||||
Some(ParseError::ModuleOrOverlayNotFound(spans[1])),
|
Some(ParseError::ModuleOrOverlayNotFound(overlay_name_span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3091,7 +2934,10 @@ pub fn parse_overlay_use(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (garbage_pipeline(spans), Some(ParseError::NonUtf8(spans[1])));
|
return (
|
||||||
|
garbage_pipeline(&[call_span]),
|
||||||
|
Some(ParseError::NonUtf8(overlay_name_span)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3132,7 +2978,7 @@ pub fn parse_overlay_use(
|
||||||
|
|
||||||
let pipeline = Pipeline::from_vec(vec![Expression {
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: call_span,
|
||||||
ty: Type::Any,
|
ty: Type::Any,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}]);
|
}]);
|
||||||
|
@ -3142,78 +2988,26 @@ pub fn parse_overlay_use(
|
||||||
|
|
||||||
pub fn parse_overlay_hide(
|
pub fn parse_overlay_hide(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
call: Box<Call>,
|
||||||
expand_aliases_denylist: &[usize],
|
|
||||||
) -> (Pipeline, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
if spans.len() > 1 && working_set.get_span_contents(span(&spans[0..2])) != b"overlay hide" {
|
let call_span = call.span();
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: Wrong call name for 'overlay hide' command".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let call = match working_set.find_decl(b"overlay hide", &Type::Any) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let ParsedInternalCall {
|
|
||||||
call,
|
|
||||||
error: mut err,
|
|
||||||
output,
|
|
||||||
} = parse_internal_call(
|
|
||||||
working_set,
|
|
||||||
span(&spans[0..2]),
|
|
||||||
&spans[2..],
|
|
||||||
decl_id,
|
|
||||||
expand_aliases_denylist,
|
|
||||||
);
|
|
||||||
let decl = working_set.get_decl(decl_id);
|
|
||||||
|
|
||||||
let call_span = span(spans);
|
|
||||||
|
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
|
||||||
if err.is_some() || call.has_flag("help") {
|
|
||||||
return (
|
|
||||||
Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call),
|
|
||||||
span: call_span,
|
|
||||||
ty: output,
|
|
||||||
custom_completion: None,
|
|
||||||
}]),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
call
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return (
|
|
||||||
garbage_pipeline(spans),
|
|
||||||
Some(ParseError::UnknownState(
|
|
||||||
"internal error: 'overlay hide' declaration not found".into(),
|
|
||||||
span(spans),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
|
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
|
||||||
match eval_constant(working_set, expr) {
|
match eval_constant(working_set, expr) {
|
||||||
Ok(val) => match value_as_string(val, expr.span) {
|
Ok(val) => match value_as_string(val, expr.span) {
|
||||||
Ok(s) => (s, expr.span),
|
Ok(s) => (s, expr.span),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (garbage_pipeline(spans), Some(err));
|
return (garbage_pipeline(&[call_span]), Some(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
String::from_utf8_lossy(working_set.last_overlay_name()).to_string(),
|
String::from_utf8_lossy(working_set.last_overlay_name()).to_string(),
|
||||||
call.head,
|
call_span,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3221,7 +3015,7 @@ pub fn parse_overlay_hide(
|
||||||
|
|
||||||
let pipeline = Pipeline::from_vec(vec![Expression {
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: call_span,
|
||||||
ty: Type::Any,
|
ty: Type::Any,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -19,9 +19,10 @@ use nu_protocol::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parse_keywords::{
|
use crate::parse_keywords::{
|
||||||
parse_alias, parse_def, parse_def_predecl, parse_export_in_block, parse_extern, parse_for,
|
is_unaliasable_parser_keyword, parse_alias, parse_def, parse_def_predecl,
|
||||||
parse_hide, parse_let_or_const, parse_module, parse_old_alias, parse_overlay, parse_source,
|
parse_export_in_block, parse_extern, parse_for, parse_hide, parse_keyword, parse_let_or_const,
|
||||||
parse_use, parse_where, parse_where_expr,
|
parse_module, parse_old_alias, parse_overlay_hide, parse_overlay_new, parse_overlay_use,
|
||||||
|
parse_source, parse_use, parse_where, parse_where_expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -5309,6 +5310,49 @@ pub fn parse_builtin_commands(
|
||||||
expand_aliases_denylist: &[usize],
|
expand_aliases_denylist: &[usize],
|
||||||
is_subexpression: bool,
|
is_subexpression: bool,
|
||||||
) -> (Pipeline, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
|
if !is_math_expression_like(working_set, lite_command.parts[0], expand_aliases_denylist)
|
||||||
|
&& !is_unaliasable_parser_keyword(working_set, &lite_command.parts)
|
||||||
|
{
|
||||||
|
let name = working_set.get_span_contents(lite_command.parts[0]);
|
||||||
|
if let Some(decl_id) = working_set.find_decl(name, &Type::Any) {
|
||||||
|
let cmd = working_set.get_decl(decl_id);
|
||||||
|
if cmd.is_alias() {
|
||||||
|
// Parse keywords that can be aliased. Note that we check for "unaliasable" keywords
|
||||||
|
// because alias can have any name, therefore, we can't check for "aliasable" keywords.
|
||||||
|
let (call_expr, err) = parse_call(
|
||||||
|
working_set,
|
||||||
|
&lite_command.parts,
|
||||||
|
lite_command.parts[0],
|
||||||
|
expand_aliases_denylist,
|
||||||
|
is_subexpression,
|
||||||
|
);
|
||||||
|
|
||||||
|
if err.is_none() {
|
||||||
|
if let Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
..
|
||||||
|
} = call_expr
|
||||||
|
{
|
||||||
|
// Apply parse keyword side effects
|
||||||
|
let cmd = working_set.get_decl(call.decl_id);
|
||||||
|
match cmd.name() {
|
||||||
|
"overlay hide" => return parse_overlay_hide(working_set, call),
|
||||||
|
"overlay new" => return parse_overlay_new(working_set, call),
|
||||||
|
"overlay use" => {
|
||||||
|
return parse_overlay_use(
|
||||||
|
working_set,
|
||||||
|
call,
|
||||||
|
expand_aliases_denylist,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => { /* this alias is not a parser keyword */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let name = working_set.get_span_contents(lite_command.parts[0]);
|
let name = working_set.get_span_contents(lite_command.parts[0]);
|
||||||
|
|
||||||
match name {
|
match name {
|
||||||
|
@ -5330,7 +5374,12 @@ pub fn parse_builtin_commands(
|
||||||
parse_use(working_set, &lite_command.parts, expand_aliases_denylist);
|
parse_use(working_set, &lite_command.parts, expand_aliases_denylist);
|
||||||
(pipeline, err)
|
(pipeline, err)
|
||||||
}
|
}
|
||||||
b"overlay" => parse_overlay(working_set, &lite_command.parts, expand_aliases_denylist),
|
b"overlay" => parse_keyword(
|
||||||
|
working_set,
|
||||||
|
lite_command,
|
||||||
|
expand_aliases_denylist,
|
||||||
|
is_subexpression,
|
||||||
|
),
|
||||||
b"source" | b"source-env" => {
|
b"source" | b"source-env" => {
|
||||||
parse_source(working_set, &lite_command.parts, expand_aliases_denylist)
|
parse_source(working_set, &lite_command.parts, expand_aliases_denylist)
|
||||||
}
|
}
|
||||||
|
@ -5346,6 +5395,7 @@ pub fn parse_builtin_commands(
|
||||||
expand_aliases_denylist,
|
expand_aliases_denylist,
|
||||||
is_subexpression,
|
is_subexpression,
|
||||||
);
|
);
|
||||||
|
|
||||||
(Pipeline::from_vec(vec![expr]), err)
|
(Pipeline::from_vec(vec![expr]), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,7 +326,7 @@ fn overlay_use_do_not_eval_twice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay() {
|
fn hide_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export def foo [] { "foo" } }"#,
|
r#"module spam { export def foo [] { "foo" } }"#,
|
||||||
r#"overlay use spam"#,
|
r#"overlay use spam"#,
|
||||||
|
@ -345,7 +345,7 @@ fn remove_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_last_overlay() {
|
fn hide_last_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export def foo [] { "foo" } }"#,
|
r#"module spam { export def foo [] { "foo" } }"#,
|
||||||
r#"overlay use spam"#,
|
r#"overlay use spam"#,
|
||||||
|
@ -364,7 +364,7 @@ fn remove_last_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_scoped() {
|
fn hide_overlay_scoped() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export def foo [] { "foo" } }"#,
|
r#"module spam { export def foo [] { "foo" } }"#,
|
||||||
r#"overlay use spam"#,
|
r#"overlay use spam"#,
|
||||||
|
@ -380,7 +380,7 @@ fn remove_overlay_scoped() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_env() {
|
fn hide_overlay_env() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
||||||
r#"overlay use spam"#,
|
r#"overlay use spam"#,
|
||||||
|
@ -396,7 +396,7 @@ fn remove_overlay_env() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_scoped_env() {
|
fn hide_overlay_scoped_env() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
||||||
r#"overlay use spam"#,
|
r#"overlay use spam"#,
|
||||||
|
@ -453,7 +453,7 @@ fn list_overlay_scoped() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_discard_decl() {
|
fn hide_overlay_discard_decl() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"def bagr [] { "bagr" }"#,
|
r#"def bagr [] { "bagr" }"#,
|
||||||
|
@ -472,7 +472,7 @@ fn remove_overlay_discard_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_discard_alias() {
|
fn hide_overlay_discard_alias() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"alias bagr = echo "bagr""#,
|
r#"alias bagr = echo "bagr""#,
|
||||||
|
@ -491,7 +491,7 @@ fn remove_overlay_discard_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_discard_env() {
|
fn hide_overlay_discard_env() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"let-env BAGR = 'bagr'"#,
|
r#"let-env BAGR = 'bagr'"#,
|
||||||
|
@ -507,7 +507,7 @@ fn remove_overlay_discard_env() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_keep_decl() {
|
fn hide_overlay_keep_decl() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"def bagr [] { "bagr" }"#,
|
r#"def bagr [] { "bagr" }"#,
|
||||||
|
@ -523,7 +523,7 @@ fn remove_overlay_keep_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_keep_alias() {
|
fn hide_overlay_keep_alias() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"alias bagr = echo 'bagr'"#,
|
r#"alias bagr = echo 'bagr'"#,
|
||||||
|
@ -539,7 +539,7 @@ fn remove_overlay_keep_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_dont_keep_env() {
|
fn hide_overlay_dont_keep_env() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"let-env BAGR = 'bagr'"#,
|
r#"let-env BAGR = 'bagr'"#,
|
||||||
|
@ -555,7 +555,7 @@ fn remove_overlay_dont_keep_env() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_dont_keep_overwritten_decl() {
|
fn hide_overlay_dont_keep_overwritten_decl() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"def foo [] { 'bar' }"#,
|
r#"def foo [] { 'bar' }"#,
|
||||||
|
@ -574,7 +574,7 @@ fn remove_overlay_dont_keep_overwritten_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_dont_keep_overwritten_alias() {
|
fn hide_overlay_dont_keep_overwritten_alias() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"alias bar = echo `baz`"#,
|
r#"alias bar = echo `baz`"#,
|
||||||
|
@ -593,7 +593,7 @@ fn remove_overlay_dont_keep_overwritten_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_dont_keep_overwritten_env() {
|
fn hide_overlay_dont_keep_overwritten_env() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"let-env BAZ = 'bagr'"#,
|
r#"let-env BAZ = 'bagr'"#,
|
||||||
|
@ -609,7 +609,7 @@ fn remove_overlay_dont_keep_overwritten_env() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_keep_decl_in_latest_overlay() {
|
fn hide_overlay_keep_decl_in_latest_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"def bagr [] { 'bagr' }"#,
|
r#"def bagr [] { 'bagr' }"#,
|
||||||
|
@ -627,7 +627,7 @@ fn remove_overlay_keep_decl_in_latest_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_keep_alias_in_latest_overlay() {
|
fn hide_overlay_keep_alias_in_latest_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"alias bagr = echo 'bagr'"#,
|
r#"alias bagr = echo 'bagr'"#,
|
||||||
|
@ -645,7 +645,7 @@ fn remove_overlay_keep_alias_in_latest_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_overlay_dont_keep_env_in_latest_overlay() {
|
fn hide_overlay_dont_keep_env_in_latest_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"overlay use samples/spam.nu"#,
|
r#"overlay use samples/spam.nu"#,
|
||||||
r#"let-env BAGR = 'bagr'"#,
|
r#"let-env BAGR = 'bagr'"#,
|
||||||
|
@ -811,7 +811,7 @@ fn overlay_can_add_renamed_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlay_remove_renamed_overlay() {
|
fn overlay_hide_renamed_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export def foo [] { "foo" } }"#,
|
r#"module spam { export def foo [] { "foo" } }"#,
|
||||||
r#"overlay use spam as eggs"#,
|
r#"overlay use spam as eggs"#,
|
||||||
|
@ -827,7 +827,7 @@ fn overlay_remove_renamed_overlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlay_remove_and_add_renamed_overlay() {
|
fn overlay_hide_and_add_renamed_overlay() {
|
||||||
let inp = &[
|
let inp = &[
|
||||||
r#"module spam { export def foo [] { "foo" } }"#,
|
r#"module spam { export def foo [] { "foo" } }"#,
|
||||||
r#"overlay use spam as eggs"#,
|
r#"overlay use spam as eggs"#,
|
||||||
|
@ -1261,3 +1261,53 @@ fn overlay_use_main_not_exported() {
|
||||||
|
|
||||||
assert!(actual.err.contains("external_command"));
|
assert!(actual.err.contains("external_command"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alias_overlay_hide() {
|
||||||
|
let inp = &[
|
||||||
|
r#"overlay new spam"#,
|
||||||
|
r#"def foo [] { 'foo' }"#,
|
||||||
|
r#"overlay new eggs"#,
|
||||||
|
r#"alias oh = overlay hide"#,
|
||||||
|
r#"oh spam"#,
|
||||||
|
r#"foo"#,
|
||||||
|
];
|
||||||
|
|
||||||
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
||||||
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
||||||
|
|
||||||
|
assert!(actual.err.contains("external_command"));
|
||||||
|
assert!(actual_repl.err.contains("external_command"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alias_overlay_use() {
|
||||||
|
let inp = &[
|
||||||
|
r#"module spam { export def foo [] { 'foo' } }"#,
|
||||||
|
r#"alias ou = overlay use"#,
|
||||||
|
r#"ou spam"#,
|
||||||
|
r#"foo"#,
|
||||||
|
];
|
||||||
|
|
||||||
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
||||||
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "foo");
|
||||||
|
assert_eq!(actual_repl.out, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alias_overlay_new() {
|
||||||
|
let inp = &[
|
||||||
|
r#"alias on = overlay new"#,
|
||||||
|
r#"on spam"#,
|
||||||
|
r#"on eggs"#,
|
||||||
|
r#"overlay list | last"#,
|
||||||
|
];
|
||||||
|
|
||||||
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
||||||
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "eggs");
|
||||||
|
assert_eq!(actual_repl.out, "eggs");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue