forked from extern/nushell
Split blocks and closures (#7075)
* Split closures and blocks * Tests mostly working * finish last fixes, passes all tests * fmt
This commit is contained in:
parent
921a66554e
commit
63433f1bc8
@ -29,7 +29,7 @@ fn get_prompt_string(
|
|||||||
stack
|
stack
|
||||||
.get_env_var(engine_state, prompt)
|
.get_env_var(engine_state, prompt)
|
||||||
.and_then(|v| match v {
|
.and_then(|v| match v {
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val: block_id,
|
val: block_id,
|
||||||
captures,
|
captures,
|
||||||
..
|
..
|
||||||
@ -59,6 +59,31 @@ fn get_prompt_string(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Value::Block { val: block_id, .. } => {
|
||||||
|
let block = engine_state.get_block(block_id);
|
||||||
|
// Use eval_subexpression to force a redirection of output, so we can use everything in prompt
|
||||||
|
let ret_val = eval_subexpression(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
block,
|
||||||
|
PipelineData::new(Span::new(0, 0)), // Don't try this at home, 0 span is ignored
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"get_prompt_string (block) {}:{}:{}",
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
column!()
|
||||||
|
);
|
||||||
|
|
||||||
|
match ret_val {
|
||||||
|
Ok(ret_val) => Some(ret_val),
|
||||||
|
Err(err) => {
|
||||||
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
report_error(&working_set, &err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Value::String { .. } => Some(PipelineData::Value(v.clone(), None)),
|
Value::String { .. } => Some(PipelineData::Value(v.clone(), None)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
@ -251,7 +251,7 @@ pub(crate) fn add_columnar_menu(
|
|||||||
Value::Nothing { .. } => {
|
Value::Nothing { .. } => {
|
||||||
Ok(line_editor.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar_menu))))
|
Ok(line_editor.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar_menu))))
|
||||||
}
|
}
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val,
|
val,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
@ -337,7 +337,7 @@ pub(crate) fn add_list_menu(
|
|||||||
Value::Nothing { .. } => {
|
Value::Nothing { .. } => {
|
||||||
Ok(line_editor.with_menu(ReedlineMenu::HistoryMenu(Box::new(list_menu))))
|
Ok(line_editor.with_menu(ReedlineMenu::HistoryMenu(Box::new(list_menu))))
|
||||||
}
|
}
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val,
|
val,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
@ -459,7 +459,7 @@ pub(crate) fn add_description_menu(
|
|||||||
completer,
|
completer,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val,
|
val,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
@ -477,7 +477,7 @@ pub(crate) fn add_description_menu(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::UnsupportedConfigValue(
|
_ => Err(ShellError::UnsupportedConfigValue(
|
||||||
"block or omitted value".to_string(),
|
"closure or omitted value".to_string(),
|
||||||
menu.source.into_abbreviated_string(config),
|
menu.source.into_abbreviated_string(config),
|
||||||
menu.source.span()?,
|
menu.source.span()?,
|
||||||
)),
|
)),
|
||||||
|
@ -743,6 +743,11 @@ pub fn eval_hook(
|
|||||||
val: block_id,
|
val: block_id,
|
||||||
span: block_span,
|
span: block_span,
|
||||||
..
|
..
|
||||||
|
}
|
||||||
|
| Value::Closure {
|
||||||
|
val: block_id,
|
||||||
|
span: block_span,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
match run_hook_block(
|
match run_hook_block(
|
||||||
engine_state,
|
engine_state,
|
||||||
@ -854,6 +859,20 @@ pub fn eval_hook(
|
|||||||
block_span,
|
block_span,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
Value::Closure {
|
||||||
|
val: block_id,
|
||||||
|
span: block_span,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
run_hook_block(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
block_id,
|
||||||
|
input,
|
||||||
|
arguments,
|
||||||
|
block_span,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
return Err(ShellError::UnsupportedConfigValue(
|
return Err(ShellError::UnsupportedConfigValue(
|
||||||
"block or string".to_string(),
|
"block or string".to_string(),
|
||||||
@ -881,6 +900,23 @@ pub fn eval_hook(
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Value::Closure {
|
||||||
|
val: block_id,
|
||||||
|
span: block_span,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
output = PipelineData::Value(
|
||||||
|
run_hook_block(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
*block_id,
|
||||||
|
input,
|
||||||
|
arguments,
|
||||||
|
*block_span,
|
||||||
|
)?,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
return Err(ShellError::UnsupportedConfigValue(
|
return Err(ShellError::UnsupportedConfigValue(
|
||||||
"block, record, or list of records".into(),
|
"block, record, or list of records".into(),
|
||||||
|
@ -372,6 +372,7 @@ fn find_matching_block_end_in_expr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expr::Block(block_id)
|
Expr::Block(block_id)
|
||||||
|
| Expr::Closure(block_id)
|
||||||
| Expr::RowCondition(block_id)
|
| Expr::RowCondition(block_id)
|
||||||
| Expr::Subexpression(block_id) => {
|
| Expr::Subexpression(block_id) => {
|
||||||
if expr_last == global_cursor_offset {
|
if expr_last == global_cursor_offset {
|
||||||
|
@ -228,7 +228,7 @@ mod test {
|
|||||||
vals: vec![Value::Bool { val: true, span }],
|
vals: vec![Value::Bool { val: true, span }],
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val: 0,
|
val: 0,
|
||||||
captures: HashMap::new(),
|
captures: HashMap::new(),
|
||||||
span,
|
span,
|
||||||
|
@ -19,11 +19,7 @@ impl Command for Def {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required("def_name", SyntaxShape::String, "definition name")
|
.required("def_name", SyntaxShape::String, "definition name")
|
||||||
.required("params", SyntaxShape::Signature, "parameters")
|
.required("params", SyntaxShape::Signature, "parameters")
|
||||||
.required(
|
.required("body", SyntaxShape::Closure(None), "body of the definition")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"body of the definition",
|
|
||||||
)
|
|
||||||
.category(Category::Core)
|
.category(Category::Core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,11 +19,7 @@ impl Command for DefEnv {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required("def_name", SyntaxShape::String, "definition name")
|
.required("def_name", SyntaxShape::String, "definition name")
|
||||||
.required("params", SyntaxShape::Signature, "parameters")
|
.required("params", SyntaxShape::Signature, "parameters")
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "body of the definition")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"body of the definition",
|
|
||||||
)
|
|
||||||
.category(Category::Core)
|
.category(Category::Core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, ListStream, PipelineData, RawStream, ShellError, Signature, SyntaxShape,
|
Category, Example, ListStream, PipelineData, RawStream, ShellError, Signature, SyntaxShape,
|
||||||
Type, Value,
|
Type, Value,
|
||||||
@ -20,8 +20,8 @@ impl Command for Do {
|
|||||||
|
|
||||||
fn signature(&self) -> nu_protocol::Signature {
|
fn signature(&self) -> nu_protocol::Signature {
|
||||||
Signature::build("do")
|
Signature::build("do")
|
||||||
|
.required("closure", SyntaxShape::Any, "the closure to run")
|
||||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||||
.required("block", SyntaxShape::Any, "the block to run")
|
|
||||||
.switch(
|
.switch(
|
||||||
"ignore-errors",
|
"ignore-errors",
|
||||||
"ignore shell errors as the block runs",
|
"ignore shell errors as the block runs",
|
||||||
@ -43,7 +43,7 @@ impl Command for Do {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
|
let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
|
||||||
let ignore_errors = call.has_flag("ignore-errors");
|
let ignore_errors = call.has_flag("ignore-errors");
|
||||||
let capture_errors = call.has_flag("capture-errors");
|
let capture_errors = call.has_flag("capture-errors");
|
||||||
|
@ -19,11 +19,7 @@ impl Command for ExportDef {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required("name", SyntaxShape::String, "definition name")
|
.required("name", SyntaxShape::String, "definition name")
|
||||||
.required("params", SyntaxShape::Signature, "parameters")
|
.required("params", SyntaxShape::Signature, "parameters")
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "body of the definition")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"body of the definition",
|
|
||||||
)
|
|
||||||
.category(Category::Core)
|
.category(Category::Core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,11 +19,7 @@ impl Command for ExportDefEnv {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required("name", SyntaxShape::String, "definition name")
|
.required("name", SyntaxShape::String, "definition name")
|
||||||
.required("params", SyntaxShape::Signature, "parameters")
|
.required("params", SyntaxShape::Signature, "parameters")
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "body of the definition")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"body of the definition",
|
|
||||||
)
|
|
||||||
.category(Category::Core)
|
.category(Category::Core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, eval_expression, CallExt};
|
use nu_engine::{eval_block, eval_expression, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
@ -31,11 +31,7 @@ impl Command for For {
|
|||||||
SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Any)),
|
SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Any)),
|
||||||
"range of the loop",
|
"range of the loop",
|
||||||
)
|
)
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "the block to run")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"the block to run",
|
|
||||||
)
|
|
||||||
.switch(
|
.switch(
|
||||||
"numbered",
|
"numbered",
|
||||||
"returned a numbered item ($it.index and $it.item)",
|
"returned a numbered item ($it.index and $it.item)",
|
||||||
@ -75,7 +71,7 @@ impl Command for For {
|
|||||||
.expect("internal error: missing keyword");
|
.expect("internal error: missing keyword");
|
||||||
let values = eval_expression(engine_state, stack, keyword_expr)?;
|
let values = eval_expression(engine_state, stack, keyword_expr)?;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 2)?;
|
let capture_block: Closure = call.req(engine_state, stack, 2)?;
|
||||||
|
|
||||||
let numbered = call.has_flag("numbered");
|
let numbered = call.has_flag("numbered");
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use nu_engine::{eval_block, eval_expression, eval_expression_with_input, CallExt};
|
use nu_engine::{eval_block, eval_expression, eval_expression_with_input, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Block, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, FromValue, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -23,7 +23,7 @@ impl Command for If {
|
|||||||
.required("cond", SyntaxShape::Expression, "condition to check")
|
.required("cond", SyntaxShape::Expression, "condition to check")
|
||||||
.required(
|
.required(
|
||||||
"then_block",
|
"then_block",
|
||||||
SyntaxShape::Block(Some(vec![])),
|
SyntaxShape::Block,
|
||||||
"block to run if check succeeds",
|
"block to run if check succeeds",
|
||||||
)
|
)
|
||||||
.optional(
|
.optional(
|
||||||
@ -51,7 +51,7 @@ impl Command for If {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let cond = call.positional_nth(0).expect("checked through parser");
|
let cond = call.positional_nth(0).expect("checked through parser");
|
||||||
let then_block: CaptureBlock = call.req(engine_state, stack, 1)?;
|
let then_block: Block = call.req(engine_state, stack, 1)?;
|
||||||
let else_case = call.positional_nth(2);
|
let else_case = call.positional_nth(2);
|
||||||
|
|
||||||
let result = eval_expression(engine_state, stack, cond)?;
|
let result = eval_expression(engine_state, stack, cond)?;
|
||||||
@ -59,10 +59,9 @@ impl Command for If {
|
|||||||
Value::Bool { val, .. } => {
|
Value::Bool { val, .. } => {
|
||||||
if *val {
|
if *val {
|
||||||
let block = engine_state.get_block(then_block.block_id);
|
let block = engine_state.get_block(then_block.block_id);
|
||||||
let mut stack = stack.captures_to_stack(&then_block.captures);
|
|
||||||
eval_block(
|
eval_block(
|
||||||
engine_state,
|
engine_state,
|
||||||
&mut stack,
|
stack,
|
||||||
block,
|
block,
|
||||||
input,
|
input,
|
||||||
call.redirect_stdout,
|
call.redirect_stdout,
|
||||||
@ -71,14 +70,10 @@ impl Command for If {
|
|||||||
} else if let Some(else_case) = else_case {
|
} else if let Some(else_case) = else_case {
|
||||||
if let Some(else_expr) = else_case.as_keyword() {
|
if let Some(else_expr) = else_case.as_keyword() {
|
||||||
if let Some(block_id) = else_expr.as_block() {
|
if let Some(block_id) = else_expr.as_block() {
|
||||||
let result = eval_expression(engine_state, stack, else_expr)?;
|
|
||||||
let else_block: CaptureBlock = FromValue::from_value(&result)?;
|
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&else_block.captures);
|
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
eval_block(
|
eval_block(
|
||||||
engine_state,
|
engine_state,
|
||||||
&mut stack,
|
stack,
|
||||||
block,
|
block,
|
||||||
input,
|
input,
|
||||||
call.redirect_stdout,
|
call.redirect_stdout,
|
||||||
|
@ -18,11 +18,7 @@ impl Command for Module {
|
|||||||
Signature::build("module")
|
Signature::build("module")
|
||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required("module_name", SyntaxShape::String, "module name")
|
.required("module_name", SyntaxShape::String, "module name")
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "body of the module")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"body of the module",
|
|
||||||
)
|
|
||||||
.category(Category::Core)
|
.category(Category::Core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ fn nu_value_to_string(value: Value, separator: &str, config: &Config) -> String
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(separator),
|
.join(separator),
|
||||||
Value::Block { val, .. } => format!("<Block {}>", val),
|
Value::Block { val, .. } => format!("<Block {}>", val),
|
||||||
|
Value::Closure { val, .. } => format!("<Closure {}>", val),
|
||||||
Value::Nothing { .. } => String::new(),
|
Value::Nothing { .. } => String::new(),
|
||||||
Value::Error { error } => format!("{:?}", error),
|
Value::Error { error } => format!("{:?}", error),
|
||||||
Value::Binary { val, .. } => format!("{:?}", val),
|
Value::Binary { val, .. } => format!("{:?}", val),
|
||||||
|
6
crates/nu-command/src/env/export_env.rs
vendored
6
crates/nu-command/src/env/export_env.rs
vendored
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, redirect_env, CallExt};
|
use nu_engine::{eval_block, redirect_env, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value,
|
Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ impl Command for ExportEnv {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"block",
|
||||||
SyntaxShape::Block(Some(vec![])),
|
SyntaxShape::Block,
|
||||||
"the block to run to set the environment",
|
"the block to run to set the environment",
|
||||||
)
|
)
|
||||||
.category(Category::Env)
|
.category(Category::Env)
|
||||||
@ -35,7 +35,7 @@ impl Command for ExportEnv {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, caller_stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, caller_stack, 0)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id);
|
let block = engine_state.get_block(capture_block.block_id);
|
||||||
let mut callee_stack = caller_stack.captures_to_stack(&capture_block.captures);
|
let mut callee_stack = caller_stack.captures_to_stack(&capture_block.captures);
|
||||||
|
|
||||||
|
6
crates/nu-command/src/env/with_env.rs
vendored
6
crates/nu-command/src/env/with_env.rs
vendored
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ impl Command for WithEnv {
|
|||||||
)
|
)
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"block",
|
||||||
SyntaxShape::Block(Some(vec![])),
|
SyntaxShape::Closure(None),
|
||||||
"the block to run once the variable is set",
|
"the block to run once the variable is set",
|
||||||
)
|
)
|
||||||
.category(Category::Env)
|
.category(Category::Env)
|
||||||
@ -80,7 +80,7 @@ fn with_env(
|
|||||||
// let external_redirection = args.call_info.args.external_redirection;
|
// let external_redirection = args.call_info.args.external_redirection;
|
||||||
let variable: Value = call.req(engine_state, stack, 0)?;
|
let variable: Value = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 1)?;
|
let capture_block: Closure = call.req(engine_state, stack, 1)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id);
|
let block = engine_state.get_block(capture_block.block_id);
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
|
|
||||||
|
@ -14,8 +14,6 @@ mod test_examples {
|
|||||||
};
|
};
|
||||||
use crate::To;
|
use crate::To;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nu_engine;
|
|
||||||
use nu_parser;
|
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Block,
|
ast::Block,
|
||||||
engine::{Command, EngineState, Stack, StateDelta, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateDelta, StateWorkingSet},
|
||||||
@ -95,7 +93,7 @@ mod test_examples {
|
|||||||
engine_state
|
engine_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_example_input_and_output_types_match_command_signature<'a>(
|
fn check_example_input_and_output_types_match_command_signature(
|
||||||
example: &Example,
|
example: &Example,
|
||||||
cwd: &PathBuf,
|
cwd: &PathBuf,
|
||||||
engine_state: &mut Box<EngineState>,
|
engine_state: &mut Box<EngineState>,
|
||||||
@ -108,7 +106,7 @@ mod test_examples {
|
|||||||
// Skip tests that don't have results to compare to
|
// Skip tests that don't have results to compare to
|
||||||
if let Some(example_output) = example.result.as_ref() {
|
if let Some(example_output) = example.result.as_ref() {
|
||||||
if let Some(example_input_type) =
|
if let Some(example_input_type) =
|
||||||
eval_pipeline_without_terminal_expression(example.example, &cwd, engine_state)
|
eval_pipeline_without_terminal_expression(example.example, cwd, engine_state)
|
||||||
{
|
{
|
||||||
let example_input_type = example_input_type.get_type();
|
let example_input_type = example_input_type.get_type();
|
||||||
let example_output_type = example_output.get_type();
|
let example_output_type = example_output.get_type();
|
||||||
@ -177,19 +175,18 @@ mod test_examples {
|
|||||||
|| example_matches_signature_via_vectorization_over_list
|
|| example_matches_signature_via_vectorization_over_list
|
||||||
|| example_matches_signature_via_cell_path_operation)
|
|| example_matches_signature_via_cell_path_operation)
|
||||||
{
|
{
|
||||||
assert!(
|
panic!(
|
||||||
false,
|
"The example `{}` demonstrates a transformation of type {:?} -> {:?}. \
|
||||||
"The example `{}` demonstrates a transformation of type {:?} -> {:?}. \
|
However, this does not match the declared signature: {:?}.{} \
|
||||||
However, this does not match the declared signature: {:?}.{} \
|
For this command, `vectorizes_over_list` is {} and `operates_on_cell_paths()` is {}.",
|
||||||
For this command, `vectorizes_over_list` is {} and `operates_on_cell_paths()` is {}.",
|
example.example,
|
||||||
example.example,
|
example_input_type,
|
||||||
example_input_type,
|
example_output_type,
|
||||||
example_output_type,
|
signature_input_output_types,
|
||||||
signature_input_output_types,
|
if signature_input_output_types.is_empty() { " (Did you forget to declare the input and output types for the command?)" } else { "" },
|
||||||
if signature_input_output_types.is_empty() { " (Did you forget to declare the input and output types for the command?)" } else { "" },
|
signature_vectorizes_over_list,
|
||||||
signature_vectorizes_over_list,
|
signature_operates_on_cell_paths
|
||||||
signature_operates_on_cell_paths
|
);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -217,7 +214,7 @@ mod test_examples {
|
|||||||
.expect("Error merging environment");
|
.expect("Error merging environment");
|
||||||
|
|
||||||
let empty_input = PipelineData::new(Span::test_data());
|
let empty_input = PipelineData::new(Span::test_data());
|
||||||
let result = eval(example.example, empty_input, &cwd, engine_state);
|
let result = eval(example.example, empty_input, cwd, engine_state);
|
||||||
|
|
||||||
// Note. Value implements PartialEq for Bool, Int, Float, String and Block
|
// Note. Value implements PartialEq for Bool, Int, Float, String and Block
|
||||||
// If the command you are testing requires to compare another case, then
|
// If the command you are testing requires to compare another case, then
|
||||||
@ -267,8 +264,8 @@ mod test_examples {
|
|||||||
eval_block(block, input, cwd, engine_state, delta)
|
eval_block(block, input, cwd, engine_state, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(contents: &str, engine_state: &Box<EngineState>) -> (Block, StateDelta) {
|
fn parse(contents: &str, engine_state: &EngineState) -> (Block, StateDelta) {
|
||||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
let (output, err) =
|
let (output, err) =
|
||||||
nu_parser::parse(&mut working_set, None, contents.as_bytes(), false, &[]);
|
nu_parser::parse(&mut working_set, None, contents.as_bytes(), false, &[]);
|
||||||
|
|
||||||
@ -300,7 +297,7 @@ mod test_examples {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
match nu_engine::eval_block(&engine_state, &mut stack, &block, input, true, true) {
|
match nu_engine::eval_block(engine_state, &mut stack, &block, input, true, true) {
|
||||||
Err(err) => panic!("test eval error in `{}`: {:?}", "TODO", err),
|
Err(err) => panic!("test eval error in `{}`: {:?}", "TODO", err),
|
||||||
Ok(result) => result.into_value(Span::test_data()),
|
Ok(result) => result.into_value(Span::test_data()),
|
||||||
}
|
}
|
||||||
@ -319,7 +316,7 @@ mod test_examples {
|
|||||||
|
|
||||||
if !block.pipelines[0].expressions.is_empty() {
|
if !block.pipelines[0].expressions.is_empty() {
|
||||||
let empty_input = PipelineData::new(Span::test_data());
|
let empty_input = PipelineData::new(Span::test_data());
|
||||||
Some(eval_block(block, empty_input, &cwd, engine_state, delta))
|
Some(eval_block(block, empty_input, cwd, engine_state, delta))
|
||||||
} else {
|
} else {
|
||||||
Some(Value::nothing(Span::test_data()))
|
Some(Value::nothing(Span::test_data()))
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::time::Duration;
|
|||||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use nu_engine::{current_dir, eval_block, CallExt};
|
use nu_engine::{current_dir, eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack, StateWorkingSet};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack, StateWorkingSet};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
format_error, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature,
|
format_error, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature,
|
||||||
Spanned, SyntaxShape, Value,
|
Spanned, SyntaxShape, Value,
|
||||||
@ -35,7 +35,7 @@ impl Command for Watch {
|
|||||||
fn signature(&self) -> nu_protocol::Signature {
|
fn signature(&self) -> nu_protocol::Signature {
|
||||||
Signature::build("watch")
|
Signature::build("watch")
|
||||||
.required("path", SyntaxShape::Filepath, "the path to watch. Can be a file or directory")
|
.required("path", SyntaxShape::Filepath, "the path to watch. Can be a file or directory")
|
||||||
.required("block", SyntaxShape::Block(None), "A Nu block of code to run whenever a file changes. The block will be passed `operation`, `path`, and `new_path` (for renames only) arguments in that order")
|
.required("block", SyntaxShape::Block, "A Nu block of code to run whenever a file changes. The block will be passed `operation`, `path`, and `new_path` (for renames only) arguments in that order")
|
||||||
.named(
|
.named(
|
||||||
"debounce-ms",
|
"debounce-ms",
|
||||||
SyntaxShape::Int,
|
SyntaxShape::Int,
|
||||||
@ -82,7 +82,7 @@ impl Command for Watch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 1)?;
|
let capture_block: Closure = call.req(engine_state, stack, 1)?;
|
||||||
let block = engine_state
|
let block = engine_state
|
||||||
.clone()
|
.clone()
|
||||||
.get_block(capture_block.block_id)
|
.get_block(capture_block.block_id)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ impl Command for All {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let block_id = capture_block.block_id;
|
let block_id = capture_block.block_id;
|
||||||
|
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
@ -67,7 +67,7 @@ impl Command for Any {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let block_id = capture_block.block_id;
|
let block_id = capture_block.block_id;
|
||||||
|
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, redirect_env, CallExt};
|
use nu_engine::{eval_block, redirect_env, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Type, Value,
|
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -17,9 +17,9 @@ impl Command for Collect {
|
|||||||
Signature::build("collect")
|
Signature::build("collect")
|
||||||
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Any)])
|
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Any)])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"the block to run once the stream is collected",
|
"the closure to run once the stream is collected",
|
||||||
)
|
)
|
||||||
.switch(
|
.switch(
|
||||||
"keep-env",
|
"keep-env",
|
||||||
@ -40,7 +40,7 @@ impl Command for Collect {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
let mut stack_captures = stack.captures_to_stack(&capture_block.captures);
|
let mut stack_captures = stack.captures_to_stack(&capture_block.captures);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::utils::chain_error_with_input;
|
use super::utils::chain_error_with_input;
|
||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||||
Span, SyntaxShape, Type, Value,
|
Span, SyntaxShape, Type, Value,
|
||||||
@ -16,7 +16,7 @@ impl Command for Each {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Run a block on each row of input"
|
"Run a closure on each row of input"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extra_usage(&self) -> &str {
|
fn extra_usage(&self) -> &str {
|
||||||
@ -40,9 +40,9 @@ with 'transpose' first."#
|
|||||||
Type::List(Box::new(Type::Any)),
|
Type::List(Box::new(Type::Any)),
|
||||||
)])
|
)])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"the block to run",
|
"the closure to run",
|
||||||
)
|
)
|
||||||
.switch("keep-empty", "keep empty result cells", Some('k'))
|
.switch("keep-empty", "keep empty result cells", Some('k'))
|
||||||
.switch("numbered", "iterate with an index", Some('n'))
|
.switch("numbered", "iterate with an index", Some('n'))
|
||||||
@ -127,7 +127,7 @@ with 'transpose' first."#
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let numbered = call.has_flag("numbered");
|
let numbered = call.has_flag("numbered");
|
||||||
let keep_empty = call.has_flag("keep-empty");
|
let keep_empty = call.has_flag("keep-empty");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||||
Span, SyntaxShape, Type, Value,
|
Span, SyntaxShape, Type, Value,
|
||||||
@ -29,9 +29,9 @@ impl Command for EachWhile {
|
|||||||
Type::List(Box::new(Type::Any)),
|
Type::List(Box::new(Type::Any)),
|
||||||
)])
|
)])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"the block to run",
|
"the closure to run",
|
||||||
)
|
)
|
||||||
.switch("numbered", "iterate with an index", Some('n'))
|
.switch("numbered", "iterate with an index", Some('n'))
|
||||||
.category(Category::Filters)
|
.category(Category::Filters)
|
||||||
@ -97,7 +97,7 @@ impl Command for EachWhile {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let numbered = call.has_flag("numbered");
|
let numbered = call.has_flag("numbered");
|
||||||
|
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
@ -354,6 +354,7 @@ fn find_with_rest_and_highlight(
|
|||||||
| Value::Range { .. }
|
| Value::Range { .. }
|
||||||
| Value::Float { .. }
|
| Value::Float { .. }
|
||||||
| Value::Block { .. }
|
| Value::Block { .. }
|
||||||
|
| Value::Closure { .. }
|
||||||
| Value::Nothing { .. }
|
| Value::Nothing { .. }
|
||||||
| Value::Error { .. } => lower_value
|
| Value::Error { .. } => lower_value
|
||||||
.eq(span, term, span)
|
.eq(span, term, span)
|
||||||
@ -413,6 +414,7 @@ fn find_with_rest_and_highlight(
|
|||||||
| Value::Range { .. }
|
| Value::Range { .. }
|
||||||
| Value::Float { .. }
|
| Value::Float { .. }
|
||||||
| Value::Block { .. }
|
| Value::Block { .. }
|
||||||
|
| Value::Closure { .. }
|
||||||
| Value::Nothing { .. }
|
| Value::Nothing { .. }
|
||||||
| Value::Error { .. } => lower_value
|
| Value::Error { .. } => lower_value
|
||||||
.eq(span, term, span)
|
.eq(span, term, span)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
|
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
|
||||||
Type, Value,
|
Type, Value,
|
||||||
@ -117,8 +117,8 @@ pub fn group_by(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match grouper {
|
match grouper {
|
||||||
Some(Value::Block { .. }) => {
|
Some(Value::Block { .. }) | Some(Value::Closure { .. }) => {
|
||||||
let block: Option<CaptureBlock> = call.opt(engine_state, stack, 0)?;
|
let block: Option<Closure> = call.opt(engine_state, stack, 0)?;
|
||||||
let error_key = "error";
|
let error_key = "error";
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::{Call, CellPath, PathMember};
|
use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -91,7 +91,7 @@ fn insert(
|
|||||||
|
|
||||||
// Replace is a block, so set it up and run it instead of using it as the replacement
|
// Replace is a block, so set it up and run it instead of using it as the replacement
|
||||||
if replacement.as_block().is_ok() {
|
if replacement.as_block().is_ok() {
|
||||||
let capture_block: CaptureBlock = FromValue::from_value(&replacement)?;
|
let capture_block: Closure = FromValue::from_value(&replacement)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -113,7 +113,7 @@ repeating this process with row 1, and so on."#
|
|||||||
|
|
||||||
let merge_value: Value = if argument_was_block {
|
let merge_value: Value = if argument_was_block {
|
||||||
// When given a block, run it to obtain the matching value.
|
// When given a block, run it to obtain the matching value.
|
||||||
let capture_block: CaptureBlock = FromValue::from_value(&replacement)?;
|
let capture_block: Closure = FromValue::from_value(&replacement)?;
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
stack.with_env(&stack.env_vars.clone(), &stack.env_hidden.clone());
|
stack.with_env(&stack.env_vars.clone(), &stack.env_hidden.clone());
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||||
Span, SyntaxShape, Type, Value,
|
Span, SyntaxShape, Type, Value,
|
||||||
@ -18,7 +18,7 @@ impl Command for ParEach {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Run a block on each element of input in parallel"
|
"Run a closure on each element of input in parallel"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> nu_protocol::Signature {
|
fn signature(&self) -> nu_protocol::Signature {
|
||||||
@ -28,9 +28,9 @@ impl Command for ParEach {
|
|||||||
Type::List(Box::new(Type::Any)),
|
Type::List(Box::new(Type::Any)),
|
||||||
)])
|
)])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"the block to run",
|
"the closure to run",
|
||||||
)
|
)
|
||||||
.switch("numbered", "iterate with an index", Some('n'))
|
.switch("numbered", "iterate with an index", Some('n'))
|
||||||
.category(Category::Filters)
|
.category(Category::Filters)
|
||||||
@ -64,7 +64,7 @@ impl Command for ParEach {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let numbered = call.has_flag("numbered");
|
let numbered = call.has_flag("numbered");
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
@ -3,7 +3,7 @@ use std::sync::atomic::Ordering;
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
|
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -26,8 +26,8 @@ impl Command for Reduce {
|
|||||||
Some('f'),
|
Some('f'),
|
||||||
)
|
)
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any, SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Any])),
|
||||||
"reducing function",
|
"reducing function",
|
||||||
)
|
)
|
||||||
.switch("numbered", "iterate with an index", Some('n'))
|
.switch("numbered", "iterate with an index", Some('n'))
|
||||||
@ -103,7 +103,7 @@ impl Command for Reduce {
|
|||||||
|
|
||||||
let fold: Option<Value> = call.get_flag(engine_state, stack, "fold")?;
|
let fold: Option<Value> = call.get_flag(engine_state, stack, "fold")?;
|
||||||
let numbered = call.has_flag("numbered");
|
let numbered = call.has_flag("numbered");
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
let block = engine_state.get_block(capture_block.block_id);
|
let block = engine_state.get_block(capture_block.block_id);
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -73,7 +73,7 @@ impl Command for SkipUntil {
|
|||||||
let span = call.head;
|
let span = call.head;
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -74,7 +74,7 @@ impl Command for SkipWhile {
|
|||||||
let span = call.head;
|
let span = call.head;
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ impl Command for TakeUntil {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{Closure, Command, EngineState, Stack},
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
SyntaxShape, Type, Value,
|
SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ impl Command for TakeWhile {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::{Call, CellPath, PathMember};
|
use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -90,7 +90,7 @@ fn update(
|
|||||||
|
|
||||||
// Replace is a block, so set it up and run it instead of using it as the replacement
|
// Replace is a block, so set it up and run it instead of using it as the replacement
|
||||||
if replacement.as_block().is_ok() {
|
if replacement.as_block().is_ok() {
|
||||||
let capture_block: CaptureBlock = FromValue::from_value(&replacement)?;
|
let capture_block: Closure = FromValue::from_value(&replacement)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::{Block, Call};
|
use nu_protocol::ast::{Block, Call};
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||||
PipelineIterator, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
PipelineIterator, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -20,9 +20,9 @@ impl Command for UpdateCells {
|
|||||||
Signature::build("update cells")
|
Signature::build("update cells")
|
||||||
.input_output_types(vec![(Type::Table(vec![]), Type::Table(vec![]))])
|
.input_output_types(vec![(Type::Table(vec![]), Type::Table(vec![]))])
|
||||||
.required(
|
.required(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"the block to run an update for each cell",
|
"the closure to run an update for each cell",
|
||||||
)
|
)
|
||||||
.named(
|
.named(
|
||||||
"columns",
|
"columns",
|
||||||
@ -125,7 +125,7 @@ impl Command for UpdateCells {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
// the block to run on each cell
|
// the block to run on each cell
|
||||||
let engine_state = engine_state.clone();
|
let engine_state = engine_state.clone();
|
||||||
let block: CaptureBlock = call.req(&engine_state, stack, 0)?;
|
let block: Closure = call.req(&engine_state, stack, 0)?;
|
||||||
let mut stack = stack.captures_to_stack(&block.captures);
|
let mut stack = stack.captures_to_stack(&block.captures);
|
||||||
let orig_env_vars = stack.env_vars.clone();
|
let orig_env_vars = stack.env_vars.clone();
|
||||||
let orig_env_hidden = stack.env_hidden.clone();
|
let orig_env_hidden = stack.env_hidden.clone();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::{Call, CellPath, PathMember};
|
use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -110,7 +110,7 @@ fn upsert(
|
|||||||
|
|
||||||
// Replace is a block, so set it up and run it instead of using it as the replacement
|
// Replace is a block, so set it up and run it instead of using it as the replacement
|
||||||
if replacement.as_block().is_ok() {
|
if replacement.as_block().is_ok() {
|
||||||
let capture_block: CaptureBlock = FromValue::from_value(&replacement)?;
|
let capture_block: Closure = FromValue::from_value(&replacement)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id).clone();
|
let block = engine_state.get_block(capture_block.block_id).clone();
|
||||||
|
|
||||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::utils::chain_error_with_input;
|
use super::utils::chain_error_with_input;
|
||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||||
Signature, Span, SyntaxShape, Type, Value,
|
Signature, Span, SyntaxShape, Type, Value,
|
||||||
@ -30,9 +30,9 @@ impl Command for Where {
|
|||||||
])
|
])
|
||||||
.optional("cond", SyntaxShape::RowCondition, "condition")
|
.optional("cond", SyntaxShape::RowCondition, "condition")
|
||||||
.named(
|
.named(
|
||||||
"block",
|
"closure",
|
||||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
|
||||||
"use where with a block or variable instead",
|
"use where with a closure",
|
||||||
Some('b'),
|
Some('b'),
|
||||||
)
|
)
|
||||||
.category(Category::Filters)
|
.category(Category::Filters)
|
||||||
@ -49,8 +49,7 @@ impl Command for Where {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
if let Ok(Some(capture_block)) = call.get_flag::<CaptureBlock>(engine_state, stack, "block")
|
if let Ok(Some(capture_block)) = call.get_flag::<Closure>(engine_state, stack, "block") {
|
||||||
{
|
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
let engine_state = engine_state.clone();
|
let engine_state = engine_state.clone();
|
||||||
@ -180,7 +179,7 @@ impl Command for Where {
|
|||||||
}
|
}
|
||||||
.map(|x| x.set_metadata(metadata))
|
.map(|x| x.set_metadata(metadata))
|
||||||
} else {
|
} else {
|
||||||
let capture_block: Option<CaptureBlock> = call.opt(engine_state, stack, 0)?;
|
let capture_block: Option<Closure> = call.opt(engine_state, stack, 0)?;
|
||||||
if let Some(block) = capture_block {
|
if let Some(block) = capture_block {
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
|
@ -217,6 +217,12 @@ fn convert_to_value(
|
|||||||
"blocks not supported in nuon".into(),
|
"blocks not supported in nuon".into(),
|
||||||
expr.span,
|
expr.span,
|
||||||
)),
|
)),
|
||||||
|
Expr::Closure(..) => Err(ShellError::OutsideSpannedLabeledError(
|
||||||
|
original_text.to_string(),
|
||||||
|
"Error when loading".into(),
|
||||||
|
"closures not supported in nuon".into(),
|
||||||
|
expr.span,
|
||||||
|
)),
|
||||||
Expr::Binary(val) => Ok(Value::Binary { val, span }),
|
Expr::Binary(val) => Ok(Value::Binary { val, span }),
|
||||||
Expr::Bool(val) => Ok(Value::Bool { val, span }),
|
Expr::Bool(val) => Ok(Value::Bool { val, span }),
|
||||||
Expr::Call(..) => Err(ShellError::OutsideSpannedLabeledError(
|
Expr::Call(..) => Err(ShellError::OutsideSpannedLabeledError(
|
||||||
|
@ -125,7 +125,7 @@ pub fn value_to_json_value(v: &Value) -> Result<nu_json::Value, ShellError> {
|
|||||||
|
|
||||||
Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?),
|
Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?),
|
||||||
Value::Error { error } => return Err(error.clone()),
|
Value::Error { error } => return Err(error.clone()),
|
||||||
Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
|
Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
|
||||||
Value::Binary { val, .. } => {
|
Value::Binary { val, .. } => {
|
||||||
nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect())
|
nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect())
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,10 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
|
|||||||
"block not supported".into(),
|
"block not supported".into(),
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
|
Value::Closure { .. } => Err(ShellError::UnsupportedInput(
|
||||||
|
"closure not supported".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
Value::Bool { val, .. } => {
|
Value::Bool { val, .. } => {
|
||||||
if *val {
|
if *val {
|
||||||
Ok("true".to_string())
|
Ok("true".to_string())
|
||||||
|
@ -100,6 +100,7 @@ fn local_into_string(value: Value, separator: &str, config: &Config) -> String {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(separator),
|
.join(separator),
|
||||||
Value::Block { val, .. } => format!("<Block {}>", val),
|
Value::Block { val, .. } => format!("<Block {}>", val),
|
||||||
|
Value::Closure { val, .. } => format!("<Closure {}>", val),
|
||||||
Value::Nothing { .. } => String::new(),
|
Value::Nothing { .. } => String::new(),
|
||||||
Value::Error { error } => format!("{:?}", error),
|
Value::Error { error } => format!("{:?}", error),
|
||||||
Value::Binary { val, .. } => format!("{:?}", val),
|
Value::Binary { val, .. } => format!("{:?}", val),
|
||||||
|
@ -67,6 +67,11 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result<toml::Value, ShellErr
|
|||||||
let code = String::from_utf8_lossy(code).to_string();
|
let code = String::from_utf8_lossy(code).to_string();
|
||||||
toml::Value::String(code)
|
toml::Value::String(code)
|
||||||
}
|
}
|
||||||
|
Value::Closure { span, .. } => {
|
||||||
|
let code = engine_state.get_span_contents(span);
|
||||||
|
let code = String::from_utf8_lossy(code).to_string();
|
||||||
|
toml::Value::String(code)
|
||||||
|
}
|
||||||
Value::Nothing { .. } => toml::Value::String("<Nothing>".to_string()),
|
Value::Nothing { .. } => toml::Value::String("<Nothing>".to_string()),
|
||||||
Value::Error { error } => return Err(error.clone()),
|
Value::Error { error } => return Err(error.clone()),
|
||||||
Value::Binary { val, .. } => toml::Value::Array(
|
Value::Binary { val, .. } => toml::Value::Array(
|
||||||
|
@ -72,6 +72,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
|
|||||||
serde_yaml::Value::Sequence(out)
|
serde_yaml::Value::Sequence(out)
|
||||||
}
|
}
|
||||||
Value::Block { .. } => serde_yaml::Value::Null,
|
Value::Block { .. } => serde_yaml::Value::Null,
|
||||||
|
Value::Closure { .. } => serde_yaml::Value::Null,
|
||||||
Value::Nothing { .. } => serde_yaml::Value::Null,
|
Value::Nothing { .. } => serde_yaml::Value::Null,
|
||||||
Value::Error { error } => return Err(error.clone()),
|
Value::Error { error } => return Err(error.clone()),
|
||||||
Value::Binary { val, .. } => serde_yaml::Value::Sequence(
|
Value::Binary { val, .. } => serde_yaml::Value::Sequence(
|
||||||
|
@ -2,7 +2,7 @@ use std::time::Instant;
|
|||||||
|
|
||||||
use nu_engine::{eval_block, CallExt};
|
use nu_engine::{eval_block, CallExt};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Value,
|
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
@ -21,11 +21,7 @@ impl Command for Benchmark {
|
|||||||
|
|
||||||
fn signature(&self) -> nu_protocol::Signature {
|
fn signature(&self) -> nu_protocol::Signature {
|
||||||
Signature::build("benchmark")
|
Signature::build("benchmark")
|
||||||
.required(
|
.required("block", SyntaxShape::Block, "the block to run")
|
||||||
"block",
|
|
||||||
SyntaxShape::Block(Some(vec![])),
|
|
||||||
"the block to run",
|
|
||||||
)
|
|
||||||
.category(Category::System)
|
.category(Category::System)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +32,7 @@ impl Command for Benchmark {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
|
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||||
let block = engine_state.get_block(capture_block.block_id);
|
let block = engine_state.get_block(capture_block.block_id);
|
||||||
|
|
||||||
let redirect_stdout = call.redirect_stdout;
|
let redirect_stdout = call.redirect_stdout;
|
||||||
|
@ -492,19 +492,23 @@ pub fn eval_expression(
|
|||||||
.into_value(expr.span),
|
.into_value(expr.span),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Expr::RowCondition(block_id) | Expr::Block(block_id) => {
|
Expr::RowCondition(block_id) | Expr::Closure(block_id) => {
|
||||||
let mut captures = HashMap::new();
|
let mut captures = HashMap::new();
|
||||||
let block = engine_state.get_block(*block_id);
|
let block = engine_state.get_block(*block_id);
|
||||||
|
|
||||||
for var_id in &block.captures {
|
for var_id in &block.captures {
|
||||||
captures.insert(*var_id, stack.get_var(*var_id, expr.span)?);
|
captures.insert(*var_id, stack.get_var(*var_id, expr.span)?);
|
||||||
}
|
}
|
||||||
Ok(Value::Block {
|
Ok(Value::Closure {
|
||||||
val: *block_id,
|
val: *block_id,
|
||||||
captures,
|
captures,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Expr::Block(block_id) => Ok(Value::Block {
|
||||||
|
val: *block_id,
|
||||||
|
span: expr.span,
|
||||||
|
}),
|
||||||
Expr::List(x) => {
|
Expr::List(x) => {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
for expr in x {
|
for expr in x {
|
||||||
|
@ -101,7 +101,10 @@ pub fn flatten_expression(
|
|||||||
output.extend(flatten_expression(working_set, inner_expr));
|
output.extend(flatten_expression(working_set, inner_expr));
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
Expr::Block(block_id) | Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
Expr::Block(block_id)
|
||||||
|
| Expr::Closure(block_id)
|
||||||
|
| Expr::RowCondition(block_id)
|
||||||
|
| Expr::Subexpression(block_id) => {
|
||||||
let outer_span = expr.span;
|
let outer_span = expr.span;
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
@ -2708,7 +2708,8 @@ pub fn parse_shape_name(
|
|||||||
let result = match bytes {
|
let result = match bytes {
|
||||||
b"any" => SyntaxShape::Any,
|
b"any" => SyntaxShape::Any,
|
||||||
b"binary" => SyntaxShape::Binary,
|
b"binary" => SyntaxShape::Binary,
|
||||||
b"block" => SyntaxShape::Block(None), //FIXME: Blocks should have known output types
|
b"block" => SyntaxShape::Block, //FIXME: Blocks should have known output types
|
||||||
|
b"closure" => SyntaxShape::Closure(None), //FIXME: Blocks should have known output types
|
||||||
b"cell-path" => SyntaxShape::CellPath,
|
b"cell-path" => SyntaxShape::CellPath,
|
||||||
b"duration" => SyntaxShape::Duration,
|
b"duration" => SyntaxShape::Duration,
|
||||||
b"path" => SyntaxShape::Filepath,
|
b"path" => SyntaxShape::Filepath,
|
||||||
@ -3050,6 +3051,7 @@ pub fn parse_row_condition(
|
|||||||
|
|
||||||
let block_id = match expression.expr {
|
let block_id = match expression.expr {
|
||||||
Expr::Block(block_id) => block_id,
|
Expr::Block(block_id) => block_id,
|
||||||
|
Expr::Closure(block_id) => block_id,
|
||||||
_ => {
|
_ => {
|
||||||
// We have an expression, so let's convert this into a block.
|
// We have an expression, so let's convert this into a block.
|
||||||
let mut block = Block::new();
|
let mut block = Block::new();
|
||||||
@ -3898,39 +3900,13 @@ pub fn parse_block_expression(
|
|||||||
contents: TokenContents::Pipe,
|
contents: TokenContents::Pipe,
|
||||||
span,
|
span,
|
||||||
}) => {
|
}) => {
|
||||||
// We've found a parameter list
|
error = error.or_else(|| {
|
||||||
let start_point = span.start;
|
Some(ParseError::Expected(
|
||||||
let mut token_iter = output.iter().enumerate().skip(1);
|
"block but found closure".into(),
|
||||||
let mut end_span = None;
|
*span,
|
||||||
let mut amt_to_skip = 1;
|
))
|
||||||
|
});
|
||||||
for token in &mut token_iter {
|
(None, 0)
|
||||||
if let Token {
|
|
||||||
contents: TokenContents::Pipe,
|
|
||||||
span,
|
|
||||||
} = token.1
|
|
||||||
{
|
|
||||||
end_span = Some(span);
|
|
||||||
amt_to_skip = token.0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let end_point = if let Some(span) = end_span {
|
|
||||||
span.end
|
|
||||||
} else {
|
|
||||||
end
|
|
||||||
};
|
|
||||||
|
|
||||||
let signature_span = Span {
|
|
||||||
start: start_point,
|
|
||||||
end: end_point,
|
|
||||||
};
|
|
||||||
let (signature, err) =
|
|
||||||
parse_signature_helper(working_set, signature_span, expand_aliases_denylist);
|
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
(Some((signature, signature_span)), amt_to_skip)
|
|
||||||
}
|
}
|
||||||
_ => (None, 0),
|
_ => (None, 0),
|
||||||
};
|
};
|
||||||
@ -3939,7 +3915,7 @@ pub fn parse_block_expression(
|
|||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
// TODO: Finish this
|
// TODO: Finish this
|
||||||
if let SyntaxShape::Block(Some(v)) = shape {
|
if let SyntaxShape::Closure(Some(v)) = shape {
|
||||||
if let Some((sig, sig_span)) = &signature {
|
if let Some((sig, sig_span)) = &signature {
|
||||||
if sig.num_positionals() > v.len() {
|
if sig.num_positionals() > v.len() {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
@ -4010,6 +3986,175 @@ pub fn parse_block_expression(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_closure_expression(
|
||||||
|
working_set: &mut StateWorkingSet,
|
||||||
|
shape: &SyntaxShape,
|
||||||
|
span: Span,
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
|
) -> (Expression, Option<ParseError>) {
|
||||||
|
trace!("parsing: closure expression");
|
||||||
|
|
||||||
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
let mut error = None;
|
||||||
|
|
||||||
|
let mut start = span.start;
|
||||||
|
let mut end = span.end;
|
||||||
|
|
||||||
|
if bytes.starts_with(b"{") {
|
||||||
|
start += 1;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Expected("block".into(), span)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if bytes.ends_with(b"}") {
|
||||||
|
end -= 1;
|
||||||
|
} else {
|
||||||
|
error = error.or_else(|| Some(ParseError::Unclosed("}".into(), Span { start: end, end })));
|
||||||
|
}
|
||||||
|
|
||||||
|
let inner_span = Span { start, end };
|
||||||
|
|
||||||
|
let source = working_set.get_span_contents(inner_span);
|
||||||
|
|
||||||
|
let (output, err) = lex(source, start, &[], &[], false);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
working_set.enter_scope();
|
||||||
|
|
||||||
|
// Check to see if we have parameters
|
||||||
|
let (signature, amt_to_skip): (Option<(Box<Signature>, Span)>, usize) = match output.first() {
|
||||||
|
Some(Token {
|
||||||
|
contents: TokenContents::Pipe,
|
||||||
|
span,
|
||||||
|
}) => {
|
||||||
|
// We've found a parameter list
|
||||||
|
let start_point = span.start;
|
||||||
|
let mut token_iter = output.iter().enumerate().skip(1);
|
||||||
|
let mut end_span = None;
|
||||||
|
let mut amt_to_skip = 1;
|
||||||
|
|
||||||
|
for token in &mut token_iter {
|
||||||
|
if let Token {
|
||||||
|
contents: TokenContents::Pipe,
|
||||||
|
span,
|
||||||
|
} = token.1
|
||||||
|
{
|
||||||
|
end_span = Some(span);
|
||||||
|
amt_to_skip = token.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let end_point = if let Some(span) = end_span {
|
||||||
|
span.end
|
||||||
|
} else {
|
||||||
|
end
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature_span = Span {
|
||||||
|
start: start_point,
|
||||||
|
end: end_point,
|
||||||
|
};
|
||||||
|
let (signature, err) =
|
||||||
|
parse_signature_helper(working_set, signature_span, expand_aliases_denylist);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
(Some((signature, signature_span)), amt_to_skip)
|
||||||
|
}
|
||||||
|
Some(Token {
|
||||||
|
contents: TokenContents::Item,
|
||||||
|
span,
|
||||||
|
}) => {
|
||||||
|
let contents = working_set.get_span_contents(*span);
|
||||||
|
if contents == b"||" {
|
||||||
|
(
|
||||||
|
Some((Box::new(Signature::new("closure".to_string())), *span)),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(None, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (None, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let (output, err) = lite_parse(&output[amt_to_skip..]);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
// TODO: Finish this
|
||||||
|
if let SyntaxShape::Closure(Some(v)) = shape {
|
||||||
|
if let Some((sig, sig_span)) = &signature {
|
||||||
|
if sig.num_positionals() > v.len() {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::Expected(
|
||||||
|
format!(
|
||||||
|
"{} block parameter{}",
|
||||||
|
v.len(),
|
||||||
|
if v.len() > 1 { "s" } else { "" }
|
||||||
|
),
|
||||||
|
*sig_span,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (expected, PositionalArg { name, shape, .. }) in
|
||||||
|
v.iter().zip(sig.required_positional.iter())
|
||||||
|
{
|
||||||
|
if expected != shape && *shape != SyntaxShape::Any {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::ParameterMismatchType(
|
||||||
|
name.to_owned(),
|
||||||
|
expected.to_string(),
|
||||||
|
shape.to_string(),
|
||||||
|
*sig_span,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut output, err) =
|
||||||
|
parse_block(working_set, &output, false, expand_aliases_denylist, false);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
if let Some(signature) = signature {
|
||||||
|
output.signature = signature.0;
|
||||||
|
} else if let Some(last) = working_set.delta.scope.last() {
|
||||||
|
// FIXME: this only supports the top $it. Is this sufficient?
|
||||||
|
|
||||||
|
if let Some(var_id) = last.get_var(b"$it") {
|
||||||
|
let mut signature = Signature::new("");
|
||||||
|
signature.required_positional.push(PositionalArg {
|
||||||
|
var_id: Some(*var_id),
|
||||||
|
name: "$it".into(),
|
||||||
|
desc: String::new(),
|
||||||
|
shape: SyntaxShape::Any,
|
||||||
|
default_value: None,
|
||||||
|
});
|
||||||
|
output.signature = Box::new(signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.span = Some(span);
|
||||||
|
|
||||||
|
working_set.exit_scope();
|
||||||
|
|
||||||
|
let block_id = working_set.add_block(output);
|
||||||
|
|
||||||
|
(
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Closure(block_id),
|
||||||
|
span,
|
||||||
|
ty: Type::Closure,
|
||||||
|
custom_completion: None,
|
||||||
|
},
|
||||||
|
error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_value(
|
pub fn parse_value(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -4099,14 +4244,16 @@ pub fn parse_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
b'{' => {
|
b'{' => {
|
||||||
if !matches!(shape, SyntaxShape::Block(..)) {
|
if !matches!(shape, SyntaxShape::Closure(..)) && !matches!(shape, SyntaxShape::Block) {
|
||||||
if let (expr, None) =
|
if let (expr, None) =
|
||||||
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
|
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
|
||||||
{
|
{
|
||||||
return (expr, None);
|
return (expr, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches!(shape, SyntaxShape::Block(_)) || matches!(shape, SyntaxShape::Any) {
|
if matches!(shape, SyntaxShape::Closure(_)) || matches!(shape, SyntaxShape::Any) {
|
||||||
|
return parse_closure_expression(working_set, shape, span, expand_aliases_denylist);
|
||||||
|
} else if matches!(shape, SyntaxShape::Block) {
|
||||||
return parse_block_expression(working_set, shape, span, expand_aliases_denylist);
|
return parse_block_expression(working_set, shape, span, expand_aliases_denylist);
|
||||||
} else if matches!(shape, SyntaxShape::Record) {
|
} else if matches!(shape, SyntaxShape::Record) {
|
||||||
return parse_record(working_set, span, expand_aliases_denylist);
|
return parse_record(working_set, span, expand_aliases_denylist);
|
||||||
@ -4236,7 +4383,8 @@ pub fn parse_value(
|
|||||||
SyntaxShape::Filesize,
|
SyntaxShape::Filesize,
|
||||||
SyntaxShape::Duration,
|
SyntaxShape::Duration,
|
||||||
SyntaxShape::Record,
|
SyntaxShape::Record,
|
||||||
SyntaxShape::Block(None),
|
SyntaxShape::Closure(None),
|
||||||
|
SyntaxShape::Block,
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
];
|
];
|
||||||
for shape in shapes.iter() {
|
for shape in shapes.iter() {
|
||||||
@ -4754,9 +4902,9 @@ pub fn parse_expression(
|
|||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}),
|
}),
|
||||||
Argument::Positional(Expression {
|
Argument::Positional(Expression {
|
||||||
expr: Expr::Block(block_id),
|
expr: Expr::Closure(block_id),
|
||||||
span: span(&spans[pos..]),
|
span: span(&spans[pos..]),
|
||||||
ty,
|
ty: Type::Closure,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@ -4774,7 +4922,7 @@ pub fn parse_expression(
|
|||||||
expr,
|
expr,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Any,
|
ty,
|
||||||
},
|
},
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
@ -5068,7 +5216,7 @@ pub fn parse_block(
|
|||||||
(block, error)
|
(block, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discover_captures_in_block(
|
pub fn discover_captures_in_closure(
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
block: &Block,
|
block: &Block,
|
||||||
seen: &mut Vec<VarId>,
|
seen: &mut Vec<VarId>,
|
||||||
@ -5140,11 +5288,25 @@ pub fn discover_captures_in_expr(
|
|||||||
let result = discover_captures_in_expr(working_set, expr, seen, seen_blocks);
|
let result = discover_captures_in_expr(working_set, expr, seen, seen_blocks);
|
||||||
output.extend(&result);
|
output.extend(&result);
|
||||||
}
|
}
|
||||||
Expr::Block(block_id) => {
|
Expr::Closure(block_id) => {
|
||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
let results = {
|
let results = {
|
||||||
let mut seen = vec![];
|
let mut seen = vec![];
|
||||||
discover_captures_in_block(working_set, block, &mut seen, seen_blocks)
|
discover_captures_in_closure(working_set, block, &mut seen, seen_blocks)
|
||||||
|
};
|
||||||
|
seen_blocks.insert(*block_id, results.clone());
|
||||||
|
for var_id in results.into_iter() {
|
||||||
|
if !seen.contains(&var_id) {
|
||||||
|
output.push(var_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Block(block_id) => {
|
||||||
|
let block = working_set.get_block(*block_id);
|
||||||
|
// FIXME: is this correct?
|
||||||
|
let results = {
|
||||||
|
let mut seen = vec![];
|
||||||
|
discover_captures_in_closure(working_set, block, &mut seen, seen_blocks)
|
||||||
};
|
};
|
||||||
seen_blocks.insert(*block_id, results.clone());
|
seen_blocks.insert(*block_id, results.clone());
|
||||||
for var_id in results.into_iter() {
|
for var_id in results.into_iter() {
|
||||||
@ -5170,7 +5332,7 @@ pub fn discover_captures_in_expr(
|
|||||||
let mut seen = vec![];
|
let mut seen = vec![];
|
||||||
seen_blocks.insert(block_id, output.clone());
|
seen_blocks.insert(block_id, output.clone());
|
||||||
|
|
||||||
let result = discover_captures_in_block(
|
let result = discover_captures_in_closure(
|
||||||
working_set,
|
working_set,
|
||||||
block,
|
block,
|
||||||
&mut seen,
|
&mut seen,
|
||||||
@ -5294,7 +5456,7 @@ pub fn discover_captures_in_expr(
|
|||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
let results = {
|
let results = {
|
||||||
let mut seen = vec![];
|
let mut seen = vec![];
|
||||||
discover_captures_in_block(working_set, block, &mut seen, seen_blocks)
|
discover_captures_in_closure(working_set, block, &mut seen, seen_blocks)
|
||||||
};
|
};
|
||||||
seen_blocks.insert(*block_id, results.clone());
|
seen_blocks.insert(*block_id, results.clone());
|
||||||
for var_id in results.into_iter() {
|
for var_id in results.into_iter() {
|
||||||
@ -5361,7 +5523,7 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
|
|||||||
let block_id = working_set.add_block(block);
|
let block_id = working_set.add_block(block);
|
||||||
|
|
||||||
output.push(Argument::Positional(Expression {
|
output.push(Argument::Positional(Expression {
|
||||||
expr: Expr::Block(block_id),
|
expr: Expr::Closure(block_id),
|
||||||
span,
|
span,
|
||||||
ty: Type::Any,
|
ty: Type::Any,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
@ -5432,7 +5594,7 @@ pub fn parse(
|
|||||||
let mut seen = vec![];
|
let mut seen = vec![];
|
||||||
let mut seen_blocks = HashMap::new();
|
let mut seen_blocks = HashMap::new();
|
||||||
|
|
||||||
let captures = discover_captures_in_block(working_set, &output, &mut seen, &mut seen_blocks);
|
let captures = discover_captures_in_closure(working_set, &output, &mut seen, &mut seen_blocks);
|
||||||
output.captures = captures;
|
output.captures = captures;
|
||||||
|
|
||||||
// Also check other blocks that might have been imported
|
// Also check other blocks that might have been imported
|
||||||
@ -5441,7 +5603,7 @@ pub fn parse(
|
|||||||
|
|
||||||
if !seen_blocks.contains_key(&block_id) {
|
if !seen_blocks.contains_key(&block_id) {
|
||||||
let captures =
|
let captures =
|
||||||
discover_captures_in_block(working_set, block, &mut seen, &mut seen_blocks);
|
discover_captures_in_closure(working_set, block, &mut seen, &mut seen_blocks);
|
||||||
seen_blocks.insert(block_id, captures);
|
seen_blocks.insert(block_id, captures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
|||||||
(Type::List(c), Type::List(d)) => type_compatible(c, d),
|
(Type::List(c), Type::List(d)) => type_compatible(c, d),
|
||||||
(Type::Number, Type::Int) => true,
|
(Type::Number, Type::Int) => true,
|
||||||
(Type::Number, Type::Float) => true,
|
(Type::Number, Type::Float) => true,
|
||||||
|
(Type::Closure, Type::Block) => true,
|
||||||
(Type::Any, _) => true,
|
(Type::Any, _) => true,
|
||||||
(_, Type::Any) => true,
|
(_, Type::Any) => true,
|
||||||
(lhs, rhs) => lhs == rhs,
|
(lhs, rhs) => lhs == rhs,
|
||||||
|
@ -937,7 +937,7 @@ mod input_types {
|
|||||||
.required("cond", SyntaxShape::Expression, "condition to check")
|
.required("cond", SyntaxShape::Expression, "condition to check")
|
||||||
.required(
|
.required(
|
||||||
"then_block",
|
"then_block",
|
||||||
SyntaxShape::Block(Some(vec![])),
|
SyntaxShape::Block,
|
||||||
"block to run if check succeeds",
|
"block to run if check succeeds",
|
||||||
)
|
)
|
||||||
.optional(
|
.optional(
|
||||||
|
@ -26,6 +26,7 @@ pub enum Expr {
|
|||||||
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
|
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
|
||||||
Subexpression(BlockId),
|
Subexpression(BlockId),
|
||||||
Block(BlockId),
|
Block(BlockId),
|
||||||
|
Closure(BlockId),
|
||||||
List(Vec<Expression>),
|
List(Vec<Expression>),
|
||||||
Table(Vec<Expression>, Vec<Vec<Expression>>),
|
Table(Vec<Expression>, Vec<Vec<Expression>>),
|
||||||
Record(Vec<(Expression, Expression)>),
|
Record(Vec<(Expression, Expression)>),
|
||||||
|
@ -63,6 +63,7 @@ impl Expression {
|
|||||||
pub fn as_block(&self) -> Option<BlockId> {
|
pub fn as_block(&self) -> Option<BlockId> {
|
||||||
match self.expr {
|
match self.expr {
|
||||||
Expr::Block(block_id) => Some(block_id),
|
Expr::Block(block_id) => Some(block_id),
|
||||||
|
Expr::Closure(block_id) => Some(block_id),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,6 +140,22 @@ impl Expression {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Closure(block_id) => {
|
||||||
|
let block = working_set.get_block(*block_id);
|
||||||
|
|
||||||
|
if block.captures.contains(&IN_VARIABLE_ID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
|
match pipeline.expressions.get(0) {
|
||||||
|
Some(expr) => expr.has_in_variable(working_set),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
Expr::Binary(_) => false,
|
Expr::Binary(_) => false,
|
||||||
Expr::Bool(_) => false,
|
Expr::Bool(_) => false,
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
@ -310,6 +327,37 @@ impl Expression {
|
|||||||
.map(|x| if *x != IN_VARIABLE_ID { *x } else { new_var_id })
|
.map(|x| if *x != IN_VARIABLE_ID { *x } else { new_var_id })
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
Expr::Closure(block_id) => {
|
||||||
|
let block = working_set.get_block(*block_id);
|
||||||
|
|
||||||
|
let new_expr = if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
|
if let Some(expr) = pipeline.expressions.get(0) {
|
||||||
|
let mut new_expr = expr.clone();
|
||||||
|
new_expr.replace_in_variable(working_set, new_var_id);
|
||||||
|
Some(new_expr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let block = working_set.get_block_mut(*block_id);
|
||||||
|
|
||||||
|
if let Some(new_expr) = new_expr {
|
||||||
|
if let Some(pipeline) = block.pipelines.get_mut(0) {
|
||||||
|
if let Some(expr) = pipeline.expressions.get_mut(0) {
|
||||||
|
*expr = new_expr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block.captures = block
|
||||||
|
.captures
|
||||||
|
.iter()
|
||||||
|
.map(|x| if *x != IN_VARIABLE_ID { *x } else { new_var_id })
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
Expr::Binary(_) => {}
|
Expr::Binary(_) => {}
|
||||||
Expr::Bool(_) => {}
|
Expr::Bool(_) => {}
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
@ -456,6 +504,17 @@ impl Expression {
|
|||||||
|
|
||||||
*block_id = working_set.add_block(block);
|
*block_id = working_set.add_block(block);
|
||||||
}
|
}
|
||||||
|
Expr::Closure(block_id) => {
|
||||||
|
let mut block = working_set.get_block(*block_id).clone();
|
||||||
|
|
||||||
|
for pipeline in block.pipelines.iter_mut() {
|
||||||
|
for expr in pipeline.expressions.iter_mut() {
|
||||||
|
expr.replace_span(working_set, replaced, new_span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*block_id = working_set.add_block(block);
|
||||||
|
}
|
||||||
Expr::Binary(_) => {}
|
Expr::Binary(_) => {}
|
||||||
Expr::Bool(_) => {}
|
Expr::Bool(_) => {}
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
|
@ -3,7 +3,12 @@ use std::collections::HashMap;
|
|||||||
use crate::{BlockId, Value, VarId};
|
use crate::{BlockId, Value, VarId};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CaptureBlock {
|
pub struct Closure {
|
||||||
pub block_id: BlockId,
|
pub block_id: BlockId,
|
||||||
pub captures: HashMap<VarId, Value>,
|
pub captures: HashMap<VarId, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Block {
|
||||||
|
pub block_id: BlockId,
|
||||||
|
}
|
||||||
|
@ -46,8 +46,11 @@ pub enum SyntaxShape {
|
|||||||
/// A binary literal
|
/// A binary literal
|
||||||
Binary,
|
Binary,
|
||||||
|
|
||||||
|
/// A closure is allowed, eg `{|| start this thing}`
|
||||||
|
Closure(Option<Vec<SyntaxShape>>),
|
||||||
|
|
||||||
/// A block is allowed, eg `{start this thing}`
|
/// A block is allowed, eg `{start this thing}`
|
||||||
Block(Option<Vec<SyntaxShape>>),
|
Block,
|
||||||
|
|
||||||
/// A table is allowed, eg `[[first, second]; [1, 2]]`
|
/// A table is allowed, eg `[[first, second]; [1, 2]]`
|
||||||
Table,
|
Table,
|
||||||
@ -106,7 +109,8 @@ impl SyntaxShape {
|
|||||||
pub fn to_type(&self) -> Type {
|
pub fn to_type(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
SyntaxShape::Any => Type::Any,
|
SyntaxShape::Any => Type::Any,
|
||||||
SyntaxShape::Block(_) => Type::Block,
|
SyntaxShape::Block => Type::Block,
|
||||||
|
SyntaxShape::Closure(_) => Type::Closure,
|
||||||
SyntaxShape::Binary => Type::Binary,
|
SyntaxShape::Binary => Type::Binary,
|
||||||
SyntaxShape::CellPath => Type::Any,
|
SyntaxShape::CellPath => Type::Any,
|
||||||
SyntaxShape::Custom(custom, _) => custom.to_type(),
|
SyntaxShape::Custom(custom, _) => custom.to_type(),
|
||||||
@ -160,7 +164,8 @@ impl Display for SyntaxShape {
|
|||||||
SyntaxShape::Directory => write!(f, "directory"),
|
SyntaxShape::Directory => write!(f, "directory"),
|
||||||
SyntaxShape::GlobPattern => write!(f, "glob"),
|
SyntaxShape::GlobPattern => write!(f, "glob"),
|
||||||
SyntaxShape::ImportPattern => write!(f, "import"),
|
SyntaxShape::ImportPattern => write!(f, "import"),
|
||||||
SyntaxShape::Block(_) => write!(f, "block"),
|
SyntaxShape::Block => write!(f, "block"),
|
||||||
|
SyntaxShape::Closure(_) => write!(f, "closure"),
|
||||||
SyntaxShape::Binary => write!(f, "binary"),
|
SyntaxShape::Binary => write!(f, "binary"),
|
||||||
SyntaxShape::Table => write!(f, "table"),
|
SyntaxShape::Table => write!(f, "table"),
|
||||||
SyntaxShape::List(x) => write!(f, "list<{}>", x),
|
SyntaxShape::List(x) => write!(f, "list<{}>", x),
|
||||||
|
@ -13,6 +13,7 @@ pub enum Type {
|
|||||||
Bool,
|
Bool,
|
||||||
String,
|
String,
|
||||||
Block,
|
Block,
|
||||||
|
Closure,
|
||||||
CellPath,
|
CellPath,
|
||||||
Duration,
|
Duration,
|
||||||
Date,
|
Date,
|
||||||
@ -72,7 +73,8 @@ impl Type {
|
|||||||
Type::Range => SyntaxShape::Range,
|
Type::Range => SyntaxShape::Range,
|
||||||
Type::Bool => SyntaxShape::Boolean,
|
Type::Bool => SyntaxShape::Boolean,
|
||||||
Type::String => SyntaxShape::String,
|
Type::String => SyntaxShape::String,
|
||||||
Type::Block => SyntaxShape::Block(None), // FIXME needs more accuracy
|
Type::Block => SyntaxShape::Block, // FIXME needs more accuracy
|
||||||
|
Type::Closure => SyntaxShape::Closure(None), // FIXME needs more accuracy
|
||||||
Type::CellPath => SyntaxShape::CellPath,
|
Type::CellPath => SyntaxShape::CellPath,
|
||||||
Type::Duration => SyntaxShape::Duration,
|
Type::Duration => SyntaxShape::Duration,
|
||||||
Type::Date => SyntaxShape::DateTime,
|
Type::Date => SyntaxShape::DateTime,
|
||||||
@ -96,6 +98,7 @@ impl Display for Type {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Type::Block => write!(f, "block"),
|
Type::Block => write!(f, "block"),
|
||||||
|
Type::Closure => write!(f, "closure"),
|
||||||
Type::Bool => write!(f, "bool"),
|
Type::Bool => write!(f, "bool"),
|
||||||
Type::CellPath => write!(f, "cell path"),
|
Type::CellPath => write!(f, "cell path"),
|
||||||
Type::Date => write!(f, "date"),
|
Type::Date => write!(f, "date"),
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::ast::{CellPath, PathMember};
|
use crate::ast::{CellPath, PathMember};
|
||||||
use crate::engine::CaptureBlock;
|
use crate::engine::{Block, Closure};
|
||||||
use crate::ShellError;
|
use crate::ShellError;
|
||||||
use crate::{Range, Spanned, Value};
|
use crate::{Range, Spanned, Value};
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
@ -502,13 +503,31 @@ impl FromValue for (Vec<String>, Vec<Value>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue for CaptureBlock {
|
impl FromValue for Closure {
|
||||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Block { val, captures, .. } => Ok(CaptureBlock {
|
Value::Closure { val, captures, .. } => Ok(Closure {
|
||||||
block_id: *val,
|
block_id: *val,
|
||||||
captures: captures.clone(),
|
captures: captures.clone(),
|
||||||
}),
|
}),
|
||||||
|
Value::Block { val, .. } => Ok(Closure {
|
||||||
|
block_id: *val,
|
||||||
|
captures: HashMap::new(),
|
||||||
|
}),
|
||||||
|
v => Err(ShellError::CantConvert(
|
||||||
|
"Closure".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromValue for Block {
|
||||||
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
|
match v {
|
||||||
|
Value::Block { val, .. } => Ok(Block { block_id: *val }),
|
||||||
v => Err(ShellError::CantConvert(
|
v => Err(ShellError::CantConvert(
|
||||||
"Block".into(),
|
"Block".into(),
|
||||||
v.get_type().to_string(),
|
v.get_type().to_string(),
|
||||||
@ -519,22 +538,22 @@ impl FromValue for CaptureBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue for Spanned<CaptureBlock> {
|
impl FromValue for Spanned<Closure> {
|
||||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Block {
|
Value::Closure {
|
||||||
val,
|
val,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
} => Ok(Spanned {
|
} => Ok(Spanned {
|
||||||
item: CaptureBlock {
|
item: Closure {
|
||||||
block_id: *val,
|
block_id: *val,
|
||||||
captures: captures.clone(),
|
captures: captures.clone(),
|
||||||
},
|
},
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
v => Err(ShellError::CantConvert(
|
v => Err(ShellError::CantConvert(
|
||||||
"Block".into(),
|
"Closure".into(),
|
||||||
v.get_type().to_string(),
|
v.get_type().to_string(),
|
||||||
v.span()?,
|
v.span()?,
|
||||||
None,
|
None,
|
||||||
|
@ -78,6 +78,10 @@ pub enum Value {
|
|||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
|
val: BlockId,
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
Closure {
|
||||||
val: BlockId,
|
val: BlockId,
|
||||||
captures: HashMap<VarId, Value>,
|
captures: HashMap<VarId, Value>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -146,11 +150,15 @@ impl Clone for Value {
|
|||||||
vals: vals.clone(),
|
vals: vals.clone(),
|
||||||
span: *span,
|
span: *span,
|
||||||
},
|
},
|
||||||
Value::Block {
|
Value::Block { val, span } => Value::Block {
|
||||||
|
val: *val,
|
||||||
|
span: *span,
|
||||||
|
},
|
||||||
|
Value::Closure {
|
||||||
val,
|
val,
|
||||||
captures,
|
captures,
|
||||||
span,
|
span,
|
||||||
} => Value::Block {
|
} => Value::Closure {
|
||||||
val: *val,
|
val: *val,
|
||||||
captures: captures.clone(),
|
captures: captures.clone(),
|
||||||
span: *span,
|
span: *span,
|
||||||
@ -246,6 +254,7 @@ impl Value {
|
|||||||
pub fn as_block(&self) -> Result<BlockId, ShellError> {
|
pub fn as_block(&self) -> Result<BlockId, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Block { val, .. } => Ok(*val),
|
Value::Block { val, .. } => Ok(*val),
|
||||||
|
Value::Closure { val, .. } => Ok(*val),
|
||||||
x => Err(ShellError::CantConvert(
|
x => Err(ShellError::CantConvert(
|
||||||
"block".into(),
|
"block".into(),
|
||||||
x.get_type().to_string(),
|
x.get_type().to_string(),
|
||||||
@ -344,6 +353,7 @@ impl Value {
|
|||||||
Value::Record { span, .. } => Ok(*span),
|
Value::Record { span, .. } => Ok(*span),
|
||||||
Value::List { span, .. } => Ok(*span),
|
Value::List { span, .. } => Ok(*span),
|
||||||
Value::Block { span, .. } => Ok(*span),
|
Value::Block { span, .. } => Ok(*span),
|
||||||
|
Value::Closure { span, .. } => Ok(*span),
|
||||||
Value::Nothing { span, .. } => Ok(*span),
|
Value::Nothing { span, .. } => Ok(*span),
|
||||||
Value::Binary { span, .. } => Ok(*span),
|
Value::Binary { span, .. } => Ok(*span),
|
||||||
Value::CellPath { span, .. } => Ok(*span),
|
Value::CellPath { span, .. } => Ok(*span),
|
||||||
@ -364,6 +374,7 @@ impl Value {
|
|||||||
Value::String { span, .. } => *span = new_span,
|
Value::String { span, .. } => *span = new_span,
|
||||||
Value::Record { span, .. } => *span = new_span,
|
Value::Record { span, .. } => *span = new_span,
|
||||||
Value::List { span, .. } => *span = new_span,
|
Value::List { span, .. } => *span = new_span,
|
||||||
|
Value::Closure { span, .. } => *span = new_span,
|
||||||
Value::Block { span, .. } => *span = new_span,
|
Value::Block { span, .. } => *span = new_span,
|
||||||
Value::Nothing { span, .. } => *span = new_span,
|
Value::Nothing { span, .. } => *span = new_span,
|
||||||
Value::Error { .. } => {}
|
Value::Error { .. } => {}
|
||||||
@ -418,6 +429,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
Value::Nothing { .. } => Type::Nothing,
|
Value::Nothing { .. } => Type::Nothing,
|
||||||
Value::Block { .. } => Type::Block,
|
Value::Block { .. } => Type::Block,
|
||||||
|
Value::Closure { .. } => Type::Closure,
|
||||||
Value::Error { .. } => Type::Error,
|
Value::Error { .. } => Type::Error,
|
||||||
Value::Binary { .. } => Type::Binary,
|
Value::Binary { .. } => Type::Binary,
|
||||||
Value::CellPath { .. } => Type::CellPath,
|
Value::CellPath { .. } => Type::CellPath,
|
||||||
@ -490,6 +502,7 @@ impl Value {
|
|||||||
.join(separator)
|
.join(separator)
|
||||||
),
|
),
|
||||||
Value::Block { val, .. } => format!("<Block {}>", val),
|
Value::Block { val, .. } => format!("<Block {}>", val),
|
||||||
|
Value::Closure { val, .. } => format!("<Closure {}>", val),
|
||||||
Value::Nothing { .. } => String::new(),
|
Value::Nothing { .. } => String::new(),
|
||||||
Value::Error { error } => format!("{:?}", error),
|
Value::Error { error } => format!("{:?}", error),
|
||||||
Value::Binary { val, .. } => format!("{:?}", val),
|
Value::Binary { val, .. } => format!("{:?}", val),
|
||||||
@ -533,6 +546,7 @@ impl Value {
|
|||||||
if cols.len() == 1 { "" } else { "s" }
|
if cols.len() == 1 { "" } else { "s" }
|
||||||
),
|
),
|
||||||
Value::Block { val, .. } => format!("<Block {}>", val),
|
Value::Block { val, .. } => format!("<Block {}>", val),
|
||||||
|
Value::Closure { val, .. } => format!("<Closure {}>", val),
|
||||||
Value::Nothing { .. } => String::new(),
|
Value::Nothing { .. } => String::new(),
|
||||||
Value::Error { error } => format!("{:?}", error),
|
Value::Error { error } => format!("{:?}", error),
|
||||||
Value::Binary { val, .. } => format!("{:?}", val),
|
Value::Binary { val, .. } => format!("{:?}", val),
|
||||||
@ -579,6 +593,7 @@ impl Value {
|
|||||||
.join(separator)
|
.join(separator)
|
||||||
),
|
),
|
||||||
Value::Block { val, .. } => format!("<Block {}>", val),
|
Value::Block { val, .. } => format!("<Block {}>", val),
|
||||||
|
Value::Closure { val, .. } => format!("<Closure {}>", val),
|
||||||
Value::Nothing { .. } => String::new(),
|
Value::Nothing { .. } => String::new(),
|
||||||
Value::Error { error } => format!("{:?}", error),
|
Value::Error { error } => format!("{:?}", error),
|
||||||
Value::Binary { val, .. } => format!("{:?}", val),
|
Value::Binary { val, .. } => format!("{:?}", val),
|
||||||
@ -1330,6 +1345,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1348,6 +1364,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1366,6 +1383,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1384,6 +1402,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1402,6 +1421,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1420,6 +1440,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1438,6 +1459,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1456,6 +1478,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Less),
|
Value::Record { .. } => Some(Ordering::Less),
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1500,6 +1523,7 @@ impl PartialOrd for Value {
|
|||||||
}
|
}
|
||||||
Value::List { .. } => Some(Ordering::Less),
|
Value::List { .. } => Some(Ordering::Less),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1518,6 +1542,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { vals: rhs, .. } => lhs.partial_cmp(rhs),
|
Value::List { vals: rhs, .. } => lhs.partial_cmp(rhs),
|
||||||
Value::Block { .. } => Some(Ordering::Less),
|
Value::Block { .. } => Some(Ordering::Less),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1536,6 +1561,26 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { .. } => Some(Ordering::Greater),
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
Value::Block { val: rhs, .. } => lhs.partial_cmp(rhs),
|
Value::Block { val: rhs, .. } => lhs.partial_cmp(rhs),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Less),
|
||||||
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
|
Value::CellPath { .. } => Some(Ordering::Less),
|
||||||
|
Value::CustomValue { .. } => Some(Ordering::Less),
|
||||||
|
},
|
||||||
|
(Value::Closure { val: lhs, .. }, rhs) => match rhs {
|
||||||
|
Value::Bool { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Int { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Float { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Filesize { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Duration { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Date { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Range { .. } => Some(Ordering::Greater),
|
||||||
|
Value::String { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Block { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Closure { val: rhs, .. } => lhs.partial_cmp(rhs),
|
||||||
Value::Nothing { .. } => Some(Ordering::Less),
|
Value::Nothing { .. } => Some(Ordering::Less),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1554,6 +1599,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { .. } => Some(Ordering::Greater),
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
Value::Block { .. } => Some(Ordering::Greater),
|
Value::Block { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Greater),
|
||||||
Value::Nothing { .. } => Some(Ordering::Equal),
|
Value::Nothing { .. } => Some(Ordering::Equal),
|
||||||
Value::Error { .. } => Some(Ordering::Less),
|
Value::Error { .. } => Some(Ordering::Less),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1572,6 +1618,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { .. } => Some(Ordering::Greater),
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
Value::Block { .. } => Some(Ordering::Greater),
|
Value::Block { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Greater),
|
||||||
Value::Nothing { .. } => Some(Ordering::Greater),
|
Value::Nothing { .. } => Some(Ordering::Greater),
|
||||||
Value::Error { .. } => Some(Ordering::Equal),
|
Value::Error { .. } => Some(Ordering::Equal),
|
||||||
Value::Binary { .. } => Some(Ordering::Less),
|
Value::Binary { .. } => Some(Ordering::Less),
|
||||||
@ -1590,6 +1637,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { .. } => Some(Ordering::Greater),
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
Value::Block { .. } => Some(Ordering::Greater),
|
Value::Block { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Greater),
|
||||||
Value::Nothing { .. } => Some(Ordering::Greater),
|
Value::Nothing { .. } => Some(Ordering::Greater),
|
||||||
Value::Error { .. } => Some(Ordering::Greater),
|
Value::Error { .. } => Some(Ordering::Greater),
|
||||||
Value::Binary { val: rhs, .. } => lhs.partial_cmp(rhs),
|
Value::Binary { val: rhs, .. } => lhs.partial_cmp(rhs),
|
||||||
@ -1608,6 +1656,7 @@ impl PartialOrd for Value {
|
|||||||
Value::Record { .. } => Some(Ordering::Greater),
|
Value::Record { .. } => Some(Ordering::Greater),
|
||||||
Value::List { .. } => Some(Ordering::Greater),
|
Value::List { .. } => Some(Ordering::Greater),
|
||||||
Value::Block { .. } => Some(Ordering::Greater),
|
Value::Block { .. } => Some(Ordering::Greater),
|
||||||
|
Value::Closure { .. } => Some(Ordering::Greater),
|
||||||
Value::Nothing { .. } => Some(Ordering::Greater),
|
Value::Nothing { .. } => Some(Ordering::Greater),
|
||||||
Value::Error { .. } => Some(Ordering::Greater),
|
Value::Error { .. } => Some(Ordering::Greater),
|
||||||
Value::Binary { .. } => Some(Ordering::Greater),
|
Value::Binary { .. } => Some(Ordering::Greater),
|
||||||
|
@ -107,7 +107,7 @@ fn missing_flags_are_nothing4() -> TestResult {
|
|||||||
#[test]
|
#[test]
|
||||||
fn proper_variable_captures() -> TestResult {
|
fn proper_variable_captures() -> TestResult {
|
||||||
run_test(
|
run_test(
|
||||||
r#"def foo [x] { let y = 100; { $y + $x } }; do (foo 23)"#,
|
r#"def foo [x] { let y = 100; { || $y + $x } }; do (foo 23)"#,
|
||||||
"123",
|
"123",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user