forked from extern/nushell
07ac3c3aab
* Add Nushell REPL simulator; Fix bug in overlay add The `nu_repl` function takes an array of strings and processes them as if they were REPL lines entered one by one. This helps to discover bugs due to the state changes between the parse and eval stages. * Fix REPL tests on Windows
97 lines
2.9 KiB
Rust
97 lines
2.9 KiB
Rust
use nu_command::create_default_context;
|
|
use nu_engine::eval_block;
|
|
use nu_parser::parse;
|
|
use nu_protocol::engine::{Stack, StateDelta, StateWorkingSet};
|
|
use nu_protocol::{PipelineData, Span, Value};
|
|
use nu_test_support::fs::in_directory;
|
|
use nu_test_support::Outcome;
|
|
|
|
fn outcome_err(msg: String) -> Outcome {
|
|
Outcome {
|
|
out: String::new(),
|
|
err: msg,
|
|
}
|
|
}
|
|
|
|
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(&cwd);
|
|
let mut stack = Stack::new();
|
|
|
|
stack.add_env_var(
|
|
"PWD".to_string(),
|
|
Value::String {
|
|
val: cwd.to_string(),
|
|
span: Span::test_data(),
|
|
},
|
|
);
|
|
|
|
let delta = StateDelta::new(&engine_state);
|
|
if let Err(err) = engine_state.merge_delta(delta, Some(&mut stack), cwd) {
|
|
return outcome_err(format!("{:?}", &err));
|
|
}
|
|
|
|
let mut last_output = String::new();
|
|
|
|
for (i, line) in source_lines.iter().enumerate() {
|
|
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(format!("{:?}", err));
|
|
}
|
|
(block, working_set.render())
|
|
};
|
|
|
|
let cwd = match nu_engine::env::current_dir(&engine_state, &stack) {
|
|
Ok(p) => p,
|
|
Err(e) => {
|
|
return outcome_err(format!("{:?}", &e));
|
|
}
|
|
};
|
|
|
|
if let Err(err) = engine_state.merge_delta(delta, Some(&mut stack), &cwd) {
|
|
return outcome_err(format!("{:?}", 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(format!("{:?}", err)),
|
|
},
|
|
Err(err) => return outcome_err(format!("{:?}", err)),
|
|
}
|
|
|
|
// FIXME: permanent state changes like this hopefully in time can be removed
|
|
// and be replaced by just passing the cwd in where needed
|
|
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(format!("{:?}", err)),
|
|
};
|
|
let _ = std::env::set_current_dir(path);
|
|
engine_state.add_env_var("PWD".into(), cwd);
|
|
}
|
|
}
|
|
|
|
outcome_ok(last_output)
|
|
}
|