diff --git a/crates/nu-engine/src/evaluate/evaluator.rs b/crates/nu-engine/src/evaluate/evaluator.rs index 1c8e7b5ad..cce272284 100644 --- a/crates/nu-engine/src/evaluate/evaluator.rs +++ b/crates/nu-engine/src/evaluate/evaluator.rs @@ -234,6 +234,8 @@ fn evaluate_reference(name: &str, ctx: &EvaluationContext, tag: Tag) -> Result crate::evaluate::variables::nu(&ctx.scope, tag), + "$scope" => crate::evaluate::variables::scope(&ctx.scope.get_aliases(), tag), + "$true" => Ok(Value { value: UntaggedValue::boolean(true), tag, diff --git a/crates/nu-engine/src/evaluate/scope.rs b/crates/nu-engine/src/evaluate/scope.rs index 63f56e9de..7bab541ea 100644 --- a/crates/nu-engine/src/evaluate/scope.rs +++ b/crates/nu-engine/src/evaluate/scope.rs @@ -33,6 +33,19 @@ impl Scope { None } + pub fn get_aliases(&self) -> IndexMap>> { + let mut output = IndexMap::new(); + + for frame in self.frames.lock().iter().rev() { + for v in frame.aliases.iter() { + if !output.contains_key(v.0) { + output.insert(v.0.clone(), v.1.clone()); + } + } + } + output + } + pub fn get_aliases_with_name(&self, name: &str) -> Option>>> { let aliases: Vec<_> = self .frames @@ -71,6 +84,20 @@ impl Scope { } } + pub fn get_alias_names(&self) -> Vec { + let mut names = vec![]; + + for frame in self.frames.lock().iter() { + let mut frame_command_names = frame.get_alias_names(); + names.append(&mut frame_command_names); + } + + names.dedup(); + names.sort(); + + names + } + pub fn get_command_names(&self) -> Vec { let mut names = vec![]; @@ -274,6 +301,10 @@ impl ScopeFrame { self.aliases.contains_key(name) } + pub fn get_alias_names(&self) -> Vec { + self.aliases.keys().map(|x| x.to_string()).collect() + } + pub fn get_command_names(&self) -> Vec { self.commands.keys().map(|x| x.to_string()).collect() } diff --git a/crates/nu-engine/src/evaluate/variables.rs b/crates/nu-engine/src/evaluate/variables.rs index cbddb5681..cc047da80 100644 --- a/crates/nu-engine/src/evaluate/variables.rs +++ b/crates/nu-engine/src/evaluate/variables.rs @@ -1,8 +1,9 @@ use crate::evaluate::scope::Scope; +use indexmap::IndexMap; use nu_data::config::NuConfig; use nu_errors::ShellError; use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tag; +use nu_source::{Spanned, Tag}; pub fn nu(scope: &Scope, tag: impl Into) -> Result { let tag = tag.into(); @@ -75,3 +76,28 @@ pub fn nu(scope: &Scope, tag: impl Into) -> Result { Ok(nu_dict.into_value()) } + +pub fn scope( + aliases: &IndexMap>>, + tag: impl Into, +) -> Result { + let tag = tag.into(); + + let mut scope_dict = TaggedDictBuilder::new(&tag); + + let mut dict = TaggedDictBuilder::new(&tag); + for v in aliases.iter() { + let values = v.1.clone(); + let mut vec = Vec::new(); + + for k in values.iter() { + vec.push(k.to_string()); + } + + let alias = vec.join(" "); + dict.insert_untagged(v.0, UntaggedValue::string(alias)); + } + + scope_dict.insert_value("aliases", dict.into_value()); + Ok(scope_dict.into_value()) +} diff --git a/crates/nu-engine/tests/evaluate/variables.rs b/crates/nu-engine/tests/evaluate/variables.rs index 48d5ae02a..84edaaf80 100644 --- a/crates/nu-engine/tests/evaluate/variables.rs +++ b/crates/nu-engine/tests/evaluate/variables.rs @@ -32,3 +32,39 @@ fn custom_config_path_variable_present() { ); }) } + +#[test] +fn scope_variable_with_alias_present() { + Playground::setup("scope_variable_alias_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + "skip_welcome_message = true", + )]); + + assert_that!( + nu.pipeline("alias t = time; echo $scope.aliases | get t"), + says().to_stdout("time") + ); + }) +} + +#[test] +fn scope_variable_with_correct_number_of_aliases_present() { + Playground::setup("scope_variable_alias_test_2", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + "skip_welcome_message = true", + )]); + + assert_that!( + nu.pipeline("alias v = version; alias t = time; echo $scope.aliases | length -c"), + says().to_stdout("2") + ); + }) +}