From 9e39284de9fc202295cbeeb2044f4ca5831186a5 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Fri, 18 Jun 2021 20:00:07 -0700 Subject: [PATCH] Add `unlet_env` command (#3629) * Add ability to remove env variables Signed-off-by: nathom * Implement unlet_env command Signed-off-by: nathom * Update parameter description Signed-off-by: nathom * Migrate to new filestructure Signed-off-by: nathom * Added tests for unlet-env Signed-off-by: nathom * Formatting Signed-off-by: nathom --- crates/nu-command/src/commands/env/mod.rs | 2 + .../nu-command/src/commands/env/unlet_env.rs | 59 +++++++++++++++++++ crates/nu-command/src/default_context.rs | 1 + crates/nu-engine/src/evaluate/scope.rs | 9 +++ tests/shell/pipeline/commands/internal.rs | 25 ++++++++ 5 files changed, 96 insertions(+) create mode 100644 crates/nu-command/src/commands/env/unlet_env.rs diff --git a/crates/nu-command/src/commands/env/mod.rs b/crates/nu-command/src/commands/env/mod.rs index 33f99fd59..26b343ac5 100644 --- a/crates/nu-command/src/commands/env/mod.rs +++ b/crates/nu-command/src/commands/env/mod.rs @@ -3,6 +3,7 @@ mod autoenv_trust; mod autoenv_untrust; mod let_env; mod load_env; +mod unlet_env; mod with_env; pub use autoenv::Autoenv; @@ -10,4 +11,5 @@ pub use autoenv_trust::AutoenvTrust; pub use autoenv_untrust::AutoenvUntrust; pub use let_env::LetEnv; pub use load_env::LoadEnv; +pub use unlet_env::UnletEnv; pub use with_env::WithEnv; diff --git a/crates/nu-command/src/commands/env/unlet_env.rs b/crates/nu-command/src/commands/env/unlet_env.rs new file mode 100644 index 000000000..d639f8803 --- /dev/null +++ b/crates/nu-command/src/commands/env/unlet_env.rs @@ -0,0 +1,59 @@ +use crate::prelude::*; +use nu_engine::WholeStreamCommand; + +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; +use nu_source::Tagged; + +pub struct UnletEnv; + +#[derive(Deserialize)] +pub struct UnletEnvArgs { + pub name: Tagged, +} + +impl WholeStreamCommand for UnletEnv { + fn name(&self) -> &str { + "unlet-env" + } + + fn signature(&self) -> Signature { + Signature::build("unlet-env").required( + "name", + SyntaxShape::String, + "the name of the environment variable", + ) + } + + fn usage(&self) -> &str { + "Delete an environment variable." + } + + fn run_with_actions(&self, args: CommandArgs) -> Result { + unlet_env(args) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Remove the environment variable named FOO.", + example: "unlet-env FOO", + result: None, + }] + } +} + +pub fn unlet_env(args: CommandArgs) -> Result { + let ctx = &args.context; + + let name: Tagged = args.req(0)?; + + if ctx.scope.remove_env_var(&name.item) == None { + return Err(ShellError::labeled_error( + "Not an environment variable. Run `echo $nu.env` to view the available variables.", + "not an environment variable", + name.span(), + )); + } + + Ok(ActionStream::empty()) +} diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index e635ae9c7..0b2f2fa68 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -13,6 +13,7 @@ pub fn create_default_context(interactive: bool) -> Result) -> Option { + if let Some(frame) = self.frames.lock().last_mut() { + if let Some(val) = frame.env.remove_entry(&name.into()) { + return Some(val.1); + } + } + None + } + pub fn add_env(&self, env_vars: IndexMap) { if let Some(frame) = self.frames.lock().last_mut() { frame.env.extend(env_vars) diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index ab8deee45..87fa0e0d1 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -411,6 +411,31 @@ fn let_env_variable() { assert_eq!(actual.out, "hello world"); } +#[test] +fn unlet_env_variable() { + let actual = nu!( + cwd: ".", + r#" + let-env TEST_VAR = "hello world" + unlet-env TEST_VAR + echo $nu.env.TEST_VAR + "# + ); + assert!(actual.err.contains("did you mean")); +} + +#[test] +fn unlet_nonexistent_variable() { + let actual = nu!( + cwd: ".", + r#" + unlet-env NONEXISTENT_VARIABLE + " + ); + + assert!(actual.err.contains("did you mean")); +} + #[test] fn let_env_doesnt_leak() { let actual = nu!(