use nu_protocol::{ ast::Call, engine::{EngineState, Stack}, FromValue, ShellError, }; use crate::eval_expression; pub trait CallExt { fn get_flag( &self, engine_state: &EngineState, stack: &mut Stack, name: &str, ) -> Result, ShellError>; fn rest( &self, engine_state: &EngineState, stack: &mut Stack, starting_pos: usize, ) -> Result, ShellError>; fn opt( &self, engine_state: &EngineState, stack: &mut Stack, pos: usize, ) -> Result, ShellError>; fn req( &self, engine_state: &EngineState, stack: &mut Stack, pos: usize, ) -> Result; fn req_parser_info( &self, engine_state: &EngineState, stack: &mut Stack, name: &str, ) -> Result; } impl CallExt for Call { fn get_flag( &self, engine_state: &EngineState, stack: &mut Stack, name: &str, ) -> Result, ShellError> { if let Some(expr) = self.get_flag_expr(name) { let result = eval_expression(engine_state, stack, &expr)?; FromValue::from_value(&result).map(Some) } else { Ok(None) } } fn rest( &self, engine_state: &EngineState, stack: &mut Stack, starting_pos: usize, ) -> Result, ShellError> { let mut output = vec![]; for expr in self.positional_iter().skip(starting_pos) { let result = eval_expression(engine_state, stack, expr)?; output.push(FromValue::from_value(&result)?); } Ok(output) } fn opt( &self, engine_state: &EngineState, stack: &mut Stack, pos: usize, ) -> Result, ShellError> { if let Some(expr) = self.positional_nth(pos) { let result = eval_expression(engine_state, stack, expr)?; FromValue::from_value(&result).map(Some) } else { Ok(None) } } fn req( &self, engine_state: &EngineState, stack: &mut Stack, pos: usize, ) -> Result { if let Some(expr) = self.positional_nth(pos) { let result = eval_expression(engine_state, stack, expr)?; FromValue::from_value(&result) } else if self.positional_len() == 0 { Err(ShellError::AccessEmptyContent { span: self.head }) } else { Err(ShellError::AccessBeyondEnd { max_idx: self.positional_len() - 1, span: self.head, }) } } fn req_parser_info( &self, engine_state: &EngineState, stack: &mut Stack, name: &str, ) -> Result { if let Some(expr) = self.get_parser_info(name) { let result = eval_expression(engine_state, stack, expr)?; FromValue::from_value(&result) } else if self.parser_info.is_empty() { Err(ShellError::AccessEmptyContent { span: self.head }) } else { Err(ShellError::AccessBeyondEnd { max_idx: self.parser_info.len() - 1, span: self.head, }) } } }