brush_core/shell/
funcs.rs1use crate::{
4 ExecutionParameters, commands, error, extensions, functions, results::ExecutionWaitResult,
5};
6
7impl<SE: extensions::ShellExtensions> crate::Shell<SE> {
8 pub const fn funcs(&self) -> &functions::FunctionEnv {
10 &self.funcs
11 }
12
13 pub const fn funcs_mut(&mut self) -> &mut functions::FunctionEnv {
15 &mut self.funcs
16 }
17
18 pub fn undefine_func(&mut self, name: &str) -> bool {
25 self.funcs.remove(name).is_some()
26 }
27
28 pub fn define_func(
37 &mut self,
38 name: impl Into<String>,
39 definition: brush_parser::ast::FunctionDefinition,
40 source_info: &crate::SourceInfo,
41 ) {
42 let reg = functions::Registration::new(definition, source_info);
43 self.funcs.update(name.into(), reg);
44 }
45
46 pub fn func_mut(&mut self, name: &str) -> Option<&mut functions::Registration> {
53 self.funcs.get_mut(name)
54 }
55
56 pub fn define_func_from_str(
64 &mut self,
65 name: impl Into<String>,
66 body_text: &str,
67 ) -> Result<(), error::Error> {
68 let name = name.into();
69
70 let mut parser =
71 super::parsing::create_parser(body_text.as_bytes(), &self.parser_options());
72 let func_body = parser.parse_function_parens_and_body().map_err(|e| {
73 error::Error::from(error::ErrorKind::FunctionParseError(name.clone(), e))
74 })?;
75
76 let def = brush_parser::ast::FunctionDefinition {
77 fname: name.clone().into(),
78 body: func_body,
79 };
80
81 self.define_func(name, def, &crate::SourceInfo::default());
82
83 Ok(())
84 }
85
86 pub async fn invoke_function<N: AsRef<str>, I: IntoIterator<Item = A>, A: AsRef<str>>(
94 &mut self,
95 name: N,
96 args: I,
97 params: &ExecutionParameters,
98 ) -> Result<u8, error::Error> {
99 let name = name.as_ref();
100 let command_name = String::from(name);
101
102 let func_registration = self
103 .funcs
104 .get(name)
105 .ok_or_else(|| error::ErrorKind::FunctionNotFound(name.to_owned()))?
106 .to_owned();
107
108 let context = commands::ExecutionContext {
109 shell: self,
110 command_name,
111 params: params.clone(),
112 };
113
114 let command_args = args
115 .into_iter()
116 .map(|s| commands::CommandArg::String(String::from(s.as_ref())))
117 .collect::<Vec<_>>();
118
119 let result =
120 commands::invoke_shell_function(func_registration, context, &command_args).await?;
121
122 match result.wait().await? {
123 ExecutionWaitResult::Completed(result) => Ok(result.exit_code.into()),
124 ExecutionWaitResult::Stopped(..) => {
125 error::unimp("stopped child from function invocation")
126 }
127 }
128 }
129}