From b2fe5fabb1be3d45adc34012dedb6b8dcc9e8978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Barrag=C3=A1n?= Date: Sun, 11 Apr 2021 19:38:47 -0700 Subject: [PATCH] Add commands to scope variable (#3272) * Add commands to scope variable * List commands with signature on scope variables Usage: ```shell echo $scope.commands | pivot ``` * Run rust formater * Update variables.rs Co-authored-by: Jonathan Turner --- crates/nu-engine/src/evaluate/evaluator.rs | 6 +++++- crates/nu-engine/src/evaluate/scope.rs | 14 +++++++++++++- crates/nu-engine/src/evaluate/variables.rs | 18 ++++++++++++++---- crates/nu-engine/tests/evaluate/variables.rs | 18 ++++++++++++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/crates/nu-engine/src/evaluate/evaluator.rs b/crates/nu-engine/src/evaluate/evaluator.rs index 6270d8ac77..034af45625 100644 --- a/crates/nu-engine/src/evaluate/evaluator.rs +++ b/crates/nu-engine/src/evaluate/evaluator.rs @@ -229,7 +229,11 @@ fn evaluate_reference(name: &str, ctx: &EvaluationContext, tag: Tag) -> Result crate::evaluate::variables::nu(&ctx.scope, tag, ctx), - "$scope" => crate::evaluate::variables::scope(&ctx.scope.get_aliases(), tag), + "$scope" => crate::evaluate::variables::scope( + &ctx.scope.get_aliases(), + &ctx.scope.get_commands(), + tag, + ), "$true" => Ok(Value { value: UntaggedValue::boolean(true), diff --git a/crates/nu-engine/src/evaluate/scope.rs b/crates/nu-engine/src/evaluate/scope.rs index 40d57f0fc8..06cf93547e 100644 --- a/crates/nu-engine/src/evaluate/scope.rs +++ b/crates/nu-engine/src/evaluate/scope.rs @@ -2,7 +2,7 @@ use crate::whole_stream_command::{whole_stream_command, Command}; use indexmap::IndexMap; use nu_errors::ShellError; use nu_parser::ParserScope; -use nu_protocol::{hir::Block, Value}; +use nu_protocol::{hir::Block, Signature, Value}; use nu_source::Spanned; use std::sync::Arc; @@ -46,6 +46,18 @@ impl Scope { output } + pub fn get_commands(&self) -> IndexMap { + let mut output = IndexMap::new(); + + for frame in self.frames.lock().iter().rev() { + for (name, command) in frame.commands.iter() { + output.insert(name.clone(), command.signature()); + } + } + + output + } + pub fn get_aliases_with_name(&self, name: &str) -> Option>>> { let aliases: Vec<_> = self .frames diff --git a/crates/nu-engine/src/evaluate/variables.rs b/crates/nu-engine/src/evaluate/variables.rs index 718eb04dae..05093cdecf 100644 --- a/crates/nu-engine/src/evaluate/variables.rs +++ b/crates/nu-engine/src/evaluate/variables.rs @@ -2,7 +2,7 @@ use crate::{evaluate::scope::Scope, EvaluationContext}; use indexmap::IndexMap; use nu_data::config::path::{default_history_path, history_path}; use nu_errors::ShellError; -use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; +use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue, Value}; use nu_source::{Spanned, Tag}; pub fn nu( @@ -83,13 +83,14 @@ pub fn nu( pub fn scope( aliases: &IndexMap>>, + commands: &IndexMap, tag: impl Into, ) -> Result { let tag = tag.into(); let mut scope_dict = TaggedDictBuilder::new(&tag); - let mut dict = TaggedDictBuilder::new(&tag); + let mut aliases_dict = TaggedDictBuilder::new(&tag); for v in aliases.iter() { let values = v.1.clone(); let mut vec = Vec::new(); @@ -99,9 +100,18 @@ pub fn scope( } let alias = vec.join(" "); - dict.insert_untagged(v.0, UntaggedValue::string(alias)); + + aliases_dict.insert_untagged(v.0, UntaggedValue::string(alias)); } - scope_dict.insert_value("aliases", dict.into_value()); + let mut commands_dict = TaggedDictBuilder::new(&tag); + for (name, signature) in commands.iter() { + commands_dict.insert_untagged(name, UntaggedValue::string(&signature.allowed().join(" "))) + } + + scope_dict.insert_value("aliases", aliases_dict.into_value()); + + scope_dict.insert_value("commands", commands_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 84edaaf804..f00db130da 100644 --- a/crates/nu-engine/tests/evaluate/variables.rs +++ b/crates/nu-engine/tests/evaluate/variables.rs @@ -68,3 +68,21 @@ fn scope_variable_with_correct_number_of_aliases_present() { ); }) } + +#[test] +fn scope_variable_with_command_present() { + Playground::setup("scope_commands_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("def meaning-of-life [--number: int] { echo $number }; echo $scope.commands | get meaning-of-life"), + says().to_stdout("-h --help --number") + ); + }) +}