mirror of
https://github.com/nushell/nushell.git
synced 2024-11-07 17:14:23 +01:00
unify the run
functions of all
and any
(#8578)
# Description
this pr reduces duplication by making `any` and `all` commands use [one
function](66ad83c15c/crates/nu-command/src/filters/any.rs (LL63-L65C28)
)
This commit is contained in:
parent
05ff7a9925
commit
403bf1a734
@ -1,11 +1,11 @@
|
||||
use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Closure, Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||
Value,
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
use super::utils;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct All;
|
||||
|
||||
@ -60,9 +60,7 @@ impl Command for All {
|
||||
},
|
||||
]
|
||||
}
|
||||
// This is almost entirely a copy-paste of `any`'s run(), so make sure any changes to this are
|
||||
// reflected in the other!! (Or, you could figure out a way for both of them to use
|
||||
// the same function...)
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
@ -70,51 +68,7 @@ impl Command for All {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
let block_id = capture_block.block_id;
|
||||
|
||||
let block = engine_state.get_block(block_id);
|
||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let engine_state = engine_state.clone();
|
||||
|
||||
for value in input.into_interruptible_iter(ctrlc) {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||
|
||||
if let Some(var_id) = var_id {
|
||||
stack.add_var(var_id, value.clone());
|
||||
}
|
||||
|
||||
let eval = eval_block(
|
||||
&engine_state,
|
||||
&mut stack,
|
||||
block,
|
||||
value.into_pipeline_data(),
|
||||
call.redirect_stdout,
|
||||
call.redirect_stderr,
|
||||
);
|
||||
match eval {
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
Ok(pipeline_data) => {
|
||||
if !pipeline_data.into_value(span).is_true() {
|
||||
return Ok(Value::Bool { val: false, span }.into_pipeline_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Value::Bool { val: true, span }.into_pipeline_data())
|
||||
utils::boolean_fold(engine_state, stack, call, input, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Closure, Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||
Value,
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
use super::utils;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Any;
|
||||
|
||||
@ -60,9 +60,7 @@ impl Command for Any {
|
||||
},
|
||||
]
|
||||
}
|
||||
// This is almost entirely a copy-paste of `all`'s run(), so make sure any changes to this are
|
||||
// reflected in the other!! Or, you could figure out a way for both of them to use
|
||||
// the same function...
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
@ -70,51 +68,7 @@ impl Command for Any {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
let block_id = capture_block.block_id;
|
||||
|
||||
let block = engine_state.get_block(block_id);
|
||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let engine_state = engine_state.clone();
|
||||
|
||||
for value in input.into_interruptible_iter(ctrlc) {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||
|
||||
if let Some(var_id) = var_id {
|
||||
stack.add_var(var_id, value.clone());
|
||||
}
|
||||
|
||||
let eval = eval_block(
|
||||
&engine_state,
|
||||
&mut stack,
|
||||
block,
|
||||
value.into_pipeline_data(),
|
||||
call.redirect_stdout,
|
||||
call.redirect_stderr,
|
||||
);
|
||||
match eval {
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
Ok(pipeline_data) => {
|
||||
if pipeline_data.into_value(span).is_true() {
|
||||
return Ok(Value::Bool { val: true, span }.into_pipeline_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Value::Bool { val: false, span }.into_pipeline_data())
|
||||
utils::boolean_fold(engine_state, stack, call, input, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
use nu_protocol::{ShellError, Span};
|
||||
use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Closure, EngineState, Stack},
|
||||
IntoPipelineData, PipelineData, ShellError, Span, Value,
|
||||
};
|
||||
|
||||
pub fn chain_error_with_input(
|
||||
error_source: ShellError,
|
||||
@ -9,3 +14,66 @@ pub fn chain_error_with_input(
|
||||
}
|
||||
error_source
|
||||
}
|
||||
|
||||
pub fn boolean_fold(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
accumulator: bool,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
let block_id = capture_block.block_id;
|
||||
|
||||
let block = engine_state.get_block(block_id);
|
||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let engine_state = engine_state.clone();
|
||||
|
||||
for value in input.into_interruptible_iter(ctrlc) {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||
|
||||
if let Some(var_id) = var_id {
|
||||
stack.add_var(var_id, value.clone());
|
||||
}
|
||||
|
||||
let eval = eval_block(
|
||||
&engine_state,
|
||||
&mut stack,
|
||||
block,
|
||||
value.into_pipeline_data(),
|
||||
call.redirect_stdout,
|
||||
call.redirect_stderr,
|
||||
);
|
||||
match eval {
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
Ok(pipeline_data) => {
|
||||
if pipeline_data.into_value(span).is_true() == accumulator {
|
||||
return Ok(Value::Bool {
|
||||
val: accumulator,
|
||||
span,
|
||||
}
|
||||
.into_pipeline_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Bool {
|
||||
val: !accumulator,
|
||||
span,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user