diff --git a/crates/nu-command/src/commands/core_commands/alias.rs b/crates/nu-command/src/commands/core_commands/alias.rs index 859e0cfdb..6321681f5 100644 --- a/crates/nu-command/src/commands/core_commands/alias.rs +++ b/crates/nu-command/src/commands/core_commands/alias.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; pub struct Alias; @@ -35,6 +35,18 @@ impl WholeStreamCommand for Alias { } } -pub fn alias(_: CommandArgs) -> Result { +pub fn alias(args: CommandArgs) -> Result { + // TODO: is there a better way of checking whether no arguments were passed? + if args.nth(0).is_none() { + let aliases = UntaggedValue::string( + &args + .scope() + .get_aliases() + .iter() + .map(|val| format!("{} = '{}'", val.0, val.1.iter().map(|x| &x.item).join(" "))) + .join("\n"), + ); + return Ok(OutputStream::one(aliases)); + } Ok(OutputStream::empty()) } diff --git a/crates/nu-command/src/commands/core_commands/mod.rs b/crates/nu-command/src/commands/core_commands/mod.rs index 75602d9d3..ea48e353b 100644 --- a/crates/nu-command/src/commands/core_commands/mod.rs +++ b/crates/nu-command/src/commands/core_commands/mod.rs @@ -13,6 +13,7 @@ mod nu_plugin; mod nu_signature; mod source; mod tags; +mod unalias; mod version; pub use self::nu_plugin::SubCommand as NuPlugin; @@ -32,4 +33,5 @@ pub use ignore::Ignore; pub use let_::Let; pub use source::Source; pub use tags::Tags; +pub use unalias::Unalias; pub use version::{version, Version}; diff --git a/crates/nu-command/src/commands/core_commands/unalias.rs b/crates/nu-command/src/commands/core_commands/unalias.rs new file mode 100644 index 000000000..75de72b95 --- /dev/null +++ b/crates/nu-command/src/commands/core_commands/unalias.rs @@ -0,0 +1,37 @@ +use crate::prelude::*; +use nu_engine::WholeStreamCommand; + +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; + +pub struct Unalias; + +impl WholeStreamCommand for Unalias { + fn name(&self) -> &str { + "unalias" + } + + fn signature(&self) -> Signature { + Signature::build("unalias").required("name", SyntaxShape::String, "the name of the alias") + } + + fn usage(&self) -> &str { + "Removes an alias" + } + + fn run(&self, args: CommandArgs) -> Result { + unalias(args) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Remove the 'v' alias", + example: "unalias v", + result: None, + }] + } +} + +pub fn unalias(_: CommandArgs) -> Result { + Ok(OutputStream::empty()) +} diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 3d54c749a..a13c3f96a 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -18,6 +18,7 @@ pub fn create_default_context(interactive: bool) -> Result) {} fn get_definitions(&self) -> Vec> { diff --git a/crates/nu-engine/src/evaluate/scope.rs b/crates/nu-engine/src/evaluate/scope.rs index 90fdcbdf2..4b1240090 100644 --- a/crates/nu-engine/src/evaluate/scope.rs +++ b/crates/nu-engine/src/evaluate/scope.rs @@ -407,6 +407,12 @@ impl ParserScope for Scope { } } + fn remove_alias(&self, name: &str) { + for frame in self.frames.lock().iter_mut().rev() { + frame.aliases.remove(name); + } + } + fn enter_scope(&self) { self.frames.lock().push(ScopeFrame::new()); } diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index 30c657c43..f12340349 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -1902,7 +1902,7 @@ fn parse_call( )), ); } - } else if lite_cmd.parts[0].item == "alias" { + } else if lite_cmd.parts[0].item == "alias" || lite_cmd.parts[0].item == "unalias" { let error = parse_alias(&lite_cmd, scope); if error.is_none() { return (Some(ClassifiedCommand::Internal(internal_command)), None); @@ -2048,26 +2048,41 @@ fn expand_shorthand_forms( } fn parse_alias(call: &LiteCommand, scope: &dyn ParserScope) -> Option { - if call.parts.len() == 2 && (call.parts[1].item == "--help" || (call.parts[1].item == "-h")) { - return None; - } + if call.parts[0].item == "alias" { + if (call.parts.len() == 1) + || (call.parts.len() == 2 + && (call.parts[1].item == "--help" || (call.parts[1].item == "-h"))) + { + return None; + } + if call.parts.len() < 4 { + return Some(ParseError::mismatch("alias", call.parts[0].clone())); + } - if call.parts.len() < 4 { - return Some(ParseError::mismatch("alias", call.parts[0].clone())); - } + if call.parts[0].item != "alias" { + return Some(ParseError::mismatch("alias", call.parts[0].clone())); + } - if call.parts[0].item != "alias" { - return Some(ParseError::mismatch("alias", call.parts[0].clone())); - } - - if call.parts[2].item != "=" { - return Some(ParseError::mismatch("=", call.parts[2].clone())); + if call.parts[2].item != "=" { + return Some(ParseError::mismatch("=", call.parts[2].clone())); + } + } else { + // unalias + if call.parts.len() != 2 { + return Some(ParseError::mismatch("unalias", call.parts[0].clone())); + } } let name = call.parts[1].item.clone(); let args: Vec<_> = call.parts.iter().skip(3).cloned().collect(); - scope.add_alias(&name, args); + match call.parts[0].item.as_str() { + "alias" => scope.add_alias(&name, args), + "unalias" => { + scope.remove_alias(&name); + } + _ => unreachable!(), + }; None } diff --git a/crates/nu-parser/src/scope.rs b/crates/nu-parser/src/scope.rs index a112e163c..4ea4c5a89 100644 --- a/crates/nu-parser/src/scope.rs +++ b/crates/nu-parser/src/scope.rs @@ -13,6 +13,8 @@ pub trait ParserScope: Debug { fn get_alias(&self, name: &str) -> Option>>; + fn remove_alias(&self, name: &str); + fn add_alias(&self, name: &str, replacement: Vec>); fn enter_scope(&self); diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 108421b5d..ec056b042 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -1145,6 +1145,21 @@ fn nothing_string_2() { assert_eq!(actual.out, "true"); } +#[test] +fn unalias_shadowing() { + let actual = nu!( + cwd: ".", pipeline( + r#" + alias ll = ls -l + let xyz = { ll -a } + unalias ll + do $xyz + "#) + ); + + assert_eq!(actual.out, ""); +} + mod parse { use nu_test_support::nu;