Fix file lookup in parser keywords; Refactor nu_repl (#6185)

* Fix file lookup in parser keywords

* Make nu_repl a testbin; Fix wrong cwd test error
This commit is contained in:
Jakub Žádník 2022-07-29 23:42:00 +03:00 committed by GitHub
parent 7a820b1304
commit d6f4189c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 353 additions and 219 deletions

View File

@ -2834,25 +2834,29 @@ pub fn parse_register(
/// This helper function is used to find files during parsing
///
/// Checks whether the file is:
/// 1. relative to the directory of the file currently being parsed
/// 2. relative to the current working directory
/// 3. within one of the NU_LIB_DIRS entries
/// First, the actual current working directory is selected as
/// a) the directory of a file currently being parsed
/// b) current working directory (PWD)
///
/// Always returns absolute path
/// Then, if the file is not found in the actual cwd, NU_LIB_DIRS is checked.
/// If there is a relative path in NU_LIB_DIRS, it is assumed to be relative to the actual cwd
/// determined in the first step.
///
/// Always returns an absolute path
fn find_in_dirs(
filename: &str,
working_set: &StateWorkingSet,
cwd: &str,
dirs_env: &str,
) -> Option<PathBuf> {
if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
if let Ok(p) = canonicalize_with(filename, currently_parsed_cwd) {
Some(p)
// Choose whether to use file-relative or PWD-relative path
let actual_cwd = if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
currently_parsed_cwd.as_path()
} else {
None
}
} else if let Ok(p) = canonicalize_with(filename, cwd) {
Path::new(cwd)
};
if let Ok(p) = canonicalize_with(filename, actual_cwd) {
Some(p)
} else {
let path = Path::new(filename);
@ -2862,8 +2866,8 @@ fn find_in_dirs(
if let Ok(dirs) = lib_dirs.as_list() {
for lib_dir in dirs {
if let Ok(dir) = lib_dir.as_path() {
if let Ok(dir_abs) = canonicalize_with(&dir, cwd) {
// make sure the dir is absolute path
if let Ok(dir_abs) = canonicalize_with(&dir, actual_cwd) {
if let Ok(path) = canonicalize_with(filename, dir_abs) {
return Some(path);
}

View File

@ -199,7 +199,7 @@ impl Value {
if let Ok(map) = create_map(value, &config) {
config.color_config = map;
} else {
eprintln!("$config.color_config is not a record")
eprintln!("$env.config.color_config is not a record")
}
}
"use_grid_icons" => {
@ -403,7 +403,7 @@ impl Value {
}
}
} else {
eprintln!("$config is not a record");
eprintln!("$env.config is not a record");
}
Ok(config)
@ -412,7 +412,7 @@ impl Value {
fn try_parse_trim_strategy(value: &Value, config: &Config) -> Result<TrimStrategy, ShellError> {
let map = create_map(value, config).map_err(|e| {
eprintln!("$config.table_trim is not a record");
eprintln!("$env.config.table_trim is not a record");
e
})?;

View File

@ -35,6 +35,25 @@ pub fn pipeline(commands: &str) -> String {
.to_string()
}
pub fn nu_repl_code(source_lines: &[&str]) -> String {
let mut out = String::from("nu --testbin=nu_repl [ ");
for line in source_lines.iter() {
// convert each "line" to really be a single line to prevent nu! macro joining the newlines
// with ';'
let line = pipeline(line);
out.push('`');
out.push_str(&line);
out.push('`');
out.push(' ');
}
out.push(']');
out
}
pub fn shell_os_paths() -> Vec<std::path::PathBuf> {
let mut original_paths = vec![];

View File

@ -177,6 +177,7 @@ fn main() -> Result<()> {
"nonu" => test_bins::nonu(),
"chop" => test_bins::chop(),
"repeater" => test_bins::repeater(),
"nu_repl" => test_bins::nu_repl(),
_ => std::process::exit(1),
}
std::process::exit(0)

View File

@ -1,5 +1,13 @@
use std::io::{self, BufRead, Write};
use nu_cli::{eval_env_change_hook, eval_hook};
use nu_command::create_default_context;
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
use nu_protocol::{CliError, PipelineData, Span, Value};
// use nu_test_support::fs::in_directory;
/// Echo's value of env keys from args
/// Example: nu --testbin env_echo FOO BAR
/// If it it's not present echo's nothing
@ -112,6 +120,126 @@ pub fn chop() {
std::process::exit(0);
}
fn outcome_err(
engine_state: &EngineState,
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
) -> ! {
let working_set = StateWorkingSet::new(engine_state);
eprintln!("Error: {:?}", CliError(error, &working_set));
std::process::exit(1);
}
fn outcome_ok(msg: String) -> ! {
println!("{}", msg);
std::process::exit(0);
}
pub fn nu_repl() {
//cwd: &str, source_lines: &[&str]) {
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let source_lines = args();
let mut engine_state = create_default_context();
let mut stack = Stack::new();
stack.add_env_var(
"PWD".to_string(),
Value::String {
val: cwd.to_string_lossy().to_string(),
span: Span::test_data(),
},
);
let mut last_output = String::new();
for (i, line) in source_lines.iter().enumerate() {
let cwd = match nu_engine::env::current_dir(&engine_state, &stack) {
Ok(d) => d,
Err(err) => {
outcome_err(&engine_state, &err);
}
};
// Before doing anything, merge the environment from the previous REPL iteration into the
// permanent state.
if let Err(err) = engine_state.merge_env(&mut stack, &cwd) {
outcome_err(&engine_state, &err);
}
// Check for pre_prompt hook
let config = engine_state.get_config();
if let Some(hook) = config.hooks.pre_prompt.clone() {
if let Err(err) = eval_hook(&mut engine_state, &mut stack, vec![], &hook) {
outcome_err(&engine_state, &err);
}
}
// Check for env change hook
let config = engine_state.get_config();
if let Err(err) = eval_env_change_hook(
config.hooks.env_change.clone(),
&mut engine_state,
&mut stack,
) {
outcome_err(&engine_state, &err);
}
// Check for pre_execution hook
let config = engine_state.get_config();
if let Some(hook) = config.hooks.pre_execution.clone() {
if let Err(err) = eval_hook(&mut engine_state, &mut stack, vec![], &hook) {
outcome_err(&engine_state, &err);
}
}
// Eval the REPL line
let (block, delta) = {
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(
&mut working_set,
Some(&format!("line{}", i)),
line.as_bytes(),
false,
&[],
);
if let Some(err) = err {
outcome_err(&engine_state, &err);
}
(block, working_set.render())
};
if let Err(err) = engine_state.merge_delta(delta) {
outcome_err(&engine_state, &err);
}
let input = PipelineData::new(Span::test_data());
let config = engine_state.get_config();
match eval_block(&engine_state, &mut stack, &block, input, false, false) {
Ok(pipeline_data) => match pipeline_data.collect_string("", config) {
Ok(s) => last_output = s,
Err(err) => outcome_err(&engine_state, &err),
},
Err(err) => outcome_err(&engine_state, &err),
}
if let Some(cwd) = stack.get_env_var(&engine_state, "PWD") {
let path = match cwd.as_string() {
Ok(p) => p,
Err(err) => outcome_err(&engine_state, &err),
};
let _ = std::env::set_current_dir(path);
engine_state.add_env_var("PWD".into(), cwd);
}
}
outcome_ok(last_output)
}
fn did_chop_arguments() -> bool {
let args: Vec<String> = args();

View File

@ -1,4 +1,4 @@
use super::nu_repl::nu_repl;
use nu_test_support::{nu, nu_repl_code};
fn env_change_hook_code_list(name: &str, code_list: &[&str]) -> String {
let mut list = String::new();
@ -115,7 +115,7 @@ fn env_change_define_command() {
"foo",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "got foo!");
@ -129,7 +129,7 @@ fn env_change_define_variable() {
"$x",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -143,7 +143,7 @@ fn env_change_define_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -157,7 +157,7 @@ fn env_change_define_alias() {
"spam",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -171,7 +171,7 @@ fn env_change_simple_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -191,7 +191,7 @@ fn env_change_simple_block_list_shadow_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -205,7 +205,7 @@ fn env_change_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -218,7 +218,7 @@ fn pre_prompt_define_command() {
"foo",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "got foo!");
@ -231,7 +231,7 @@ fn pre_prompt_simple_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -249,7 +249,7 @@ fn pre_prompt_simple_block_list_shadow_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -262,7 +262,7 @@ fn pre_prompt_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -275,7 +275,7 @@ fn pre_execution_define_command() {
"foo",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "got foo!");
@ -288,7 +288,7 @@ fn pre_execution_simple_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -306,7 +306,7 @@ fn pre_execution_simple_block_list_shadow_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -319,7 +319,7 @@ fn pre_execution_block_preserve_env_var() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -339,7 +339,7 @@ fn env_change_shadow_command() {
"foo",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "got foo!");
@ -353,7 +353,7 @@ fn env_change_block_dont_preserve_command() {
"foo",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
#[cfg(windows)]
assert!(actual_repl.out != "foo");
@ -373,7 +373,7 @@ fn env_change_block_condition_pwd() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "spam");
@ -393,7 +393,7 @@ fn env_change_block_condition_correct_args() {
"$env.SPAM",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "true");
@ -407,7 +407,7 @@ fn env_change_dont_panic_with_many_args() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("IncompatibleParametersSingle"));
assert_eq!(actual_repl.out, "");
@ -427,7 +427,7 @@ fn err_hook_wrong_env_type_1() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("UnsupportedConfigValue"));
assert_eq!(actual_repl.out, "");
@ -444,7 +444,7 @@ fn err_hook_wrong_env_type_2() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("TypeMismatch"));
assert_eq!(actual_repl.out, "");
@ -466,7 +466,7 @@ fn err_hook_wrong_env_type_3() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("UnsupportedConfigValue"));
assert_eq!(actual_repl.out, "");
@ -489,7 +489,7 @@ fn err_hook_non_boolean_condition_output() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("UnsupportedConfigValue"));
assert_eq!(actual_repl.out, "");
@ -512,7 +512,7 @@ fn err_hook_non_condition_not_a_block() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("UnsupportedConfigValue"));
assert_eq!(actual_repl.out, "");
@ -534,7 +534,7 @@ fn err_hook_parse_error() {
"",
];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.err.contains("UnsupportedConfigValue"));
assert_eq!(actual_repl.out, "");
@ -544,7 +544,7 @@ fn err_hook_parse_error() {
fn err_hook_dont_allow_string() {
let inp = &[&pre_prompt_hook(r#"'def foo [] { "got foo!" }'"#), "foo"];
let actual_repl = nu_repl("tests/hooks", inp);
let actual_repl = nu!(cwd: "tests/hooks", nu_repl_code(inp));
assert!(actual_repl.out.is_empty());
assert!(actual_repl.err.contains("UnsupportedConfigValue"));

View File

@ -2,7 +2,6 @@ extern crate nu_test_support;
mod hooks;
mod modules;
mod nu_repl;
mod overlays;
mod parsing;
mod path;

View File

@ -1,130 +0,0 @@
use nu_cli::{eval_env_change_hook, eval_hook};
use nu_command::create_default_context;
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
use nu_protocol::{CliError, PipelineData, Span, Value};
use nu_test_support::fs::in_directory;
use nu_test_support::Outcome;
fn outcome_err(
engine_state: &EngineState,
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
) -> Outcome {
let working_set = StateWorkingSet::new(engine_state);
eprintln!("Error: {:?}", CliError(error, &working_set));
Outcome {
out: String::new(),
err: format!("{:?}", error),
}
}
fn outcome_ok(msg: String) -> Outcome {
Outcome {
out: msg,
err: String::new(),
}
}
pub fn nu_repl(cwd: &str, source_lines: &[&str]) -> Outcome {
let cwd = in_directory(cwd);
let mut engine_state = create_default_context();
let mut stack = Stack::new();
stack.add_env_var(
"PWD".to_string(),
Value::String {
val: cwd.to_string(),
span: Span::test_data(),
},
);
let mut last_output = String::new();
for (i, line) in source_lines.iter().enumerate() {
let cwd = match nu_engine::env::current_dir(&engine_state, &stack) {
Ok(d) => d,
Err(err) => {
return outcome_err(&engine_state, &err);
}
};
// Before doing anything, merge the environment from the previous REPL iteration into the
// permanent state.
if let Err(err) = engine_state.merge_env(&mut stack, &cwd) {
return outcome_err(&engine_state, &err);
}
// Check for pre_prompt hook
let config = engine_state.get_config();
if let Some(hook) = config.hooks.pre_prompt.clone() {
if let Err(err) = eval_hook(&mut engine_state, &mut stack, vec![], &hook) {
return outcome_err(&engine_state, &err);
}
}
// Check for env change hook
let config = engine_state.get_config();
if let Err(err) = eval_env_change_hook(
config.hooks.env_change.clone(),
&mut engine_state,
&mut stack,
) {
return outcome_err(&engine_state, &err);
}
// Check for pre_execution hook
let config = engine_state.get_config();
if let Some(hook) = config.hooks.pre_execution.clone() {
if let Err(err) = eval_hook(&mut engine_state, &mut stack, vec![], &hook) {
return outcome_err(&engine_state, &err);
}
}
// Eval the REPL line
let (block, delta) = {
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(
&mut working_set,
Some(&format!("line{}", i)),
line.as_bytes(),
false,
&[],
);
if let Some(err) = err {
return outcome_err(&engine_state, &err);
}
(block, working_set.render())
};
if let Err(err) = engine_state.merge_delta(delta) {
return outcome_err(&engine_state, &err);
}
let input = PipelineData::new(Span::test_data());
let config = engine_state.get_config();
match eval_block(&engine_state, &mut stack, &block, input, false, false) {
Ok(pipeline_data) => match pipeline_data.collect_string("", config) {
Ok(s) => last_output = s,
Err(err) => return outcome_err(&engine_state, &err),
},
Err(err) => return outcome_err(&engine_state, &err),
}
if let Some(cwd) = stack.get_env_var(&engine_state, "PWD") {
let path = match cwd.as_string() {
Ok(p) => p,
Err(err) => return outcome_err(&engine_state, &err),
};
let _ = std::env::set_current_dir(path);
engine_state.add_env_var("PWD".into(), cwd);
}
}
outcome_ok(last_output)
}

View File

@ -1,5 +1,4 @@
use super::nu_repl::nu_repl;
use nu_test_support::{nu, pipeline};
use nu_test_support::{nu, nu_repl_code, pipeline};
#[test]
fn add_overlay() {
@ -10,7 +9,7 @@ fn add_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -25,7 +24,7 @@ fn add_overlay_env() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -36,7 +35,7 @@ fn add_overlay_from_file_decl() {
let inp = &[r#"overlay add samples/spam.nu"#, r#"foo"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -47,7 +46,7 @@ fn add_overlay_from_file_decl() {
fn add_overlay_from_file_decl_cd() {
let inp = &[r#"cd samples"#, r#"overlay add spam.nu"#, r#"foo"#];
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual_repl.out, "foo");
}
@ -57,7 +56,7 @@ fn add_overlay_from_file_alias() {
let inp = &[r#"overlay add samples/spam.nu"#, r#"bar"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "bar");
assert_eq!(actual_repl.out, "bar");
@ -68,7 +67,7 @@ fn add_overlay_from_file_env() {
let inp = &[r#"overlay add samples/spam.nu"#, r#"$env.BAZ"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "baz");
assert_eq!(actual_repl.out, "baz");
@ -83,7 +82,7 @@ fn add_overlay_scoped() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -103,7 +102,7 @@ fn update_overlay_from_module() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "bar");
assert_eq!(actual_repl.out, "bar");
@ -120,7 +119,7 @@ fn update_overlay_from_module_env() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "bar");
assert_eq!(actual_repl.out, "bar");
@ -136,7 +135,7 @@ fn remove_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -155,7 +154,7 @@ fn remove_last_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -174,7 +173,7 @@ fn remove_overlay_scoped() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -190,7 +189,7 @@ fn remove_overlay_env() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.err.contains("did you mean"));
assert!(actual_repl.err.contains("DidYouMean"));
@ -206,7 +205,7 @@ fn remove_overlay_scoped_env() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -217,7 +216,7 @@ fn list_default_overlay() {
let inp = &[r#"overlay list | last"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "zero");
assert_eq!(actual_repl.out, "zero");
@ -232,7 +231,7 @@ fn list_last_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "spam");
assert_eq!(actual_repl.out, "spam");
@ -247,7 +246,7 @@ fn list_overlay_scoped() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "spam");
assert_eq!(actual_repl.out, "spam");
@ -263,7 +262,7 @@ fn remove_overlay_discard_decl() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -282,7 +281,7 @@ fn remove_overlay_discard_alias() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -295,13 +294,13 @@ fn remove_overlay_discard_alias() {
fn remove_overlay_discard_env() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"let-env BAGR = "bagr""#,
r#"let-env BAGR = `bagr`"#,
r#"overlay remove spam"#,
r#"$env.BAGR"#,
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.err.contains("did you mean"));
assert!(actual_repl.err.contains("DidYouMean"));
@ -317,7 +316,7 @@ fn remove_overlay_keep_decl() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -327,13 +326,13 @@ fn remove_overlay_keep_decl() {
fn remove_overlay_keep_alias() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"alias bagr = "bagr""#,
r#"alias bagr = `bagr`"#,
r#"overlay remove --keep-custom spam"#,
r#"bagr"#,
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -343,13 +342,13 @@ fn remove_overlay_keep_alias() {
fn remove_overlay_keep_env() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"let-env BAGR = "bagr""#,
r#"let-env BAGR = `bagr`"#,
r#"overlay remove --keep-custom spam"#,
r#"$env.BAGR"#,
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -365,7 +364,7 @@ fn remove_overlay_keep_discard_overwritten_decl() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -378,13 +377,13 @@ fn remove_overlay_keep_discard_overwritten_decl() {
fn remove_overlay_keep_discard_overwritten_alias() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"alias bar = 'baz'"#,
r#"alias bar = `baz`"#,
r#"overlay remove --keep-custom spam"#,
r#"bar"#,
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(!actual.err.is_empty());
#[cfg(windows)]
@ -397,13 +396,13 @@ fn remove_overlay_keep_discard_overwritten_alias() {
fn remove_overlay_keep_discard_overwritten_env() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"let-env BAZ = "bagr""#,
r#"let-env BAZ = `bagr`"#,
r#"overlay remove --keep-custom spam"#,
r#"$env.BAZ"#,
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.err.contains("did you mean"));
assert!(actual_repl.err.contains("DidYouMean"));
@ -421,7 +420,7 @@ fn remove_overlay_keep_decl_in_latest_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -431,7 +430,7 @@ fn remove_overlay_keep_decl_in_latest_overlay() {
fn remove_overlay_keep_alias_in_latest_overlay() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"alias bagr = 'bagr'"#,
r#"alias bagr = `bagr`"#,
r#"module eggs { }"#,
r#"overlay add eggs"#,
r#"overlay remove --keep-custom spam"#,
@ -439,7 +438,7 @@ fn remove_overlay_keep_alias_in_latest_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -449,7 +448,7 @@ fn remove_overlay_keep_alias_in_latest_overlay() {
fn remove_overlay_keep_env_in_latest_overlay() {
let inp = &[
r#"overlay add samples/spam.nu"#,
r#"let-env BAGR = "bagr""#,
r#"let-env BAGR = `bagr`"#,
r#"module eggs { }"#,
r#"overlay add eggs"#,
r#"overlay remove --keep-custom spam"#,
@ -457,7 +456,7 @@ fn remove_overlay_keep_env_in_latest_overlay() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert!(actual.out.contains("bagr"));
assert!(actual_repl.out.contains("bagr"));
@ -474,7 +473,7 @@ fn preserve_overrides() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "new-foo");
assert_eq!(actual_repl.out, "new-foo");
@ -491,7 +490,7 @@ fn reset_overrides() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
@ -502,7 +501,7 @@ fn overlay_new() {
let inp = &[r#"overlay new spam"#, r#"overlay list | last"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "spam");
assert_eq!(actual_repl.out, "spam");
@ -518,7 +517,7 @@ fn overlay_keep_pwd() {
];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
assert_eq!(actual.out, "samples");
assert_eq!(actual_repl.out, "samples");

View File

@ -1,4 +1,6 @@
use nu_test_support::{nu, pipeline};
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, nu_repl_code, pipeline};
#[cfg(feature = "which-support")]
mod environment;
@ -56,3 +58,115 @@ fn do_not_panic_if_broken_pipe() {
assert!(child_output.stderr.is_empty());
}
#[test]
fn nu_lib_dirs_repl() {
Playground::setup("nu_lib_dirs_repl", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);
let inp_lines = &[
r#"let-env NU_LIB_DIRS = [ ('scripts' | path expand) ]"#,
r#"source foo.nu"#,
r#"$env.FOO"#,
];
let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(inp_lines));
assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}
#[test]
fn nu_lib_dirs_script() {
Playground::setup("nu_lib_dirs_script", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)])
.with_files(vec![FileWithContentToBeTrimmed(
"main.nu",
r#"
source foo.nu
"#,
)]);
let inp_lines = &[
r#"let-env NU_LIB_DIRS = [ ('scripts' | path expand) ]"#,
r#"source main.nu"#,
r#"$env.FOO"#,
];
let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(inp_lines));
assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}
#[test]
fn nu_lib_dirs_relative_repl() {
Playground::setup("nu_lib_dirs_relative_repl", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);
let inp_lines = &[
r#"let-env NU_LIB_DIRS = [ 'scripts' ]"#,
r#"source foo.nu"#,
r#"$env.FOO"#,
];
let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(inp_lines));
assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}
#[test]
fn nu_lib_dirs_relative_script() {
Playground::setup("nu_lib_dirs_relative_script", |dirs, sandbox| {
sandbox
.mkdir("scripts")
.with_files(vec![FileWithContentToBeTrimmed(
"scripts/main.nu",
r#"
source ../foo.nu
"#,
)])
.with_files(vec![FileWithContentToBeTrimmed(
"foo.nu",
r#"
let-env FOO = "foo"
"#,
)]);
let inp_lines = &[
r#"let-env NU_LIB_DIRS = [ 'scripts' ]"#,
r#"source scripts/main.nu"#,
r#"$env.FOO"#,
];
let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(inp_lines));
assert!(actual_repl.err.is_empty());
assert_eq!(actual_repl.out, "foo");
})
}