mirror of
https://github.com/nushell/nushell.git
synced 2025-07-01 07:00:37 +02:00
Add blocks as env hooks; Preserve hook environment
This commit is contained in:
@ -21,7 +21,7 @@ pub use menus::{DescriptionMenu, NuHelpCompleter};
|
|||||||
pub use nu_highlight::NuHighlight;
|
pub use nu_highlight::NuHighlight;
|
||||||
pub use print::Print;
|
pub use print::Print;
|
||||||
pub use prompt::NushellPrompt;
|
pub use prompt::NushellPrompt;
|
||||||
pub use repl::eval_env_change_hooks;
|
pub use repl::eval_env_change_hook;
|
||||||
pub use repl::evaluate_repl;
|
pub use repl::evaluate_repl;
|
||||||
pub use syntax_highlight::NuHighlighter;
|
pub use syntax_highlight::NuHighlighter;
|
||||||
pub use util::{eval_source, gather_parent_env_vars, get_init_cwd, report_error};
|
pub use util::{eval_source, gather_parent_env_vars, get_init_cwd, report_error};
|
||||||
|
@ -26,7 +26,7 @@ const PRE_EXECUTE_MARKER: &str = "\x1b]133;C\x1b\\";
|
|||||||
const CMD_FINISHED_MARKER: &str = "\x1b]133;D\x1b\\";
|
const CMD_FINISHED_MARKER: &str = "\x1b]133;D\x1b\\";
|
||||||
const RESET_APPLICATION_MODE: &str = "\x1b[?1l";
|
const RESET_APPLICATION_MODE: &str = "\x1b[?1l";
|
||||||
|
|
||||||
pub fn eval_env_change_hooks(
|
pub fn eval_env_change_hook(
|
||||||
env_change_hook: Option<Value>,
|
env_change_hook: Option<Value>,
|
||||||
engine_state: &mut EngineState,
|
engine_state: &mut EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
@ -301,7 +301,7 @@ pub fn evaluate_repl(
|
|||||||
// Next, check all the environment variables they ask for
|
// Next, check all the environment variables they ask for
|
||||||
// fire the "env_change" hook
|
// fire the "env_change" hook
|
||||||
if let Err(error) =
|
if let Err(error) =
|
||||||
eval_env_change_hooks(config.hooks.env_change_str.clone(), engine_state, stack)
|
eval_env_change_hook(config.hooks.env_change_str.clone(), engine_state, stack)
|
||||||
{
|
{
|
||||||
report_error_new(&engine_state, &error)
|
report_error_new(&engine_state, &error)
|
||||||
}
|
}
|
||||||
@ -615,8 +615,16 @@ pub fn eval_hook(
|
|||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
let input = PipelineData::new(*span);
|
let input = PipelineData::new(*span);
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&HashMap::new());
|
let mut callee_stack = stack.gather_captures(&block.captures);
|
||||||
match eval_block(engine_state, &mut stack, block, input, false, false) {
|
|
||||||
|
match eval_block(
|
||||||
|
engine_state,
|
||||||
|
&mut callee_stack,
|
||||||
|
block,
|
||||||
|
input,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
) {
|
||||||
Ok(pipeline_data) => {
|
Ok(pipeline_data) => {
|
||||||
match pipeline_data.into_value(*span) {
|
match pipeline_data.into_value(*span) {
|
||||||
Value::Bool { val, span } => val,
|
Value::Bool { val, span } => val,
|
||||||
@ -701,7 +709,7 @@ pub fn eval_hook(
|
|||||||
val: block_id,
|
val: block_id,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
} => {}
|
} => run_hook_block(&engine_state, stack, block_id, arguments, span)?,
|
||||||
other => {
|
other => {
|
||||||
return Err(ShellError::UnsupportedConfigValue(
|
return Err(ShellError::UnsupportedConfigValue(
|
||||||
"block or string".to_string(),
|
"block or string".to_string(),
|
||||||
@ -796,6 +804,7 @@ pub fn run_hook_block(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
|
|
||||||
let input = PipelineData::new(span);
|
let input = PipelineData::new(span);
|
||||||
|
|
||||||
let mut callee_stack = stack.gather_captures(&block.captures);
|
let mut callee_stack = stack.gather_captures(&block.captures);
|
||||||
@ -811,7 +820,24 @@ pub fn run_hook_block(
|
|||||||
match eval_block(engine_state, &mut callee_stack, block, input, false, false) {
|
match eval_block(engine_state, &mut callee_stack, block, input, false, false) {
|
||||||
Ok(pipeline_data) => match pipeline_data.into_value(span) {
|
Ok(pipeline_data) => match pipeline_data.into_value(span) {
|
||||||
Value::Error { error } => Err(error),
|
Value::Error { error } => Err(error),
|
||||||
_ => Ok(()),
|
_ => {
|
||||||
|
// If all went fine, preserve the environment of the called block
|
||||||
|
let caller_env_vars = stack.get_env_var_names(engine_state);
|
||||||
|
|
||||||
|
// remove env vars that are present in the caller but not in the callee
|
||||||
|
// (the callee hid them)
|
||||||
|
for var in caller_env_vars.iter() {
|
||||||
|
if !callee_stack.has_env_var(engine_state, var) {
|
||||||
|
stack.remove_env_var(engine_state, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new env vars from callee to caller
|
||||||
|
for (var, value) in callee_stack.get_stack_env_vars() {
|
||||||
|
stack.add_env_var(var, value);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
|
@ -71,3 +71,17 @@ fn env_change_define_alias() {
|
|||||||
assert_eq!(actual_repl.err, "");
|
assert_eq!(actual_repl.err, "");
|
||||||
assert_eq!(actual_repl.out, "spam");
|
assert_eq!(actual_repl.out, "spam");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn env_change_block_preserve_env_var() {
|
||||||
|
let inp = &[
|
||||||
|
&hook_env_with_code(r#"{ let-env SPAM = "spam" }"#),
|
||||||
|
"let-env FOO = 1",
|
||||||
|
"$env.SPAM",
|
||||||
|
];
|
||||||
|
|
||||||
|
let actual_repl = nu_repl("tests/hooks", inp);
|
||||||
|
|
||||||
|
assert_eq!(actual_repl.err, "");
|
||||||
|
assert_eq!(actual_repl.out, "spam");
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use nu_cli::eval_env_change_hooks;
|
use nu_cli::eval_env_change_hook;
|
||||||
use nu_command::create_default_context;
|
use nu_command::create_default_context;
|
||||||
use nu_engine::eval_block;
|
use nu_engine::eval_block;
|
||||||
use nu_parser::parse;
|
use nu_parser::parse;
|
||||||
@ -46,7 +46,7 @@ pub fn nu_repl(cwd: &str, source_lines: &[&str]) -> Outcome {
|
|||||||
// Check for env change hook
|
// Check for env change hook
|
||||||
let config = engine_state.get_config();
|
let config = engine_state.get_config();
|
||||||
|
|
||||||
if let Err(error) = eval_env_change_hooks(
|
if let Err(error) = eval_env_change_hook(
|
||||||
config.hooks.env_change_str.clone(),
|
config.hooks.env_change_str.clone(),
|
||||||
&mut engine_state,
|
&mut engine_state,
|
||||||
&mut stack,
|
&mut stack,
|
||||||
|
Reference in New Issue
Block a user