nu_cli/
eval_cmds.rs

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