From 72d3860d05e0cc62a22d9316f9028d01f309fa13 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 9 May 2024 23:29:27 +0000 Subject: [PATCH] Refactor the CLI code a bit (#12782) # Description Refactors the code in `nu-cli`, `main.rs`, `run.rs`, and few others. Namely, I added `EngineState::generate_nu_constant` function to eliminate some duplicate code. Otherwise, I changed a bunch of areas to return errors instead of calling `std::process::exit`. # User-Facing Changes Should be none. --- benches/benchmarks.rs | 8 +- crates/nu-cli/src/config_files.rs | 23 +-- crates/nu-cli/src/eval_cmds.rs | 53 ++--- crates/nu-cli/src/eval_file.rs | 192 ++++-------------- crates/nu-cli/src/prompt_update.rs | 7 +- crates/nu-cli/src/repl.rs | 8 +- crates/nu-cli/src/util.rs | 21 +- .../support/completions_helpers.rs | 7 +- crates/nu-cmd-base/src/util.rs | 7 +- crates/nu-engine/src/env.rs | 8 +- crates/nu-lsp/src/diagnostics.rs | 9 +- crates/nu-protocol/src/engine/engine_state.rs | 5 +- crates/nu-protocol/src/errors/cli_error.rs | 1 - crates/nu-protocol/src/eval_const.rs | 4 +- src/command.rs | 1 - src/config_files.rs | 14 +- src/ide.rs | 19 +- src/main.rs | 13 +- src/run.rs | 51 +++-- 19 files changed, 146 insertions(+), 305 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 9de7cc5758..84552daef9 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -4,8 +4,7 @@ use nu_plugin_protocol::{PluginCallResponse, PluginOutput}; use nu_protocol::{ engine::{EngineState, Stack}, - eval_const::create_nu_constant, - PipelineData, Span, Spanned, Value, NU_VARIABLE_ID, + PipelineData, Span, Spanned, Value, }; use nu_std::load_standard_library; use nu_utils::{get_default_config, get_default_env}; @@ -30,9 +29,7 @@ fn setup_engine() -> EngineState { // parsing config.nu breaks without PWD set, so set a valid path engine_state.add_env_var("PWD".into(), Value::string(cwd, Span::test_data())); - let nu_const = create_nu_constant(&engine_state, Span::unknown()) - .expect("Failed to create nushell constant."); - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); engine_state } @@ -86,6 +83,7 @@ fn bench_command( b.iter(move || { let mut stack = stack.clone(); let mut engine = engine.clone(); + #[allow(clippy::unit_arg)] black_box( evaluate_commands( &commands, diff --git a/crates/nu-cli/src/config_files.rs b/crates/nu-cli/src/config_files.rs index 091fe7daa3..e89fa6c1d1 100644 --- a/crates/nu-cli/src/config_files.rs +++ b/crates/nu-cli/src/config_files.rs @@ -1,12 +1,12 @@ use crate::util::eval_source; #[cfg(feature = "plugin")] use nu_path::canonicalize_with; -use nu_protocol::{ - engine::{EngineState, Stack, StateWorkingSet}, - report_error, HistoryFileFormat, PipelineData, -}; #[cfg(feature = "plugin")] -use nu_protocol::{ParseError, PluginRegistryFile, Spanned}; +use nu_protocol::{engine::StateWorkingSet, report_error, ParseError, PluginRegistryFile, Spanned}; +use nu_protocol::{ + engine::{EngineState, Stack}, + report_error_new, HistoryFileFormat, PipelineData, +}; #[cfg(feature = "plugin")] use nu_utils::utils::perf; use std::path::PathBuf; @@ -25,10 +25,9 @@ pub fn read_plugin_file( plugin_file: Option>, storage_path: &str, ) { + use nu_protocol::ShellError; use std::path::Path; - use nu_protocol::{report_error_new, ShellError}; - let span = plugin_file.as_ref().map(|s| s.span); // Check and warn + abort if this is a .nu plugin file @@ -239,13 +238,11 @@ pub fn eval_config_contents( match engine_state.cwd(Some(stack)) { Ok(cwd) => { if let Err(e) = engine_state.merge_env(stack, cwd) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } Err(e) => { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } } @@ -266,8 +263,8 @@ pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> O #[cfg(feature = "plugin")] pub fn migrate_old_plugin_file(engine_state: &EngineState, storage_path: &str) -> bool { use nu_protocol::{ - report_error_new, PluginExample, PluginIdentity, PluginRegistryItem, - PluginRegistryItemData, PluginSignature, ShellError, + PluginExample, PluginIdentity, PluginRegistryItem, PluginRegistryItemData, PluginSignature, + ShellError, }; use std::collections::BTreeMap; diff --git a/crates/nu-cli/src/eval_cmds.rs b/crates/nu-cli/src/eval_cmds.rs index 1e3cc70348..0b0b5f8ddf 100644 --- a/crates/nu-cli/src/eval_cmds.rs +++ b/crates/nu-cli/src/eval_cmds.rs @@ -5,8 +5,9 @@ use nu_parser::parse; use nu_protocol::{ debugger::WithoutDebug, engine::{EngineState, Stack, StateWorkingSet}, - report_error, PipelineData, Spanned, Value, + report_error, PipelineData, ShellError, Spanned, Value, }; +use std::sync::Arc; /// Run a command (or commands) given to us by the user pub fn evaluate_commands( @@ -16,13 +17,9 @@ pub fn evaluate_commands( input: PipelineData, table_mode: Option, no_newline: bool, -) -> Result> { +) -> Result<(), ShellError> { // Translate environment variables from Strings to Values - if let Some(e) = convert_env_values(engine_state, stack) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); - std::process::exit(1); - } + convert_env_values(engine_state, stack)?; // Parse the source code let (block, delta) = { @@ -41,7 +38,6 @@ pub fn evaluate_commands( if let Some(err) = working_set.parse_errors.first() { report_error(&working_set, err); - std::process::exit(1); } @@ -49,35 +45,26 @@ pub fn evaluate_commands( }; // Update permanent state - if let Err(err) = engine_state.merge_delta(delta) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &err); - } + engine_state.merge_delta(delta)?; // Run the block - let exit_code = match eval_block::(engine_state, stack, &block, input) { - Ok(pipeline_data) => { - let mut config = engine_state.get_config().clone(); - if let Some(t_mode) = table_mode { - config.table_mode = t_mode.coerce_str()?.parse().unwrap_or_default(); - } - crate::eval_file::print_table_or_error( - engine_state, - stack, - pipeline_data, - &mut config, - no_newline, - ) - } - Err(err) => { - let working_set = StateWorkingSet::new(engine_state); + let pipeline = eval_block::(engine_state, stack, &block, input)?; - report_error(&working_set, &err); - std::process::exit(1); - } - }; + if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline { + return Err(*error); + } + + if let Some(t_mode) = table_mode { + Arc::make_mut(&mut engine_state.config).table_mode = + t_mode.coerce_str()?.parse().unwrap_or_default(); + } + + let exit_code = pipeline.print(engine_state, stack, no_newline, false)?; + if exit_code != 0 { + std::process::exit(exit_code as i32); + } info!("evaluate {}:{}:{}", file!(), line!(), column!()); - Ok(exit_code) + Ok(()) } diff --git a/crates/nu-cli/src/eval_file.rs b/crates/nu-cli/src/eval_file.rs index 8107de71a5..7483c6bc33 100644 --- a/crates/nu-cli/src/eval_file.rs +++ b/crates/nu-cli/src/eval_file.rs @@ -1,15 +1,14 @@ use crate::util::eval_source; use log::{info, trace}; -use miette::{IntoDiagnostic, Result}; use nu_engine::{convert_env_values, eval_block}; use nu_parser::parse; use nu_path::canonicalize_with; use nu_protocol::{ debugger::WithoutDebug, engine::{EngineState, Stack, StateWorkingSet}, - report_error, Config, PipelineData, ShellError, Span, Value, + report_error, PipelineData, ShellError, Span, Value, }; -use std::{io::Write, sync::Arc}; +use std::sync::Arc; /// Entry point for evaluating a file. /// @@ -21,73 +20,40 @@ pub fn evaluate_file( engine_state: &mut EngineState, stack: &mut Stack, input: PipelineData, -) -> Result<()> { +) -> Result<(), ShellError> { // Convert environment variables from Strings to Values and store them in the engine state. - if let Some(e) = convert_env_values(engine_state, stack) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); - std::process::exit(1); - } + convert_env_values(engine_state, stack)?; let cwd = engine_state.cwd_as_string(Some(stack))?; - let file_path = canonicalize_with(&path, cwd).unwrap_or_else(|e| { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, - &ShellError::FileNotFoundCustom { - msg: format!("Could not access file '{}': {:?}", path, e.to_string()), - span: Span::unknown(), - }, - ); - std::process::exit(1); - }); + let file_path = + canonicalize_with(&path, cwd).map_err(|err| ShellError::FileNotFoundCustom { + msg: format!("Could not access file '{path}': {err}"), + span: Span::unknown(), + })?; - let file_path_str = file_path.to_str().unwrap_or_else(|| { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, - &ShellError::NonUtf8Custom { - msg: format!( - "Input file name '{}' is not valid UTF8", - file_path.to_string_lossy() - ), - span: Span::unknown(), - }, - ); - std::process::exit(1); - }); + let file_path_str = file_path + .to_str() + .ok_or_else(|| ShellError::NonUtf8Custom { + msg: format!( + "Input file name '{}' is not valid UTF8", + file_path.to_string_lossy() + ), + span: Span::unknown(), + })?; - let file = std::fs::read(&file_path) - .into_diagnostic() - .unwrap_or_else(|e| { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, - &ShellError::FileNotFoundCustom { - msg: format!( - "Could not read file '{}': {:?}", - file_path_str, - e.to_string() - ), - span: Span::unknown(), - }, - ); - std::process::exit(1); - }); + let file = std::fs::read(&file_path).map_err(|err| ShellError::FileNotFoundCustom { + msg: format!("Could not read file '{file_path_str}': {err}"), + span: Span::unknown(), + })?; engine_state.file = Some(file_path.clone()); - let parent = file_path.parent().unwrap_or_else(|| { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, - &ShellError::FileNotFoundCustom { - msg: format!("The file path '{file_path_str}' does not have a parent"), - span: Span::unknown(), - }, - ); - std::process::exit(1); - }); + let parent = file_path + .parent() + .ok_or_else(|| ShellError::FileNotFoundCustom { + msg: format!("The file path '{file_path_str}' does not have a parent"), + span: Span::unknown(), + })?; stack.add_env_var( "FILE_PWD".to_string(), @@ -127,42 +93,25 @@ pub fn evaluate_file( } // Merge the changes into the engine state. - engine_state - .merge_delta(working_set.delta) - .expect("merging delta into engine_state should succeed"); + engine_state.merge_delta(working_set.delta)?; // Check if the file contains a main command. if engine_state.find_decl(b"main", &[]).is_some() { // Evaluate the file, but don't run main yet. - let pipeline_data = - eval_block::(engine_state, stack, &block, PipelineData::empty()); - let pipeline_data = match pipeline_data { - Err(ShellError::Return { .. }) => { - // Allow early return before main is run. - return Ok(()); - } - x => x, - } - .unwrap_or_else(|e| { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); - std::process::exit(1); - }); - - // Print the pipeline output of the file. - // The pipeline output of a file is the pipeline output of its last command. - let result = pipeline_data.print(engine_state, stack, true, false); - match result { - Err(err) => { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &err); - std::process::exit(1); - } - Ok(exit_code) => { - if exit_code != 0 { - std::process::exit(exit_code as i32); + let pipeline = + match eval_block::(engine_state, stack, &block, PipelineData::empty()) { + Ok(data) => data, + Err(ShellError::Return { .. }) => { + // Allow early return before main is run. + return Ok(()); } - } + Err(err) => return Err(err), + }; + + // Print the pipeline output of the last command of the file. + let exit_code = pipeline.print(engine_state, stack, true, false)?; + if exit_code != 0 { + std::process::exit(exit_code as i32); } // Invoke the main command with arguments. @@ -186,60 +135,3 @@ pub fn evaluate_file( Ok(()) } - -pub(crate) fn print_table_or_error( - engine_state: &mut EngineState, - stack: &mut Stack, - mut pipeline_data: PipelineData, - config: &mut Config, - no_newline: bool, -) -> Option { - let exit_code = match &mut pipeline_data { - PipelineData::ExternalStream { exit_code, .. } => exit_code.take(), - _ => None, - }; - - // Change the engine_state config to use the passed in configuration - engine_state.set_config(config.clone()); - - if let PipelineData::Value(Value::Error { error, .. }, ..) = &pipeline_data { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &**error); - std::process::exit(1); - } - - // We don't need to do anything special to print a table because print() handles it - print_or_exit(pipeline_data, engine_state, stack, no_newline); - - // Make sure everything has finished - if let Some(exit_code) = exit_code { - let mut exit_code: Vec<_> = exit_code.into_iter().collect(); - exit_code - .pop() - .and_then(|last_exit_code| match last_exit_code { - Value::Int { val: code, .. } => Some(code), - _ => None, - }) - } else { - None - } -} - -fn print_or_exit( - pipeline_data: PipelineData, - engine_state: &EngineState, - stack: &mut Stack, - no_newline: bool, -) { - let result = pipeline_data.print(engine_state, stack, no_newline, false); - - let _ = std::io::stdout().flush(); - let _ = std::io::stderr().flush(); - - if let Err(error) = result { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &error); - let _ = std::io::stderr().flush(); - std::process::exit(1); - } -} diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index 827bff0e5a..0c24b8282a 100644 --- a/crates/nu-cli/src/prompt_update.rs +++ b/crates/nu-cli/src/prompt_update.rs @@ -2,8 +2,8 @@ use crate::NushellPrompt; use log::trace; use nu_engine::ClosureEvalOnce; use nu_protocol::{ - engine::{EngineState, Stack, StateWorkingSet}, - report_error, Config, PipelineData, Value, + engine::{EngineState, Stack}, + report_error_new, Config, PipelineData, Value, }; use reedline::Prompt; @@ -77,8 +77,7 @@ fn get_prompt_string( result .map_err(|err| { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &err); + report_error_new(engine_state, &err); }) .ok() } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 02609924a1..3fe51db496 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -26,9 +26,8 @@ use nu_parser::{lex, parse, trim_quotes_str}; use nu_protocol::{ config::NuCursorShape, engine::{EngineState, Stack, StateWorkingSet}, - eval_const::create_nu_constant, report_error_new, HistoryConfig, HistoryFileFormat, PipelineData, ShellError, Span, Spanned, - Value, NU_VARIABLE_ID, + Value, }; use nu_utils::{ filesystem::{have_permission, PermissionResult}, @@ -87,7 +86,7 @@ pub fn evaluate_repl( let start_time = std::time::Instant::now(); // Translate environment variables from Strings to Values - if let Some(e) = convert_env_values(engine_state, &unique_stack) { + if let Err(e) = convert_env_values(engine_state, &unique_stack) { report_error_new(engine_state, &e); } perf( @@ -145,8 +144,7 @@ pub fn evaluate_repl( engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64); // Regenerate the $nu constant to contain the startup time and any other potential updates - let nu_const = create_nu_constant(engine_state, Span::unknown())?; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); if load_std_lib.is_none() && engine_state.get_config().show_banner { eval_source( diff --git a/crates/nu-cli/src/util.rs b/crates/nu-cli/src/util.rs index 8ff4ef35ea..2f996691c9 100644 --- a/crates/nu-cli/src/util.rs +++ b/crates/nu-cli/src/util.rs @@ -39,9 +39,8 @@ fn gather_env_vars( init_cwd: &Path, ) { fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, + report_error_new( + engine_state, &ShellError::GenericError { error: format!("Environment variable was not captured: {env_str}"), msg: "".into(), @@ -71,9 +70,8 @@ fn gather_env_vars( } None => { // Could not capture current working directory - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, + report_error_new( + engine_state, &ShellError::GenericError { error: "Current directory is not a valid utf-8 path".into(), msg: "".into(), @@ -278,10 +276,7 @@ pub fn eval_source( match result { Err(err) => { - let working_set = StateWorkingSet::new(engine_state); - - report_error(&working_set, &err); - + report_error_new(engine_state, &err); return false; } Ok(exit_code) => { @@ -297,11 +292,7 @@ pub fn eval_source( } Err(err) => { set_last_exit_code(stack, 1); - - let working_set = StateWorkingSet::new(engine_state); - - report_error(&working_set, &err); - + report_error_new(engine_state, &err); return false; } } diff --git a/crates/nu-cli/tests/completions/support/completions_helpers.rs b/crates/nu-cli/tests/completions/support/completions_helpers.rs index bdc52739ee..47f46ab00e 100644 --- a/crates/nu-cli/tests/completions/support/completions_helpers.rs +++ b/crates/nu-cli/tests/completions/support/completions_helpers.rs @@ -3,8 +3,7 @@ use nu_parser::parse; use nu_protocol::{ debugger::WithoutDebug, engine::{EngineState, Stack, StateWorkingSet}, - eval_const::create_nu_constant, - PipelineData, ShellError, Span, Value, NU_VARIABLE_ID, + PipelineData, ShellError, Span, Value, }; use nu_test_support::fs; use reedline::Suggestion; @@ -28,9 +27,7 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) { let mut engine_state = create_default_context(); // Add $nu - let nu_const = - create_nu_constant(&engine_state, Span::test_data()).expect("Failed creating $nu"); - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); // New stack let mut stack = Stack::new(); diff --git a/crates/nu-cmd-base/src/util.rs b/crates/nu-cmd-base/src/util.rs index 619237a21c..4d19fdb3c6 100644 --- a/crates/nu-cmd-base/src/util.rs +++ b/crates/nu-cmd-base/src/util.rs @@ -1,6 +1,6 @@ use nu_protocol::{ - engine::{EngineState, Stack, StateWorkingSet}, - report_error, Range, ShellError, Span, Value, + engine::{EngineState, Stack}, + report_error_new, Range, ShellError, Span, Value, }; use std::{ops::Bound, path::PathBuf}; @@ -14,8 +14,7 @@ pub fn get_init_cwd() -> PathBuf { pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> PathBuf { engine_state.cwd(Some(stack)).unwrap_or_else(|e| { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); crate::util::get_init_cwd() }) } diff --git a/crates/nu-engine/src/env.rs b/crates/nu-engine/src/env.rs index ae226c4421..44692dd131 100644 --- a/crates/nu-engine/src/env.rs +++ b/crates/nu-engine/src/env.rs @@ -32,7 +32,7 @@ enum ConversionResult { /// It returns Option instead of Result since we do want to translate all the values we can and /// skip errors. This function is called in the main() so we want to keep running, we cannot just /// exit. -pub fn convert_env_values(engine_state: &mut EngineState, stack: &Stack) -> Option { +pub fn convert_env_values(engine_state: &mut EngineState, stack: &Stack) -> Result<(), ShellError> { let mut error = None; let mut new_scope = HashMap::new(); @@ -85,7 +85,11 @@ pub fn convert_env_values(engine_state: &mut EngineState, stack: &Stack) -> Opti }); } - error + if let Some(err) = error { + Err(err) + } else { + Ok(()) + } } /// Translate one environment variable from Value to String diff --git a/crates/nu-lsp/src/diagnostics.rs b/crates/nu-lsp/src/diagnostics.rs index a9bbab77a9..423fffbf6c 100644 --- a/crates/nu-lsp/src/diagnostics.rs +++ b/crates/nu-lsp/src/diagnostics.rs @@ -7,8 +7,7 @@ use miette::{IntoDiagnostic, Result}; use nu_parser::parse; use nu_protocol::{ engine::{EngineState, StateWorkingSet}, - eval_const::create_nu_constant, - Span, Value, NU_VARIABLE_ID, + Value, }; impl LanguageServer { @@ -19,11 +18,7 @@ impl LanguageServer { ) -> Result<()> { let cwd = std::env::current_dir().expect("Could not get current working directory."); engine_state.add_env_var("PWD".into(), Value::test_string(cwd.to_string_lossy())); - - let Ok(nu_const) = create_nu_constant(engine_state, Span::unknown()) else { - return Ok(()); - }; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); let mut working_set = StateWorkingSet::new(engine_state); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 1593b3341a..4a0ff4c4ae 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -6,6 +6,7 @@ use crate::{ CachedFile, Command, CommandType, EnvVars, OverlayFrame, ScopeFrame, Stack, StateDelta, Variable, Visibility, DEFAULT_OVERLAY_NAME, }, + eval_const::create_nu_constant, BlockId, Category, Config, DeclId, Example, FileId, HistoryConfig, Module, ModuleId, OverlayId, ShellError, Signature, Span, Type, Value, VarId, VirtualPathId, }; @@ -753,8 +754,8 @@ impl EngineState { var.const_val.as_ref() } - pub fn set_variable_const_val(&mut self, var_id: VarId, val: Value) { - self.vars[var_id].const_val = Some(val); + pub fn generate_nu_constant(&mut self) { + self.vars[NU_VARIABLE_ID].const_val = Some(create_nu_constant(self, Span::unknown())); } pub fn get_decl(&self, decl_id: DeclId) -> &dyn Command { diff --git a/crates/nu-protocol/src/errors/cli_error.rs b/crates/nu-protocol/src/errors/cli_error.rs index 6be1ebce40..003564f933 100644 --- a/crates/nu-protocol/src/errors/cli_error.rs +++ b/crates/nu-protocol/src/errors/cli_error.rs @@ -41,7 +41,6 @@ pub fn report_error_new( error: &(dyn miette::Diagnostic + Send + Sync + 'static), ) { let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, error); } diff --git a/crates/nu-protocol/src/eval_const.rs b/crates/nu-protocol/src/eval_const.rs index e45e3b7e4b..140a8303d9 100644 --- a/crates/nu-protocol/src/eval_const.rs +++ b/crates/nu-protocol/src/eval_const.rs @@ -12,7 +12,7 @@ use std::{ }; /// Create a Value for `$nu`. -pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result { +pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Value { fn canonicalize_path(engine_state: &EngineState, path: &Path) -> PathBuf { #[allow(deprecated)] let cwd = engine_state.current_work_dir(); @@ -200,7 +200,7 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result { if let Err(e) = engine_state.merge_env(stack, cwd) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } Err(e) => { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } } @@ -193,13 +191,11 @@ fn eval_default_config( match engine_state.cwd(Some(stack)) { Ok(cwd) => { if let Err(e) = engine_state.merge_env(stack, cwd) { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } Err(e) => { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); + report_error_new(engine_state, &e); } } } diff --git a/src/ide.rs b/src/ide.rs index 73419ed857..a3474fe3b6 100644 --- a/src/ide.rs +++ b/src/ide.rs @@ -3,8 +3,7 @@ use nu_cli::NuCompleter; use nu_parser::{flatten_block, parse, FlatShape}; use nu_protocol::{ engine::{EngineState, Stack, StateWorkingSet}, - eval_const::create_nu_constant, - report_error, DeclId, ShellError, Span, Value, VarId, NU_VARIABLE_ID, + report_error_new, DeclId, ShellError, Span, Value, VarId, }; use reedline::Completer; use serde_json::{json, Value as JsonValue}; @@ -56,9 +55,8 @@ fn read_in_file<'a>( let file = std::fs::read(file_path) .into_diagnostic() .unwrap_or_else(|e| { - let working_set = StateWorkingSet::new(engine_state); - report_error( - &working_set, + report_error_new( + engine_state, &ShellError::FileNotFoundCustom { msg: format!("Could not read file '{}': {:?}", file_path, e.to_string()), span: Span::unknown(), @@ -77,16 +75,7 @@ fn read_in_file<'a>( pub fn check(engine_state: &mut EngineState, file_path: &str, max_errors: &Value) { let cwd = std::env::current_dir().expect("Could not get current working directory."); engine_state.add_env_var("PWD".into(), Value::test_string(cwd.to_string_lossy())); - let working_set = StateWorkingSet::new(engine_state); - - let nu_const = match create_nu_constant(engine_state, Span::unknown()) { - Ok(nu_const) => nu_const, - Err(err) => { - report_error(&working_set, &err); - std::process::exit(1); - } - }; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); let mut working_set = StateWorkingSet::new(engine_state); let file = std::fs::read(file_path); diff --git a/src/main.rs b/src/main.rs index b7e70f1ed4..714b932df8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,8 @@ use nu_cmd_base::util::get_init_cwd; use nu_lsp::LanguageServer; use nu_path::canonicalize_with; use nu_protocol::{ - engine::EngineState, eval_const::create_nu_constant, report_error_new, util::BufferedReader, - PipelineData, RawStream, ShellError, Span, Value, NU_VARIABLE_ID, + engine::EngineState, report_error_new, util::BufferedReader, PipelineData, RawStream, + ShellError, Span, Value, }; use nu_std::load_standard_library; use nu_utils::utils::perf; @@ -378,8 +378,7 @@ fn main() -> Result<()> { start_time = std::time::Instant::now(); // Set up the $nu constant before evaluating config files (need to have $nu available in them) - let nu_const = create_nu_constant(&engine_state, input.span().unwrap_or_else(Span::unknown))?; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); perf( "create_nu_constant", start_time, @@ -462,7 +461,8 @@ fn main() -> Result<()> { &commands, input, entire_start_time, - ) + ); + Ok(()) } else if !script_name.is_empty() { run_file( &mut engine_state, @@ -471,7 +471,8 @@ fn main() -> Result<()> { script_name, args_to_script, input, - ) + ); + Ok(()) } else { run_repl(&mut engine_state, parsed_nu_cli_args, entire_start_time) } diff --git a/src/run.rs b/src/run.rs index 81274df3de..2996bc76f8 100644 --- a/src/run.rs +++ b/src/run.rs @@ -8,19 +8,22 @@ use log::trace; #[cfg(feature = "plugin")] use nu_cli::read_plugin_file; use nu_cli::{evaluate_commands, evaluate_file, evaluate_repl}; -use nu_protocol::{eval_const::create_nu_constant, PipelineData, Span, NU_VARIABLE_ID}; +use nu_protocol::{ + engine::{EngineState, Stack}, + report_error_new, PipelineData, Spanned, +}; use nu_utils::utils::perf; pub(crate) fn run_commands( - engine_state: &mut nu_protocol::engine::EngineState, + engine_state: &mut EngineState, parsed_nu_cli_args: command::NushellCliArgs, use_color: bool, - commands: &nu_protocol::Spanned, + commands: &Spanned, input: PipelineData, entire_start_time: std::time::Instant, -) -> Result<(), miette::ErrReport> { +) { trace!("run_commands"); - let mut stack = nu_protocol::engine::Stack::new(); + let mut stack = Stack::new(); let start_time = std::time::Instant::now(); // if the --no-config-file(-n) option is NOT passed, load the plugin file, @@ -103,18 +106,20 @@ pub(crate) fn run_commands( engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64); // Regenerate the $nu constant to contain the startup time and any other potential updates - let nu_const = create_nu_constant(engine_state, commands.span)?; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); let start_time = std::time::Instant::now(); - let ret_val = evaluate_commands( + if let Err(err) = evaluate_commands( commands, engine_state, &mut stack, input, parsed_nu_cli_args.table_mode, parsed_nu_cli_args.no_newline.is_some(), - ); + ) { + report_error_new(engine_state, &err); + std::process::exit(1); + } perf( "evaluate_commands", start_time, @@ -123,24 +128,18 @@ pub(crate) fn run_commands( column!(), use_color, ); - - match ret_val { - Ok(Some(exit_code)) => std::process::exit(exit_code as i32), - Ok(None) => Ok(()), - Err(e) => Err(e), - } } pub(crate) fn run_file( - engine_state: &mut nu_protocol::engine::EngineState, + engine_state: &mut EngineState, parsed_nu_cli_args: command::NushellCliArgs, use_color: bool, script_name: String, args_to_script: Vec, input: PipelineData, -) -> Result<(), miette::ErrReport> { +) { trace!("run_file"); - let mut stack = nu_protocol::engine::Stack::new(); + let mut stack = Stack::new(); // if the --no-config-file(-n) option is NOT passed, load the plugin file, // load the default env file or custom (depending on parsed_nu_cli_args.env_file), @@ -201,17 +200,19 @@ pub(crate) fn run_file( } // Regenerate the $nu constant to contain the startup time and any other potential updates - let nu_const = create_nu_constant(engine_state, input.span().unwrap_or_else(Span::unknown))?; - engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const); + engine_state.generate_nu_constant(); let start_time = std::time::Instant::now(); - let ret_val = evaluate_file( + if let Err(err) = evaluate_file( script_name, &args_to_script, engine_state, &mut stack, input, - ); + ) { + report_error_new(engine_state, &err); + std::process::exit(1); + } perf( "evaluate_file", start_time, @@ -239,17 +240,15 @@ pub(crate) fn run_file( column!(), use_color, ); - - ret_val } pub(crate) fn run_repl( - engine_state: &mut nu_protocol::engine::EngineState, + engine_state: &mut EngineState, parsed_nu_cli_args: command::NushellCliArgs, entire_start_time: std::time::Instant, ) -> Result<(), miette::ErrReport> { trace!("run_repl"); - let mut stack = nu_protocol::engine::Stack::new(); + let mut stack = Stack::new(); let start_time = std::time::Instant::now(); if parsed_nu_cli_args.no_config_file.is_none() {