mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 08:23:24 +01:00
Match Hook
fields to match new config defaults
This commit is contained in:
parent
8c1ab7e0a3
commit
cba76b6e23
@ -16,7 +16,7 @@ use crate::{
|
||||
use crossterm::cursor::SetCursorStyle;
|
||||
use log::{error, trace, warn};
|
||||
use miette::{ErrReport, IntoDiagnostic, Result};
|
||||
use nu_cmd_base::{hook::eval_hook, util::get_editor};
|
||||
use nu_cmd_base::util::get_editor;
|
||||
use nu_color_config::StyleComputer;
|
||||
#[allow(deprecated)]
|
||||
use nu_engine::{convert_env_values, current_dir_str, env_to_strings};
|
||||
@ -313,20 +313,26 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
|
||||
perf!("reset signals", start_time, use_color);
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// Right before we start our prompt and take input from the user,
|
||||
// fire the "pre_prompt" hook
|
||||
if let Some(hook) = engine_state.get_config().hooks.pre_prompt.clone() {
|
||||
if let Err(err) = eval_hook(engine_state, &mut stack, None, vec![], &hook, "pre_prompt") {
|
||||
report_shell_error(engine_state, &err);
|
||||
}
|
||||
// Right before we start our prompt and take input from the user, fire the "pre_prompt" hook
|
||||
if let Err(err) = hook::eval_hooks(
|
||||
engine_state,
|
||||
&mut stack,
|
||||
vec![],
|
||||
&engine_state.get_config().hooks.pre_prompt.clone(),
|
||||
"pre_prompt",
|
||||
) {
|
||||
report_shell_error(engine_state, &err);
|
||||
}
|
||||
perf!("pre-prompt hook", start_time, use_color);
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// Next, check all the environment variables they ask for
|
||||
// fire the "env_change" hook
|
||||
let env_change = engine_state.get_config().hooks.env_change.clone();
|
||||
if let Err(error) = hook::eval_env_change_hook(env_change, engine_state, &mut stack) {
|
||||
if let Err(error) = hook::eval_env_change_hook(
|
||||
&engine_state.get_config().hooks.env_change.clone(),
|
||||
engine_state,
|
||||
&mut stack,
|
||||
) {
|
||||
report_shell_error(engine_state, &error)
|
||||
}
|
||||
perf!("env-change hook", start_time, use_color);
|
||||
@ -511,18 +517,17 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
|
||||
|
||||
// Right before we start running the code the user gave us, fire the `pre_execution`
|
||||
// hook
|
||||
if let Some(hook) = config.hooks.pre_execution.clone() {
|
||||
{
|
||||
// Set the REPL buffer to the current command for the "pre_execution" hook
|
||||
let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
|
||||
repl.buffer = repl_cmd_line_text.to_string();
|
||||
drop(repl);
|
||||
|
||||
if let Err(err) = eval_hook(
|
||||
if let Err(err) = hook::eval_hooks(
|
||||
engine_state,
|
||||
&mut stack,
|
||||
None,
|
||||
vec![],
|
||||
&hook,
|
||||
&engine_state.get_config().hooks.pre_execution.clone(),
|
||||
"pre_execution",
|
||||
) {
|
||||
report_shell_error(engine_state, &err);
|
||||
|
@ -7,49 +7,56 @@ use nu_protocol::{
|
||||
engine::{Closure, EngineState, Stack, StateWorkingSet},
|
||||
PipelineData, PositionalArg, ShellError, Span, Type, Value, VarId,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub fn eval_env_change_hook(
|
||||
env_change_hook: Option<Value>,
|
||||
env_change_hook: &HashMap<String, Value>,
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
) -> Result<(), ShellError> {
|
||||
if let Some(hook) = env_change_hook {
|
||||
match hook {
|
||||
Value::Record { val, .. } => {
|
||||
for (env_name, hook_value) in &*val {
|
||||
let before = engine_state.previous_env_vars.get(env_name);
|
||||
let after = stack.get_env_var(engine_state, env_name);
|
||||
if before != after {
|
||||
let before = before.cloned().unwrap_or_default();
|
||||
let after = after.cloned().unwrap_or_default();
|
||||
for (env, hook) in env_change_hook {
|
||||
let before = engine_state.previous_env_vars.get(env);
|
||||
let after = stack.get_env_var(engine_state, env);
|
||||
if before != after {
|
||||
let before = before.cloned().unwrap_or_default();
|
||||
let after = after.cloned().unwrap_or_default();
|
||||
|
||||
eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
vec![("$before".into(), before), ("$after".into(), after.clone())],
|
||||
hook_value,
|
||||
"env_change",
|
||||
)?;
|
||||
eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
vec![("$before".into(), before), ("$after".into(), after.clone())],
|
||||
hook,
|
||||
"env_change",
|
||||
)?;
|
||||
|
||||
Arc::make_mut(&mut engine_state.previous_env_vars)
|
||||
.insert(env_name.clone(), after);
|
||||
}
|
||||
}
|
||||
}
|
||||
x => {
|
||||
return Err(ShellError::TypeMismatch {
|
||||
err_message: "record for the 'env_change' hook".to_string(),
|
||||
span: x.span(),
|
||||
});
|
||||
}
|
||||
Arc::make_mut(&mut engine_state.previous_env_vars).insert(env.clone(), after);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn eval_hooks(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
arguments: Vec<(String, Value)>,
|
||||
hooks: &[Value],
|
||||
hook_name: &str,
|
||||
) -> Result<(), ShellError> {
|
||||
for hook in hooks {
|
||||
eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
arguments.clone(),
|
||||
hook,
|
||||
&format!("{hook_name} list, recursive"),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn eval_hook(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
@ -127,16 +134,7 @@ pub fn eval_hook(
|
||||
}
|
||||
}
|
||||
Value::List { vals, .. } => {
|
||||
for val in vals {
|
||||
eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
arguments.clone(),
|
||||
val,
|
||||
&format!("{hook_name} list, recursive"),
|
||||
)?;
|
||||
}
|
||||
eval_hooks(engine_state, stack, arguments, vals, hook_name)?;
|
||||
}
|
||||
Value::Record { val, .. } => {
|
||||
// Hooks can optionally be a record in this form:
|
||||
|
@ -1,13 +1,13 @@
|
||||
use super::prelude::*;
|
||||
use crate as nu_protocol;
|
||||
use crate::Record;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Definition of a parsed hook from the config object
|
||||
#[derive(Clone, Debug, IntoValue, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Hooks {
|
||||
pub pre_prompt: Option<Value>,
|
||||
pub pre_execution: Option<Value>,
|
||||
pub env_change: Option<Value>,
|
||||
pub pre_prompt: Vec<Value>,
|
||||
pub pre_execution: Vec<Value>,
|
||||
pub env_change: HashMap<String, Value>,
|
||||
pub display_output: Option<Value>,
|
||||
pub command_not_found: Option<Value>,
|
||||
}
|
||||
@ -15,14 +15,14 @@ pub struct Hooks {
|
||||
impl Hooks {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pre_prompt: Some(Value::list(vec![], Span::unknown())),
|
||||
pre_execution: Some(Value::list(vec![], Span::unknown())),
|
||||
env_change: Some(Value::record(Record::default(), Span::unknown())),
|
||||
pre_prompt: Vec::new(),
|
||||
pre_execution: Vec::new(),
|
||||
env_change: HashMap::new(),
|
||||
display_output: Some(Value::string(
|
||||
"if (term size).columns >= 100 { table -e } else { table }",
|
||||
Span::unknown(),
|
||||
)),
|
||||
command_not_found: Some(Value::list(vec![], Span::unknown())),
|
||||
command_not_found: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -40,14 +40,6 @@ impl UpdateFromValue for Hooks {
|
||||
path: &mut ConfigPath<'a>,
|
||||
errors: &mut ConfigErrors,
|
||||
) {
|
||||
fn update_option(field: &mut Option<Value>, value: &Value) {
|
||||
if value.is_nothing() {
|
||||
*field = None;
|
||||
} else {
|
||||
*field = Some(value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let Value::Record { val: record, .. } = value else {
|
||||
errors.type_mismatch(path, Type::record(), value);
|
||||
return;
|
||||
@ -56,11 +48,35 @@ impl UpdateFromValue for Hooks {
|
||||
for (col, val) in record.iter() {
|
||||
let path = &mut path.push(col);
|
||||
match col.as_str() {
|
||||
"pre_prompt" => update_option(&mut self.pre_prompt, val),
|
||||
"pre_execution" => update_option(&mut self.pre_execution, val),
|
||||
"env_change" => update_option(&mut self.env_change, val),
|
||||
"display_output" => update_option(&mut self.display_output, val),
|
||||
"command_not_found" => update_option(&mut self.command_not_found, val),
|
||||
"pre_prompt" => {
|
||||
if let Ok(hooks) = val.as_list() {
|
||||
self.pre_prompt = hooks.into()
|
||||
} else {
|
||||
errors.type_mismatch(path, Type::list(Type::Any), val);
|
||||
}
|
||||
}
|
||||
"pre_execution" => {
|
||||
if let Ok(hooks) = val.as_list() {
|
||||
self.pre_execution = hooks.into()
|
||||
} else {
|
||||
errors.type_mismatch(path, Type::list(Type::Any), val);
|
||||
}
|
||||
}
|
||||
"env_change" => self.env_change.update(val, path, errors),
|
||||
"display_output" => {
|
||||
self.display_output = if val.is_nothing() {
|
||||
None
|
||||
} else {
|
||||
Some(val.clone())
|
||||
}
|
||||
}
|
||||
"command_not_found" => {
|
||||
self.command_not_found = if val.is_nothing() {
|
||||
None
|
||||
} else {
|
||||
Some(val.clone())
|
||||
}
|
||||
}
|
||||
_ => errors.unknown_option(path, val),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use nu_cmd_base::hook::{eval_env_change_hook, eval_hook};
|
||||
use nu_cmd_base::hook::{eval_env_change_hook, eval_hooks};
|
||||
use nu_engine::eval_block;
|
||||
use nu_parser::parse;
|
||||
use nu_protocol::{
|
||||
@ -250,24 +250,14 @@ pub fn nu_repl() {
|
||||
}
|
||||
|
||||
// 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,
|
||||
None,
|
||||
vec![],
|
||||
&hook,
|
||||
"pre_prompt",
|
||||
) {
|
||||
outcome_err(&engine_state, &err);
|
||||
}
|
||||
let hook = engine_state.get_config().hooks.pre_prompt.clone();
|
||||
if let Err(err) = eval_hooks(&mut engine_state, &mut stack, vec![], &hook, "pre_prompt") {
|
||||
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(),
|
||||
&engine_state.get_config().hooks.env_change.clone(),
|
||||
&mut engine_state,
|
||||
&mut stack,
|
||||
) {
|
||||
@ -275,7 +265,6 @@ pub fn nu_repl() {
|
||||
}
|
||||
|
||||
// Check for pre_execution hook
|
||||
let config = engine_state.get_config();
|
||||
|
||||
engine_state
|
||||
.repl_state
|
||||
@ -283,17 +272,15 @@ pub fn nu_repl() {
|
||||
.expect("repl state mutex")
|
||||
.buffer = line.to_string();
|
||||
|
||||
if let Some(hook) = config.hooks.pre_execution.clone() {
|
||||
if let Err(err) = eval_hook(
|
||||
&mut engine_state,
|
||||
&mut stack,
|
||||
None,
|
||||
vec![],
|
||||
&hook,
|
||||
"pre_execution",
|
||||
) {
|
||||
outcome_err(&engine_state, &err);
|
||||
}
|
||||
let hook = engine_state.get_config().hooks.pre_execution.clone();
|
||||
if let Err(err) = eval_hooks(
|
||||
&mut engine_state,
|
||||
&mut stack,
|
||||
vec![],
|
||||
&hook,
|
||||
"pre_execution",
|
||||
) {
|
||||
outcome_err(&engine_state, &err);
|
||||
}
|
||||
|
||||
// Eval the REPL line
|
||||
|
Loading…
Reference in New Issue
Block a user