1use log::info;
2use nu_engine::eval_block;
3use nu_parser::{find_main_block_id_in_script, parse};
4use nu_protocol::{
5 PipelineData, ShellError, Spanned, Value,
6 debugger::WithoutDebug,
7 engine::{EngineState, Stack, StateWorkingSet},
8 process::check_exit_status_future,
9 report_error::report_compile_error,
10 report_parse_error, report_parse_warning,
11 shell_error::generic::GenericError,
12};
13use std::sync::Arc;
14
15use crate::util::print_pipeline;
16
17#[derive(Default)]
18pub struct EvaluateCommandsOpts {
19 pub table_mode: Option<Value>,
20 pub error_style: Option<Value>,
21 pub no_newline: bool,
22}
23
24pub fn evaluate_commands(
26 commands: &Spanned<String>,
27 engine_state: &mut EngineState,
28 stack: &mut Stack,
29 input: PipelineData,
30 args: Vec<String>,
31 opts: EvaluateCommandsOpts,
32) -> Result<(), ShellError> {
33 let EvaluateCommandsOpts {
34 table_mode,
35 error_style,
36 no_newline,
37 } = opts;
38
39 if let Some(e_style) = error_style {
41 match e_style.coerce_str()?.parse() {
42 Ok(e_style) => {
43 Arc::make_mut(&mut engine_state.config).error_style = e_style;
44 }
45 Err(err) => {
46 return Err(ShellError::Generic(GenericError::new(
47 "Invalid value for `--error-style`",
48 err.to_string(),
49 e_style.span(),
50 )));
51 }
52 }
53 }
54
55 let (block, delta) = {
57 if let Some(ref t_mode) = table_mode {
58 Arc::make_mut(&mut engine_state.config).table.mode =
59 t_mode.coerce_str()?.parse().unwrap_or_default();
60 }
61
62 let mut working_set = StateWorkingSet::new(engine_state);
63
64 let check_errors = |working_set: &StateWorkingSet| {
65 if let Some(warning) = working_set.parse_warnings.first() {
66 report_parse_warning(Some(stack), working_set, warning);
67 }
68
69 if let Some(err) = working_set.parse_errors.first() {
70 report_parse_error(Some(stack), working_set, err);
71 std::process::exit(1);
72 }
73
74 if let Some(err) = working_set.compile_errors.first() {
75 report_compile_error(Some(stack), working_set, err);
76 std::process::exit(1);
77 }
78 };
79
80 let mut output = parse(&mut working_set, None, commands.item.as_bytes(), false);
81 check_errors(&working_set);
82
83 if find_main_block_id_in_script(&working_set, &output).is_some() {
84 output = parse(
87 &mut working_set,
88 None,
89 format!("main {}", args.join(" ")).as_bytes(),
90 false,
91 );
92 check_errors(&working_set);
93 }
94
95 (output, working_set.render())
96 };
97
98 engine_state.merge_delta(delta)?;
100
101 let pipeline = eval_block::<WithoutDebug>(engine_state, stack, &block, input)?;
103
104 let pipeline_data = pipeline.body;
105 if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline_data {
106 return Err(*error);
107 }
108
109 if let Some(t_mode) = table_mode {
110 Arc::make_mut(&mut engine_state.config).table.mode =
111 t_mode.coerce_str()?.parse().unwrap_or_default();
112 }
113
114 print_pipeline(engine_state, stack, pipeline_data, no_newline)?;
115 info!("evaluate {}:{}:{}", file!(), line!(), column!());
116 let pipefail = nu_experimental::PIPE_FAIL.get();
117 if !pipefail {
118 return Ok(());
119 }
120 check_exit_status_future(pipeline.exit)
122}