diff --git a/crates/nu-cli/src/env/directory_specific_environment.rs b/crates/nu-cli/src/env/directory_specific_environment.rs index 0705bb064e..74ea07da17 100644 --- a/crates/nu-cli/src/env/directory_specific_environment.rs +++ b/crates/nu-cli/src/env/directory_specific_environment.rs @@ -1,42 +1,59 @@ -use indexmap::indexmap; -use std::{ - collections::HashMap, - fmt::Debug, - path::PathBuf, -}; - +use indexmap::IndexMap; +use nu_protocol::{Primitive, UntaggedValue, Value}; +use std::{fmt::Debug, path::PathBuf}; #[derive(Debug, Default)] pub struct DirectorySpecificEnvironment { pub whitelisted_directories: Vec, //Directory -> Env key. If an environment var has been added from a .nu in a directory, we track it here so we can remove it when the user leaves the directory. - pub added_env_vars: HashMap>, + pub added_env_vars: IndexMap>, //Directory -> (env_key, value). If a .nu overwrites some existing environment variables, they are added here so that they can be restored later. - pub overwritten_env_values: HashMap>, + pub overwritten_env_values: IndexMap>, } impl DirectorySpecificEnvironment { - pub fn new(whitelisted_directories: Vec) -> DirectorySpecificEnvironment { + pub fn new(whitelisted_directories: Option) -> DirectorySpecificEnvironment { + let mut whitelisted_directories = if let Some(Value { + value: UntaggedValue::Table(ref wrapped_directories), + tag: _, + }) = whitelisted_directories + { + wrapped_directories + .iter() + .fold(vec![], |mut directories, dirval| { + if let Value { + value: UntaggedValue::Primitive(Primitive::String(ref dir)), + tag: _, + } = dirval + { + directories.push(PathBuf::from(&dir)); + } + directories + }) + } else { + vec![] + }; + whitelisted_directories.sort(); + DirectorySpecificEnvironment { whitelisted_directories, - added_env_vars: HashMap::new(), - overwritten_env_values: HashMap::new(), + added_env_vars: IndexMap::new(), + overwritten_env_values: IndexMap::new(), } } - pub fn env_vars_to_add(&mut self) -> std::io::Result> { + pub fn env_vars_to_add(&mut self) -> std::io::Result> { let current_dir = std::env::current_dir()?; - let mut vars_to_add = HashMap::new(); + let mut vars_to_add = IndexMap::new(); for dir in &self.whitelisted_directories { //Start in the current directory, then traverse towards the root with working_dir to see if we are in a subdirectory of a valid directory. let mut working_dir = Some(current_dir.as_path()); while let Some(wdir) = working_dir { if wdir == dir.as_path() { - //Read the .nu file and parse it into a nice map let toml_doc = std::fs::read_to_string(wdir.join(".nu").as_path())? .parse::() @@ -87,4 +104,4 @@ impl DirectorySpecificEnvironment { Ok(vars_to_delete) } -} \ No newline at end of file +} diff --git a/crates/nu-cli/src/env/environment.rs b/crates/nu-cli/src/env/environment.rs index 8106f0e518..0e987e06d1 100644 --- a/crates/nu-cli/src/env/environment.rs +++ b/crates/nu-cli/src/env/environment.rs @@ -1,9 +1,9 @@ use crate::data::config::Conf; use crate::env::directory_specific_environment::*; use indexmap::{indexmap, IndexSet}; -use nu_protocol::{Primitive, UntaggedValue, Value}; +use nu_protocol::{UntaggedValue, Value}; use std::ffi::OsString; -use std::{fmt::Debug, path::PathBuf}; +use std::fmt::Debug; pub trait Env: Debug + Send { fn env(&self) -> Option; @@ -43,7 +43,7 @@ impl Environment { Environment { environment_vars: None, path_vars: None, - direnv: DirectorySpecificEnvironment::new(vec![]), + direnv: DirectorySpecificEnvironment::new(None), } } @@ -51,28 +51,10 @@ impl Environment { let env = configuration.env(); let path = configuration.path(); - let mut directories = vec![]; - if let Some(Value { - value: UntaggedValue::Table(ref directories_as_values), - tag: _, - }) = configuration.direnv_whitelist() - { - for dirval in directories_as_values { - if let Value { - value: UntaggedValue::Primitive(Primitive::String(ref dir)), - tag: _, - } = dirval - { - directories.push(PathBuf::from(&dir)); - } - } - }; - directories.sort(); - Environment { environment_vars: env, path_vars: path, - direnv: DirectorySpecificEnvironment::new(directories), + direnv: DirectorySpecificEnvironment::new(configuration.direnv_whitelist()), } }