From 965cea3af5f7325ef5648cfc96c02a8813dc9608 Mon Sep 17 00:00:00 2001 From: Fernando Herrera Date: Sat, 19 Feb 2022 20:54:43 +0000 Subject: [PATCH] flag to pass config file in nu (#4552) * flag to pass config file in nu * return when no folder is created * simple syntax for function --- Cargo.lock | 2 +- src/config_files.rs | 89 ++++++++++++++++++++++++++++----------------- src/main.rs | 47 +++++++++++++----------- src/repl.rs | 9 +++-- 4 files changed, 88 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c654f26aad..de51a6caae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3312,7 +3312,7 @@ dependencies = [ [[package]] name = "reedline" version = "0.2.0" -source = "git+https://github.com/nushell/reedline?branch=main#42ec23f08399519e79077921a08901420e27b05c" +source = "git+https://github.com/nushell/reedline?branch=main#e87e9d1fd3d392308975fb6f89c1a67cc43bc8b9" dependencies = [ "chrono", "crossterm", diff --git a/src/config_files.rs b/src/config_files.rs index 25984efbd3..3dd6a2a762 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -1,8 +1,10 @@ use crate::is_perf_true; use crate::utils::{eval_source, report_error}; use log::info; +use nu_parser::ParseError; +use nu_path::canonicalize_with; use nu_protocol::engine::{EngineState, Stack, StateDelta, StateWorkingSet}; -use nu_protocol::{PipelineData, Span}; +use nu_protocol::{PipelineData, Span, Spanned}; use std::path::PathBuf; const NUSHELL_FOLDER: &str = "nushell"; @@ -38,54 +40,73 @@ pub(crate) fn read_plugin_file(engine_state: &mut EngineState, stack: &mut Stack } } -pub(crate) fn read_config_file(engine_state: &mut EngineState, stack: &mut Stack) { +pub(crate) fn read_config_file( + engine_state: &mut EngineState, + stack: &mut Stack, + config_file: Option>, +) { // Load config startup file - if let Some(mut config_path) = nu_path::config_dir() { + if let Some(file) = config_file { + let working_set = StateWorkingSet::new(engine_state); + let cwd = working_set.get_cwd(); + + match canonicalize_with(&file.item, cwd) { + Ok(path) => { + eval_config_contents(path, engine_state, stack); + } + Err(_) => { + let e = ParseError::FileNotFound(file.item, file.span); + report_error(&working_set, &e); + } + } + } else if let Some(mut config_path) = nu_path::config_dir() { config_path.push(NUSHELL_FOLDER); // Create config directory if it does not exist if !config_path.exists() { if let Err(err) = std::fs::create_dir_all(&config_path) { eprintln!("Failed to create config directory: {}", err); + return; } - } else { - config_path.push(CONFIG_FILE); + } - if config_path.exists() { - // FIXME: remove this message when we're ready - //println!("Loading config from: {:?}", config_path); - let config_filename = config_path.to_string_lossy().to_owned(); + config_path.push(CONFIG_FILE); + eval_config_contents(config_path, engine_state, stack); + } - if let Ok(contents) = std::fs::read(&config_path) { - eval_source( - engine_state, - stack, - &contents, - &config_filename, - PipelineData::new(Span::new(0, 0)), - ); - // Merge the delta in case env vars changed in the config - match nu_engine::env::current_dir(engine_state, stack) { - Ok(cwd) => { - if let Err(e) = - engine_state.merge_delta(StateDelta::new(), Some(stack), cwd) - { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); - } - } - Err(e) => { - let working_set = StateWorkingSet::new(engine_state); - report_error(&working_set, &e); - } + if is_perf_true() { + info!("read_config_file {}:{}:{}", file!(), line!(), column!()); + } +} + +fn eval_config_contents(config_path: PathBuf, engine_state: &mut EngineState, stack: &mut Stack) { + if config_path.exists() & config_path.is_file() { + let config_filename = config_path.to_string_lossy().to_owned(); + + if let Ok(contents) = std::fs::read(&config_path) { + eval_source( + engine_state, + stack, + &contents, + &config_filename, + PipelineData::new(Span::new(0, 0)), + ); + + // Merge the delta in case env vars changed in the config + match nu_engine::env::current_dir(engine_state, stack) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_delta(StateDelta::new(), Some(stack), cwd) { + let working_set = StateWorkingSet::new(engine_state); + report_error(&working_set, &e); } } + Err(e) => { + let working_set = StateWorkingSet::new(engine_state); + report_error(&working_set, &e); + } } } } - if is_perf_true() { - info!("read_config_file {}:{}:{}", file!(), line!(), column!()); - } } pub(crate) fn create_history_path() -> Option { diff --git a/src/main.rs b/src/main.rs index 27f7d73bd5..dcc1102bb4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,7 +78,6 @@ fn main() -> Result<()> { // Would be nice if we had a way to parse this. The first flags we see will be going to nushell // then it'll be the script name // then the args to the script - let mut collect_arg_nushell = false; for arg in std::env::args().skip(1) { if !script_name.is_empty() { @@ -102,13 +101,14 @@ fn main() -> Result<()> { || arg == "--develop" || arg == "--debug" || arg == "--loglevel" - || arg == "--config-file" + || arg == "--config" || arg == "--perf" || arg == "--threads" || arg == "--version" { collect_arg_nushell = true; } + args_to_nushell.push(arg); } else { // Our script file @@ -198,7 +198,7 @@ fn main() -> Result<()> { ret_val } else { - let ret_val = repl::evaluate(&mut engine_state); + let ret_val = repl::evaluate(&mut engine_state, binary_args.config_file); if is_perf_true() { info!("repl eval {}:{}:{}", file!(), line!(), column!()); } @@ -255,29 +255,26 @@ fn parse_commandline_args( let commands: Option = call.get_flag_expr("commands"); let testbin: Option = call.get_flag_expr("testbin"); let perf = call.has_flag("perf"); + let config_file: Option = call.get_flag_expr("config"); let threads: Option = call.get_flag(engine_state, &mut stack, "threads")?; - let commands = if let Some(expression) = commands { - let contents = engine_state.get_span_contents(&expression.span); + fn extract_contents( + expression: Option, + engine_state: &mut EngineState, + ) -> Option> { + expression.map(|expr| { + let contents = engine_state.get_span_contents(&expr.span); - Some(Spanned { - item: String::from_utf8_lossy(contents).to_string(), - span: expression.span, + Spanned { + item: String::from_utf8_lossy(contents).to_string(), + span: expr.span, + } }) - } else { - None - }; + } - let testbin = if let Some(expression) = testbin { - let contents = engine_state.get_span_contents(&expression.span); - - Some(Spanned { - item: String::from_utf8_lossy(contents).to_string(), - span: expression.span, - }) - } else { - None - }; + let commands = extract_contents(commands, engine_state); + let testbin = extract_contents(testbin, engine_state); + let config_file = extract_contents(config_file, engine_state); let help = call.has_flag("help"); @@ -311,6 +308,7 @@ fn parse_commandline_args( interactive_shell, commands, testbin, + config_file, perf, threads, }); @@ -330,6 +328,7 @@ struct NushellCliArgs { interactive_shell: Option>, commands: Option>, testbin: Option>, + config_file: Option>, perf: bool, threads: Option, } @@ -371,6 +370,12 @@ impl Command for Nu { SyntaxShape::Filepath, "name of the optional script file to run", ) + .named( + "config", + SyntaxShape::String, + "run internal test binary", + None, + ) .named( "threads", SyntaxShape::Int, diff --git a/src/repl.rs b/src/repl.rs index ef91589559..084c501268 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -12,15 +12,18 @@ use nu_cli::{NuCompleter, NuHighlighter, NuValidator, NushellPrompt}; use nu_color_config::get_color_config; use nu_engine::convert_env_values; use nu_parser::lex; -use nu_protocol::PipelineData; use nu_protocol::{ engine::{EngineState, StateWorkingSet}, Config, ShellError, Span, Value, CONFIG_VARIABLE_ID, }; +use nu_protocol::{PipelineData, Spanned}; use reedline::{DefaultHinter, Emacs, Vi}; use std::{sync::atomic::Ordering, time::Instant}; -pub(crate) fn evaluate(engine_state: &mut EngineState) -> Result<()> { +pub(crate) fn evaluate( + engine_state: &mut EngineState, + config_file: Option>, +) -> Result<()> { // use crate::logger::{configure, logger}; use reedline::{FileBackedHistory, Reedline, Signal}; @@ -53,7 +56,7 @@ pub(crate) fn evaluate(engine_state: &mut EngineState) -> Result<()> { info!("read_config_file {}:{}:{}", file!(), line!(), column!()); } - config_files::read_config_file(engine_state, &mut stack); + config_files::read_config_file(engine_state, &mut stack, config_file); let history_path = config_files::create_history_path(); // Load config struct form config variable