mirror of
https://github.com/nushell/nushell.git
synced 2025-04-01 03:36:53 +02: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::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Closure, Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||||
Value,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::utils;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct All;
|
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(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
@ -70,51 +68,7 @@ impl Command for All {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
utils::boolean_fold(engine_state, stack, call, input, false)
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Closure, Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||||
Value,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::utils;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Any;
|
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(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
@ -70,51 +68,7 @@ impl Command for Any {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
utils::boolean_fold(engine_state, stack, call, input, true)
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
pub fn chain_error_with_input(
|
||||||
error_source: ShellError,
|
error_source: ShellError,
|
||||||
@ -9,3 +14,66 @@ pub fn chain_error_with_input(
|
|||||||
}
|
}
|
||||||
error_source
|
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