ListStream touchup (#12524)

# Description

Does some misc changes to `ListStream`:
- Moves it into its own module/file separate from `RawStream`.
- `ListStream`s now have an associated `Span`.
- This required changes to `ListStreamInfo` in `nu-plugin`. Note sure if
this is a breaking change for the plugin protocol.
- Hides the internals of `ListStream` but also adds a few more methods.
- This includes two functions to more easily alter a stream (these take
a `ListStream` and return a `ListStream` instead of having to go through
the whole `into_pipeline_data(..)` route).
  -  `map`: takes a `FnMut(Value) -> Value`
  - `modify`: takes a function to modify the inner stream.
This commit is contained in:
Ian Manske 2024-05-05 16:00:59 +00:00 committed by GitHub
parent 3143ded374
commit e879d4ecaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
106 changed files with 957 additions and 874 deletions

View File

@ -107,7 +107,7 @@ impl Command for History {
file: history_path.display().to_string(), file: history_path.display().to_string(),
span: head, span: head,
})? })?
.into_pipeline_data(ctrlc)), .into_pipeline_data(head, ctrlc)),
HistoryFileFormat::Sqlite => Ok(history_reader HistoryFileFormat::Sqlite => Ok(history_reader
.and_then(|h| { .and_then(|h| {
h.search(SearchQuery::everything(SearchDirection::Forward, None)) h.search(SearchQuery::everything(SearchDirection::Forward, None))
@ -122,7 +122,7 @@ impl Command for History {
file: history_path.display().to_string(), file: history_path.display().to_string(),
span: head, span: head,
})? })?
.into_pipeline_data(ctrlc)), .into_pipeline_data(head, ctrlc)),
} }
} }
} else { } else {

View File

@ -87,7 +87,7 @@ impl Command for EachWhile {
Err(_) => None, Err(_) => None,
}) })
.fuse() .fuse()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()),
PipelineData::ExternalStream { PipelineData::ExternalStream {
@ -108,7 +108,7 @@ impl Command for EachWhile {
} }
}) })
.fuse() .fuse()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
// This match allows non-iterables to be accepted, // This match allows non-iterables to be accepted,
// which is currently considered undesirable (Nov 2022). // which is currently considered undesirable (Nov 2022).

View File

@ -108,7 +108,7 @@ impl Command for UpdateCells {
columns, columns,
span: head, span: head,
} }
.into_pipeline_data(engine_state.ctrlc.clone()) .into_pipeline_data(head, engine_state.ctrlc.clone())
.set_metadata(metadata)) .set_metadata(metadata))
} }
} }

View File

@ -238,10 +238,7 @@ fn format(
} }
} }
Ok(PipelineData::ListStream( Ok(ListStream::new(list.into_iter(), head_span, engine_state.ctrlc.clone()).into())
ListStream::from_stream(list.into_iter(), None),
None,
))
} }
// Unwrapping this ShellError is a bit unfortunate. // Unwrapping this ShellError is a bit unfortunate.
// Ideally, its Span would be preserved. // Ideally, its Span would be preserved.

View File

@ -62,6 +62,7 @@ impl Command for Do {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let block: Closure = call.req(engine_state, caller_stack, 0)?; let block: Closure = call.req(engine_state, caller_stack, 0)?;
let rest: Vec<Value> = call.rest(engine_state, caller_stack, 1)?; let rest: Vec<Value> = call.rest(engine_state, caller_stack, 1)?;
let ignore_all_errors = call.has_flag(engine_state, caller_stack, "ignore-errors")?; let ignore_all_errors = call.has_flag(engine_state, caller_stack, "ignore-errors")?;
@ -75,7 +76,7 @@ impl Command for Do {
let mut callee_stack = caller_stack.captures_to_stack_preserve_out_dest(block.captures); let mut callee_stack = caller_stack.captures_to_stack_preserve_out_dest(block.captures);
let block = engine_state.get_block(block.block_id); let block = engine_state.get_block(block.block_id);
bind_args_to(&mut callee_stack, &block.signature, rest, call.head)?; bind_args_to(&mut callee_stack, &block.signature, rest, head)?;
let eval_block_with_early_return = get_eval_block_with_early_return(engine_state); let eval_block_with_early_return = get_eval_block_with_early_return(engine_state);
let result = eval_block_with_early_return(engine_state, &mut callee_stack, block, input); let result = eval_block_with_early_return(engine_state, &mut callee_stack, block, input);
@ -117,7 +118,7 @@ impl Command for Do {
None, None,
) )
}) })
.err_span(call.head) .err_span(head)
}) })
.transpose()?; .transpose()?;
@ -148,13 +149,9 @@ impl Command for Do {
None None
}; };
let mut exit_code_ctrlc = None;
let exit_code: Vec<Value> = match exit_code { let exit_code: Vec<Value> = match exit_code {
None => vec![], None => vec![],
Some(exit_code_stream) => { Some(exit_code_stream) => exit_code_stream.into_iter().collect(),
exit_code_ctrlc.clone_from(&exit_code_stream.ctrlc);
exit_code_stream.into_iter().collect()
}
}; };
if let Some(Value::Int { val: code, .. }) = exit_code.last() { if let Some(Value::Int { val: code, .. }) = exit_code.last() {
if *code != 0 { if *code != 0 {
@ -174,10 +171,7 @@ impl Command for Do {
span, span,
None, None,
)), )),
exit_code: Some(ListStream::from_stream( exit_code: Some(ListStream::new(exit_code.into_iter(), span, None)),
exit_code.into_iter(),
exit_code_ctrlc,
)),
span, span,
metadata, metadata,
trim_end_newline, trim_end_newline,
@ -205,21 +199,15 @@ impl Command for Do {
Ok(PipelineData::Value(Value::Error { .. }, ..)) | Err(_) if ignore_shell_errors => { Ok(PipelineData::Value(Value::Error { .. }, ..)) | Err(_) if ignore_shell_errors => {
Ok(PipelineData::empty()) Ok(PipelineData::empty())
} }
Ok(PipelineData::ListStream(ls, metadata)) if ignore_shell_errors => { Ok(PipelineData::ListStream(stream, metadata)) if ignore_shell_errors => {
// check if there is a `Value::Error` in given list stream first. let stream = stream.map(move |value| {
let mut values = vec![]; if let Value::Error { .. } = value {
let ctrlc = ls.ctrlc.clone(); Value::nothing(head)
for v in ls {
if let Value::Error { .. } = v {
values.push(Value::nothing(call.head));
} else { } else {
values.push(v) value
} }
} });
Ok(PipelineData::ListStream( Ok(PipelineData::ListStream(stream, metadata))
ListStream::from_stream(values.into_iter(), ctrlc),
metadata,
))
} }
r => r, r => r,
} }

View File

@ -1,5 +1,4 @@
use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression}; use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression};
use nu_protocol::ListStream;
#[derive(Clone)] #[derive(Clone)]
pub struct For; pub struct For;
@ -88,7 +87,11 @@ impl Command for For {
let span = value.span(); let span = value.span();
match value { match value {
Value::List { vals, .. } => { Value::List { vals, .. } => {
for (idx, x) in ListStream::from_stream(vals.into_iter(), ctrlc).enumerate() { for (idx, x) in vals.into_iter().enumerate() {
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
break;
}
// with_env() is used here to ensure that each iteration uses // with_env() is used here to ensure that each iteration uses
// a different set of environment variables. // a different set of environment variables.
// Hence, a 'cd' in the first loop won't affect the next loop. // Hence, a 'cd' in the first loop won't affect the next loop.

View File

@ -26,13 +26,10 @@ impl Command for ScopeAliases {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let mut scope_data = ScopeData::new(engine_state, stack); let mut scope_data = ScopeData::new(engine_state, stack);
scope_data.populate_decls(); scope_data.populate_decls();
Ok(Value::list(scope_data.collect_aliases(head), head).into_pipeline_data())
Ok(scope_data.collect_aliases(span).into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -26,13 +26,10 @@ impl Command for ScopeCommands {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let mut scope_data = ScopeData::new(engine_state, stack); let mut scope_data = ScopeData::new(engine_state, stack);
scope_data.populate_decls(); scope_data.populate_decls();
Ok(Value::list(scope_data.collect_commands(head), head).into_pipeline_data())
Ok(scope_data.collect_commands(span).into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -26,13 +26,10 @@ impl Command for ScopeExterns {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let mut scope_data = ScopeData::new(engine_state, stack); let mut scope_data = ScopeData::new(engine_state, stack);
scope_data.populate_decls(); scope_data.populate_decls();
Ok(Value::list(scope_data.collect_externs(head), head).into_pipeline_data())
Ok(scope_data.collect_externs(span).into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -26,13 +26,10 @@ impl Command for ScopeModules {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let mut scope_data = ScopeData::new(engine_state, stack); let mut scope_data = ScopeData::new(engine_state, stack);
scope_data.populate_modules(); scope_data.populate_modules();
Ok(Value::list(scope_data.collect_modules(head), head).into_pipeline_data())
Ok(scope_data.collect_modules(span).into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -26,13 +26,10 @@ impl Command for ScopeVariables {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let mut scope_data = ScopeData::new(engine_state, stack); let mut scope_data = ScopeData::new(engine_state, stack);
scope_data.populate_vars(); scope_data.populate_vars();
Ok(Value::list(scope_data.collect_vars(head), head).into_pipeline_data())
Ok(scope_data.collect_vars(span).into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -69,35 +69,47 @@ impl Command for PluginList {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.span(); let head = call.head;
// Group plugin decls by plugin identity // Group plugin decls by plugin identity
let decls = engine_state.plugin_decls().into_group_map_by(|decl| { let decls = engine_state.plugin_decls().into_group_map_by(|decl| {
decl.plugin_identity() decl.plugin_identity()
.expect("plugin decl should have identity") .expect("plugin decl should have identity")
}); });
// Build plugins list // Build plugins list
let list = engine_state.plugins().iter().map(|plugin| { let list = engine_state.plugins().iter().map(|plugin| {
// Find commands that belong to the plugin // Find commands that belong to the plugin
let commands = decls.get(plugin.identity()) let commands = decls.get(plugin.identity())
.into_iter() .into_iter()
.flat_map(|decls| { .flat_map(|decls| {
decls.iter().map(|decl| Value::string(decl.name(), span)) decls.iter().map(|decl| Value::string(decl.name(), head))
}) })
.collect(); .collect();
Value::record(record! { let pid = plugin
"name" => Value::string(plugin.identity().name(), span), .pid()
"is_running" => Value::bool(plugin.is_running(), span), .map(|p| Value::int(p as i64, head))
"pid" => plugin.pid() .unwrap_or(Value::nothing(head));
.map(|p| Value::int(p as i64, span))
.unwrap_or(Value::nothing(span)), let shell = plugin
"filename" => Value::string(plugin.identity().filename().to_string_lossy(), span), .identity()
"shell" => plugin.identity().shell() .shell()
.map(|s| Value::string(s.to_string_lossy(), span)) .map(|s| Value::string(s.to_string_lossy(), head))
.unwrap_or(Value::nothing(span)), .unwrap_or(Value::nothing(head));
"commands" => Value::list(commands, span),
}, span) let record = record! {
}).collect::<Vec<Value>>(); "name" => Value::string(plugin.identity().name(), head),
Ok(list.into_pipeline_data(engine_state.ctrlc.clone())) "is_running" => Value::bool(plugin.is_running(), head),
"pid" => pid,
"filename" => Value::string(plugin.identity().filename().to_string_lossy(), head),
"shell" => shell,
"commands" => Value::list(commands, head),
};
Value::record(record, head)
}).collect();
Ok(Value::list(list, head).into_pipeline_data())
} }
} }

View File

@ -98,7 +98,7 @@ fn into_cell_path(call: &Call, input: PipelineData) -> Result<PipelineData, Shel
match input { match input {
PipelineData::Value(value, _) => Ok(value_to_cell_path(&value, head)?.into_pipeline_data()), PipelineData::Value(value, _) => Ok(value_to_cell_path(&value, head)?.into_pipeline_data()),
PipelineData::ListStream(stream, ..) => { PipelineData::ListStream(stream, ..) => {
let list: Vec<_> = stream.collect(); let list: Vec<_> = stream.into_iter().collect();
Ok(list_to_cell_path(&list, head)?.into_pipeline_data()) Ok(list_to_cell_path(&list, head)?.into_pipeline_data())
} }
PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType { PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType {

View File

@ -81,7 +81,7 @@ impl Command for IntoValue {
display_as_filesizes, display_as_filesizes,
span, span,
} }
.into_pipeline_data(ctrlc) .into_pipeline_data(span, ctrlc)
.set_metadata(metadata)) .set_metadata(metadata))
} }
} }

View File

@ -203,8 +203,8 @@ fn action(
ctrl_c: Option<Arc<AtomicBool>>, ctrl_c: Option<Arc<AtomicBool>>,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
match input { match input {
PipelineData::ListStream(list_stream, _) => { PipelineData::ListStream(stream, _) => {
insert_in_transaction(list_stream.stream, span, table, ctrl_c) insert_in_transaction(stream.into_iter(), span, table, ctrl_c)
} }
PipelineData::Value( PipelineData::Value(
Value::List { Value::List {

View File

@ -30,17 +30,17 @@ impl Command for SubCommand {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; let head = call.head;
Ok(TZ_VARIANTS Ok(TZ_VARIANTS
.iter() .iter()
.map(move |x| { .map(move |x| {
Value::record( Value::record(
record! { "timezone" => Value::string(x.name(), span) }, record! { "timezone" => Value::string(x.name(), head) },
span, head,
) )
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -34,16 +34,14 @@ impl Command for Explain {
stack: &mut Stack, stack: &mut Stack,
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
// This was all delightfully stolen from benchmark :) // This was all delightfully stolen from benchmark :)
let capture_block: Closure = 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 ctrlc = engine_state.ctrlc.clone();
let mut stack = stack.captures_to_stack(capture_block.captures); let mut stack = stack.captures_to_stack(capture_block.captures);
let elements = get_pipeline_elements(engine_state, &mut stack, block, head);
let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head); Ok(Value::list(elements, head).into_pipeline_data())
Ok(elements.into_pipeline_data(ctrlc))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -47,13 +47,21 @@ impl Command for MetadataSet {
let metadata = PipelineMetadata { let metadata = PipelineMetadata {
data_source: DataSource::FilePath(path.into()), data_source: DataSource::FilePath(path.into()),
}; };
Ok(input.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(input.into_pipeline_data_with_metadata(
head,
engine_state.ctrlc.clone(),
metadata,
))
} }
(None, true) => { (None, true) => {
let metadata = PipelineMetadata { let metadata = PipelineMetadata {
data_source: DataSource::Ls, data_source: DataSource::Ls,
}; };
Ok(input.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(input.into_pipeline_data_with_metadata(
head,
engine_state.ctrlc.clone(),
metadata,
))
} }
_ => Err(ShellError::IncorrectValue { _ => Err(ShellError::IncorrectValue {
msg: "Expected either --datasource-ls(-l) or --datasource-filepath(-f)".to_string(), msg: "Expected either --datasource-ls(-l) or --datasource-filepath(-f)".to_string(),

View File

@ -121,7 +121,7 @@ impl Command for Du {
}; };
Ok( Ok(
du_for_one_pattern(args, &current_dir, tag, engine_state.ctrlc.clone())? du_for_one_pattern(args, &current_dir, tag, engine_state.ctrlc.clone())?
.into_pipeline_data(engine_state.ctrlc.clone()), .into_pipeline_data(tag, engine_state.ctrlc.clone()),
) )
} }
Some(paths) => { Some(paths) => {
@ -147,7 +147,7 @@ impl Command for Du {
Ok(result_iters Ok(result_iters
.into_iter() .into_iter()
.flatten() .flatten()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(tag, engine_state.ctrlc.clone()))
} }
} }
} }

View File

@ -199,7 +199,7 @@ impl Command for Glob {
} }
}; };
Ok(if !not_patterns.is_empty() { let result = if !not_patterns.is_empty() {
let np: Vec<&str> = not_patterns.iter().map(|s| s as &str).collect(); let np: Vec<&str> = not_patterns.iter().map(|s| s as &str).collect();
let glob_results = glob let glob_results = glob
.walk_with_behavior( .walk_with_behavior(
@ -218,10 +218,7 @@ impl Command for Glob {
inner: vec![], inner: vec![],
})? })?
.flatten(); .flatten();
let result = glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)?; glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)
result
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone())
} else { } else {
let glob_results = glob let glob_results = glob
.walk_with_behavior( .walk_with_behavior(
@ -232,11 +229,12 @@ impl Command for Glob {
}, },
) )
.flatten(); .flatten();
let result = glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)?; glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)
result }?;
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()) Ok(result
}) .into_iter()
.into_pipeline_data(span, engine_state.ctrlc.clone()))
} }
} }

View File

@ -115,10 +115,11 @@ impl Command for Ls {
match input_pattern_arg { match input_pattern_arg {
None => Ok(ls_for_one_pattern(None, args, ctrl_c.clone(), cwd)? None => Ok(ls_for_one_pattern(None, args, ctrl_c.clone(), cwd)?
.into_pipeline_data_with_metadata( .into_pipeline_data_with_metadata(
call_span,
ctrl_c,
PipelineMetadata { PipelineMetadata {
data_source: DataSource::Ls, data_source: DataSource::Ls,
}, },
ctrl_c,
)), )),
Some(pattern) => { Some(pattern) => {
let mut result_iters = vec![]; let mut result_iters = vec![];
@ -137,10 +138,11 @@ impl Command for Ls {
.into_iter() .into_iter()
.flatten() .flatten()
.into_pipeline_data_with_metadata( .into_pipeline_data_with_metadata(
call_span,
ctrl_c,
PipelineMetadata { PipelineMetadata {
data_source: DataSource::Ls, data_source: DataSource::Ls,
}, },
ctrl_c,
)) ))
} }
} }

View File

@ -209,7 +209,10 @@ impl Command for Open {
} else if output.len() == 1 { } else if output.len() == 1 {
Ok(output.remove(0)) Ok(output.remove(0))
} else { } else {
Ok(output.into_iter().flatten().into_pipeline_data(ctrlc)) Ok(output
.into_iter()
.flatten()
.into_pipeline_data(call_span, ctrlc))
} }
} }

View File

@ -465,7 +465,7 @@ fn rm(
} }
}) })
.filter(|x| !matches!(x.get_type(), Type::Nothing)) .filter(|x| !matches!(x.get_type(), Type::Nothing))
.into_pipeline_data(ctrlc) .into_pipeline_data(span, ctrlc)
.print_not_formatted(engine_state, false, true)?; .print_not_formatted(engine_state, false, true)?;
Ok(PipelineData::empty()) Ok(PipelineData::empty())

View File

@ -116,7 +116,7 @@ only unwrap the outer list, and leave the variable's contents untouched."#
Ok(input Ok(input
.into_iter() .into_iter()
.chain(other.into_pipeline_data()) .chain(other.into_pipeline_data())
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -62,73 +62,68 @@ impl Command for Columns {
fn run( fn run(
&self, &self,
engine_state: &EngineState, _engine_state: &EngineState,
_stack: &mut Stack, _stack: &mut Stack,
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = call.head; getcol(call.head, input)
getcol(engine_state, span, input)
} }
} }
fn getcol( fn getcol(head: Span, input: PipelineData) -> Result<PipelineData, ShellError> {
engine_state: &EngineState,
head: Span,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let ctrlc = engine_state.ctrlc.clone();
let metadata = input.metadata(); let metadata = input.metadata();
match input { match input {
PipelineData::Empty => Ok(PipelineData::Empty), PipelineData::Empty => Ok(PipelineData::Empty),
PipelineData::Value(v, ..) => { PipelineData::Value(v, ..) => {
let span = v.span(); let span = v.span();
match v { let cols = match v {
Value::List { Value::List {
vals: input_vals, .. vals: input_vals, ..
} => { } => get_columns(&input_vals)
let input_cols = get_columns(&input_vals); .into_iter()
Ok(input_cols .map(move |x| Value::string(x, span))
.into_iter() .collect(),
.map(move |x| Value::string(x, span))
.into_pipeline_data(ctrlc)
.set_metadata(metadata))
}
Value::Custom { val, .. } => { Value::Custom { val, .. } => {
// TODO: should we get CustomValue to expose columns in a more efficient way? // TODO: should we get CustomValue to expose columns in a more efficient way?
// Would be nice to be able to get columns without generating the whole value // Would be nice to be able to get columns without generating the whole value
let input_as_base_value = val.to_base_value(span)?; let input_as_base_value = val.to_base_value(span)?;
let input_cols = get_columns(&[input_as_base_value]); get_columns(&[input_as_base_value])
Ok(input_cols
.into_iter() .into_iter()
.map(move |x| Value::string(x, span)) .map(move |x| Value::string(x, span))
.into_pipeline_data(ctrlc) .collect()
.set_metadata(metadata))
} }
Value::Record { val, .. } => Ok(val Value::Record { val, .. } => val
.into_owned() .into_owned()
.into_iter() .into_iter()
.map(move |(x, _)| Value::string(x, head)) .map(move |(x, _)| Value::string(x, head))
.into_pipeline_data(ctrlc) .collect(),
.set_metadata(metadata)),
// Propagate errors // Propagate errors
Value::Error { error, .. } => Err(*error), Value::Error { error, .. } => return Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => {
exp_input_type: "record or table".into(), return Err(ShellError::OnlySupportsThisInputType {
wrong_type: other.get_type().to_string(), exp_input_type: "record or table".into(),
dst_span: head, wrong_type: other.get_type().to_string(),
src_span: other.span(), dst_span: head,
}), src_span: other.span(),
} })
}
};
Ok(Value::list(cols, head)
.into_pipeline_data()
.set_metadata(metadata))
} }
PipelineData::ListStream(stream, ..) => { PipelineData::ListStream(stream, ..) => {
let v: Vec<_> = stream.into_iter().collect(); let values = stream.into_iter().collect::<Vec<_>>();
let input_cols = get_columns(&v); let cols = get_columns(&values)
Ok(input_cols
.into_iter() .into_iter()
.map(move |x| Value::string(x, head)) .map(|s| Value::string(s, head))
.into_pipeline_data_with_metadata(metadata, ctrlc)) .collect();
Ok(Value::list(cols, head)
.into_pipeline_data()
.set_metadata(metadata))
} }
PipelineData::ExternalStream { .. } => Err(ShellError::OnlySupportsThisInputType { PipelineData::ExternalStream { .. } => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "record or table".into(), exp_input_type: "record or table".into(),

View File

@ -90,7 +90,8 @@ fn drop_cols(
// is displayed farther to the right. // is displayed farther to the right.
let metadata = input.metadata(); let metadata = input.metadata();
match input { match input {
PipelineData::ListStream(mut stream, ..) => { PipelineData::ListStream(stream, ..) => {
let mut stream = stream.into_iter();
if let Some(mut first) = stream.next() { if let Some(mut first) = stream.next() {
let drop_cols = drop_cols_set(&mut first, head, columns)?; let drop_cols = drop_cols_set(&mut first, head, columns)?;
@ -101,7 +102,7 @@ fn drop_cols(
Err(e) => Value::error(e, head), Err(e) => Value::error(e, head),
} }
})) }))
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} else { } else {
Ok(PipelineData::Empty) Ok(PipelineData::Empty)
} }

View File

@ -100,6 +100,7 @@ impl Command for DropNth {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let metadata = input.metadata(); let metadata = input.metadata();
let number_or_range = extract_int_or_range(engine_state, stack, call)?; let number_or_range = extract_int_or_range(engine_state, stack, call)?;
@ -115,7 +116,7 @@ impl Command for DropNth {
return Err(ShellError::UnsupportedInput { return Err(ShellError::UnsupportedInput {
msg: "float range".into(), msg: "float range".into(),
input: "value originates from here".into(), input: "value originates from here".into(),
msg_span: call.head, msg_span: head,
input_span: number_or_range.span, input_span: number_or_range.span,
}); });
} }
@ -129,7 +130,7 @@ impl Command for DropNth {
return Err(ShellError::UnsupportedInput { return Err(ShellError::UnsupportedInput {
msg: "drop nth accepts only positive ints".into(), msg: "drop nth accepts only positive ints".into(),
input: "value originates from here".into(), input: "value originates from here".into(),
msg_span: call.head, msg_span: head,
input_span: number_or_range.span, input_span: number_or_range.span,
}); });
} }
@ -139,7 +140,7 @@ impl Command for DropNth {
msg: "The upper bound needs to be equal or larger to the lower bound" msg: "The upper bound needs to be equal or larger to the lower bound"
.into(), .into(),
input: "value originates from here".into(), input: "value originates from here".into(),
msg_span: call.head, msg_span: head,
input_span: number_or_range.span, input_span: number_or_range.span,
}); });
} }
@ -154,8 +155,9 @@ impl Command for DropNth {
.into_iter() .into_iter()
.take(start) .take(start)
.into_pipeline_data_with_metadata( .into_pipeline_data_with_metadata(
metadata, head,
engine_state.ctrlc.clone(), engine_state.ctrlc.clone(),
metadata,
)) ))
} }
}; };
@ -175,7 +177,7 @@ impl Command for DropNth {
rows, rows,
current: 0, current: 0,
} }
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -138,7 +138,7 @@ with 'transpose' first."#
} }
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()),
PipelineData::ExternalStream { PipelineData::ExternalStream {
@ -170,7 +170,7 @@ with 'transpose' first."#
} }
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
// This match allows non-iterables to be accepted, // This match allows non-iterables to be accepted,
// which is currently considered undesirable (Nov 2022). // which is currently considered undesirable (Nov 2022).

View File

@ -60,10 +60,11 @@ pub fn empty(
} }
}, },
PipelineData::ListStream(s, ..) => { PipelineData::ListStream(s, ..) => {
let empty = s.into_iter().next().is_none();
if negate { if negate {
Ok(Value::bool(s.count() != 0, head).into_pipeline_data()) Ok(Value::bool(!empty, head).into_pipeline_data())
} else { } else {
Ok(Value::bool(s.count() == 0, head).into_pipeline_data()) Ok(Value::bool(empty, head).into_pipeline_data())
} }
} }
PipelineData::Value(value, ..) => { PipelineData::Value(value, ..) => {

View File

@ -50,9 +50,9 @@ impl Command for Enumerate {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let metadata = input.metadata(); let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let span = call.head;
Ok(input Ok(input
.into_iter() .into_iter()
@ -60,13 +60,13 @@ impl Command for Enumerate {
.map(move |(idx, x)| { .map(move |(idx, x)| {
Value::record( Value::record(
record! { record! {
"index" => Value::int(idx as i64, span), "index" => Value::int(idx as i64, head),
"item" => x, "item" => x,
}, },
span, head,
) )
}) })
.into_pipeline_data_with_metadata(metadata, ctrlc)) .into_pipeline_data_with_metadata(head, ctrlc, metadata))
} }
} }

View File

@ -78,7 +78,7 @@ impl Command for Every {
None None
} }
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -67,7 +67,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
Some(Value::error(err, span)) Some(Value::error(err, span))
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()),
PipelineData::ExternalStream { PipelineData::ExternalStream {
@ -92,7 +92,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
} }
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
// This match allows non-iterables to be accepted, // This match allows non-iterables to be accepted,
// which is currently considered undesirable (Nov 2022). // which is currently considered undesirable (Nov 2022).
@ -108,7 +108,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
Some(Value::error(err, span)) Some(Value::error(err, span))
} }
} }
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
} }
.map(|data| data.set_metadata(metadata)) .map(|data| data.set_metadata(metadata))

View File

@ -3,7 +3,7 @@ use fancy_regex::Regex;
use nu_ansi_term::Style; use nu_ansi_term::Style;
use nu_color_config::StyleComputer; use nu_color_config::StyleComputer;
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::{Config, ListStream}; use nu_protocol::Config;
use nu_utils::IgnoreCaseExt; use nu_utils::IgnoreCaseExt;
#[derive(Clone)] #[derive(Clone)]
@ -416,9 +416,9 @@ fn find_with_rest_and_highlight(
}, },
ctrlc, ctrlc,
), ),
PipelineData::ListStream(stream, metadata) => Ok(ListStream::from_stream( PipelineData::ListStream(stream, metadata) => {
stream let stream = stream.modify(|iter| {
.map(move |mut x| { iter.map(move |mut x| {
let span = x.span(); let span = x.span();
match &mut x { match &mut x {
Value::Record { val, .. } => highlight_terms_in_record_with_search_columns( Value::Record { val, .. } => highlight_terms_in_record_with_search_columns(
@ -442,10 +442,11 @@ fn find_with_rest_and_highlight(
&cols_to_search_in_filter, &cols_to_search_in_filter,
invert, invert,
) )
}), })
ctrlc.clone(), });
)
.into_pipeline_data_with_metadata(metadata, ctrlc)), Ok(PipelineData::ListStream(stream, metadata))
}
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()),
PipelineData::ExternalStream { PipelineData::ExternalStream {
stdout: Some(stream), stdout: Some(stream),
@ -496,7 +497,7 @@ fn find_with_rest_and_highlight(
Err(e) => return Err(e), Err(e) => return Err(e),
}; };
} }
Ok(output.into_pipeline_data(ctrlc)) Ok(output.into_pipeline_data(span, ctrlc))
} }
} }
} }

View File

@ -143,7 +143,7 @@ fn first_helper(
} else { } else {
Ok(iter Ok(iter
.take(rows) .take(rows)
.into_pipeline_data_with_metadata(metadata, ctrlc)) .into_pipeline_data_with_metadata(span, ctrlc, metadata))
} }
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
@ -156,17 +156,18 @@ fn first_helper(
}), }),
} }
} }
PipelineData::ListStream(mut ls, metadata) => { PipelineData::ListStream(stream, metadata) => {
if return_single_element { if return_single_element {
if let Some(v) = ls.next() { if let Some(v) = stream.into_iter().next() {
Ok(v.into_pipeline_data()) Ok(v.into_pipeline_data())
} else { } else {
Err(ShellError::AccessEmptyContent { span: head }) Err(ShellError::AccessEmptyContent { span: head })
} }
} else { } else {
Ok(ls Ok(PipelineData::ListStream(
.take(rows) stream.modify(|iter| iter.take(rows)),
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) metadata,
))
} }
} }
PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType { PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType {

View File

@ -89,7 +89,7 @@ If multiple cell paths are given, this will produce a list of values."#
output.push(val?); output.push(val?);
} }
Ok(output.into_iter().into_pipeline_data(ctrlc)) Ok(output.into_iter().into_pipeline_data(span, ctrlc))
} }
.map(|x| x.set_metadata(metadata)) .map(|x| x.set_metadata(metadata))
} }

View File

@ -1,4 +1,5 @@
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::ValueIterator;
#[derive(Clone)] #[derive(Clone)]
pub struct Group; pub struct Group;
@ -52,6 +53,7 @@ impl Command for Group {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let group_size: Spanned<usize> = call.req(engine_state, stack, 0)?; let group_size: Spanned<usize> = call.req(engine_state, stack, 0)?;
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let metadata = input.metadata(); let metadata = input.metadata();
@ -61,16 +63,16 @@ impl Command for Group {
let each_group_iterator = EachGroupIterator { let each_group_iterator = EachGroupIterator {
group_size: group_size.item, group_size: group_size.item,
input: Box::new(input.into_iter()), input: Box::new(input.into_iter()),
span: call.head, span: head,
}; };
Ok(each_group_iterator.into_pipeline_data_with_metadata(metadata, ctrlc)) Ok(each_group_iterator.into_pipeline_data_with_metadata(head, ctrlc, metadata))
} }
} }
struct EachGroupIterator { struct EachGroupIterator {
group_size: usize, group_size: usize,
input: Box<dyn Iterator<Item = Value> + Send>, input: ValueIterator,
span: Span, span: Span,
} }

View File

@ -159,7 +159,7 @@ fn insert(
} }
Ok(value.into_pipeline_data_with_metadata(metadata)) Ok(value.into_pipeline_data_with_metadata(metadata))
} }
PipelineData::ListStream(mut stream, metadata) => { PipelineData::ListStream(stream, metadata) => {
if let Some(( if let Some((
&PathMember::Int { &PathMember::Int {
val, val,
@ -169,6 +169,7 @@ fn insert(
path, path,
)) = cell_path.members.split_first() )) = cell_path.members.split_first()
{ {
let mut stream = stream.into_iter();
let mut pre_elems = vec![]; let mut pre_elems = vec![];
for idx in 0..val { for idx in 0..val {
@ -221,40 +222,39 @@ fn insert(
Ok(pre_elems Ok(pre_elems
.into_iter() .into_iter()
.chain(stream) .chain(stream)
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} else if let Value::Closure { val, .. } = replacement { } else if let Value::Closure { val, .. } = replacement {
let mut closure = ClosureEval::new(engine_state, stack, val); let mut closure = ClosureEval::new(engine_state, stack, val);
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { let err = insert_value_by_closure(
let err = insert_value_by_closure( &mut value,
&mut value, &mut closure,
&mut closure, head,
head, &cell_path.members,
&cell_path.members, false,
false, );
);
if let Err(e) = err { if let Err(e) = err {
Value::error(e, head) Value::error(e, head)
} else { } else {
value value
} }
}) });
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(PipelineData::ListStream(stream, metadata))
} else { } else {
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { if let Err(e) = value.insert_data_at_cell_path(
if let Err(e) = value.insert_data_at_cell_path( &cell_path.members,
&cell_path.members, replacement.clone(),
replacement.clone(), head,
head, ) {
) { Value::error(e, head)
Value::error(e, head) } else {
} else { value
value }
} });
})
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(PipelineData::ListStream(stream, metadata))
} }
} }
PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { PipelineData::Empty => Err(ShellError::IncompatiblePathAccess {

View File

@ -147,7 +147,7 @@ interleave
// Now that threads are writing to the channel, we just return it as a stream // Now that threads are writing to the channel, we just return it as a stream
Ok(rx Ok(rx
.into_iter() .into_iter()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
} }

View File

@ -66,7 +66,7 @@ impl Command for Items {
} }
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
Value::Error { error, .. } => Err(*error), Value::Error { error, .. } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {

View File

@ -52,9 +52,8 @@ impl Command for Lines {
} }
PipelineData::Empty => Ok(PipelineData::Empty), PipelineData::Empty => Ok(PipelineData::Empty),
PipelineData::ListStream(stream, metadata) => { PipelineData::ListStream(stream, metadata) => {
let iter = stream let stream = stream.modify(|iter| {
.into_iter() iter.filter_map(move |value| {
.filter_map(move |value| {
let span = value.span(); let span = value.span();
if let Value::String { val, .. } = value { if let Value::String { val, .. } = value {
Some( Some(
@ -72,11 +71,10 @@ impl Command for Lines {
None None
} }
}) })
.flatten(); .flatten()
});
Ok(iter Ok(PipelineData::ListStream(stream, metadata))
.into_pipeline_data(engine_state.ctrlc.clone())
.set_metadata(metadata))
} }
PipelineData::Value(val, ..) => { PipelineData::Value(val, ..) => {
match val { match val {
@ -97,7 +95,7 @@ impl Command for Lines {
.. ..
} => Ok(RawStreamLinesAdapter::new(stream, head, skip_empty) } => Ok(RawStreamLinesAdapter::new(stream, head, skip_empty)
.map(move |x| x.unwrap_or_else(|err| Value::error(err, head))) .map(move |x| x.unwrap_or_else(|err| Value::error(err, head)))
.into_pipeline_data(ctrlc) .into_pipeline_data(head, ctrlc)
.set_metadata(metadata)), .set_metadata(metadata)),
} }
} }

View File

@ -85,11 +85,10 @@ repeating this process with row 1, and so on."#
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let merge_value: Value = call.req(engine_state, stack, 0)?; let merge_value: Value = call.req(engine_state, stack, 0)?;
let metadata = input.metadata(); let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let call = call.clone();
match (&input, merge_value) { match (&input, merge_value) {
// table (list of records) // table (list of records)
@ -104,29 +103,25 @@ repeating this process with row 1, and so on."#
.into_iter() .into_iter()
.map(move |inp| match (inp.as_record(), table_iter.next()) { .map(move |inp| match (inp.as_record(), table_iter.next()) {
(Ok(inp), Some(to_merge)) => match to_merge.as_record() { (Ok(inp), Some(to_merge)) => match to_merge.as_record() {
Ok(to_merge) => Value::record(do_merge(inp, to_merge), call.head), Ok(to_merge) => Value::record(do_merge(inp, to_merge), head),
Err(error) => Value::error(error, call.head), Err(error) => Value::error(error, head),
}, },
(_, None) => inp, (_, None) => inp,
(Err(error), _) => Value::error(error, call.head), (Err(error), _) => Value::error(error, head),
}); });
if let Some(md) = metadata { Ok(res.into_pipeline_data_with_metadata(head, ctrlc, metadata))
Ok(res.into_pipeline_data_with_metadata(md, ctrlc))
} else {
Ok(res.into_pipeline_data(ctrlc))
}
} }
// record // record
( (
PipelineData::Value(Value::Record { val: inp, .. }, ..), PipelineData::Value(Value::Record { val: inp, .. }, ..),
Value::Record { val: to_merge, .. }, Value::Record { val: to_merge, .. },
) => Ok(Value::record(do_merge(inp, &to_merge), call.head).into_pipeline_data()), ) => Ok(Value::record(do_merge(inp, &to_merge), head).into_pipeline_data()),
(PipelineData::Value(val, ..), ..) => { (PipelineData::Value(val, ..), ..) => {
// Only point the "value originates here" arrow at the merge value // Only point the "value originates here" arrow at the merge value
// if it was generated from a block. Otherwise, point at the pipeline value. -Leon 2022-10-27 // if it was generated from a block. Otherwise, point at the pipeline value. -Leon 2022-10-27
let span = if val.span() == Span::test_data() { let span = if val.span() == Span::test_data() {
Span::new(call.head.start, call.head.start) Span::new(head.start, head.start)
} else { } else {
val.span() val.span()
}; };
@ -134,14 +129,14 @@ repeating this process with row 1, and so on."#
Err(ShellError::PipelineMismatch { Err(ShellError::PipelineMismatch {
exp_input_type: "input, and argument, to be both record or both table" exp_input_type: "input, and argument, to be both record or both table"
.to_string(), .to_string(),
dst_span: call.head, dst_span: head,
src_span: span, src_span: span,
}) })
} }
_ => Err(ShellError::PipelineMismatch { _ => Err(ShellError::PipelineMismatch {
exp_input_type: "input, and argument, to be both record or both table".to_string(), exp_input_type: "input, and argument, to be both record or both table".to_string(),
dst_span: call.head, dst_span: head,
src_span: Span::new(call.head.start, call.head.start), src_span: Span::new(head.start, head.start),
}), }),
} }
} }

View File

@ -109,6 +109,7 @@ impl Command for Move {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let columns: Vec<Value> = call.rest(engine_state, stack, 0)?; let columns: Vec<Value> = call.rest(engine_state, stack, 0)?;
let after: Option<Value> = call.get_flag(engine_state, stack, "after")?; let after: Option<Value> = call.get_flag(engine_state, stack, "after")?;
let before: Option<Value> = call.get_flag(engine_state, stack, "before")?; let before: Option<Value> = call.get_flag(engine_state, stack, "before")?;
@ -126,7 +127,7 @@ impl Command for Move {
return Err(ShellError::GenericError { return Err(ShellError::GenericError {
error: "Cannot move columns".into(), error: "Cannot move columns".into(),
msg: "Use either --after, or --before, not both".into(), msg: "Use either --after, or --before, not both".into(),
span: Some(call.head), span: Some(head),
help: None, help: None,
inner: vec![], inner: vec![],
}) })
@ -135,7 +136,7 @@ impl Command for Move {
return Err(ShellError::GenericError { return Err(ShellError::GenericError {
error: "Cannot move columns".into(), error: "Cannot move columns".into(),
msg: "Missing --after or --before flag".into(), msg: "Missing --after or --before flag".into(),
span: Some(call.head), span: Some(head),
help: None, help: None,
inner: vec![], inner: vec![],
}) })
@ -144,36 +145,29 @@ impl Command for Move {
let metadata = input.metadata(); let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let call = call.clone();
match input { match input {
PipelineData::Value(Value::List { .. }, ..) | PipelineData::ListStream { .. } => { PipelineData::Value(Value::List { .. }, ..) | PipelineData::ListStream { .. } => {
let res = input.into_iter().map(move |x| match x.as_record() { let res = input.into_iter().map(move |x| match x.as_record() {
Ok(record) => { Ok(record) => {
match move_record_columns(record, &columns, &before_or_after, call.head) { match move_record_columns(record, &columns, &before_or_after, head) {
Ok(val) => val, Ok(val) => val,
Err(error) => Value::error(error, call.head), Err(error) => Value::error(error, head),
} }
} }
Err(error) => Value::error(error, call.head), Err(error) => Value::error(error, head),
}); });
if let Some(md) = metadata { Ok(res.into_pipeline_data_with_metadata(head, ctrlc, metadata))
Ok(res.into_pipeline_data_with_metadata(md, ctrlc))
} else {
Ok(res.into_pipeline_data(ctrlc))
}
} }
PipelineData::Value(Value::Record { val, .. }, ..) => { PipelineData::Value(Value::Record { val, .. }, ..) => {
Ok( Ok(move_record_columns(&val, &columns, &before_or_after, head)?
move_record_columns(&val, &columns, &before_or_after, call.head)? .into_pipeline_data())
.into_pipeline_data(),
)
} }
_ => Err(ShellError::PipelineMismatch { _ => Err(ShellError::PipelineMismatch {
exp_input_type: "record or table".to_string(), exp_input_type: "record or table".to_string(),
dst_span: call.head, dst_span: head,
src_span: Span::new(call.head.start, call.head.start), src_span: Span::new(head.start, head.start),
}), }),
} }
} }

View File

@ -159,7 +159,7 @@ impl Command for ParEach {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) apply_order(vec).into_pipeline_data(span, engine_state.ctrlc.clone())
})), })),
Value::Range { val, .. } => Ok(create_pool(max_threads)?.install(|| { Value::Range { val, .. } => Ok(create_pool(max_threads)?.install(|| {
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
@ -186,7 +186,7 @@ impl Command for ParEach {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
apply_order(vec).into_pipeline_data(ctrlc) apply_order(vec).into_pipeline_data(span, ctrlc)
})), })),
// This match allows non-iterables to be accepted, // This match allows non-iterables to be accepted,
// which is currently considered undesirable (Nov 2022). // which is currently considered undesirable (Nov 2022).
@ -197,6 +197,7 @@ impl Command for ParEach {
} }
PipelineData::ListStream(stream, ..) => Ok(create_pool(max_threads)?.install(|| { PipelineData::ListStream(stream, ..) => Ok(create_pool(max_threads)?.install(|| {
let vec = stream let vec = stream
.into_iter()
.enumerate() .enumerate()
.par_bridge() .par_bridge()
.map(move |(index, value)| { .map(move |(index, value)| {
@ -216,7 +217,7 @@ impl Command for ParEach {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) apply_order(vec).into_pipeline_data(head, engine_state.ctrlc.clone())
})), })),
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()),
PipelineData::ExternalStream { PipelineData::ExternalStream {
@ -241,7 +242,7 @@ impl Command for ParEach {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) apply_order(vec).into_pipeline_data(head, engine_state.ctrlc.clone())
})), })),
} }
.and_then(|x| x.filter(|v| !v.is_nothing(), engine_state.ctrlc.clone())) .and_then(|x| x.filter(|v| !v.is_nothing(), engine_state.ctrlc.clone()))

View File

@ -117,7 +117,7 @@ only unwrap the outer list, and leave the variable's contents untouched."#
.into_pipeline_data() .into_pipeline_data()
.into_iter() .into_iter()
.chain(input) .chain(input)
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -64,6 +64,7 @@ impl Command for Range {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let metadata = input.metadata(); let metadata = input.metadata();
let rows: Spanned<NumRange> = call.req(engine_state, stack, 0)?; let rows: Spanned<NumRange> = call.req(engine_state, stack, 0)?;
@ -102,20 +103,20 @@ impl Command for Range {
}; };
if from > to { if from > to {
Ok(PipelineData::Value(Value::nothing(call.head), None)) Ok(PipelineData::Value(Value::nothing(head), None))
} else { } else {
let iter = v.into_iter().skip(from).take(to - from + 1); let iter = v.into_iter().skip(from).take(to - from + 1);
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())) Ok(iter.into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
} else { } else {
let from = start as usize; let from = start as usize;
let to = end as usize; let to = end as usize;
if from > to { if from > to {
Ok(PipelineData::Value(Value::nothing(call.head), None)) Ok(PipelineData::Value(Value::nothing(head), None))
} else { } else {
let iter = input.into_iter().skip(from).take(to - from + 1); let iter = input.into_iter().skip(from).take(to - from + 1);
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())) Ok(iter.into_pipeline_data(head, engine_state.ctrlc.clone()))
} }
} }
.map(|x| x.set_metadata(metadata)) .map(|x| x.set_metadata(metadata))

View File

@ -59,11 +59,11 @@ impl Command for Reverse {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let metadata = input.metadata(); let metadata = input.metadata();
let values = input.into_iter_strict(head)?.collect::<Vec<_>>();
let v: Vec<_> = input.into_iter_strict(call.head)?.collect(); let iter = values.into_iter().rev();
let iter = v.into_iter().rev(); Ok(iter.into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
Ok(iter.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()))
} }
} }

View File

@ -215,7 +215,7 @@ fn select(
rows: unique_rows.into_iter().peekable(), rows: unique_rows.into_iter().peekable(),
current: 0, current: 0,
} }
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()) .into_pipeline_data_with_metadata(call_span, engine_state.ctrlc.clone(), metadata)
} else { } else {
input input
}; };
@ -253,9 +253,11 @@ fn select(
} }
} }
Ok(output Ok(output.into_iter().into_pipeline_data_with_metadata(
.into_iter() call_span,
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) engine_state.ctrlc.clone(),
metadata,
))
} }
_ => { _ => {
if !columns.is_empty() { if !columns.is_empty() {
@ -300,7 +302,11 @@ fn select(
} }
} }
Ok(values.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(values.into_pipeline_data_with_metadata(
call_span,
engine_state.ctrlc.clone(),
metadata,
))
} }
_ => Ok(PipelineData::empty()), _ => Ok(PipelineData::empty()),
} }

View File

@ -30,10 +30,10 @@ impl Command for Shuffle {
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let metadata = input.metadata(); let metadata = input.metadata();
let mut v: Vec<_> = input.into_iter_strict(call.head)?.collect(); let mut values = input.into_iter_strict(call.head)?.collect::<Vec<_>>();
v.shuffle(&mut thread_rng()); values.shuffle(&mut thread_rng());
let iter = v.into_iter(); let iter = values.into_iter();
Ok(iter.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(iter.into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -101,7 +101,7 @@ impl Command for Skip {
_ => Ok(input _ => Ok(input
.into_iter_strict(call.head)? .into_iter_strict(call.head)?
.skip(n) .skip(n)
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(input_span, ctrlc, metadata)),
} }
} }
} }

View File

@ -88,7 +88,7 @@ impl Command for SkipUntil {
.map(|data| data.into_value(head).is_false()) .map(|data| data.into_value(head).is_false())
.unwrap_or(false) .unwrap_or(false)
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -93,7 +93,7 @@ impl Command for SkipWhile {
.map(|data| data.into_value(head).is_true()) .map(|data| data.into_value(head).is_true())
.unwrap_or(false) .unwrap_or(false)
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -134,10 +134,11 @@ impl Command for Sort {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let reverse = call.has_flag(engine_state, stack, "reverse")?; let reverse = call.has_flag(engine_state, stack, "reverse")?;
let insensitive = call.has_flag(engine_state, stack, "ignore-case")?; let insensitive = call.has_flag(engine_state, stack, "ignore-case")?;
let natural = call.has_flag(engine_state, stack, "natural")?; let natural = call.has_flag(engine_state, stack, "natural")?;
let metadata = &input.metadata(); let metadata = input.metadata();
let span = input.span().unwrap_or(call.head); let span = input.span().unwrap_or(call.head);
match input { match input {
@ -163,18 +164,18 @@ impl Command for Sort {
pipe_data => { pipe_data => {
let mut vec: Vec<_> = pipe_data.into_iter().collect(); let mut vec: Vec<_> = pipe_data.into_iter().collect();
sort(&mut vec, call.head, insensitive, natural)?; sort(&mut vec, head, insensitive, natural)?;
if reverse { if reverse {
vec.reverse() vec.reverse()
} }
let iter = vec.into_iter(); let iter = vec.into_iter();
match metadata { Ok(iter.into_pipeline_data_with_metadata(
Some(m) => Ok(iter head,
.into_pipeline_data_with_metadata(m.clone(), engine_state.ctrlc.clone())), engine_state.ctrlc.clone(),
None => Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())), metadata,
} ))
} }
} }
} }

View File

@ -78,33 +78,29 @@ impl Command for SortBy {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let columns: Vec<String> = call.rest(engine_state, stack, 0)?; let columns: Vec<String> = call.rest(engine_state, stack, 0)?;
let reverse = call.has_flag(engine_state, stack, "reverse")?; let reverse = call.has_flag(engine_state, stack, "reverse")?;
let insensitive = call.has_flag(engine_state, stack, "ignore-case")?; let insensitive = call.has_flag(engine_state, stack, "ignore-case")?;
let natural = call.has_flag(engine_state, stack, "natural")?; let natural = call.has_flag(engine_state, stack, "natural")?;
let metadata = &input.metadata(); let metadata = input.metadata();
let mut vec: Vec<_> = input.into_iter_strict(call.head)?.collect(); let mut vec: Vec<_> = input.into_iter_strict(head)?.collect();
if columns.is_empty() { if columns.is_empty() {
return Err(ShellError::MissingParameter { return Err(ShellError::MissingParameter {
param_name: "columns".into(), param_name: "columns".into(),
span: call.head, span: head,
}); });
} }
crate::sort(&mut vec, columns, call.head, insensitive, natural)?; crate::sort(&mut vec, columns, head, insensitive, natural)?;
if reverse { if reverse {
vec.reverse() vec.reverse()
} }
let iter = vec.into_iter(); let iter = vec.into_iter();
match metadata { Ok(iter.into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
Some(m) => {
Ok(iter.into_pipeline_data_with_metadata(m.clone(), engine_state.ctrlc.clone()))
}
None => Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())),
}
} }
} }

View File

@ -42,6 +42,7 @@ impl Command for Take {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let rows_desired: usize = call.req(engine_state, stack, 0)?; let rows_desired: usize = call.req(engine_state, stack, 0)?;
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
@ -54,7 +55,7 @@ impl Command for Take {
Value::List { vals, .. } => Ok(vals Value::List { vals, .. } => Ok(vals
.into_iter() .into_iter()
.take(rows_desired) .take(rows_desired)
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
Value::Binary { val, .. } => { Value::Binary { val, .. } => {
let slice: Vec<u8> = val.into_iter().take(rows_desired).collect(); let slice: Vec<u8> = val.into_iter().take(rows_desired).collect();
Ok(PipelineData::Value(Value::binary(slice, span), metadata)) Ok(PipelineData::Value(Value::binary(slice, span), metadata))
@ -62,33 +63,34 @@ impl Command for Take {
Value::Range { val, .. } => Ok(val Value::Range { val, .. } => Ok(val
.into_range_iter(span, ctrlc.clone()) .into_range_iter(span, ctrlc.clone())
.take(rows_desired) .take(rows_desired)
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error, .. } => Err(*error), Value::Error { error, .. } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(), exp_input_type: "list, binary or range".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: call.head, dst_span: head,
src_span: other.span(), src_span: other.span(),
}), }),
} }
} }
PipelineData::ListStream(ls, metadata) => Ok(ls PipelineData::ListStream(stream, metadata) => Ok(PipelineData::ListStream(
.take(rows_desired) stream.modify(|iter| iter.take(rows_desired)),
.into_pipeline_data_with_metadata(metadata, ctrlc)), metadata,
)),
PipelineData::ExternalStream { span, .. } => { PipelineData::ExternalStream { span, .. } => {
Err(ShellError::OnlySupportsThisInputType { Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(), exp_input_type: "list, binary or range".into(),
wrong_type: "raw data".into(), wrong_type: "raw data".into(),
dst_span: call.head, dst_span: head,
src_span: span, src_span: span,
}) })
} }
PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType { PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(), exp_input_type: "list, binary or range".into(),
wrong_type: "null".into(), wrong_type: "null".into(),
dst_span: call.head, dst_span: head,
src_span: call.head, src_span: head,
}), }),
} }
} }

View File

@ -84,7 +84,7 @@ impl Command for TakeUntil {
.map(|data| data.into_value(head).is_false()) .map(|data| data.into_value(head).is_false())
.unwrap_or(false) .unwrap_or(false)
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -84,7 +84,7 @@ impl Command for TakeWhile {
.map(|data| data.into_value(head).is_true()) .map(|data| data.into_value(head).is_true())
.unwrap_or(false) .unwrap_or(false)
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -64,6 +64,7 @@ use it in your pipeline."#
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_stderr = call.has_flag(engine_state, stack, "stderr")?; let use_stderr = call.has_flag(engine_state, stack, "stderr")?;
let Spanned { let Spanned {
@ -125,7 +126,7 @@ use it in your pipeline."#
if use_stderr { if use_stderr {
let stderr = stderr let stderr = stderr
.map(|stderr| { .map(|stderr| {
let iter = tee(stderr.stream, with_stream).err_span(call.head)?; let iter = tee(stderr.stream, with_stream).err_span(head)?;
Ok::<_, ShellError>(RawStream::new( Ok::<_, ShellError>(RawStream::new(
Box::new(iter.map(flatten_result)), Box::new(iter.map(flatten_result)),
stderr.ctrlc, stderr.ctrlc,
@ -145,7 +146,7 @@ use it in your pipeline."#
} else { } else {
let stdout = stdout let stdout = stdout
.map(|stdout| { .map(|stdout| {
let iter = tee(stdout.stream, with_stream).err_span(call.head)?; let iter = tee(stdout.stream, with_stream).err_span(head)?;
Ok::<_, ShellError>(RawStream::new( Ok::<_, ShellError>(RawStream::new(
Box::new(iter.map(flatten_result)), Box::new(iter.map(flatten_result)),
stdout.ctrlc, stdout.ctrlc,
@ -168,15 +169,16 @@ use it in your pipeline."#
_ if use_stderr => Err(ShellError::UnsupportedInput { _ if use_stderr => Err(ShellError::UnsupportedInput {
msg: "--stderr can only be used on external streams".into(), msg: "--stderr can only be used on external streams".into(),
input: "the input to `tee` is not an external stream".into(), input: "the input to `tee` is not an external stream".into(),
msg_span: call.head, msg_span: head,
input_span: input.span().unwrap_or(call.head), input_span: input.span().unwrap_or(head),
}), }),
// Handle others with the plain iterator // Handle others with the plain iterator
_ => { _ => {
let teed = tee(input.into_iter(), move |rx| { let teed = tee(input.into_iter(), move |rx| {
let input_from_channel = rx.into_pipeline_data_with_metadata( let input_from_channel = rx.into_pipeline_data_with_metadata(
metadata_clone, head,
closure_engine_state.ctrlc.clone(), closure_engine_state.ctrlc.clone(),
metadata_clone,
); );
let result = eval_block_with_early_return( let result = eval_block_with_early_return(
&closure_engine_state, &closure_engine_state,
@ -187,9 +189,13 @@ use it in your pipeline."#
// Make sure to drain any iterator produced to avoid unexpected behavior // Make sure to drain any iterator produced to avoid unexpected behavior
result.and_then(|data| data.drain()) result.and_then(|data| data.drain())
}) })
.err_span(call.head)? .err_span(head)?
.map(move |result| result.unwrap_or_else(|err| Value::error(err, closure_span))) .map(move |result| result.unwrap_or_else(|err| Value::error(err, closure_span)))
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()); .into_pipeline_data_with_metadata(
head,
engine_state.ctrlc.clone(),
metadata,
);
Ok(teed) Ok(teed)
} }

View File

@ -284,7 +284,7 @@ pub fn transpose(
metadata, metadata,
)) ))
} else { } else {
Ok(result_data.into_pipeline_data_with_metadata(metadata, ctrlc)) Ok(result_data.into_pipeline_data_with_metadata(name, ctrlc, metadata))
} }
} }

View File

@ -143,7 +143,7 @@ fn update(
} }
Ok(value.into_pipeline_data_with_metadata(metadata)) Ok(value.into_pipeline_data_with_metadata(metadata))
} }
PipelineData::ListStream(mut stream, metadata) => { PipelineData::ListStream(stream, metadata) => {
if let Some(( if let Some((
&PathMember::Int { &PathMember::Int {
val, val,
@ -153,6 +153,7 @@ fn update(
path, path,
)) = cell_path.members.split_first() )) = cell_path.members.split_first()
{ {
let mut stream = stream.into_iter();
let mut pre_elems = vec![]; let mut pre_elems = vec![];
for idx in 0..=val { for idx in 0..=val {
@ -186,38 +187,38 @@ fn update(
Ok(pre_elems Ok(pre_elems
.into_iter() .into_iter()
.chain(stream) .chain(stream)
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} else if let Value::Closure { val, .. } = replacement { } else if let Value::Closure { val, .. } = replacement {
let mut closure = ClosureEval::new(engine_state, stack, val); let mut closure = ClosureEval::new(engine_state, stack, val);
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { let err = update_value_by_closure(
let err = update_value_by_closure( &mut value,
&mut value, &mut closure,
&mut closure, head,
head, &cell_path.members,
&cell_path.members, false,
false, );
);
if let Err(e) = err { if let Err(e) = err {
Value::error(e, head) Value::error(e, head)
} else { } else {
value value
} }
}) });
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()))
Ok(PipelineData::ListStream(stream, metadata))
} else { } else {
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { if let Err(e) =
if let Err(e) = value.update_data_at_cell_path(&cell_path.members, replacement.clone())
value.update_data_at_cell_path(&cell_path.members, replacement.clone()) {
{ Value::error(e, head)
Value::error(e, head) } else {
} else { value
value }
} });
})
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(PipelineData::ListStream(stream, metadata))
} }
} }
PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { PipelineData::Empty => Err(ShellError::IncompatiblePathAccess {

View File

@ -189,7 +189,7 @@ fn upsert(
} }
Ok(value.into_pipeline_data_with_metadata(metadata)) Ok(value.into_pipeline_data_with_metadata(metadata))
} }
PipelineData::ListStream(mut stream, metadata) => { PipelineData::ListStream(stream, metadata) => {
if let Some(( if let Some((
&PathMember::Int { &PathMember::Int {
val, val,
@ -199,6 +199,7 @@ fn upsert(
path, path,
)) = cell_path.members.split_first() )) = cell_path.members.split_first()
{ {
let mut stream = stream.into_iter();
let mut pre_elems = vec![]; let mut pre_elems = vec![];
for idx in 0..val { for idx in 0..val {
@ -246,38 +247,38 @@ fn upsert(
Ok(pre_elems Ok(pre_elems
.into_iter() .into_iter()
.chain(stream) .chain(stream)
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} else if let Value::Closure { val, .. } = replacement { } else if let Value::Closure { val, .. } = replacement {
let mut closure = ClosureEval::new(engine_state, stack, val); let mut closure = ClosureEval::new(engine_state, stack, val);
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { let err = upsert_value_by_closure(
let err = upsert_value_by_closure( &mut value,
&mut value, &mut closure,
&mut closure, head,
head, &cell_path.members,
&cell_path.members, false,
false, );
);
if let Err(e) = err { if let Err(e) = err {
Value::error(e, head) Value::error(e, head)
} else { } else {
value value
} }
}) });
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()))
Ok(PipelineData::ListStream(stream, metadata))
} else { } else {
Ok(stream let stream = stream.map(move |mut value| {
.map(move |mut value| { if let Err(e) =
if let Err(e) = value.upsert_data_at_cell_path(&cell_path.members, replacement.clone())
value.upsert_data_at_cell_path(&cell_path.members, replacement.clone()) {
{ Value::error(e, head)
Value::error(e, head) } else {
} else { value
value }
} });
})
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) Ok(PipelineData::ListStream(stream, metadata))
} }
} }
PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { PipelineData::Empty => Err(ShellError::IncompatiblePathAccess {

View File

@ -144,7 +144,7 @@ fn values(
Value::List { vals, .. } => match get_values(&vals, head, span) { Value::List { vals, .. } => match get_values(&vals, head, span) {
Ok(cols) => Ok(cols Ok(cols) => Ok(cols
.into_iter() .into_iter()
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
Err(err) => Err(err), Err(err) => Err(err),
}, },
Value::Custom { val, .. } => { Value::Custom { val, .. } => {
@ -152,7 +152,7 @@ fn values(
match get_values(&[input_as_base_value], head, span) { match get_values(&[input_as_base_value], head, span) {
Ok(cols) => Ok(cols Ok(cols) => Ok(cols
.into_iter() .into_iter()
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
@ -160,7 +160,7 @@ fn values(
.values() .values()
.cloned() .cloned()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
// Propagate errors // Propagate errors
Value::Error { error, .. } => Err(*error), Value::Error { error, .. } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {
@ -176,7 +176,7 @@ fn values(
match get_values(&vals, head, head) { match get_values(&vals, head, head) {
Ok(cols) => Ok(cols Ok(cols) => Ok(cols
.into_iter() .into_iter()
.into_pipeline_data_with_metadata(metadata, ctrlc)), .into_pipeline_data_with_metadata(head, ctrlc, metadata)),
Err(err) => Err(err), Err(err) => Err(err),
} }
} }

View File

@ -61,7 +61,7 @@ not supported."#
Ok(data) => data.into_value(head).is_true().then_some(value), Ok(data) => data.into_value(head).is_true().then_some(value),
Err(err) => Some(Value::error(err, head)), Err(err) => Some(Value::error(err, head)),
}) })
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,5 @@
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::ValueIterator;
#[derive(Clone)] #[derive(Clone)]
pub struct Window; pub struct Window;
@ -110,6 +111,7 @@ impl Command for Window {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let group_size: Spanned<usize> = call.req(engine_state, stack, 0)?; let group_size: Spanned<usize> = call.req(engine_state, stack, 0)?;
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let metadata = input.metadata(); let metadata = input.metadata();
@ -123,19 +125,19 @@ impl Command for Window {
let each_group_iterator = EachWindowIterator { let each_group_iterator = EachWindowIterator {
group_size: group_size.item, group_size: group_size.item,
input: Box::new(input.into_iter()), input: Box::new(input.into_iter()),
span: call.head, span: head,
previous: None, previous: None,
stride, stride,
remainder, remainder,
}; };
Ok(each_group_iterator.into_pipeline_data_with_metadata(metadata, ctrlc)) Ok(each_group_iterator.into_pipeline_data_with_metadata(head, ctrlc, metadata))
} }
} }
struct EachWindowIterator { struct EachWindowIterator {
group_size: usize, group_size: usize,
input: Box<dyn Iterator<Item = Value> + Send>, input: ValueIterator,
span: Span, span: Span,
previous: Option<Vec<Value>>, previous: Option<Vec<Value>>,
stride: usize, stride: usize,

View File

@ -42,9 +42,9 @@ impl Command for Wrap {
| PipelineData::ListStream { .. } => Ok(input | PipelineData::ListStream { .. } => Ok(input
.into_iter() .into_iter()
.map(move |x| Value::record(record! { name.clone() => x }, span)) .map(move |x| Value::record(record! { name.clone() => x }, span))
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())), .into_pipeline_data_with_metadata(span, engine_state.ctrlc.clone(), metadata)),
PipelineData::ExternalStream { .. } => Ok(Value::record( PipelineData::ExternalStream { .. } => Ok(Value::record(
record! { name => input.into_value(call.head) }, record! { name => input.into_value(span) },
span, span,
) )
.into_pipeline_data_with_metadata(metadata)), .into_pipeline_data_with_metadata(metadata)),

View File

@ -112,7 +112,7 @@ impl Command for Zip {
.into_iter() .into_iter()
.zip(other) .zip(other)
.map(move |(x, y)| Value::list(vec![x, y], head)) .map(move |(x, y)| Value::list(vec![x, y], head))
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata))
} }
} }

View File

@ -84,8 +84,11 @@ impl Command for FromJson {
.collect() .collect()
}; };
Ok(converted_lines Ok(converted_lines.into_pipeline_data_with_metadata(
.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) span,
engine_state.ctrlc.clone(),
metadata,
))
} else if strict { } else if strict {
Ok(convert_string_to_value_strict(&string_input, span)? Ok(convert_string_to_value_strict(&string_input, span)?
.into_pipeline_data_with_metadata(metadata)) .into_pipeline_data_with_metadata(metadata))

View File

@ -109,10 +109,9 @@ MessagePack: https://msgpack.org/
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let span = input.span().unwrap_or(call.head);
let objects = call.has_flag(engine_state, stack, "objects")?; let objects = call.has_flag(engine_state, stack, "objects")?;
let opts = Opts { let opts = Opts {
span, span: call.head,
objects, objects,
ctrlc: engine_state.ctrlc.clone(), ctrlc: engine_state.ctrlc.clone(),
}; };
@ -126,10 +125,10 @@ MessagePack: https://msgpack.org/
stdout: Some(raw_stream), stdout: Some(raw_stream),
.. ..
} => read_msgpack(ReadRawStream::new(raw_stream), opts), } => read_msgpack(ReadRawStream::new(raw_stream), opts),
_ => Err(ShellError::PipelineMismatch { input => Err(ShellError::PipelineMismatch {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
dst_span: call.head, dst_span: call.head,
src_span: span, src_span: input.span().unwrap_or(call.head),
}), }),
} }
} }
@ -257,7 +256,7 @@ pub(crate) fn read_msgpack(
None None
} }
}) })
.into_pipeline_data(ctrlc)) .into_pipeline_data(span, ctrlc))
} else { } else {
// Read a single value and then make sure it's EOF // Read a single value and then make sure it's EOF
let result = read_value(&mut input, span, 0)?; let result = read_value(&mut input, span, 0)?;

View File

@ -1,6 +1,6 @@
use chrono_humanize::HumanTime; use chrono_humanize::HumanTime;
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::{format_duration, format_filesize_from_conf, Config, ListStream, RawStream}; use nu_protocol::{format_duration, format_filesize_from_conf, Config, RawStream, ValueIterator};
#[derive(Clone)] #[derive(Clone)]
pub struct ToText; pub struct ToText;
@ -41,7 +41,7 @@ impl Command for ToText {
Ok(PipelineData::ExternalStream { Ok(PipelineData::ExternalStream {
stdout: Some(RawStream::new( stdout: Some(RawStream::new(
Box::new(ListStreamIterator { Box::new(ListStreamIterator {
stream, stream: stream.into_inner(),
separator: line_ending.into(), separator: line_ending.into(),
config: config.clone(), config: config.clone(),
}), }),
@ -86,7 +86,7 @@ impl Command for ToText {
} }
struct ListStreamIterator { struct ListStreamIterator {
stream: ListStream, stream: ValueIterator,
separator: String, separator: String,
config: Config, config: Config,
} }

View File

@ -183,7 +183,7 @@ used as the next argument to the closure, otherwise generation stops.
Ok(iter Ok(iter
.flatten() .flatten()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(call.head, engine_state.ctrlc.clone()))
} }
} }

View File

@ -1,4 +1,5 @@
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::ListStream;
#[derive(Clone)] #[derive(Clone)]
pub struct Seq; pub struct Seq;
@ -119,36 +120,32 @@ pub fn run_seq(
let step = if free.len() > 2 { free[1] } else { 1.0 }; let step = if free.len() > 2 { free[1] } else { 1.0 };
let last = { free[free.len() - 1] }; let last = { free[free.len() - 1] };
if !contains_decimals { let stream = if !contains_decimals {
// integers only ListStream::new(
Ok(PipelineData::ListStream( IntSeq {
nu_protocol::ListStream::from_stream( count: first as i64,
IntSeq { step: step as i64,
count: first as i64, last: last as i64,
step: step as i64, span,
last: last as i64, },
span, span,
}, engine_state.ctrlc.clone(),
engine_state.ctrlc.clone(), )
),
None,
))
} else { } else {
// floats ListStream::new(
Ok(PipelineData::ListStream( FloatSeq {
nu_protocol::ListStream::from_stream( first,
FloatSeq { step,
first, last,
step, index: 0,
last, span,
index: 0, },
span, span,
}, engine_state.ctrlc.clone(),
engine_state.ctrlc.clone(), )
), };
None,
)) Ok(stream.into())
}
} }
struct FloatSeq { struct FloatSeq {

View File

@ -92,17 +92,12 @@ pub fn help_aliases(
&highlight_style, &highlight_style,
)?; )?;
return Ok(found_cmds_vec return Ok(Value::list(found_cmds_vec, head).into_pipeline_data());
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()));
} }
if rest.is_empty() { if rest.is_empty() {
let found_cmds_vec = build_help_aliases(engine_state, stack, head); let found_cmds_vec = build_help_aliases(engine_state, stack, head);
Ok(Value::list(found_cmds_vec, head).into_pipeline_data())
Ok(found_cmds_vec
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} else { } else {
let mut name = String::new(); let mut name = String::new();

View File

@ -72,17 +72,12 @@ pub fn help_commands(
&highlight_style, &highlight_style,
)?; )?;
return Ok(found_cmds_vec return Ok(Value::list(found_cmds_vec, head).into_pipeline_data());
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()));
} }
if rest.is_empty() { if rest.is_empty() {
let found_cmds_vec = build_help_commands(engine_state, head); let found_cmds_vec = build_help_commands(engine_state, head);
Ok(Value::list(found_cmds_vec, head).into_pipeline_data())
Ok(found_cmds_vec
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} else { } else {
let mut name = String::new(); let mut name = String::new();

View File

@ -21,7 +21,7 @@ impl Command for HelpEscapes {
fn run( fn run(
&self, &self,
engine_state: &EngineState, _engine_state: &EngineState,
_stack: &mut Stack, _stack: &mut Stack,
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
@ -40,9 +40,7 @@ impl Command for HelpEscapes {
)); ));
} }
Ok(recs Ok(Value::list(recs, call.head).into_pipeline_data())
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} }
} }

View File

@ -92,17 +92,12 @@ pub fn help_externs(
&highlight_style, &highlight_style,
)?; )?;
return Ok(found_cmds_vec return Ok(Value::list(found_cmds_vec, head).into_pipeline_data());
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()));
} }
if rest.is_empty() { if rest.is_empty() {
let found_cmds_vec = build_help_externs(engine_state, stack, head); let found_cmds_vec = build_help_externs(engine_state, stack, head);
Ok(Value::list(found_cmds_vec, head).into_pipeline_data())
Ok(found_cmds_vec
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} else { } else {
let mut name = String::new(); let mut name = String::new();

View File

@ -98,17 +98,12 @@ pub fn help_modules(
&highlight_style, &highlight_style,
)?; )?;
return Ok(found_cmds_vec return Ok(Value::list(found_cmds_vec, head).into_pipeline_data());
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()));
} }
if rest.is_empty() { if rest.is_empty() {
let found_cmds_vec = build_help_modules(engine_state, stack, head); let found_cmds_vec = build_help_modules(engine_state, stack, head);
Ok(Value::list(found_cmds_vec, head).into_pipeline_data())
Ok(found_cmds_vec
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} else { } else {
let mut name = String::new(); let mut name = String::new();

View File

@ -21,7 +21,7 @@ impl Command for HelpOperators {
fn run( fn run(
&self, &self,
engine_state: &EngineState, _engine_state: &EngineState,
_stack: &mut Stack, _stack: &mut Stack,
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
@ -43,9 +43,7 @@ impl Command for HelpOperators {
)); ));
} }
Ok(recs Ok(Value::list(recs, head).into_pipeline_data())
.into_iter()
.into_pipeline_data(engine_state.ctrlc.clone()))
} }
} }

View File

@ -69,7 +69,7 @@ pub fn calculate(
let span = values.span().unwrap_or(name); let span = values.span().unwrap_or(name);
match values { match values {
PipelineData::ListStream(s, ..) => { PipelineData::ListStream(s, ..) => {
helper_for_tables(&s.collect::<Vec<Value>>(), span, name, mf) helper_for_tables(&s.into_iter().collect::<Vec<Value>>(), span, name, mf)
} }
PipelineData::Value(Value::List { ref vals, .. }, ..) => match &vals[..] { PipelineData::Value(Value::List { ref vals, .. }, ..) => match &vals[..] {
[Value::Record { .. }, _end @ ..] => helper_for_tables( [Value::Record { .. }, _end @ ..] => helper_for_tables(

View File

@ -660,7 +660,7 @@ Operating system commands:
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
if list { if list {
return generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring); return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring));
} }
// The code can now be one of the ansi abbreviations like green_bold // The code can now be one of the ansi abbreviations like green_bold
@ -694,7 +694,7 @@ Operating system commands:
let ctrlc = working_set.permanent().ctrlc.clone(); let ctrlc = working_set.permanent().ctrlc.clone();
if list { if list {
return generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring); return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring));
} }
// The code can now be one of the ansi abbreviations like green_bold // The code can now be one of the ansi abbreviations like green_bold
@ -833,8 +833,8 @@ fn generate_ansi_code_list(
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
call_span: Span, call_span: Span,
use_ansi_coloring: bool, use_ansi_coloring: bool,
) -> Result<PipelineData, ShellError> { ) -> PipelineData {
return Ok(CODE_LIST CODE_LIST
.iter() .iter()
.enumerate() .enumerate()
.map(move |(i, ansi_code)| { .map(move |(i, ansi_code)| {
@ -865,7 +865,7 @@ fn generate_ansi_code_list(
Value::record(record, call_span) Value::record(record, call_span)
}) })
.into_pipeline_data(ctrlc)); .into_pipeline_data(call_span, ctrlc)
} }
fn build_ansi_hashmap(v: &[AnsiCode]) -> HashMap<&str, &str> { fn build_ansi_hashmap(v: &[AnsiCode]) -> HashMap<&str, &str> {

View File

@ -78,10 +78,7 @@ fn dice(
Value::int(thread_rng.gen_range(1..sides + 1) as i64, span) Value::int(thread_rng.gen_range(1..sides + 1) as i64, span)
}); });
Ok(PipelineData::ListStream( Ok(ListStream::new(iter, span, engine_state.ctrlc.clone()).into())
ListStream::from_stream(iter, engine_state.ctrlc.clone()),
None,
))
} }
#[cfg(test)] #[cfg(test)]

View File

@ -230,7 +230,7 @@ impl Command for Char {
// handle -l flag // handle -l flag
if list { if list {
return generate_character_list(ctrlc, call.head); return Ok(generate_character_list(ctrlc, call.head));
} }
// handle -i flag // handle -i flag
@ -265,7 +265,7 @@ impl Command for Char {
// handle -l flag // handle -l flag
if list { if list {
return generate_character_list(ctrlc, call_span); return Ok(generate_character_list(ctrlc, call_span));
} }
// handle -i flag // handle -i flag
@ -286,11 +286,8 @@ impl Command for Char {
} }
} }
fn generate_character_list( fn generate_character_list(ctrlc: Option<Arc<AtomicBool>>, call_span: Span) -> PipelineData {
ctrlc: Option<Arc<AtomicBool>>, CHAR_MAP
call_span: Span,
) -> Result<PipelineData, ShellError> {
Ok(CHAR_MAP
.iter() .iter()
.map(move |(name, s)| { .map(move |(name, s)| {
let unicode = Value::string( let unicode = Value::string(
@ -308,7 +305,7 @@ fn generate_character_list(
Value::record(record, call_span) Value::record(record, call_span)
}) })
.into_pipeline_data(ctrlc)) .into_pipeline_data(call_span, ctrlc)
} }
fn handle_integer_flag( fn handle_integer_flag(

View File

@ -159,7 +159,7 @@ fn guess_width(
Err(e) => Value::error(e, input_span), Err(e) => Value::error(e, input_span),
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(input_span, engine_state.ctrlc.clone()))
} else { } else {
let length = result[0].len(); let length = result[0].len();
let columns: Vec<String> = (0..length).map(|n| format!("column{n}")).collect(); let columns: Vec<String> = (0..length).map(|n| format!("column{n}")).collect();
@ -184,7 +184,7 @@ fn guess_width(
Err(e) => Value::error(e, input_span), Err(e) => Value::error(e, input_span),
} }
}) })
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(input_span, engine_state.ctrlc.clone()))
} }
} }
@ -278,7 +278,7 @@ fn detect_columns(
None => Value::record(record, name_span), None => Value::record(record, name_span),
} }
}) })
.into_pipeline_data(ctrlc)) .into_pipeline_data(call.head, ctrlc))
} else { } else {
Ok(PipelineData::empty()) Ok(PipelineData::empty())
} }

View File

@ -1,6 +1,6 @@
use fancy_regex::Regex; use fancy_regex::Regex;
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::ListStream; use nu_protocol::{ListStream, ValueIterator};
use std::sync::{ use std::sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@ -187,44 +187,36 @@ fn operate(
} }
} }
Ok(PipelineData::ListStream( Ok(ListStream::new(parsed.into_iter(), head, ctrlc).into())
ListStream::from_stream(parsed.into_iter(), ctrlc),
None,
))
} }
PipelineData::ListStream(stream, ..) => Ok(PipelineData::ListStream( PipelineData::ListStream(stream, ..) => Ok(stream
ListStream::from_stream( .modify(|stream| ParseStreamer {
ParseStreamer { span: head,
span: head, excess: Vec::new(),
excess: Vec::new(), regex: regex_pattern,
regex: regex_pattern, columns,
columns, stream,
stream: stream.stream,
ctrlc: ctrlc.clone(),
},
ctrlc, ctrlc,
), })
None, .into()),
)),
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::Empty), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::Empty),
PipelineData::ExternalStream { PipelineData::ExternalStream {
stdout: Some(stream), stdout: Some(stream),
.. ..
} => Ok(PipelineData::ListStream( } => Ok(ListStream::new(
ListStream::from_stream( ParseStreamerExternal {
ParseStreamerExternal { span: head,
span: head, excess: Vec::new(),
excess: Vec::new(), regex: regex_pattern,
regex: regex_pattern, columns,
columns, stream: stream.stream,
stream: stream.stream, },
}, head,
ctrlc, ctrlc,
), )
None, .into()),
)),
} }
} }
@ -299,7 +291,7 @@ pub struct ParseStreamer {
excess: Vec<Value>, excess: Vec<Value>,
regex: Regex, regex: Regex,
columns: Vec<String>, columns: Vec<String>,
stream: Box<dyn Iterator<Item = Value> + Send + 'static>, stream: ValueIterator,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
} }

View File

@ -196,9 +196,12 @@ fn split_list(
let mut temp_list = Vec::new(); let mut temp_list = Vec::new();
let mut returned_list = Vec::new(); let mut returned_list = Vec::new();
let iter = input.into_interruptible_iter(engine_state.ctrlc.clone());
let matcher = Matcher::new(call.has_flag(engine_state, stack, "regex")?, separator)?; let matcher = Matcher::new(call.has_flag(engine_state, stack, "regex")?, separator)?;
for val in iter { for val in input {
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
break;
}
if matcher.compare(&val)? { if matcher.compare(&val)? {
if !temp_list.is_empty() { if !temp_list.is_empty() {
returned_list.push(Value::list(temp_list.clone(), call.head)); returned_list.push(Value::list(temp_list.clone(), call.head));

View File

@ -88,7 +88,7 @@ impl Command for Complete {
}; };
if let Some(exit_code) = exit_code { if let Some(exit_code) = exit_code {
let mut v: Vec<_> = exit_code.collect(); let mut v: Vec<_> = exit_code.into_iter().collect();
if let Some(v) = v.pop() { if let Some(v) = v.pop() {
record.push("exit_code", v); record.push("exit_code", v);

View File

@ -195,5 +195,5 @@ fn run_ps(
Ok(output Ok(output
.into_iter() .into_iter()
.into_pipeline_data(engine_state.ctrlc.clone())) .into_pipeline_data(span, engine_state.ctrlc.clone()))
} }

View File

@ -106,7 +106,7 @@ fn registry_query(
*registry_key_span, *registry_key_span,
)) ))
} }
Ok(reg_values.into_pipeline_data(engine_state.ctrlc.clone())) Ok(reg_values.into_pipeline_data(call_span, engine_state.ctrlc.clone()))
} else { } else {
match registry_value { match registry_value {
Some(value) => { Some(value) => {

View File

@ -163,8 +163,6 @@ impl ExternalCommand {
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = self.name.span; let head = self.name.span;
let ctrlc = engine_state.ctrlc.clone();
#[allow(unused_mut)] #[allow(unused_mut)]
let (cmd, mut reader) = self.create_process(&input, false, head)?; let (cmd, mut reader) = self.create_process(&input, false, head)?;
@ -431,7 +429,7 @@ impl ExternalCommand {
( (
Some(RawStream::new( Some(RawStream::new(
Box::new(ByteLines::new(combined)), Box::new(ByteLines::new(combined)),
ctrlc.clone(), engine_state.ctrlc.clone(),
head, head,
None, None,
)), )),
@ -439,11 +437,21 @@ impl ExternalCommand {
) )
} else { } else {
let stdout = child.as_mut().stdout.take().map(|out| { let stdout = child.as_mut().stdout.take().map(|out| {
RawStream::new(Box::new(ByteLines::new(out)), ctrlc.clone(), head, None) RawStream::new(
Box::new(ByteLines::new(out)),
engine_state.ctrlc.clone(),
head,
None,
)
}); });
let stderr = child.as_mut().stderr.take().map(|err| { let stderr = child.as_mut().stderr.take().map(|err| {
RawStream::new(Box::new(ByteLines::new(err)), ctrlc.clone(), head, None) RawStream::new(
Box::new(ByteLines::new(err)),
engine_state.ctrlc.clone(),
head,
None,
)
}); });
if matches!(self.err, OutDest::Pipe) { if matches!(self.err, OutDest::Pipe) {
@ -505,15 +513,16 @@ impl ExternalCommand {
}) })
.err_span(head)?; .err_span(head)?;
let exit_code_receiver = ValueReceiver::new(exit_code_rx); let exit_code = Some(ListStream::new(
ValueReceiver::new(exit_code_rx),
head,
None,
));
Ok(PipelineData::ExternalStream { Ok(PipelineData::ExternalStream {
stdout, stdout,
stderr, stderr,
exit_code: Some(ListStream::from_stream( exit_code,
Box::new(exit_code_receiver),
ctrlc.clone(),
)),
span: head, span: head,
metadata: None, metadata: None,
trim_end_newline: true, trim_end_newline: true,

View File

@ -214,6 +214,7 @@ fn which(
stack: &mut Stack, stack: &mut Stack,
call: &Call, call: &Call,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let head = call.head;
let which_args = WhichArgs { let which_args = WhichArgs {
applications: call.rest(engine_state, stack, 0)?, applications: call.rest(engine_state, stack, 0)?,
all: call.has_flag(engine_state, stack, "all")?, all: call.has_flag(engine_state, stack, "all")?,
@ -223,7 +224,7 @@ fn which(
if which_args.applications.is_empty() { if which_args.applications.is_empty() {
return Err(ShellError::MissingParameter { return Err(ShellError::MissingParameter {
param_name: "application".into(), param_name: "application".into(),
span: call.head, span: head,
}); });
} }
@ -231,7 +232,7 @@ fn which(
#[allow(deprecated)] #[allow(deprecated)]
let cwd = env::current_dir_str(engine_state, stack)?; let cwd = env::current_dir_str(engine_state, stack)?;
let paths = env::path_str(engine_state, stack, call.head)?; let paths = env::path_str(engine_state, stack, head)?;
for app in which_args.applications { for app in which_args.applications {
let values = which_single( let values = which_single(
@ -244,7 +245,7 @@ fn which(
output.extend(values); output.extend(values);
} }
Ok(output.into_iter().into_pipeline_data(ctrlc)) Ok(output.into_iter().into_pipeline_data(head, ctrlc))
} }
#[cfg(test)] #[cfg(test)]

View File

@ -5,7 +5,9 @@
use lscolors::{LsColors, Style}; use lscolors::{LsColors, Style};
use nu_color_config::{color_from_hex, StyleComputer, TextStyle}; use nu_color_config::{color_from_hex, StyleComputer, TextStyle};
use nu_engine::{command_prelude::*, env::get_config, env_to_string}; use nu_engine::{command_prelude::*, env::get_config, env_to_string};
use nu_protocol::{Config, DataSource, ListStream, PipelineMetadata, RawStream, TableMode}; use nu_protocol::{
Config, DataSource, ListStream, PipelineMetadata, RawStream, TableMode, ValueIterator,
};
use nu_table::{ use nu_table::{
common::create_nu_table_config, CollapsedTable, ExpandedTable, JustTable, NuTable, NuTableCell, common::create_nu_table_config, CollapsedTable, ExpandedTable, JustTable, NuTable, NuTableCell,
StringResult, TableOpts, TableOutput, StringResult, TableOpts, TableOutput,
@ -381,7 +383,7 @@ fn handle_table_command(
// None of these two receive a StyleComputer because handle_row_stream() can produce it by itself using engine_state and stack. // None of these two receive a StyleComputer because handle_row_stream() can produce it by itself using engine_state and stack.
PipelineData::Value(Value::List { vals, .. }, metadata) => { PipelineData::Value(Value::List { vals, .. }, metadata) => {
let ctrlc = input.engine_state.ctrlc.clone(); let ctrlc = input.engine_state.ctrlc.clone();
let stream = ListStream::from_stream(vals.into_iter(), ctrlc); let stream = ListStream::new(vals.into_iter(), span, ctrlc);
input.data = PipelineData::Empty; input.data = PipelineData::Empty;
handle_row_stream(input, cfg, stream, metadata) handle_row_stream(input, cfg, stream, metadata)
@ -405,7 +407,7 @@ fn handle_table_command(
} }
PipelineData::Value(Value::Range { val, .. }, metadata) => { PipelineData::Value(Value::Range { val, .. }, metadata) => {
let ctrlc = input.engine_state.ctrlc.clone(); let ctrlc = input.engine_state.ctrlc.clone();
let stream = ListStream::from_stream(val.into_range_iter(span, ctrlc.clone()), ctrlc); let stream = ListStream::new(val.into_range_iter(span, ctrlc), span, None);
input.data = PipelineData::Empty; input.data = PipelineData::Empty;
handle_row_stream(input, cfg, stream, metadata) handle_row_stream(input, cfg, stream, metadata)
} }
@ -537,7 +539,6 @@ fn handle_row_stream(
data_source: DataSource::Ls, data_source: DataSource::Ls,
}) => { }) => {
let config = get_config(input.engine_state, input.stack); let config = get_config(input.engine_state, input.stack);
let ctrlc = ctrlc.clone();
let ls_colors_env_str = match input.stack.get_env_var(input.engine_state, "LS_COLORS") { let ls_colors_env_str = match input.stack.get_env_var(input.engine_state, "LS_COLORS") {
Some(v) => Some(env_to_string( Some(v) => Some(env_to_string(
"LS_COLORS", "LS_COLORS",
@ -549,67 +550,55 @@ fn handle_row_stream(
}; };
let ls_colors = get_ls_colors(ls_colors_env_str); let ls_colors = get_ls_colors(ls_colors_env_str);
ListStream::from_stream( stream.map(move |mut value| {
stream.map(move |mut x| match &mut x { if let Value::Record { val: record, .. } = &mut value {
Value::Record { val: record, .. } => { // Only the name column gets special colors, for now
// Only the name column gets special colors, for now if let Some(value) = record.to_mut().get_mut("name") {
if let Some(value) = record.to_mut().get_mut("name") { let span = value.span();
let span = value.span(); if let Value::String { val, .. } = value {
if let Value::String { val, .. } = value { if let Some(val) = render_path_name(val, &config, &ls_colors, span) {
if let Some(val) = render_path_name(val, &config, &ls_colors, span) *value = val;
{
*value = val;
}
} }
} }
x
} }
_ => x, }
}), value
ctrlc, })
)
} }
// Next, `to html -l` sources: // Next, `to html -l` sources:
Some(PipelineMetadata { Some(PipelineMetadata {
data_source: DataSource::HtmlThemes, data_source: DataSource::HtmlThemes,
}) => { }) => {
let ctrlc = ctrlc.clone(); stream.map(|mut value| {
if let Value::Record { val: record, .. } = &mut value {
ListStream::from_stream( for (rec_col, rec_val) in record.to_mut().iter_mut() {
stream.map(move |mut x| match &mut x { // Every column in the HTML theme table except 'name' is colored
Value::Record { val: record, .. } => { if rec_col != "name" {
for (rec_col, rec_val) in record.to_mut().iter_mut() { continue;
// Every column in the HTML theme table except 'name' is colored }
if rec_col != "name" { // Simple routine to grab the hex code, convert to a style,
continue; // then place it in a new Value::String.
}
// Simple routine to grab the hex code, convert to a style, let span = rec_val.span();
// then place it in a new Value::String. if let Value::String { val, .. } = rec_val {
let s = match color_from_hex(val) {
let span = rec_val.span(); Ok(c) => match c {
if let Value::String { val, .. } = rec_val { // .normal() just sets the text foreground color.
let s = match color_from_hex(val) { Some(c) => c.normal(),
Ok(c) => match c { None => nu_ansi_term::Style::default(),
// .normal() just sets the text foreground color. },
Some(c) => c.normal(), Err(_) => nu_ansi_term::Style::default(),
None => nu_ansi_term::Style::default(), };
}, *rec_val = Value::string(
Err(_) => nu_ansi_term::Style::default(), // Apply the style (ANSI codes) to the string
}; s.paint(&*val).to_string(),
*rec_val = Value::string( span,
// Apply the style (ANSI codes) to the string );
s.paint(&*val).to_string(),
span,
);
}
} }
x
} }
_ => x, }
}), value
ctrlc, })
)
} }
_ => stream, _ => stream,
}; };
@ -662,7 +651,7 @@ fn make_clickable_link(
struct PagingTableCreator { struct PagingTableCreator {
head: Span, head: Span,
stream: ListStream, stream: ValueIterator,
engine_state: EngineState, engine_state: EngineState,
stack: Stack, stack: Stack,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
@ -683,7 +672,7 @@ impl PagingTableCreator {
) -> Self { ) -> Self {
PagingTableCreator { PagingTableCreator {
head, head,
stream, stream: stream.into_inner(),
engine_state, engine_state,
stack, stack,
ctrlc, ctrlc,
@ -822,7 +811,7 @@ impl Iterator for PagingTableCreator {
} }
fn stream_collect( fn stream_collect(
stream: &mut ListStream, stream: impl Iterator<Item = Value>,
size: usize, size: usize,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
) -> (Vec<Value>, bool) { ) -> (Vec<Value>, bool) {
@ -830,7 +819,7 @@ fn stream_collect(
let mut end = true; let mut end = true;
let mut batch = Vec::with_capacity(size); let mut batch = Vec::with_capacity(size);
for (i, item) in stream.by_ref().enumerate() { for (i, item) in stream.enumerate() {
batch.push(item); batch.push(item);
// If we've been buffering over a second, go ahead and send out what we have so far // If we've been buffering over a second, go ahead and send out what we have so far
@ -853,7 +842,7 @@ fn stream_collect(
} }
fn stream_collect_abbriviated( fn stream_collect_abbriviated(
stream: &mut ListStream, stream: impl Iterator<Item = Value>,
size: usize, size: usize,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
) -> (Vec<Value>, usize, bool) { ) -> (Vec<Value>, usize, bool) {
@ -866,7 +855,7 @@ fn stream_collect_abbriviated(
return (vec![], 0, false); return (vec![], 0, false);
} }
for item in stream.by_ref() { for item in stream {
read += 1; read += 1;
if read <= size { if read <= size {

View File

@ -22,9 +22,9 @@ pub fn collect_pipeline(input: PipelineData) -> Result<(Vec<String>, Vec<Vec<Val
} }
} }
fn collect_list_stream(mut stream: ListStream) -> (Vec<String>, Vec<Vec<Value>>) { fn collect_list_stream(stream: ListStream) -> (Vec<String>, Vec<Vec<Value>>) {
let mut records = vec![]; let mut records = vec![];
for item in stream.by_ref() { for item in stream {
records.push(item); records.push(item);
} }
@ -70,7 +70,7 @@ fn collect_external_stream(
data.push(value); data.push(value);
} }
if let Some(exit_code) = exit_code { if let Some(exit_code) = exit_code {
let list = exit_code.collect::<Vec<_>>(); let list = exit_code.into_iter().collect::<Vec<_>>();
let val = Value::list(list, span); let val = Value::list(list, span);
columns.push(String::from("exit_code")); columns.push(String::from("exit_code"));

View File

@ -183,7 +183,7 @@ pub trait InterfaceManager {
PipelineDataHeader::ListStream(info) => { PipelineDataHeader::ListStream(info) => {
let handle = self.stream_manager().get_handle(); let handle = self.stream_manager().get_handle();
let reader = handle.read_stream(info.id, self.get_interface())?; let reader = handle.read_stream(info.id, self.get_interface())?;
PipelineData::ListStream(ListStream::from_stream(reader, ctrlc.cloned()), None) ListStream::new(reader, info.span, ctrlc.cloned()).into()
} }
PipelineDataHeader::ExternalStream(info) => { PipelineDataHeader::ExternalStream(info) => {
let handle = self.stream_manager().get_handle(); let handle = self.stream_manager().get_handle();
@ -203,7 +203,7 @@ pub trait InterfaceManager {
.map(|list_info| { .map(|list_info| {
handle handle
.read_stream(list_info.id, self.get_interface()) .read_stream(list_info.id, self.get_interface())
.map(|reader| ListStream::from_stream(reader, ctrlc.cloned())) .map(|reader| ListStream::new(reader, info.span, ctrlc.cloned()))
}) })
.transpose()?, .transpose()?,
span: info.span, span: info.span,
@ -278,7 +278,10 @@ pub trait Interface: Clone + Send {
PipelineData::ListStream(stream, _) => { PipelineData::ListStream(stream, _) => {
let (id, writer) = new_stream(LIST_STREAM_HIGH_PRESSURE)?; let (id, writer) = new_stream(LIST_STREAM_HIGH_PRESSURE)?;
Ok(( Ok((
PipelineDataHeader::ListStream(ListStreamInfo { id }), PipelineDataHeader::ListStream(ListStreamInfo {
id,
span: stream.span(),
}),
PipelineDataWriter::ListStream(writer, stream), PipelineDataWriter::ListStream(writer, stream),
)) ))
} }
@ -316,7 +319,7 @@ pub trait Interface: Clone + Send {
.map(|(stream, (id, _))| RawStreamInfo::new(*id, stream)), .map(|(stream, (id, _))| RawStreamInfo::new(*id, stream)),
exit_code: exit_code_stream exit_code: exit_code_stream
.as_ref() .as_ref()
.map(|&(id, _)| ListStreamInfo { id }), .map(|&(id, _)| ListStreamInfo { id, span }),
trim_end_newline, trim_end_newline,
}); });
// Collect the writers // Collect the writers

View File

@ -161,7 +161,10 @@ fn read_pipeline_data_list_stream() -> Result<(), ShellError> {
} }
test.add(StreamMessage::End(7)); test.add(StreamMessage::End(7));
let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 7 }); let header = PipelineDataHeader::ListStream(ListStreamInfo {
id: 7,
span: Span::test_data(),
});
let pipe = manager.read_pipeline_data(header, None)?; let pipe = manager.read_pipeline_data(header, None)?;
assert!( assert!(
@ -221,7 +224,10 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> {
is_binary: true, is_binary: true,
known_size: None, known_size: None,
}), }),
exit_code: Some(ListStreamInfo { id: 14 }), exit_code: Some(ListStreamInfo {
id: 14,
span: Span::test_data(),
}),
trim_end_newline: true, trim_end_newline: true,
}); });
@ -273,7 +279,10 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> {
} }
assert_eq!(iterations, count, "stderr length"); assert_eq!(iterations, count, "stderr length");
assert_eq!(vec![Value::test_int(1)], exit_code.collect::<Vec<_>>()); assert_eq!(
vec![Value::test_int(1)],
exit_code.into_iter().collect::<Vec<_>>()
);
} }
_ => panic!("unexpected PipelineData: {pipe:?}"), _ => panic!("unexpected PipelineData: {pipe:?}"),
} }
@ -284,30 +293,13 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> {
Ok(()) Ok(())
} }
#[test]
fn read_pipeline_data_ctrlc() -> Result<(), ShellError> {
let manager = TestInterfaceManager::new(&TestCase::new());
let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 0 });
let ctrlc = Default::default();
match manager.read_pipeline_data(header, Some(&ctrlc))? {
PipelineData::ListStream(
ListStream {
ctrlc: stream_ctrlc,
..
},
_,
) => {
assert!(Arc::ptr_eq(&ctrlc, &stream_ctrlc.expect("ctrlc not set")));
Ok(())
}
_ => panic!("Unexpected PipelineData, should have been ListStream"),
}
}
#[test] #[test]
fn read_pipeline_data_prepared_properly() -> Result<(), ShellError> { fn read_pipeline_data_prepared_properly() -> Result<(), ShellError> {
let manager = TestInterfaceManager::new(&TestCase::new()); let manager = TestInterfaceManager::new(&TestCase::new());
let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }); let header = PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
});
match manager.read_pipeline_data(header, None)? { match manager.read_pipeline_data(header, None)? {
PipelineData::ListStream(_, meta) => match meta { PipelineData::ListStream(_, meta) => match meta {
Some(PipelineMetadata { data_source }) => match data_source { Some(PipelineMetadata { data_source }) => match data_source {
@ -404,7 +396,7 @@ fn write_pipeline_data_list_stream() -> Result<(), ShellError> {
// Set up pipeline data for a list stream // Set up pipeline data for a list stream
let pipe = PipelineData::ListStream( let pipe = PipelineData::ListStream(
ListStream::from_stream(values.clone().into_iter(), None), ListStream::new(values.clone().into_iter(), Span::test_data(), None),
None, None,
); );
@ -474,8 +466,9 @@ fn write_pipeline_data_external_stream() -> Result<(), ShellError> {
span, span,
None, None,
)), )),
exit_code: Some(ListStream::from_stream( exit_code: Some(ListStream::new(
std::iter::once(exit_code.clone()), std::iter::once(exit_code.clone()),
Span::test_data(),
None, None,
)), )),
span, span,

View File

@ -11,8 +11,8 @@ use nu_plugin_protocol::{
PluginOutput, ProtocolInfo, StreamId, StreamMessage, PluginOutput, ProtocolInfo, StreamId, StreamMessage,
}; };
use nu_protocol::{ use nu_protocol::{
ast::Operator, CustomValue, IntoInterruptiblePipelineData, IntoSpanned, ListStream, ast::Operator, CustomValue, IntoSpanned, PipelineData, PluginSignature, ShellError, Span,
PipelineData, PluginSignature, ShellError, Span, Spanned, Value, Spanned, Value,
}; };
use std::{ use std::{
collections::{btree_map, BTreeMap}, collections::{btree_map, BTreeMap},
@ -592,14 +592,15 @@ impl InterfaceManager for PluginInterfaceManager {
})?; })?;
Ok(data) Ok(data)
} }
PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => { PipelineData::ListStream(stream, meta) => {
let source = self.state.source.clone(); let source = self.state.source.clone();
Ok(stream Ok(PipelineData::ListStream(
.map(move |mut value| { stream.map(move |mut value| {
let _ = PluginCustomValueWithSource::add_source_in(&mut value, &source); let _ = PluginCustomValueWithSource::add_source_in(&mut value, &source);
value value
}) }),
.into_pipeline_data_with_metadata(meta, ctrlc)) meta,
))
} }
PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data),
} }
@ -1076,18 +1077,19 @@ impl Interface for PluginInterface {
state.prepare_value(&mut value, &self.state.source)?; state.prepare_value(&mut value, &self.state.source)?;
Ok(PipelineData::Value(value, meta)) Ok(PipelineData::Value(value, meta))
} }
PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => { PipelineData::ListStream(stream, meta) => {
let source = self.state.source.clone(); let source = self.state.source.clone();
let state = state.clone(); let state = state.clone();
Ok(stream Ok(PipelineData::ListStream(
.map(move |mut value| { stream.map(move |mut value| {
match state.prepare_value(&mut value, &source) { match state.prepare_value(&mut value, &source) {
Ok(()) => value, Ok(()) => value,
// Put the error in the stream instead // Put the error in the stream instead
Err(err) => Value::error(err, value.span()), Err(err) => Value::error(err, value.span()),
} }
}) }),
.into_pipeline_data_with_metadata(meta, ctrlc)) meta,
))
} }
PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data),
} }

View File

@ -52,7 +52,10 @@ fn manager_consume_all_exits_after_streams_and_interfaces_are_dropped() -> Resul
// Create a stream... // Create a stream...
let stream = manager.read_pipeline_data( let stream = manager.read_pipeline_data(
PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
}),
None, None,
)?; )?;
@ -105,7 +108,10 @@ fn manager_consume_all_propagates_io_error_to_readers() -> Result<(), ShellError
test.set_read_error(test_io_error()); test.set_read_error(test_io_error());
let stream = manager.read_pipeline_data( let stream = manager.read_pipeline_data(
PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
}),
None, None,
)?; )?;
@ -331,7 +337,10 @@ fn manager_consume_call_response_forwards_to_subscriber_with_pipeline_data(
manager.consume(PluginOutput::CallResponse( manager.consume(PluginOutput::CallResponse(
0, 0,
PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
})),
))?; ))?;
for i in 0..2 { for i in 0..2 {
@ -372,7 +381,10 @@ fn manager_consume_call_response_registers_streams() -> Result<(), ShellError> {
// Check list streams, external streams // Check list streams, external streams
manager.consume(PluginOutput::CallResponse( manager.consume(PluginOutput::CallResponse(
0, 0,
PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
})),
))?; ))?;
manager.consume(PluginOutput::CallResponse( manager.consume(PluginOutput::CallResponse(
1, 1,
@ -388,7 +400,10 @@ fn manager_consume_call_response_registers_streams() -> Result<(), ShellError> {
is_binary: false, is_binary: false,
known_size: None, known_size: None,
}), }),
exit_code: Some(ListStreamInfo { id: 3 }), exit_code: Some(ListStreamInfo {
id: 3,
span: Span::test_data(),
}),
trim_end_newline: false, trim_end_newline: false,
})), })),
))?; ))?;
@ -448,7 +463,10 @@ fn manager_consume_engine_call_forwards_to_subscriber_with_pipeline_data() -> Re
span: Span::test_data(), span: Span::test_data(),
}, },
positional: vec![], positional: vec![],
input: PipelineDataHeader::ListStream(ListStreamInfo { id: 2 }), input: PipelineDataHeader::ListStream(ListStreamInfo {
id: 2,
span: Span::test_data(),
}),
redirect_stdout: false, redirect_stdout: false,
redirect_stderr: false, redirect_stderr: false,
}, },
@ -681,7 +699,7 @@ fn manager_prepare_pipeline_data_adds_source_to_list_streams() -> Result<(), She
[Value::test_custom_value(Box::new( [Value::test_custom_value(Box::new(
test_plugin_custom_value(), test_plugin_custom_value(),
))] ))]
.into_pipeline_data(None), .into_pipeline_data(Span::test_data(), None),
)?; )?;
let value = data let value = data
@ -855,7 +873,7 @@ fn interface_write_plugin_call_writes_run_with_stream_input() -> Result<(), Shel
positional: vec![], positional: vec![],
named: vec![], named: vec![],
}, },
input: values.clone().into_pipeline_data(None), input: values.clone().into_pipeline_data(Span::test_data(), None),
}), }),
None, None,
)?; )?;
@ -1131,7 +1149,10 @@ fn interface_prepare_pipeline_data_accepts_normal_streams() -> Result<(), ShellE
let interface = TestCase::new().plugin("test").get_interface(); let interface = TestCase::new().plugin("test").get_interface();
let values = normal_values(&interface); let values = normal_values(&interface);
let state = CurrentCallState::default(); let state = CurrentCallState::default();
let data = interface.prepare_pipeline_data(values.clone().into_pipeline_data(None), &state)?; let data = interface.prepare_pipeline_data(
values.clone().into_pipeline_data(Span::test_data(), None),
&state,
)?;
let mut count = 0; let mut count = 0;
for (expected_value, actual_value) in values.iter().zip(data) { for (expected_value, actual_value) in values.iter().zip(data) {
@ -1191,7 +1212,10 @@ fn interface_prepare_pipeline_data_rejects_bad_custom_value_in_a_stream() -> Res
let interface = TestCase::new().plugin("test").get_interface(); let interface = TestCase::new().plugin("test").get_interface();
let values = bad_custom_values(); let values = bad_custom_values();
let state = CurrentCallState::default(); let state = CurrentCallState::default();
let data = interface.prepare_pipeline_data(values.clone().into_pipeline_data(None), &state)?; let data = interface.prepare_pipeline_data(
values.clone().into_pipeline_data(Span::test_data(), None),
&state,
)?;
let mut count = 0; let mut count = 0;
for value in data { for value in data {

View File

@ -116,6 +116,7 @@ impl PipelineDataHeader {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct ListStreamInfo { pub struct ListStreamInfo {
pub id: StreamId, pub id: StreamId,
pub span: Span,
} }
/// Additional information about external streams /// Additional information about external streams

View File

@ -79,7 +79,7 @@
//! //!
//! // #[test] //! // #[test]
//! fn test_lowercase() -> Result<(), ShellError> { //! fn test_lowercase() -> Result<(), ShellError> {
//! let input = vec![Value::test_string("FooBar")].into_pipeline_data(None); //! let input = vec![Value::test_string("FooBar")].into_pipeline_data(Span::test_data(), None);
//! let output = PluginTest::new("lowercase", LowercasePlugin.into())? //! let output = PluginTest::new("lowercase", LowercasePlugin.into())?
//! .eval_with("lowercase", input)? //! .eval_with("lowercase", input)?
//! .into_value(Span::test_data()); //! .into_value(Span::test_data());

View File

@ -91,7 +91,7 @@ impl PluginTest {
/// let result = PluginTest::new("my_plugin", MyPlugin.into())? /// let result = PluginTest::new("my_plugin", MyPlugin.into())?
/// .eval_with( /// .eval_with(
/// "my-command", /// "my-command",
/// vec![Value::test_int(42)].into_pipeline_data(None) /// vec![Value::test_int(42)].into_pipeline_data(Span::test_data(), None)
/// )? /// )?
/// .into_value(Span::test_data()); /// .into_value(Span::test_data());
/// assert_eq!(Value::test_string("42"), result); /// assert_eq!(Value::test_string("42"), result);

View File

@ -68,7 +68,7 @@ impl Plugin for LowercasePlugin {
fn test_lowercase_using_eval_with() -> Result<(), ShellError> { fn test_lowercase_using_eval_with() -> Result<(), ShellError> {
let result = PluginTest::new("lowercase", LowercasePlugin.into())?.eval_with( let result = PluginTest::new("lowercase", LowercasePlugin.into())?.eval_with(
"lowercase", "lowercase",
vec![Value::test_string("HeLlO wOrLd")].into_pipeline_data(None), vec![Value::test_string("HeLlO wOrLd")].into_pipeline_data(Span::test_data(), None),
)?; )?;
assert_eq!( assert_eq!(

View File

@ -11,8 +11,8 @@ use nu_plugin_protocol::{
ProtocolInfo, ProtocolInfo,
}; };
use nu_protocol::{ use nu_protocol::{
engine::Closure, Config, IntoInterruptiblePipelineData, LabeledError, ListStream, PipelineData, engine::Closure, Config, LabeledError, PipelineData, PluginSignature, ShellError, Span,
PluginSignature, ShellError, Span, Spanned, Value, Spanned, Value,
}; };
use std::{ use std::{
collections::{btree_map, BTreeMap, HashMap}, collections::{btree_map, BTreeMap, HashMap},
@ -336,14 +336,15 @@ impl InterfaceManager for EngineInterfaceManager {
PluginCustomValue::deserialize_custom_values_in(value)?; PluginCustomValue::deserialize_custom_values_in(value)?;
Ok(data) Ok(data)
} }
PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => Ok(stream PipelineData::ListStream(stream, meta) => {
.map(|mut value| { let stream = stream.map(|mut value| {
let span = value.span(); let span = value.span();
PluginCustomValue::deserialize_custom_values_in(&mut value) PluginCustomValue::deserialize_custom_values_in(&mut value)
.map(|()| value) .map(|()| value)
.unwrap_or_else(|err| Value::error(err, span)) .unwrap_or_else(|err| Value::error(err, span))
}) });
.into_pipeline_data_with_metadata(meta, ctrlc)), Ok(PipelineData::ListStream(stream, meta))
}
PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data),
} }
} }
@ -910,14 +911,15 @@ impl Interface for EngineInterface {
PluginCustomValue::serialize_custom_values_in(value)?; PluginCustomValue::serialize_custom_values_in(value)?;
Ok(data) Ok(data)
} }
PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => Ok(stream PipelineData::ListStream(stream, meta) => {
.map(|mut value| { let stream = stream.map(|mut value| {
let span = value.span(); let span = value.span();
PluginCustomValue::serialize_custom_values_in(&mut value) PluginCustomValue::serialize_custom_values_in(&mut value)
.map(|_| value) .map(|_| value)
.unwrap_or_else(|err| Value::error(err, span)) .unwrap_or_else(|err| Value::error(err, span))
}) });
.into_pipeline_data_with_metadata(meta, ctrlc)), Ok(PipelineData::ListStream(stream, meta))
}
PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data),
} }
} }

View File

@ -56,7 +56,10 @@ fn manager_consume_all_exits_after_streams_and_interfaces_are_dropped() -> Resul
// Create a stream... // Create a stream...
let stream = manager.read_pipeline_data( let stream = manager.read_pipeline_data(
PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
}),
None, None,
)?; )?;
@ -109,7 +112,10 @@ fn manager_consume_all_propagates_io_error_to_readers() -> Result<(), ShellError
test.set_read_error(test_io_error()); test.set_read_error(test_io_error());
let stream = manager.read_pipeline_data( let stream = manager.read_pipeline_data(
PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
}),
None, None,
)?; )?;
@ -395,7 +401,10 @@ fn manager_consume_call_run_forwards_to_receiver_with_pipeline_data() -> Result<
positional: vec![], positional: vec![],
named: vec![], named: vec![],
}, },
input: PipelineDataHeader::ListStream(ListStreamInfo { id: 6 }), input: PipelineDataHeader::ListStream(ListStreamInfo {
id: 6,
span: Span::test_data(),
}),
}), }),
))?; ))?;
@ -534,7 +543,10 @@ fn manager_consume_engine_call_response_forwards_to_subscriber_with_pipeline_dat
manager.consume(PluginInput::EngineCallResponse( manager.consume(PluginInput::EngineCallResponse(
0, 0,
EngineCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), EngineCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo {
id: 0,
span: Span::test_data(),
})),
))?; ))?;
for i in 0..2 { for i in 0..2 {
@ -590,7 +602,7 @@ fn manager_prepare_pipeline_data_deserializes_custom_values_in_streams() -> Resu
[Value::test_custom_value(Box::new( [Value::test_custom_value(Box::new(
test_plugin_custom_value(), test_plugin_custom_value(),
))] ))]
.into_pipeline_data(None), .into_pipeline_data(Span::test_data(), None),
)?; )?;
let value = data let value = data
@ -621,7 +633,8 @@ fn manager_prepare_pipeline_data_embeds_deserialization_errors_in_streams() -> R
let span = Span::new(20, 30); let span = Span::new(20, 30);
let data = manager.prepare_pipeline_data( let data = manager.prepare_pipeline_data(
[Value::custom(Box::new(invalid_custom_value), span)].into_pipeline_data(None), [Value::custom(Box::new(invalid_custom_value), span)]
.into_pipeline_data(Span::test_data(), None),
)?; )?;
let value = data let value = data
@ -703,7 +716,8 @@ fn interface_write_response_with_stream() -> Result<(), ShellError> {
interface interface
.write_response(Ok::<_, ShellError>( .write_response(Ok::<_, ShellError>(
[Value::test_int(3), Value::test_int(4), Value::test_int(5)].into_pipeline_data(None), [Value::test_int(3), Value::test_int(4), Value::test_int(5)]
.into_pipeline_data(Span::test_data(), None),
))? ))?
.write()?; .write()?;
@ -1105,7 +1119,7 @@ fn interface_prepare_pipeline_data_serializes_custom_values_in_streams() -> Resu
[Value::test_custom_value(Box::new( [Value::test_custom_value(Box::new(
expected_test_custom_value(), expected_test_custom_value(),
))] ))]
.into_pipeline_data(None), .into_pipeline_data(Span::test_data(), None),
&(), &(),
)?; )?;
@ -1163,7 +1177,8 @@ fn interface_prepare_pipeline_data_embeds_serialization_errors_in_streams() -> R
let span = Span::new(40, 60); let span = Span::new(40, 60);
let data = interface.prepare_pipeline_data( let data = interface.prepare_pipeline_data(
[Value::custom(Box::new(CantSerialize::BadVariant), span)].into_pipeline_data(None), [Value::custom(Box::new(CantSerialize::BadVariant), span)]
.into_pipeline_data(Span::test_data(), None),
&(), &(),
)?; )?;

Some files were not shown because too many files have changed in this diff Show More