nu_protocol/config/
hooks.rs1use super::prelude::*;
2use crate::engine::EnvName;
3use std::collections::HashMap;
4
5#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7pub struct Hooks {
8 pub pre_prompt: Vec<Value>,
9 pub pre_execution: Vec<Value>,
10 pub env_change: HashMap<EnvName, Vec<Value>>,
11 pub display_output: Option<Value>,
12 pub command_not_found: Option<Value>,
13}
14
15impl Hooks {
16 pub fn new() -> Self {
17 Self {
18 pre_prompt: Vec::new(),
19 pre_execution: Vec::new(),
20 env_change: HashMap::new(),
21 display_output: Some(Value::string(
22 "if (term size).columns >= 100 { table -e } else { table }",
23 Span::unknown(),
24 )),
25 command_not_found: None,
26 }
27 }
28}
29
30impl Default for Hooks {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl IntoValue for Hooks {
37 fn into_value(self, span: Span) -> Value {
38 let env_change = self
39 .env_change
40 .into_iter()
41 .map(|(key, value)| (key.into_string(), value.into_value(span)))
42 .collect::<crate::Record>();
43
44 record! {
45 "pre_prompt" => self.pre_prompt.into_value(span),
46 "pre_execution" => self.pre_execution.into_value(span),
47 "env_change" => env_change.into_value(span),
48 "display_output" => self.display_output.into_value(span),
49 "command_not_found" => self.command_not_found.into_value(span),
50 }
51 .into_value(span)
52 }
53}
54
55impl UpdateFromValue for Hooks {
56 fn update<'a>(
57 &mut self,
58 value: &'a Value,
59 path: &mut ConfigPath<'a>,
60 errors: &mut ConfigErrors,
61 ) {
62 let Value::Record { val: record, .. } = value else {
63 errors.type_mismatch(path, Type::record(), value);
64 return;
65 };
66
67 for (col, val) in record.iter() {
68 let path = &mut path.push(col);
69 match col.as_str() {
70 "pre_prompt" => {
71 if let Ok(hooks) = val.as_list() {
72 self.pre_prompt = hooks.into()
73 } else {
74 errors.type_mismatch(path, Type::list(Type::Any), val);
75 }
76 }
77 "pre_execution" => {
78 if let Ok(hooks) = val.as_list() {
79 self.pre_execution = hooks.into()
80 } else {
81 errors.type_mismatch(path, Type::list(Type::Any), val);
82 }
83 }
84 "env_change" => {
85 if let Ok(record) = val.as_record() {
86 self.env_change = record
87 .iter()
88 .map(|(key, val)| {
89 let old = self
90 .env_change
91 .remove(&EnvName::from(key))
92 .unwrap_or_default();
93 let new = if let Ok(hooks) = val.as_list() {
94 hooks.into()
95 } else {
96 errors.type_mismatch(
97 &path.push(key),
98 Type::list(Type::Any),
99 val,
100 );
101 old
102 };
103 (key.as_str().into(), new)
104 })
105 .collect();
106 } else {
107 errors.type_mismatch(path, Type::record(), val);
108 }
109 }
110 "display_output" => {
111 self.display_output = if val.is_nothing() {
112 None
113 } else {
114 Some(val.clone())
115 }
116 }
117 "command_not_found" => {
118 self.command_not_found = if val.is_nothing() {
119 None
120 } else {
121 Some(val.clone())
122 }
123 }
124 _ => errors.unknown_option(path, val),
125 }
126 }
127 }
128}