diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index c13dc2ab..322f65c5 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -173,7 +173,7 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box Result { - let name_span = args.call_info.name_tag.clone(); + let ctx = EvaluationContext::from_args(&args); - let path = match args.scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => nu_data::config::default_path().ok(), + let result = if let Some(global_cfg) = &mut args.configs.lock().global_config { + global_cfg.vars.clear(); + global_cfg.write()?; + ctx.reload_config(global_cfg)?; + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::Row(global_cfg.vars.clone().into()).into_value(args.call_info.name_tag), + ))) + } else { + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] + .into_iter() + .to_output_stream()) }; - let mut result = nu_data::config::read(name_span, &path)?; - - result.clear(); - - config::write(&result, &path)?; - - Ok(OutputStream::one(ReturnSuccess::value( - UntaggedValue::Row(result.into()).into_value(args.call_info.name_tag), - ))) + result } diff --git a/crates/nu-command/src/commands/config/command.rs b/crates/nu-command/src/commands/config/command.rs index b573e933..50bdd49d 100644 --- a/crates/nu-command/src/commands/config/command.rs +++ b/crates/nu-command/src/commands/config/command.rs @@ -32,7 +32,7 @@ impl WholeStreamCommand for Command { .to_output_stream()) } else { Ok(vec![ReturnSuccess::value(UntaggedValue::Error( - ShellError::untagged_runtime_error("No global config found!"), + crate::commands::config::err_no_global_cfg_present(), ))] .into_iter() .to_output_stream()) diff --git a/crates/nu-command/src/commands/config/get.rs b/crates/nu-command/src/commands/config/get.rs index 36f3cb9a..56e3405b 100644 --- a/crates/nu-command/src/commands/config/get.rs +++ b/crates/nu-command/src/commands/config/get.rs @@ -1,9 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; +use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; pub struct SubCommand; @@ -44,33 +42,27 @@ impl WholeStreamCommand for SubCommand { pub fn get(args: CommandArgs) -> Result { let name = args.call_info.name_tag.clone(); - let scope = args.scope.clone(); + let ctx = EvaluationContext::from_args(&args); + let (Arguments { column_path }, _) = args.process()?; - let path = match scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => nu_data::config::default_path().ok(), + let result = if let Some(global_cfg) = &ctx.configs.lock().global_config { + let result = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name); + let value = crate::commands::get::get_column_path(&column_path, &result)?; + Ok(match value { + Value { + value: UntaggedValue::Table(list), + .. + } => list.into_iter().to_output_stream(), + x => OutputStream::one(ReturnSuccess::value(x)), + }) + } else { + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] + .into_iter() + .to_output_stream()) }; - let result = UntaggedValue::row(nu_data::config::read(&name, &path)?).into_value(&name); - - let value = crate::commands::get::get_column_path(&column_path, &result)?; - - Ok(match value { - Value { - value: UntaggedValue::Table(list), - .. - } => { - let list: Vec<_> = list - .iter() - .map(|x| ReturnSuccess::value(x.clone())) - .collect(); - - list.into_iter().to_output_stream() - } - x => OutputStream::one(ReturnSuccess::value(x)), - }) + result } diff --git a/crates/nu-command/src/commands/config/mod.rs b/crates/nu-command/src/commands/config/mod.rs index 8b5c5757..62f626cf 100644 --- a/crates/nu-command/src/commands/config/mod.rs +++ b/crates/nu-command/src/commands/config/mod.rs @@ -13,3 +13,9 @@ pub use path::SubCommand as ConfigPath; pub use remove::SubCommand as ConfigRemove; pub use set::SubCommand as ConfigSet; pub use set_into::SubCommand as ConfigSetInto; + +use nu_errors::ShellError; + +pub fn err_no_global_cfg_present() -> ShellError { + ShellError::untagged_runtime_error("No global config found!") +} diff --git a/crates/nu-command/src/commands/config/path.rs b/crates/nu-command/src/commands/config/path.rs index 8ca46587..c9f6c5c7 100644 --- a/crates/nu-command/src/commands/config/path.rs +++ b/crates/nu-command/src/commands/config/path.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue}; pub struct SubCommand; @@ -32,18 +32,15 @@ impl WholeStreamCommand for SubCommand { } pub fn path(args: CommandArgs) -> Result { - Ok(OutputStream::one(ReturnSuccess::value( - match args.scope.get_var("config-path") { - Some( - path - @ - Value { - value: UntaggedValue::Primitive(Primitive::FilePath(_)), - .. - }, - ) => path, - _ => UntaggedValue::Primitive(Primitive::FilePath(nu_data::config::default_path()?)) - .into_value(args.call_info.name_tag), - }, - ))) + if let Some(global_cfg) = &mut args.configs.lock().global_config { + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::Primitive(Primitive::FilePath(global_cfg.file_path.clone())), + ))) + } else { + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] + .into_iter() + .to_output_stream()) + } } diff --git a/crates/nu-command/src/commands/config/remove.rs b/crates/nu-command/src/commands/config/remove.rs index da7b1d74..f28e20dd 100644 --- a/crates/nu-command/src/commands/config/remove.rs +++ b/crates/nu-command/src/commands/config/remove.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; use nu_source::Tagged; pub struct SubCommand; @@ -42,35 +42,35 @@ impl WholeStreamCommand for SubCommand { } pub fn remove(args: CommandArgs) -> Result { - let name_span = args.call_info.name_tag.clone(); - let scope = args.scope.clone(); + let ctx = EvaluationContext::from_args(&args); let (Arguments { remove }, _) = args.process()?; - let path = match scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => nu_data::config::default_path().ok(), - }; - - let mut result = nu_data::config::read(name_span, &path)?; - let key = remove.to_string(); - if result.contains_key(&key) { - result.swap_remove(&key); - config::write(&result, &path)?; - Ok(vec![ReturnSuccess::value( - UntaggedValue::Row(result.into()).into_value(remove.tag()), - )] + let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config { + if global_cfg.vars.contains_key(&key) { + global_cfg.vars.swap_remove(&key); + global_cfg.write()?; + ctx.reload_config(global_cfg)?; + Ok(vec![ReturnSuccess::value( + UntaggedValue::row(global_cfg.vars.clone()).into_value(remove.tag()), + )] + .into_iter() + .to_output_stream()) + } else { + Err(ShellError::labeled_error( + "Key does not exist in config", + "key", + remove.tag(), + )) + } + } else { + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] .into_iter() .to_output_stream()) - } else { - Err(ShellError::labeled_error( - "Key does not exist in config", - "key", - remove.tag(), - )) - } + }; + + result } diff --git a/crates/nu-command/src/commands/config/set.rs b/crates/nu-command/src/commands/config/set.rs index d73cd3bf..e93faadf 100644 --- a/crates/nu-command/src/commands/config/set.rs +++ b/crates/nu-command/src/commands/config/set.rs @@ -1,9 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, ConfigPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; +use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; pub struct SubCommand; @@ -61,7 +59,6 @@ impl WholeStreamCommand for SubCommand { pub fn set(args: CommandArgs) -> Result { let name = args.call_info.name_tag.clone(); let ctx = EvaluationContext::from_args(&args); - let scope = args.scope.clone(); let ( Arguments { column_path, @@ -70,38 +67,38 @@ pub fn set(args: CommandArgs) -> Result { _, ) = args.process()?; - let path = match scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => nu_data::config::default_path().ok(), + let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config { + let configuration = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name); + + if let UntaggedValue::Table(rows) = &value.value { + if rows.len() == 1 && rows[0].is_row() { + value = rows[0].clone(); + } + } + + match configuration.forgiving_insert_data_at_column_path(&column_path, value) { + Ok(Value { + value: UntaggedValue::Row(changes), + .. + }) => { + global_cfg.vars = changes.entries; + global_cfg.write()?; + ctx.reload_config(global_cfg)?; + + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::row(global_cfg.vars.clone()).into_value(name), + ))) + } + Ok(_) => Ok(OutputStream::empty()), + Err(reason) => Err(reason), + } + } else { + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] + .into_iter() + .to_output_stream()) }; - let raw_entries = nu_data::config::read(&name, &path)?; - let configuration = UntaggedValue::row(raw_entries).into_value(&name); - - if let UntaggedValue::Table(rows) = &value.value { - if rows.len() == 1 && rows[0].is_row() { - value = rows[0].clone(); - } - } - - match configuration.forgiving_insert_data_at_column_path(&column_path, value) { - Ok(Value { - value: UntaggedValue::Row(changes), - .. - }) => { - config::write(&changes.entries, &path)?; - ctx.reload_config(&ConfigPath::Global( - path.expect("Global config path is always some"), - ))?; - - Ok(OutputStream::one(ReturnSuccess::value( - UntaggedValue::Row(changes).into_value(name), - ))) - } - Ok(_) => Ok(OutputStream::empty()), - Err(reason) => Err(reason), - } + result } diff --git a/crates/nu-command/src/commands/config/set_into.rs b/crates/nu-command/src/commands/config/set_into.rs index e38242dc..51182d90 100644 --- a/crates/nu-command/src/commands/config/set_into.rs +++ b/crates/nu-command/src/commands/config/set_into.rs @@ -1,9 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{ - ConfigPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; pub struct SubCommand; @@ -46,55 +44,43 @@ impl WholeStreamCommand for SubCommand { pub fn set_into(args: CommandArgs) -> Result { let name = args.call_info.name_tag.clone(); let ctx = EvaluationContext::from_args(&args); - let scope = args.scope.clone(); let (Arguments { set_into: v }, input) = args.process()?; - let path = match scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => nu_data::config::default_path().ok(), - }; - - let mut result = nu_data::config::read(&name, &path)?; - let rows: Vec = input.collect(); let key = v.to_string(); - Ok(if rows.is_empty() { - return Err(ShellError::labeled_error( - "No values given for set_into", - "needs value(s) from pipeline", - v.tag(), - )); - } else if rows.len() == 1 { - // A single value - let value = &rows[0]; + let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config { + if rows.is_empty() { + return Err(ShellError::labeled_error( + "No values given for set_into", + "needs value(s) from pipeline", + v.tag(), + )); + } else if rows.len() == 1 { + // A single value + let value = &rows[0]; - result.insert(key, value.clone()); + global_cfg.vars.insert(key, value.clone()); + } else { + // Take in the pipeline as a table + let value = UntaggedValue::Table(rows).into_value(name.clone()); - config::write(&result, &path)?; - ctx.reload_config(&ConfigPath::Global( - path.expect("Global config path is always some"), - ))?; + global_cfg.vars.insert(key, value); + } - OutputStream::one(ReturnSuccess::value( - UntaggedValue::Row(result.into()).into_value(name), - )) + global_cfg.write()?; + ctx.reload_config(global_cfg)?; + + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::row(global_cfg.vars.clone()).into_value(name), + ))) } else { - // Take in the pipeline as a table - let value = UntaggedValue::Table(rows).into_value(name.clone()); + Ok(vec![ReturnSuccess::value(UntaggedValue::Error( + crate::commands::config::err_no_global_cfg_present(), + ))] + .into_iter() + .to_output_stream()) + }; - result.insert(key, value); - - config::write(&result, &path)?; - ctx.reload_config(&ConfigPath::Global( - path.expect("Global config path is always some"), - ))?; - - OutputStream::one(ReturnSuccess::value( - UntaggedValue::Row(result.into()).into_value(name), - )) - }) + result } diff --git a/crates/nu-command/src/commands/history.rs b/crates/nu-command/src/commands/history.rs index 92b27ffd..0a7c83f7 100644 --- a/crates/nu-command/src/commands/history.rs +++ b/crates/nu-command/src/commands/history.rs @@ -1,5 +1,4 @@ use crate::prelude::*; -use nu_data::config::{Conf, NuConfig}; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; @@ -32,11 +31,15 @@ impl WholeStreamCommand for History { } fn history(args: CommandArgs) -> Result { - let config: Box = Box::new(NuConfig::new()); let tag = args.call_info.name_tag.clone(); + let ctx = EvaluationContext::from_args(&args); let (Arguments { clear }, _) = args.process()?; - let path = nu_data::config::path::history_path(&config); + let path = if let Some(global_cfg) = &ctx.configs.lock().global_config { + nu_data::config::path::history_path_or_default(global_cfg) + } else { + nu_data::config::path::default_history_path() + }; match clear { Some(_) => { diff --git a/crates/nu-command/tests/commands/config.rs b/crates/nu-command/tests/commands/config.rs new file mode 100644 index 00000000..cd40e5c2 --- /dev/null +++ b/crates/nu-command/tests/commands/config.rs @@ -0,0 +1,138 @@ +use nu_test_support::fs::AbsolutePath; +use nu_test_support::fs::Stub::FileWithContent; +use nu_test_support::playground::{says, Playground}; + +use hamcrest2::assert_that; +use hamcrest2::prelude::*; + +#[test] +fn clearing_config_clears_config() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + skip_welcome_message = true + "#, + )]); + + assert_that!( + nu.pipeline("config clear; config get skip_welcome_message"), + says().to_stdout("") + ); + let config_contents = std::fs::read_to_string(file).expect("Could not read file"); + assert!(config_contents.is_empty()); + }); +} + +#[test] +fn config_get_returns_value() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + skip_welcome_message = true + "#, + )]); + + assert_that!( + //Clears config + nu.pipeline("config get skip_welcome_message"), + says().to_stdout("true") + ); + }); +} + +#[test] +fn config_set_sets_value() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + skip_welcome_message = true + "#, + )]); + + assert_that!( + //Clears config + nu.pipeline("config set key value; config get key"), + says().to_stdout("value") + ); + let config_contents = std::fs::read_to_string(file).expect("Could not read file"); + assert!(config_contents.contains("key = \"value\"")); + }); +} + +#[test] +fn config_set_into_sets_value() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + skip_welcome_message = true + "#, + )]); + + assert_that!( + //Clears config + nu.pipeline("echo value | config set_into key; config get key"), + says().to_stdout("value") + ); + let config_contents = std::fs::read_to_string(file).expect("Could not read file"); + assert!(config_contents.contains("key = \"value\"")); + }); +} + +#[test] +fn config_rm_removes_value() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + key = "value" + skip_welcome_message = true + "#, + )]); + + assert_that!( + nu.pipeline("config remove key; config get key"), + says().to_stdout("") + ); + let config_contents = std::fs::read_to_string(file).expect("Could not read file"); + assert!(!config_contents.contains("key = \"value\"")); + }); +} + +#[test] +fn config_path_returns_correct_path() { + Playground::setup("environment_syncing_test_1", |dirs, nu| { + let file = AbsolutePath::new(dirs.test().join("config.toml")); + + nu.with_config(&file); + nu.with_files(vec![FileWithContent( + "config.toml", + r#" + skip_welcome_message = true + "#, + )]); + + assert_that!( + nu.pipeline("config path"), + says().to_stdout(&file.inner.to_string_lossy().to_string()) + ); + }); +} diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs index e7ca5f22..ebf4295c 100644 --- a/crates/nu-command/tests/commands/mod.rs +++ b/crates/nu-command/tests/commands/mod.rs @@ -4,6 +4,7 @@ mod append; mod cal; mod cd; mod compact; +mod config; mod cp; mod def; mod default; diff --git a/crates/nu-data/src/config.rs b/crates/nu-data/src/config.rs index 47358f46..b9f0b452 100644 --- a/crates/nu-data/src/config.rs +++ b/crates/nu-data/src/config.rs @@ -16,8 +16,8 @@ use indexmap::IndexMap; use log::trace; use nu_errors::{CoerceInto, ShellError}; use nu_protocol::{ - ConfigPath, Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember, - UntaggedValue, Value, + Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember, UntaggedValue, + Value, }; use nu_source::{SpannedItem, Tag, TaggedItem}; use std::fs::{self, OpenOptions}; @@ -328,6 +328,6 @@ fn touch(path: &Path) -> io::Result<()> { } } -pub fn cfg_path_to_scope_tag(cfg_path: &ConfigPath) -> String { - cfg_path.get_path().to_string_lossy().to_string() +pub fn cfg_path_to_scope_tag(cfg_path: &Path) -> String { + cfg_path.to_string_lossy().to_string() } diff --git a/crates/nu-data/src/config/nuconfig.rs b/crates/nu-data/src/config/nuconfig.rs index be08d679..74d20d91 100644 --- a/crates/nu-data/src/config/nuconfig.rs +++ b/crates/nu-data/src/config/nuconfig.rs @@ -5,6 +5,8 @@ use nu_protocol::Value; use nu_source::Tag; use std::{fmt::Debug, path::PathBuf}; +use super::write; + #[derive(Debug, Clone, Default)] pub struct NuConfig { pub vars: IndexMap, @@ -63,6 +65,11 @@ impl NuConfig { }) } + /// Writes self.values under self.file_path + pub fn write(&self) -> Result<(), ShellError> { + write(&self.vars, &Some(self.file_path.clone())) + } + pub fn new() -> NuConfig { let vars = if let Ok(variables) = read(Tag::unknown(), &None) { variables diff --git a/crates/nu-data/src/config/path.rs b/crates/nu-data/src/config/path.rs index a6f98268..3e0f951c 100644 --- a/crates/nu-data/src/config/path.rs +++ b/crates/nu-data/src/config/path.rs @@ -1,6 +1,7 @@ -use crate::config::Conf; use std::path::PathBuf; +use super::NuConfig; + const DEFAULT_LOCATION: &str = "history.txt"; pub fn default_history_path() -> PathBuf { @@ -12,14 +13,18 @@ pub fn default_history_path() -> PathBuf { .unwrap_or_else(|_| PathBuf::from(DEFAULT_LOCATION)) } -pub fn history_path(config: &dyn Conf) -> PathBuf { - let default_history_path = default_history_path(); - - config.var("history-path").map_or( - default_history_path.clone(), - |custom_path| match custom_path.as_string() { - Ok(path) => PathBuf::from(path), - Err(_) => default_history_path, - }, - ) +/// Get history path of config, if present +pub fn history_path(config: &NuConfig) -> Option { + config + .var("history-path") + .map(|custom_path| match custom_path.as_string() { + Ok(path) => Some(PathBuf::from(path)), + Err(_) => None, + }) + .flatten() +} + +/// Get history path in config or default +pub fn history_path_or_default(config: &NuConfig) -> PathBuf { + history_path(config).unwrap_or_else(default_history_path) } diff --git a/crates/nu-engine/src/evaluate/evaluator.rs b/crates/nu-engine/src/evaluate/evaluator.rs index d0a26eb7..6270d8ac 100644 --- a/crates/nu-engine/src/evaluate/evaluator.rs +++ b/crates/nu-engine/src/evaluate/evaluator.rs @@ -227,7 +227,7 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value { fn evaluate_reference(name: &str, ctx: &EvaluationContext, tag: Tag) -> Result { match name { - "$nu" => crate::evaluate::variables::nu(&ctx.scope, tag), + "$nu" => crate::evaluate::variables::nu(&ctx.scope, tag, ctx), "$scope" => crate::evaluate::variables::scope(&ctx.scope.get_aliases(), tag), diff --git a/crates/nu-engine/src/evaluate/variables.rs b/crates/nu-engine/src/evaluate/variables.rs index 31d8aa88..718eb04d 100644 --- a/crates/nu-engine/src/evaluate/variables.rs +++ b/crates/nu-engine/src/evaluate/variables.rs @@ -1,11 +1,15 @@ -use crate::evaluate::scope::Scope; +use crate::{evaluate::scope::Scope, EvaluationContext}; use indexmap::IndexMap; -use nu_data::config::path::history_path; +use nu_data::config::path::{default_history_path, history_path}; use nu_errors::ShellError; -use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value}; +use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; use nu_source::{Spanned, Tag}; -pub fn nu(scope: &Scope, tag: impl Into) -> Result { +pub fn nu( + scope: &Scope, + tag: impl Into, + ctx: &EvaluationContext, +) -> Result { let env = &scope.get_env_vars(); let tag = tag.into(); @@ -17,18 +21,33 @@ pub fn nu(scope: &Scope, tag: impl Into) -> Result { dict.insert_untagged(v.0, UntaggedValue::string(v.1)); } } + nu_dict.insert_value("env", dict.into_value()); - let config_file = match scope.get_var("config-path") { - Some(Value { - value: UntaggedValue::Primitive(Primitive::FilePath(path)), - .. - }) => Some(path), - _ => None, - }; + nu_dict.insert_value( + "history-path", + UntaggedValue::filepath(default_history_path()).into_value(&tag), + ); - let config = nu_data::config::read(&tag, &config_file)?; - nu_dict.insert_value("config", UntaggedValue::row(config).into_value(&tag)); + if let Some(global_cfg) = &ctx.configs.lock().global_config { + nu_dict.insert_value( + "config", + UntaggedValue::row(global_cfg.vars.clone()).into_value(&tag), + ); + + nu_dict.insert_value( + "config-path", + UntaggedValue::filepath(global_cfg.file_path.clone()).into_value(&tag), + ); + + // overwrite hist-path if present + if let Some(hist_path) = history_path(global_cfg) { + nu_dict.insert_value( + "history-path", + UntaggedValue::filepath(hist_path).into_value(&tag), + ); + } + } let mut table = vec![]; for v in env.iter() { @@ -50,17 +69,6 @@ pub fn nu(scope: &Scope, tag: impl Into) -> Result { let temp = std::env::temp_dir(); nu_dict.insert_value("temp-dir", UntaggedValue::filepath(temp).into_value(&tag)); - let config = if let Some(path) = config_file { - path - } else { - nu_data::config::default_path()? - }; - - nu_dict.insert_value( - "config-path", - UntaggedValue::filepath(config).into_value(&tag), - ); - #[cfg(feature = "rustyline-support")] { let keybinding_path = nu_data::keybinding::keybinding_path()?; @@ -70,13 +78,6 @@ pub fn nu(scope: &Scope, tag: impl Into) -> Result { ); } - let config: Box = Box::new(nu_data::config::NuConfig::new()); - let history = history_path(&config); - nu_dict.insert_value( - "history-path", - UntaggedValue::filepath(history).into_value(&tag), - ); - Ok(nu_dict.into_value()) } diff --git a/crates/nu-engine/src/evaluation_context.rs b/crates/nu-engine/src/evaluation_context.rs index bf33b897..7a72ccfc 100644 --- a/crates/nu-engine/src/evaluation_context.rs +++ b/crates/nu-engine/src/evaluation_context.rs @@ -161,7 +161,7 @@ impl EvaluationContext { }) .transpose()?; - let tag = config::cfg_path_to_scope_tag(cfg_path); + let tag = config::cfg_path_to_scope_tag(cfg_path.get_path()); self.scope.enter_scope_with_tag(tag); self.scope.add_env(cfg.env_map()); @@ -188,30 +188,8 @@ impl EvaluationContext { /// If an error occurs while reloading the config: /// The config is not reloaded /// The error is returned - pub fn reload_config(&self, cfg_path: &ConfigPath) -> Result<(), ShellError> { - trace!("Reloading cfg {:?}", cfg_path); - - let mut configs = self.configs.lock(); - let cfg = match cfg_path { - ConfigPath::Global(path) => { - configs.global_config.iter_mut().find(|cfg| &cfg.file_path == path).ok_or_else(|| - ShellError::labeled_error( - &format!("Error reloading global config with path of {}. No such global config present.", path.display()), - "Config path error", - Span::unknown(), - ) - )? - } - ConfigPath::Local(path) => { - configs.local_configs.iter_mut().find(|cfg| &cfg.file_path == path).ok_or_else(|| - ShellError::labeled_error( - &format!("Error reloading local config with path of {}. No such local config present.", path.display()), - "Config path error", - Span::unknown(), - ) - )? - } - }; + pub fn reload_config(&self, cfg: &mut NuConfig) -> Result<(), ShellError> { + trace!("Reloading cfg {:?}", cfg.file_path); cfg.reload(); @@ -244,7 +222,7 @@ impl EvaluationContext { }) .transpose()?; - let tag = config::cfg_path_to_scope_tag(cfg_path); + let tag = config::cfg_path_to_scope_tag(&cfg.file_path); let mut frame = ScopeFrame::with_tag(tag.clone()); frame.env = cfg.env_map(); @@ -265,7 +243,7 @@ impl EvaluationContext { pub fn unload_config(&self, cfg_path: &ConfigPath) { trace!("UnLoading cfg {:?}", cfg_path); - let tag = config::cfg_path_to_scope_tag(cfg_path); + let tag = config::cfg_path_to_scope_tag(cfg_path.get_path()); //Run exitscripts with scope frame and cfg still applied if let Some(scripts) = self.scope.get_exitscripts_of_frame_with_tag(&tag) { diff --git a/crates/nu-test-support/src/fs.rs b/crates/nu-test-support/src/fs.rs index 170f971d..bf7d87df 100644 --- a/crates/nu-test-support/src/fs.rs +++ b/crates/nu-test-support/src/fs.rs @@ -45,7 +45,7 @@ impl From for PathBuf { } pub struct AbsolutePath { - inner: PathBuf, + pub inner: PathBuf, } impl AbsolutePath {