From deeb1da359004e7b033280582f335214db17a1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Wed, 22 Dec 2021 00:32:38 +0200 Subject: [PATCH] Allow having only one env conversion (#548) Allows setting only `from_string` or `to_string` in `env_conversions` config. Previously, both were required. --- crates/nu-command/src/env/env_command.rs | 2 +- crates/nu-engine/src/env.rs | 111 +++++++++++++---------- crates/nu-protocol/src/config.rs | 26 ++---- src/main.rs | 6 +- 4 files changed, 75 insertions(+), 70 deletions(-) diff --git a/crates/nu-command/src/env/env_command.rs b/crates/nu-command/src/env/env_command.rs index 2c00e25411..3dc1fc3de9 100644 --- a/crates/nu-command/src/env/env_command.rs +++ b/crates/nu-command/src/env/env_command.rs @@ -12,7 +12,7 @@ impl Command for Env { } fn usage(&self) -> &str { - "Display current environment" + "Display current environment variables" } fn signature(&self) -> nu_protocol::Signature { diff --git a/crates/nu-engine/src/env.rs b/crates/nu-engine/src/env.rs index f87afeb32f..a60896f07f 100644 --- a/crates/nu-engine/src/env.rs +++ b/crates/nu-engine/src/env.rs @@ -16,7 +16,7 @@ const ENV_SEP: &str = ":"; /// 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 env_to_values( +pub fn convert_env_values( engine_state: &EngineState, stack: &mut Stack, config: &Config, @@ -28,40 +28,48 @@ pub fn env_to_values( let mut new_scope = HashMap::new(); for (name, val) in scope { - if let Some(conv) = config.env_conversions.get(name) { - let span = match val.span() { - Ok(sp) => sp, - Err(e) => { - error = error.or(Some(e)); - continue; - } - }; - - let block = engine_state.get_block(conv.from_string.0); - - if let Some(var) = block.signature.get_positional(0) { - let mut stack = stack.collect_captures(&block.captures); - if let Some(var_id) = &var.var_id { - stack.add_var(*var_id, val.clone()); - } - - let result = - eval_block(engine_state, &mut stack, block, PipelineData::new(span)); - - match result { - Ok(data) => { - let val = data.into_value(span); - new_scope.insert(name.to_string(), val); + if let Some(env_conv) = config.env_conversions.get(name) { + if let Some((block_id, from_span)) = env_conv.from_string { + let val_span = match val.span() { + Ok(sp) => sp, + Err(e) => { + error = error.or(Some(e)); + continue; } - Err(e) => error = error.or(Some(e)), + }; + + let block = engine_state.get_block(block_id); + + if let Some(var) = block.signature.get_positional(0) { + let mut stack = stack.collect_captures(&block.captures); + if let Some(var_id) = &var.var_id { + stack.add_var(*var_id, val.clone()); + } + + let result = eval_block( + engine_state, + &mut stack, + block, + PipelineData::new(val_span), + ); + + match result { + Ok(data) => { + let val = data.into_value(val_span); + new_scope.insert(name.to_string(), val); + } + Err(e) => error = error.or(Some(e)), + } + } else { + error = error.or_else(|| { + Some(ShellError::MissingParameter( + "block input".into(), + from_span, + )) + }); } } else { - error = error.or_else(|| { - Some(ShellError::MissingParameter( - "block input".into(), - conv.from_string.1, - )) - }); + new_scope.insert(name.to_string(), val.clone()); } } else { new_scope.insert(name.to_string(), val.clone()); @@ -84,28 +92,31 @@ pub fn env_to_string( stack: &mut Stack, config: &Config, ) -> Result { - if let Some(conv) = config.env_conversions.get(env_name) { - let block = engine_state.get_block(conv.to_string.0); + if let Some(env_conv) = config.env_conversions.get(env_name) { + if let Some((block_id, to_span)) = env_conv.to_string { + let block = engine_state.get_block(block_id); - if let Some(var) = block.signature.get_positional(0) { - let span = value.span()?; - let mut stack = stack.collect_captures(&block.captures); + if let Some(var) = block.signature.get_positional(0) { + let val_span = value.span()?; + let mut stack = stack.collect_captures(&block.captures); - if let Some(var_id) = &var.var_id { - stack.add_var(*var_id, value); + if let Some(var_id) = &var.var_id { + stack.add_var(*var_id, value); + } + + Ok( + // This one is OK to fail: We want to know if custom conversion is working + eval_block(engine_state, &mut stack, block, PipelineData::new(val_span))? + .into_value(val_span) + .as_string()?, + ) + } else { + Err(ShellError::MissingParameter("block input".into(), to_span)) } - - Ok( - // This one is OK to fail: We want to know if custom conversion is working - eval_block(engine_state, &mut stack, block, PipelineData::new(span))? - .into_value(span) - .as_string()?, - ) } else { - Err(ShellError::MissingParameter( - "block input".into(), - conv.to_string.1, - )) + // Do not fail here. Must sicceed, otherwise setting a non-string env var would constantly + // throw errors when running externals etc. + Ok(value.into_string(ENV_SEP, config)) } } else { // Do not fail here. Must sicceed, otherwise setting a non-string env var would constantly diff --git a/crates/nu-protocol/src/config.rs b/crates/nu-protocol/src/config.rs index a8a96280cc..63f96761b4 100644 --- a/crates/nu-protocol/src/config.rs +++ b/crates/nu-protocol/src/config.rs @@ -6,8 +6,8 @@ const ANIMATE_PROMPT_DEFAULT: bool = false; #[derive(Serialize, Deserialize, Clone, Debug)] pub struct EnvConversion { - pub from_string: (BlockId, Span), - pub to_string: (BlockId, Span), + pub from_string: Option<(BlockId, Span)>, + pub to_string: Option<(BlockId, Span)>, } impl EnvConversion { @@ -28,20 +28,13 @@ impl EnvConversion { } } - match (conv_map.get("from_string"), conv_map.get("to_string")) { - (None, _) => Err(ShellError::MissingConfigValue( - "'from_string' field".into(), - value.span()?, - )), - (_, None) => Err(ShellError::MissingConfigValue( - "'to_string' field".into(), - value.span()?, - )), - (Some(from), Some(to)) => Ok(EnvConversion { - from_string: *from, - to_string: *to, - }), - } + let from_string = conv_map.get("from_string").cloned(); + let to_string = conv_map.get("to_string").cloned(); + + Ok(EnvConversion { + from_string, + to_string, + }) } } @@ -177,6 +170,7 @@ impl Value { let mut env_conversions = HashMap::new(); for (env_var, record) in env_vars.iter().zip(conversions) { + // println!("{}: {:?}", env_var, record); env_conversions.insert(env_var.into(), EnvConversion::from_record(record)?); } diff --git a/src/main.rs b/src/main.rs index 3ce3bbca99..3f288f6539 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use dialoguer::{ use miette::{IntoDiagnostic, Result}; use nu_cli::{CliError, NuCompleter, NuHighlighter, NuValidator, NushellPrompt}; use nu_command::create_default_context; -use nu_engine::{env_to_values, eval_block}; +use nu_engine::{convert_env_values, eval_block}; use nu_parser::{lex, parse, trim_quotes, Token, TokenContents}; use nu_protocol::{ ast::Call, @@ -153,7 +153,7 @@ fn main() -> Result<()> { }; // Translate environment variables from Strings to Values - if let Some(e) = env_to_values(&engine_state, &mut stack, &config) { + if let Some(e) = convert_env_values(&engine_state, &mut stack, &config) { let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &e); std::process::exit(1); @@ -289,7 +289,7 @@ fn main() -> Result<()> { }; // Translate environment variables from Strings to Values - if let Some(e) = env_to_values(&engine_state, &mut stack, &config) { + if let Some(e) = convert_env_values(&engine_state, &mut stack, &config) { let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &e); }