Add unlet_env command (#3629)

* Add ability to remove env variables

Signed-off-by: nathom <nathanthomas707@gmail.com>

* Implement unlet_env command

Signed-off-by: nathom <nathanthomas707@gmail.com>

* Update parameter description

Signed-off-by: nathom <nathanthomas707@gmail.com>

* Migrate to new filestructure

Signed-off-by: nathom <nathanthomas707@gmail.com>

* Added tests for unlet-env

Signed-off-by: nathom <nathanthomas707@gmail.com>

* Formatting

Signed-off-by: nathom <nathanthomas707@gmail.com>
This commit is contained in:
Nathan Thomas 2021-06-18 20:00:07 -07:00 committed by GitHub
parent 26899bc0f0
commit 9e39284de9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 0 deletions

View file

@ -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;

View file

@ -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<String>,
}
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<ActionStream, ShellError> {
unlet_env(args)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Remove the environment variable named FOO.",
example: "unlet-env FOO",
result: None,
}]
}
}
pub fn unlet_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
let ctx = &args.context;
let name: Tagged<String> = 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())
}

View file

@ -13,6 +13,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(NuPlugin),
whole_stream_command(Let),
whole_stream_command(LetEnv),
whole_stream_command(UnletEnv),
whole_stream_command(LoadEnv),
whole_stream_command(Def),
whole_stream_command(Source),

View file

@ -239,6 +239,15 @@ impl Scope {
}
}
pub fn remove_env_var(&self, name: impl Into<String>) -> Option<String> {
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<String, String>) {
if let Some(frame) = self.frames.lock().last_mut() {
frame.env.extend(env_vars)

View file

@ -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!(