nu_cli/
eval_cmds.rs

1use log::info;
2use nu_engine::eval_block;
3use nu_parser::parse;
4use nu_protocol::{
5    cli_error::report_compile_error,
6    debugger::WithoutDebug,
7    engine::{EngineState, Stack, StateWorkingSet},
8    report_parse_error, report_parse_warning, PipelineData, ShellError, Spanned, Value,
9};
10use std::sync::Arc;
11
12use crate::util::print_pipeline;
13
14#[derive(Default)]
15pub struct EvaluateCommandsOpts {
16    pub table_mode: Option<Value>,
17    pub error_style: Option<Value>,
18    pub no_newline: bool,
19}
20
21/// Run a command (or commands) given to us by the user
22pub fn evaluate_commands(
23    commands: &Spanned<String>,
24    engine_state: &mut EngineState,
25    stack: &mut Stack,
26    input: PipelineData,
27    opts: EvaluateCommandsOpts,
28) -> Result<(), ShellError> {
29    let EvaluateCommandsOpts {
30        table_mode,
31        error_style,
32        no_newline,
33    } = opts;
34
35    // Handle the configured error style early
36    if let Some(e_style) = error_style {
37        match e_style.coerce_str()?.parse() {
38            Ok(e_style) => {
39                Arc::make_mut(&mut engine_state.config).error_style = e_style;
40            }
41            Err(err) => {
42                return Err(ShellError::GenericError {
43                    error: "Invalid value for `--error-style`".into(),
44                    msg: err.into(),
45                    span: Some(e_style.span()),
46                    help: None,
47                    inner: vec![],
48                });
49            }
50        }
51    }
52
53    // Parse the source code
54    let (block, delta) = {
55        if let Some(ref t_mode) = table_mode {
56            Arc::make_mut(&mut engine_state.config).table.mode =
57                t_mode.coerce_str()?.parse().unwrap_or_default();
58        }
59
60        let mut working_set = StateWorkingSet::new(engine_state);
61
62        let output = parse(&mut working_set, None, commands.item.as_bytes(), false);
63        if let Some(warning) = working_set.parse_warnings.first() {
64            report_parse_warning(&working_set, warning);
65        }
66
67        if let Some(err) = working_set.parse_errors.first() {
68            report_parse_error(&working_set, err);
69            std::process::exit(1);
70        }
71
72        if let Some(err) = working_set.compile_errors.first() {
73            report_compile_error(&working_set, err);
74            std::process::exit(1);
75        }
76
77        (output, working_set.render())
78    };
79
80    // Update permanent state
81    engine_state.merge_delta(delta)?;
82
83    // Run the block
84    let pipeline = eval_block::<WithoutDebug>(engine_state, stack, &block, input)?;
85
86    if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline {
87        return Err(*error);
88    }
89
90    if let Some(t_mode) = table_mode {
91        Arc::make_mut(&mut engine_state.config).table.mode =
92            t_mode.coerce_str()?.parse().unwrap_or_default();
93    }
94
95    print_pipeline(engine_state, stack, pipeline, no_newline)?;
96
97    info!("evaluate {}:{}:{}", file!(), line!(), column!());
98
99    Ok(())
100}