mirror of
https://github.com/nushell/nushell.git
synced 2025-03-26 23:36:20 +01:00
Add export-env
command (#6355)
* WIP Start export-env * Add missing file * Do not modify the parser Let's leave that for later * Enable tests for export-env; Fmt
This commit is contained in:
parent
529c98085a
commit
5a56d47f25
@ -3,9 +3,9 @@ use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportEnv;
|
||||
pub struct ExportEnvModule;
|
||||
|
||||
impl Command for ExportEnv {
|
||||
impl Command for ExportEnvModule {
|
||||
fn name(&self) -> &str {
|
||||
"export env"
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ pub use export::ExportCommand;
|
||||
pub use export_alias::ExportAlias;
|
||||
pub use export_def::ExportDef;
|
||||
pub use export_def_env::ExportDefEnv;
|
||||
pub use export_env::ExportEnv;
|
||||
pub use export_env::ExportEnvModule;
|
||||
pub use export_extern::ExportExtern;
|
||||
pub use export_use::ExportUse;
|
||||
pub use extern_::Extern;
|
||||
|
@ -40,7 +40,7 @@ pub fn create_default_context() -> EngineState {
|
||||
ExportCommand,
|
||||
ExportDef,
|
||||
ExportDefEnv,
|
||||
ExportEnv,
|
||||
ExportEnvModule,
|
||||
ExportExtern,
|
||||
ExportUse,
|
||||
Extern,
|
||||
@ -352,6 +352,7 @@ pub fn create_default_context() -> EngineState {
|
||||
// Env
|
||||
bind_command! {
|
||||
Env,
|
||||
ExportEnv,
|
||||
LetEnv,
|
||||
LoadEnv,
|
||||
WithEnv,
|
||||
|
74
crates/nu-command/src/env/export_env.rs
vendored
Normal file
74
crates/nu-command/src/env/export_env.rs
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
use nu_engine::{eval_block, redirect_env, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, Signature, Span, SyntaxShape, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportEnv;
|
||||
|
||||
impl Command for ExportEnv {
|
||||
fn name(&self) -> &str {
|
||||
"export-env"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("export-env")
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![])),
|
||||
"the block to run to set the environment",
|
||||
)
|
||||
.category(Category::Env)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Run a block and preserve its environment in a current scope."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
caller_stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
let capture_block: CaptureBlock = call.req(engine_state, caller_stack, 0)?;
|
||||
let block = engine_state.get_block(capture_block.block_id);
|
||||
let mut callee_stack = caller_stack.captures_to_stack(&capture_block.captures);
|
||||
|
||||
let _ = eval_block(
|
||||
engine_state,
|
||||
&mut callee_stack,
|
||||
block,
|
||||
input,
|
||||
call.redirect_stdout,
|
||||
call.redirect_stderr,
|
||||
);
|
||||
|
||||
redirect_env(engine_state, caller_stack, &callee_stack);
|
||||
|
||||
Ok(PipelineData::new(call.head))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Set an environment",
|
||||
example: r#"export-env { let-env SPAM = 'eggs' }; $env.SPAM"#,
|
||||
result: Some(Value::string("eggs", Span::test_data())),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(ExportEnv {})
|
||||
}
|
||||
}
|
2
crates/nu-command/src/env/mod.rs
vendored
2
crates/nu-command/src/env/mod.rs
vendored
@ -1,5 +1,6 @@
|
||||
mod config;
|
||||
mod env_command;
|
||||
mod export_env;
|
||||
mod let_env;
|
||||
mod load_env;
|
||||
mod with_env;
|
||||
@ -9,6 +10,7 @@ pub use config::ConfigMeta;
|
||||
pub use config::ConfigNu;
|
||||
pub use config::ConfigReset;
|
||||
pub use env_command::Env;
|
||||
pub use export_env::ExportEnv;
|
||||
pub use let_env::LetEnv;
|
||||
pub use load_env::LoadEnv;
|
||||
pub use with_env::WithEnv;
|
||||
|
@ -13,8 +13,8 @@ use crate::To;
|
||||
|
||||
#[cfg(test)]
|
||||
use super::{
|
||||
Ansi, Date, From, If, Into, Math, Path, Random, Split, SplitColumn, SplitRow, Str, StrCollect,
|
||||
StrLength, StrReplace, Url, Wrap,
|
||||
Ansi, Date, From, If, Into, LetEnv, Math, Path, Random, Split, SplitColumn, SplitRow, Str,
|
||||
StrCollect, StrLength, StrReplace, Url, Wrap,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@ -47,6 +47,7 @@ pub fn test_examples(cmd: impl Command + 'static) {
|
||||
working_set.add_decl(Box::new(Url));
|
||||
working_set.add_decl(Box::new(Ansi));
|
||||
working_set.add_decl(Box::new(Wrap));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
|
||||
use super::Echo;
|
||||
working_set.add_decl(Box::new(Echo));
|
||||
|
@ -159,20 +159,7 @@ pub fn eval_call(
|
||||
);
|
||||
|
||||
if block.redirect_env {
|
||||
let caller_env_vars = caller_stack.get_env_var_names(engine_state);
|
||||
|
||||
// remove env vars that are present in the caller but not in the callee
|
||||
// (the callee hid them)
|
||||
for var in caller_env_vars.iter() {
|
||||
if !callee_stack.has_env_var(engine_state, var) {
|
||||
caller_stack.remove_env_var(engine_state, var);
|
||||
}
|
||||
}
|
||||
|
||||
// add new env vars from callee to caller
|
||||
for (var, value) in callee_stack.get_stack_env_vars() {
|
||||
caller_stack.add_env_var(var, value);
|
||||
}
|
||||
redirect_env(engine_state, caller_stack, &callee_stack);
|
||||
}
|
||||
|
||||
result
|
||||
@ -184,6 +171,24 @@ pub fn eval_call(
|
||||
}
|
||||
}
|
||||
|
||||
/// Redirect the environment from callee to the caller.
|
||||
pub fn redirect_env(engine_state: &EngineState, caller_stack: &mut Stack, callee_stack: &Stack) {
|
||||
let caller_env_vars = caller_stack.get_env_var_names(engine_state);
|
||||
|
||||
// remove env vars that are present in the caller but not in the callee
|
||||
// (the callee hid them)
|
||||
for var in caller_env_vars.iter() {
|
||||
if !callee_stack.has_env_var(engine_state, var) {
|
||||
caller_stack.remove_env_var(engine_state, var);
|
||||
}
|
||||
}
|
||||
|
||||
// add new env vars from callee to caller
|
||||
for (var, value) in callee_stack.get_stack_env_vars() {
|
||||
caller_stack.add_env_var(var, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Eval extarnal expression
|
||||
///
|
||||
/// It returns PipelineData with a boolean flag, indicate that if the external runs to failed.
|
||||
|
@ -11,6 +11,6 @@ pub use documentation::get_full_help;
|
||||
pub use env::*;
|
||||
pub use eval::{
|
||||
eval_block, eval_call, eval_expression, eval_expression_with_input, eval_operator,
|
||||
eval_subexpression, eval_variable,
|
||||
eval_subexpression, eval_variable, redirect_env,
|
||||
};
|
||||
pub use glob_from::glob_from;
|
||||
|
Loading…
Reference in New Issue
Block a user