mirror of
https://github.com/nushell/nushell
synced 2024-12-26 04:53:09 +00:00
Refactor scope
commands (#10023)
This commit is contained in:
parent
35f8d8548a
commit
e88a51e930
14 changed files with 440 additions and 269 deletions
|
@ -35,7 +35,7 @@ impl Command for ScopeAliases {
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
let mut scope_data = ScopeData::new(engine_state, stack);
|
||||||
scope_data.populate_all();
|
scope_data.populate_decls();
|
||||||
|
|
||||||
Ok(scope_data.collect_aliases(span).into_pipeline_data(ctrlc))
|
Ok(scope_data.collect_aliases(span).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Command for ScopeCommands {
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
let mut scope_data = ScopeData::new(engine_state, stack);
|
||||||
scope_data.populate_all();
|
scope_data.populate_decls();
|
||||||
|
|
||||||
Ok(scope_data.collect_commands(span).into_pipeline_data(ctrlc))
|
Ok(scope_data.collect_commands(span).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,7 @@ impl Command for ScopeEngineStats {
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
let scope_data = ScopeData::new(engine_state, stack);
|
||||||
scope_data.populate_all();
|
|
||||||
|
|
||||||
Ok(scope_data.collect_engine_state(span).into_pipeline_data())
|
Ok(scope_data.collect_engine_state(span).into_pipeline_data())
|
||||||
}
|
}
|
||||||
|
|
62
crates/nu-cmd-lang/src/core_commands/scope/externs.rs
Normal file
62
crates/nu-cmd-lang/src/core_commands/scope/externs.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use nu_engine::scope::ScopeData;
|
||||||
|
use nu_protocol::ast::Call;
|
||||||
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
|
use nu_protocol::{
|
||||||
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ScopeExterns;
|
||||||
|
|
||||||
|
impl Command for ScopeExterns {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"scope externs"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("scope externs")
|
||||||
|
.input_output_types(vec![(Type::Nothing, Type::Any)])
|
||||||
|
.allow_variants_without_examples(true)
|
||||||
|
.category(Category::Filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Output info on the known externals in the current scope."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
_input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let span = call.head;
|
||||||
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
|
||||||
|
let mut scope_data = ScopeData::new(engine_state, stack);
|
||||||
|
scope_data.populate_decls();
|
||||||
|
|
||||||
|
Ok(scope_data.collect_externs(span).into_pipeline_data(ctrlc))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Show the known externals in the current scope",
|
||||||
|
example: "scope externs",
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
use crate::test_examples;
|
||||||
|
|
||||||
|
test_examples(ScopeExterns {})
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ mod aliases;
|
||||||
mod command;
|
mod command;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod engine_stats;
|
mod engine_stats;
|
||||||
|
mod externs;
|
||||||
mod modules;
|
mod modules;
|
||||||
mod variables;
|
mod variables;
|
||||||
|
|
||||||
|
@ -9,5 +10,6 @@ pub use aliases::*;
|
||||||
pub use command::*;
|
pub use command::*;
|
||||||
pub use commands::*;
|
pub use commands::*;
|
||||||
pub use engine_stats::*;
|
pub use engine_stats::*;
|
||||||
|
pub use externs::*;
|
||||||
pub use modules::*;
|
pub use modules::*;
|
||||||
pub use variables::*;
|
pub use variables::*;
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Command for ScopeVariables {
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
let mut scope_data = ScopeData::new(engine_state, stack);
|
||||||
scope_data.populate_all();
|
scope_data.populate_vars();
|
||||||
|
|
||||||
Ok(scope_data.collect_vars(span).into_pipeline_data(ctrlc))
|
Ok(scope_data.collect_vars(span).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ pub fn create_default_context() -> EngineState {
|
||||||
ScopeAliases,
|
ScopeAliases,
|
||||||
ScopeCommands,
|
ScopeCommands,
|
||||||
ScopeEngineStats,
|
ScopeEngineStats,
|
||||||
|
ScopeExterns,
|
||||||
ScopeModules,
|
ScopeModules,
|
||||||
ScopeVariables,
|
ScopeVariables,
|
||||||
Try,
|
Try,
|
||||||
|
|
|
@ -169,7 +169,7 @@ pub fn help_aliases(
|
||||||
|
|
||||||
fn build_help_aliases(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
|
fn build_help_aliases(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
let mut scope_data = ScopeData::new(engine_state, stack);
|
||||||
scope_data.populate_all();
|
scope_data.populate_decls();
|
||||||
|
|
||||||
scope_data.collect_aliases(span)
|
scope_data.collect_aliases(span)
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ pub fn help_externs(
|
||||||
|
|
||||||
fn build_help_externs(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
|
fn build_help_externs(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
|
||||||
let mut scope = ScopeData::new(engine_state, stack);
|
let mut scope = ScopeData::new(engine_state, stack);
|
||||||
scope.populate_all();
|
scope.populate_decls();
|
||||||
scope.collect_externs(span)
|
scope.collect_externs(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ use nu_test_support::fs::Stub::FileWithContent;
|
||||||
use nu_test_support::playground::Playground;
|
use nu_test_support::playground::Playground;
|
||||||
use nu_test_support::{nu, nu_repl_code, pipeline};
|
use nu_test_support::{nu, nu_repl_code, pipeline};
|
||||||
|
|
||||||
|
// Note: These tests might slightly overlap with tests/scope/mod.rs
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_commands_length() {
|
fn help_commands_length() {
|
||||||
let actual = nu!("help commands | length");
|
let actual = nu!("help commands | length");
|
||||||
|
@ -22,7 +24,6 @@ fn help_shows_signature() {
|
||||||
assert!(!actual.out.contains("Input/output types"));
|
assert!(!actual.out.contains("Input/output types"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_aliases() {
|
fn help_aliases() {
|
||||||
let code = &[
|
let code = &[
|
||||||
|
@ -34,7 +35,6 @@ fn help_aliases() {
|
||||||
assert_eq!(actual.out, "1");
|
assert_eq!(actual.out, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_alias_usage_1() {
|
fn help_alias_usage_1() {
|
||||||
Playground::setup("help_alias_usage_1", |dirs, sandbox| {
|
Playground::setup("help_alias_usage_1", |dirs, sandbox| {
|
||||||
|
@ -56,7 +56,6 @@ fn help_alias_usage_1() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_alias_usage_2() {
|
fn help_alias_usage_2() {
|
||||||
let code = &[
|
let code = &[
|
||||||
|
@ -68,7 +67,6 @@ fn help_alias_usage_2() {
|
||||||
assert_eq!(actual.out, "line2");
|
assert_eq!(actual.out, "line2");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_alias_usage_3() {
|
fn help_alias_usage_3() {
|
||||||
Playground::setup("help_alias_usage_3", |dirs, sandbox| {
|
Playground::setup("help_alias_usage_3", |dirs, sandbox| {
|
||||||
|
@ -91,7 +89,6 @@ fn help_alias_usage_3() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_alias_name() {
|
fn help_alias_name() {
|
||||||
Playground::setup("help_alias_name", |dirs, sandbox| {
|
Playground::setup("help_alias_name", |dirs, sandbox| {
|
||||||
|
@ -113,7 +110,6 @@ fn help_alias_name() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_alias_name_f() {
|
fn help_alias_name_f() {
|
||||||
Playground::setup("help_alias_name_f", |dirs, sandbox| {
|
Playground::setup("help_alias_name_f", |dirs, sandbox| {
|
||||||
|
@ -133,7 +129,6 @@ fn help_alias_name_f() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_export_alias_name_single_word() {
|
fn help_export_alias_name_single_word() {
|
||||||
Playground::setup("help_export_alias_name_single_word", |dirs, sandbox| {
|
Playground::setup("help_export_alias_name_single_word", |dirs, sandbox| {
|
||||||
|
@ -155,7 +150,6 @@ fn help_export_alias_name_single_word() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_export_alias_name_multi_word() {
|
fn help_export_alias_name_multi_word() {
|
||||||
Playground::setup("help_export_alias_name_multi_word", |dirs, sandbox| {
|
Playground::setup("help_export_alias_name_multi_word", |dirs, sandbox| {
|
||||||
|
@ -302,7 +296,6 @@ fn help_usage_extra_usage_command() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Need to decide how to do help messages of new aliases"]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn help_usage_extra_usage_alias() {
|
fn help_usage_extra_usage_alias() {
|
||||||
Playground::setup("help_usage_extra_usage_alias", |dirs, sandbox| {
|
Playground::setup("help_usage_extra_usage_alias", |dirs, sandbox| {
|
||||||
|
@ -360,7 +353,7 @@ fn help_modules_main_2() {
|
||||||
r#"module spam {
|
r#"module spam {
|
||||||
export def main [] { 'foo' };
|
export def main [] { 'foo' };
|
||||||
}"#,
|
}"#,
|
||||||
"help modules | where name == spam | get 0.commands.0",
|
"help modules | where name == spam | get 0.commands.0.name",
|
||||||
];
|
];
|
||||||
|
|
||||||
let actual = nu!(pipeline(&inp.join("; ")));
|
let actual = nu!(pipeline(&inp.join("; ")));
|
||||||
|
@ -368,19 +361,6 @@ fn help_modules_main_2() {
|
||||||
assert_eq!(actual.out, "spam");
|
assert_eq!(actual.out, "spam");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore = "TODO: Can't have alias with the same name as command"]
|
|
||||||
#[test]
|
|
||||||
fn help_alias_before_command() {
|
|
||||||
let code = &[
|
|
||||||
"alias SPAM = echo 'spam'",
|
|
||||||
"def SPAM [] { 'spam' }",
|
|
||||||
"help SPAM",
|
|
||||||
];
|
|
||||||
let actual = nu!(nu_repl_code(code));
|
|
||||||
|
|
||||||
assert!(actual.out.contains("Alias"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nothing_type_annotation() {
|
fn nothing_type_annotation() {
|
||||||
let actual = nu!(pipeline(
|
let actual = nu!(pipeline(
|
||||||
|
|
|
@ -1,53 +1,10 @@
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{Command, EngineState, Stack, Visibility},
|
engine::{Command, EngineState, Stack, Visibility},
|
||||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
ModuleId, Signature, Span, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
use std::borrow::Borrow;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn create_scope(
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &Stack,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<Value, ShellError> {
|
|
||||||
let mut scope_data = ScopeData::new(engine_state, stack);
|
|
||||||
|
|
||||||
scope_data.populate_all();
|
|
||||||
|
|
||||||
let mut cols = vec![];
|
|
||||||
let mut vals = vec![];
|
|
||||||
|
|
||||||
cols.push("vars".to_string());
|
|
||||||
vals.push(Value::List {
|
|
||||||
vals: scope_data.collect_vars(span),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
cols.push("commands".to_string());
|
|
||||||
vals.push(Value::List {
|
|
||||||
vals: scope_data.collect_commands(span),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
cols.push("aliases".to_string());
|
|
||||||
vals.push(Value::List {
|
|
||||||
vals: scope_data.collect_aliases(span),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
cols.push("modules".to_string());
|
|
||||||
vals.push(Value::List {
|
|
||||||
vals: scope_data.collect_modules(span),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
cols.push("engine_state".to_string());
|
|
||||||
vals.push(scope_data.collect_engine_state(span));
|
|
||||||
|
|
||||||
Ok(Value::Record { cols, vals, span })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ScopeData<'e, 's> {
|
pub struct ScopeData<'e, 's> {
|
||||||
engine_state: &'e EngineState,
|
engine_state: &'e EngineState,
|
||||||
stack: &'s Stack,
|
stack: &'s Stack,
|
||||||
|
@ -69,11 +26,16 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn populate_all(&mut self) {
|
pub fn populate_vars(&mut self) {
|
||||||
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
||||||
self.vars_map.extend(&overlay_frame.vars);
|
self.vars_map.extend(&overlay_frame.vars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decls include all commands, i.e., normal commands, aliases, and externals
|
||||||
|
pub fn populate_decls(&mut self) {
|
||||||
|
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
||||||
self.decls_map.extend(&overlay_frame.decls);
|
self.decls_map.extend(&overlay_frame.decls);
|
||||||
self.modules_map.extend(&overlay_frame.modules);
|
|
||||||
self.visibility.merge_with(overlay_frame.visibility.clone());
|
self.visibility.merge_with(overlay_frame.visibility.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,20 +48,28 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
|
|
||||||
pub fn collect_vars(&self, span: Span) -> Vec<Value> {
|
pub fn collect_vars(&self, span: Span) -> Vec<Value> {
|
||||||
let mut vars = vec![];
|
let mut vars = vec![];
|
||||||
for var in &self.vars_map {
|
|
||||||
let var_name = Value::string(String::from_utf8_lossy(var.0).to_string(), span);
|
|
||||||
|
|
||||||
let var_type = Value::string(self.engine_state.get_var(**var.1).ty.to_string(), span);
|
for (var_name, var_id) in &self.vars_map {
|
||||||
|
let var_name = Value::string(String::from_utf8_lossy(var_name).to_string(), span);
|
||||||
|
|
||||||
let var_value = if let Ok(val) = self.stack.get_var(**var.1, span) {
|
let var_type = Value::string(self.engine_state.get_var(**var_id).ty.to_string(), span);
|
||||||
|
|
||||||
|
let var_value = if let Ok(val) = self.stack.get_var(**var_id, span) {
|
||||||
val
|
val
|
||||||
} else {
|
} else {
|
||||||
Value::nothing(span)
|
Value::nothing(span)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let var_id_val = Value::int(**var_id as i64, span);
|
||||||
|
|
||||||
vars.push(Value::Record {
|
vars.push(Value::Record {
|
||||||
cols: vec!["name".to_string(), "type".to_string(), "value".to_string()],
|
cols: vec![
|
||||||
vals: vec![var_name, var_type, var_value],
|
"name".to_string(),
|
||||||
|
"type".to_string(),
|
||||||
|
"value".to_string(),
|
||||||
|
"var_id".to_string(),
|
||||||
|
],
|
||||||
|
vals: vec![var_name, var_type, var_value, var_id_val],
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -108,6 +78,7 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
|
|
||||||
pub fn collect_commands(&self, span: Span) -> Vec<Value> {
|
pub fn collect_commands(&self, span: Span) -> Vec<Value> {
|
||||||
let mut commands = vec![];
|
let mut commands = vec![];
|
||||||
|
|
||||||
for (command_name, decl_id) in &self.decls_map {
|
for (command_name, decl_id) in &self.decls_map {
|
||||||
if self.visibility.is_decl_id_visible(decl_id)
|
if self.visibility.is_decl_id_visible(decl_id)
|
||||||
&& !self.engine_state.get_decl(**decl_id).is_alias()
|
&& !self.engine_state.get_decl(**decl_id).is_alias()
|
||||||
|
@ -115,27 +86,12 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
|
|
||||||
let mut module_commands = vec![];
|
|
||||||
for module in &self.modules_map {
|
|
||||||
let module_name = String::from_utf8_lossy(module.0).to_string();
|
|
||||||
let module_id = self.engine_state.find_module(module.0, &[]);
|
|
||||||
if let Some(module_id) = module_id {
|
|
||||||
let module = self.engine_state.get_module(module_id);
|
|
||||||
if module.has_decl(command_name) {
|
|
||||||
module_commands.push(module_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cols.push("name".into());
|
cols.push("name".into());
|
||||||
vals.push(Value::String {
|
vals.push(Value::String {
|
||||||
val: String::from_utf8_lossy(command_name).to_string(),
|
val: String::from_utf8_lossy(command_name).to_string(),
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
cols.push("module_name".into());
|
|
||||||
vals.push(Value::string(module_commands.join(", "), span));
|
|
||||||
|
|
||||||
let decl = self.engine_state.get_decl(**decl_id);
|
let decl = self.engine_state.get_decl(**decl_id);
|
||||||
let signature = decl.signature();
|
let signature = decl.signature();
|
||||||
|
|
||||||
|
@ -238,6 +194,9 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cols.push("decl_id".into());
|
||||||
|
vals.push(Value::int(**decl_id as i64, span));
|
||||||
|
|
||||||
commands.push(Value::Record { cols, vals, span })
|
commands.push(Value::Record { cols, vals, span })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,6 +447,7 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
|
|
||||||
pub fn collect_externs(&self, span: Span) -> Vec<Value> {
|
pub fn collect_externs(&self, span: Span) -> Vec<Value> {
|
||||||
let mut externals = vec![];
|
let mut externals = vec![];
|
||||||
|
|
||||||
for (command_name, decl_id) in &self.decls_map {
|
for (command_name, decl_id) in &self.decls_map {
|
||||||
let decl = self.engine_state.get_decl(**decl_id);
|
let decl = self.engine_state.get_decl(**decl_id);
|
||||||
|
|
||||||
|
@ -495,36 +455,21 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
|
|
||||||
let mut module_commands = vec![];
|
|
||||||
for module in &self.modules_map {
|
|
||||||
let module_name = String::from_utf8_lossy(module.0).to_string();
|
|
||||||
let module_id = self.engine_state.find_module(module.0, &[]);
|
|
||||||
if let Some(module_id) = module_id {
|
|
||||||
let module = self.engine_state.get_module(module_id);
|
|
||||||
if module.has_decl(command_name) {
|
|
||||||
module_commands.push(module_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cols.push("name".into());
|
cols.push("name".into());
|
||||||
vals.push(Value::String {
|
vals.push(Value::String {
|
||||||
val: String::from_utf8_lossy(command_name).to_string(),
|
val: String::from_utf8_lossy(command_name).to_string(),
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
cols.push("module_name".into());
|
|
||||||
vals.push(Value::String {
|
|
||||||
val: module_commands.join(", "),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
cols.push("usage".to_string());
|
cols.push("usage".to_string());
|
||||||
vals.push(Value::String {
|
vals.push(Value::String {
|
||||||
val: decl.usage().into(),
|
val: decl.usage().into(),
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cols.push("decl_id".into());
|
||||||
|
vals.push(Value::int(**decl_id as i64, span));
|
||||||
|
|
||||||
externals.push(Value::Record { cols, vals, span })
|
externals.push(Value::Record { cols, vals, span })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,17 +479,23 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
|
|
||||||
pub fn collect_aliases(&self, span: Span) -> Vec<Value> {
|
pub fn collect_aliases(&self, span: Span) -> Vec<Value> {
|
||||||
let mut aliases = vec![];
|
let mut aliases = vec![];
|
||||||
for (_, decl_id) in self.engine_state.get_decls_sorted(false) {
|
|
||||||
|
for (decl_name, decl_id) in self.engine_state.get_decls_sorted(false) {
|
||||||
if self.visibility.is_decl_id_visible(&decl_id) {
|
if self.visibility.is_decl_id_visible(&decl_id) {
|
||||||
let decl = self.engine_state.get_decl(decl_id);
|
let decl = self.engine_state.get_decl(decl_id);
|
||||||
if let Some(alias) = decl.as_alias() {
|
if let Some(alias) = decl.as_alias() {
|
||||||
let sig = decl.signature().update_from_command(decl.borrow());
|
|
||||||
let key = sig.name;
|
|
||||||
|
|
||||||
aliases.push(Value::Record {
|
aliases.push(Value::Record {
|
||||||
cols: vec!["name".into(), "expansion".into(), "usage".into()],
|
cols: vec![
|
||||||
|
"name".into(),
|
||||||
|
"expansion".into(),
|
||||||
|
"usage".into(),
|
||||||
|
"decl_id".into(),
|
||||||
|
],
|
||||||
vals: vec![
|
vals: vec![
|
||||||
Value::String { val: key, span },
|
Value::String {
|
||||||
|
val: String::from_utf8_lossy(&decl_name).to_string(),
|
||||||
|
span,
|
||||||
|
},
|
||||||
Value::String {
|
Value::String {
|
||||||
val: String::from_utf8_lossy(
|
val: String::from_utf8_lossy(
|
||||||
self.engine_state.get_span_contents(alias.wrapped_call.span),
|
self.engine_state.get_span_contents(alias.wrapped_call.span),
|
||||||
|
@ -553,7 +504,11 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
Value::String {
|
Value::String {
|
||||||
val: alias.signature().usage,
|
val: alias.usage().to_string(),
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
Value::Int {
|
||||||
|
val: decl_id as i64,
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -567,70 +522,156 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
aliases
|
aliases
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_module(&self, module_name: &[u8], module_id: &ModuleId, span: Span) -> Value {
|
||||||
|
let module = self.engine_state.get_module(*module_id);
|
||||||
|
|
||||||
|
let all_decls = module.decls();
|
||||||
|
|
||||||
|
let export_commands: Vec<Value> = all_decls
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name_bytes, decl_id)| {
|
||||||
|
let decl = self.engine_state.get_decl(*decl_id);
|
||||||
|
|
||||||
|
if !decl.is_alias() && !decl.is_known_external() {
|
||||||
|
Some(Value::record(
|
||||||
|
vec!["name".into(), "decl_id".into()],
|
||||||
|
vec![
|
||||||
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
||||||
|
Value::int(*decl_id as i64, span),
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let export_aliases: Vec<Value> = all_decls
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name_bytes, decl_id)| {
|
||||||
|
let decl = self.engine_state.get_decl(*decl_id);
|
||||||
|
|
||||||
|
if decl.is_alias() {
|
||||||
|
Some(Value::record(
|
||||||
|
vec!["name".into(), "decl_id".into()],
|
||||||
|
vec![
|
||||||
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
||||||
|
Value::int(*decl_id as i64, span),
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let export_externs: Vec<Value> = all_decls
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name_bytes, decl_id)| {
|
||||||
|
let decl = self.engine_state.get_decl(*decl_id);
|
||||||
|
|
||||||
|
if decl.is_known_external() {
|
||||||
|
Some(Value::record(
|
||||||
|
vec!["name".into(), "decl_id".into()],
|
||||||
|
vec![
|
||||||
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
||||||
|
Value::int(*decl_id as i64, span),
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let export_submodules: Vec<Value> = module
|
||||||
|
.submodules()
|
||||||
|
.iter()
|
||||||
|
.map(|(name_bytes, submodule_id)| self.collect_module(name_bytes, submodule_id, span))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let export_consts: Vec<Value> = module
|
||||||
|
.vars()
|
||||||
|
.iter()
|
||||||
|
.map(|(name_bytes, var_id)| {
|
||||||
|
Value::record(
|
||||||
|
vec!["name".into(), "type".into(), "var_id".into()],
|
||||||
|
vec![
|
||||||
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
||||||
|
Value::string(self.engine_state.get_var(*var_id).ty.to_string(), span),
|
||||||
|
Value::int(*var_id as i64, span),
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let export_env_block = module.env_block.map_or_else(
|
||||||
|
|| Value::nothing(span),
|
||||||
|
|block_id| Value::Block {
|
||||||
|
val: block_id,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let module_usage = self
|
||||||
|
.engine_state
|
||||||
|
.build_module_usage(*module_id)
|
||||||
|
.map(|(usage, _)| usage)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
Value::Record {
|
||||||
|
cols: vec![
|
||||||
|
"name".into(),
|
||||||
|
"commands".into(),
|
||||||
|
"aliases".into(),
|
||||||
|
"externs".into(),
|
||||||
|
"submodules".into(),
|
||||||
|
"constants".into(),
|
||||||
|
"env_block".into(),
|
||||||
|
"usage".into(),
|
||||||
|
"module_id".into(),
|
||||||
|
],
|
||||||
|
vals: vec![
|
||||||
|
Value::string(String::from_utf8_lossy(module_name), span),
|
||||||
|
Value::List {
|
||||||
|
vals: export_commands,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: export_aliases,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: export_externs,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: export_submodules,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: export_consts,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
export_env_block,
|
||||||
|
Value::string(module_usage, span),
|
||||||
|
Value::int(*module_id as i64, span),
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn collect_modules(&self, span: Span) -> Vec<Value> {
|
pub fn collect_modules(&self, span: Span) -> Vec<Value> {
|
||||||
let mut modules = vec![];
|
let mut modules = vec![];
|
||||||
|
|
||||||
for (module_name, module_id) in &self.modules_map {
|
for (module_name, module_id) in &self.modules_map {
|
||||||
let module = self.engine_state.get_module(**module_id);
|
modules.push(self.collect_module(module_name, module_id, span));
|
||||||
|
|
||||||
let export_commands: Vec<Value> = module
|
|
||||||
.decls()
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, id)| {
|
|
||||||
self.visibility.is_decl_id_visible(id)
|
|
||||||
&& !self.engine_state.get_decl(*id).is_alias()
|
|
||||||
})
|
|
||||||
.map(|(bytes, _)| Value::string(String::from_utf8_lossy(bytes), span))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let export_aliases: Vec<Value> = module
|
|
||||||
.decls()
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, id)| {
|
|
||||||
self.visibility.is_decl_id_visible(id)
|
|
||||||
&& self.engine_state.get_decl(*id).is_alias()
|
|
||||||
})
|
|
||||||
.map(|(bytes, _)| Value::string(String::from_utf8_lossy(bytes), span))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let export_env_block = module.env_block.map_or_else(
|
|
||||||
|| Value::nothing(span),
|
|
||||||
|block_id| Value::Block {
|
|
||||||
val: block_id,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let module_usage = self
|
|
||||||
.engine_state
|
|
||||||
.build_module_usage(**module_id)
|
|
||||||
.map(|(usage, _)| usage)
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
modules.push(Value::Record {
|
|
||||||
cols: vec![
|
|
||||||
"name".into(),
|
|
||||||
"commands".into(),
|
|
||||||
"aliases".into(),
|
|
||||||
"env_block".into(),
|
|
||||||
"usage".into(),
|
|
||||||
],
|
|
||||||
vals: vec![
|
|
||||||
Value::string(String::from_utf8_lossy(module_name), span),
|
|
||||||
Value::List {
|
|
||||||
vals: export_commands,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
Value::List {
|
|
||||||
vals: export_aliases,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
export_env_block,
|
|
||||||
Value::string(module_usage, span),
|
|
||||||
],
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modules.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
modules.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
||||||
modules
|
modules
|
||||||
}
|
}
|
||||||
|
@ -660,6 +701,7 @@ impl<'e, 's> ScopeData<'e, 's> {
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
Value::Record {
|
Value::Record {
|
||||||
cols: engine_state_cols,
|
cols: engine_state_cols,
|
||||||
vals: engine_state_vals,
|
vals: engine_state_vals,
|
||||||
|
|
|
@ -749,6 +749,7 @@ pub fn parse_alias(
|
||||||
|
|
||||||
if let Some(decl_id) = working_set.find_decl(b"alias") {
|
if let Some(decl_id) = working_set.find_decl(b"alias") {
|
||||||
let (command_spans, rest_spans) = spans.split_at(split_id);
|
let (command_spans, rest_spans) = spans.split_at(split_id);
|
||||||
|
let (usage, extra_usage) = working_set.build_usage(&lite_command.comments);
|
||||||
|
|
||||||
let original_starting_error_count = working_set.parse_errors.len();
|
let original_starting_error_count = working_set.parse_errors.len();
|
||||||
|
|
||||||
|
@ -906,6 +907,8 @@ pub fn parse_alias(
|
||||||
name: alias_name,
|
name: alias_name,
|
||||||
command,
|
command,
|
||||||
wrapped_call,
|
wrapped_call,
|
||||||
|
usage,
|
||||||
|
extra_usage,
|
||||||
};
|
};
|
||||||
|
|
||||||
working_set.add_decl(Box::new(decl));
|
working_set.add_decl(Box::new(decl));
|
||||||
|
|
|
@ -3,15 +3,16 @@ use crate::PipelineData;
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Call, Expression},
|
ast::{Call, Expression},
|
||||||
engine::Command,
|
engine::Command,
|
||||||
BlockId, Example, ShellError, Signature,
|
ShellError, Signature,
|
||||||
};
|
};
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Alias {
|
pub struct Alias {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub command: Option<Box<dyn Command>>, // None if external call
|
pub command: Option<Box<dyn Command>>, // None if external call
|
||||||
pub wrapped_call: Expression,
|
pub wrapped_call: Expression,
|
||||||
|
pub usage: String,
|
||||||
|
pub extra_usage: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Alias {
|
impl Command for Alias {
|
||||||
|
@ -28,19 +29,11 @@ impl Command for Alias {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
if let Some(cmd) = &self.command {
|
&self.usage
|
||||||
cmd.usage()
|
|
||||||
} else {
|
|
||||||
"This alias wraps an unknown external command."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extra_usage(&self) -> &str {
|
fn extra_usage(&self) -> &str {
|
||||||
if let Some(cmd) = &self.command {
|
&self.extra_usage
|
||||||
cmd.extra_usage()
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
|
@ -57,30 +50,6 @@ impl Command for Alias {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.examples()
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_builtin(&self) -> bool {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_builtin()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_known_external(&self) -> bool {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_known_external()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_alias(&self) -> bool {
|
fn is_alias(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -88,54 +57,4 @@ impl Command for Alias {
|
||||||
fn as_alias(&self) -> Option<&Alias> {
|
fn as_alias(&self) -> Option<&Alias> {
|
||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_custom_command(&self) -> bool {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_custom_command()
|
|
||||||
} else if self.get_block_id().is_some() {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
self.is_known_external()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_sub(&self) -> bool {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_sub()
|
|
||||||
} else {
|
|
||||||
self.name().contains(' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_parser_keyword(&self) -> bool {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_parser_keyword()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_plugin(&self) -> Option<(&PathBuf, &Option<PathBuf>)> {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.is_plugin()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_block_id(&self) -> Option<BlockId> {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.get_block_id()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn search_terms(&self) -> Vec<&str> {
|
|
||||||
if let Some(cmd) = &self.command {
|
|
||||||
cmd.search_terms()
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
use nu_test_support::fs::Stub::FileWithContent;
|
||||||
use nu_test_support::nu;
|
use nu_test_support::nu;
|
||||||
|
use nu_test_support::playground::Playground;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[ignore = "TODO: This shows old-style aliases. New aliases are under commands"]
|
// Note: These tests might slightly overlap with crates/nu-command/tests/commands/help.rs
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_shows_alias() {
|
fn scope_shows_alias() {
|
||||||
let actual = nu!("alias xaz = echo alias1
|
let actual = nu!("alias xaz = echo alias1
|
||||||
|
@ -71,7 +74,7 @@ fn scope_doesnt_show_hidden_command() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// same problem as 'which' command
|
// same problem as 'which' command
|
||||||
#[ignore]
|
#[ignore = "See https://github.com/nushell/nushell/issues/4837"]
|
||||||
#[test]
|
#[test]
|
||||||
fn correctly_report_of_shadowed_alias() {
|
fn correctly_report_of_shadowed_alias() {
|
||||||
let actual = nu!("alias xaz = echo alias1
|
let actual = nu!("alias xaz = echo alias1
|
||||||
|
@ -83,3 +86,163 @@ fn correctly_report_of_shadowed_alias() {
|
||||||
|
|
||||||
assert_eq!(actual.out, "echo alias2");
|
assert_eq!(actual.out, "echo alias2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correct_scope_modules_fields() {
|
||||||
|
let module_setup = r#"
|
||||||
|
# nice spam
|
||||||
|
|
||||||
|
export module eggs {
|
||||||
|
export module bacon {
|
||||||
|
export def sausage [] { 'sausage' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export def main [] { 'foo' };
|
||||||
|
export alias xaz = print
|
||||||
|
export extern git []
|
||||||
|
export const X = 4
|
||||||
|
|
||||||
|
export-env { $env.SPAM = 'spam' }
|
||||||
|
"#;
|
||||||
|
|
||||||
|
Playground::setup("correct_scope_modules_fields", |dirs, sandbox| {
|
||||||
|
sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]);
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "spam");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.usage",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "nice spam");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.env_block | is-empty",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "false");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.commands.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "spam");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.aliases.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "xaz");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.externs.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "git");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.constants.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "X");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.submodules.0.submodules.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "bacon");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope modules | where name == spam | get 0.submodules.0.submodules.0.commands.0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "sausage");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correct_scope_aliases_fields() {
|
||||||
|
let module_setup = r#"
|
||||||
|
# nice alias
|
||||||
|
export alias xaz = print
|
||||||
|
"#;
|
||||||
|
|
||||||
|
Playground::setup("correct_scope_aliases_fields", |dirs, sandbox| {
|
||||||
|
sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]);
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope aliases | where name == 'spam xaz' | get 0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "spam xaz");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope aliases | where name == 'spam xaz' | get 0.expansion",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "print");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope aliases | where name == 'spam xaz' | get 0.usage",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "nice alias");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope aliases | where name == 'spam xaz' | get 0.decl_id | is-empty",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "false");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correct_scope_externs_fields() {
|
||||||
|
let module_setup = r#"
|
||||||
|
# nice extern
|
||||||
|
export extern git []
|
||||||
|
"#;
|
||||||
|
|
||||||
|
Playground::setup("correct_scope_aliases_fields", |dirs, sandbox| {
|
||||||
|
sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]);
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope externs | where name == 'spam git' | get 0.name",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "spam git");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope externs | where name == 'spam git' | get 0.usage",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "nice extern");
|
||||||
|
|
||||||
|
let inp = &[
|
||||||
|
"use spam.nu",
|
||||||
|
"scope externs | where name == 'spam git' | get 0.decl_id | is-empty",
|
||||||
|
];
|
||||||
|
let actual = nu!(cwd: dirs.test(), &inp.join("; "));
|
||||||
|
assert_eq!(actual.out, "false");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue