mirror of
https://github.com/nushell/nushell.git
synced 2025-01-18 12:22:21 +01:00
Introduce metadata into the pipeline (#397)
This commit is contained in:
parent
56307553ae
commit
45eba8b922
@ -34,19 +34,22 @@ impl Command for Echo {
|
|||||||
let n = to_be_echoed.len();
|
let n = to_be_echoed.len();
|
||||||
match n.cmp(&1usize) {
|
match n.cmp(&1usize) {
|
||||||
// More than one value is converted in a stream of values
|
// More than one value is converted in a stream of values
|
||||||
std::cmp::Ordering::Greater => PipelineData::Stream(ValueStream::from_stream(
|
std::cmp::Ordering::Greater => PipelineData::Stream(
|
||||||
to_be_echoed.into_iter(),
|
ValueStream::from_stream(to_be_echoed.into_iter(), engine_state.ctrlc.clone()),
|
||||||
engine_state.ctrlc.clone(),
|
None,
|
||||||
)),
|
),
|
||||||
|
|
||||||
// But a single value can be forwarded as it is
|
// But a single value can be forwarded as it is
|
||||||
std::cmp::Ordering::Equal => PipelineData::Value(to_be_echoed[0].clone()),
|
std::cmp::Ordering::Equal => PipelineData::Value(to_be_echoed[0].clone(), None),
|
||||||
|
|
||||||
// When there are no elements, we echo the empty string
|
// When there are no elements, we echo the empty string
|
||||||
std::cmp::Ordering::Less => PipelineData::Value(Value::String {
|
std::cmp::Ordering::Less => PipelineData::Value(
|
||||||
val: "".to_string(),
|
Value::String {
|
||||||
span: call.head,
|
val: "".to_string(),
|
||||||
}),
|
span: call.head,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lscolors::{LsColors, Style};
|
|
||||||
use nu_engine::eval_expression;
|
use nu_engine::eval_expression;
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, IntoInterruptiblePipelineData, PipelineData, Signature, SyntaxShape, Value,
|
Category, DataSource, IntoInterruptiblePipelineData, PipelineData, PipelineMetadata, Signature,
|
||||||
|
SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -37,7 +37,6 @@ impl Command for Ls {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let config = stack.get_config()?;
|
|
||||||
let pattern = if let Some(expr) = call.positional.get(0) {
|
let pattern = if let Some(expr) = call.positional.get(0) {
|
||||||
let result = eval_expression(engine_state, stack, expr)?;
|
let result = eval_expression(engine_state, stack, expr)?;
|
||||||
let mut result = result.as_string()?;
|
let mut result = result.as_string()?;
|
||||||
@ -57,10 +56,6 @@ impl Command for Ls {
|
|||||||
|
|
||||||
let call_span = call.head;
|
let call_span = call.head;
|
||||||
let glob = glob::glob(&pattern).unwrap();
|
let glob = glob::glob(&pattern).unwrap();
|
||||||
let ls_colors = match stack.get_env_var("LS_COLORS") {
|
|
||||||
Some(s) => LsColors::from_string(&s),
|
|
||||||
None => LsColors::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(glob
|
Ok(glob
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -72,22 +67,11 @@ impl Command for Ls {
|
|||||||
let is_dir = metadata.is_dir();
|
let is_dir = metadata.is_dir();
|
||||||
let filesize = metadata.len();
|
let filesize = metadata.len();
|
||||||
let mut cols = vec!["name".into(), "type".into(), "size".into()];
|
let mut cols = vec!["name".into(), "type".into(), "size".into()];
|
||||||
let style =
|
|
||||||
ls_colors.style_for_path_with_metadata(path.clone(), Some(&metadata));
|
|
||||||
let ansi_style = style.map(Style::to_crossterm_style).unwrap_or_default();
|
|
||||||
let use_ls_colors = config.use_ls_colors;
|
|
||||||
|
|
||||||
let mut vals = vec![
|
let mut vals = vec![
|
||||||
if use_ls_colors {
|
Value::String {
|
||||||
Value::String {
|
val: path.to_string_lossy().to_string(),
|
||||||
val: ansi_style.apply(path.to_string_lossy()).to_string(),
|
span: call_span,
|
||||||
span: call_span,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Value::String {
|
|
||||||
val: path.to_string_lossy().to_string(),
|
|
||||||
span: call_span,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
if is_symlink {
|
if is_symlink {
|
||||||
Value::string("symlink", call_span)
|
Value::string("symlink", call_span)
|
||||||
@ -120,34 +104,26 @@ impl Command for Ls {
|
|||||||
span: call_span,
|
span: call_span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => Value::Record {
|
||||||
let style = ls_colors.style_for_path(path.clone());
|
cols: vec!["name".into(), "type".into(), "size".into()],
|
||||||
let ansi_style = style.map(Style::to_crossterm_style).unwrap_or_default();
|
vals: vec![
|
||||||
let use_ls_colors = config.use_ls_colors;
|
Value::String {
|
||||||
|
val: path.to_string_lossy().to_string(),
|
||||||
Value::Record {
|
span: call_span,
|
||||||
cols: vec!["name".into(), "type".into(), "size".into()],
|
},
|
||||||
vals: vec![
|
Value::Nothing { span: call_span },
|
||||||
if use_ls_colors {
|
Value::Nothing { span: call_span },
|
||||||
Value::String {
|
],
|
||||||
val: ansi_style.apply(path.to_string_lossy()).to_string(),
|
span: call_span,
|
||||||
span: call_span,
|
},
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Value::String {
|
|
||||||
val: path.to_string_lossy().to_string(),
|
|
||||||
span: call_span,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Value::Nothing { span: call_span },
|
|
||||||
Value::Nothing { span: call_span },
|
|
||||||
],
|
|
||||||
span: call_span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => Value::Nothing { span: call_span },
|
_ => Value::Nothing { span: call_span },
|
||||||
})
|
})
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone()))
|
.into_pipeline_data_with_metadata(
|
||||||
|
PipelineMetadata {
|
||||||
|
data_source: DataSource::Ls,
|
||||||
|
},
|
||||||
|
engine_state.ctrlc.clone(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,8 @@ impl Command for Each {
|
|||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::Range { .. })
|
PipelineData::Value(Value::Range { .. }, ..)
|
||||||
| PipelineData::Value(Value::List { .. })
|
| PipelineData::Value(Value::List { .. }, ..)
|
||||||
| PipelineData::Stream { .. } => Ok(input
|
| PipelineData::Stream { .. } => Ok(input
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -109,7 +109,7 @@ impl Command for Each {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.into_pipeline_data(ctrlc)),
|
.into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }, ..) => {
|
||||||
let mut output_cols = vec![];
|
let mut output_cols = vec![];
|
||||||
let mut output_vals = vec![];
|
let mut output_vals = vec![];
|
||||||
|
|
||||||
@ -138,9 +138,12 @@ impl Command for Each {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
||||||
PipelineData::Value(Value::Record {
|
PipelineData::Value(
|
||||||
mut cols, mut vals, ..
|
Value::Record {
|
||||||
}) => {
|
mut cols, mut vals, ..
|
||||||
|
},
|
||||||
|
..,
|
||||||
|
) => {
|
||||||
// TODO check that the lengths match when traversing record
|
// TODO check that the lengths match when traversing record
|
||||||
output_cols.append(&mut cols);
|
output_cols.append(&mut cols);
|
||||||
output_vals.append(&mut vals);
|
output_vals.append(&mut vals);
|
||||||
@ -159,7 +162,7 @@ impl Command for Each {
|
|||||||
}
|
}
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
PipelineData::Value(x) => {
|
PipelineData::Value(x, ..) => {
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
|
|
||||||
if let Some(var) = block.signature.get_positional(0) {
|
if let Some(var) = block.signature.get_positional(0) {
|
||||||
|
@ -26,7 +26,7 @@ impl Command for Length {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::Nothing { .. }) => Ok(Value::Int {
|
PipelineData::Value(Value::Nothing { .. }, ..) => Ok(Value::Int {
|
||||||
val: 0,
|
val: 0,
|
||||||
span: call.head,
|
span: call.head,
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl Command for Lines {
|
|||||||
// Collect is needed because the string may not live long enough for
|
// Collect is needed because the string may not live long enough for
|
||||||
// the Rc structure to continue using it. If split could take ownership
|
// the Rc structure to continue using it. If split could take ownership
|
||||||
// of the split values, then this wouldn't be needed
|
// of the split values, then this wouldn't be needed
|
||||||
PipelineData::Value(Value::String { val, span }) => {
|
PipelineData::Value(Value::String { val, span }, ..) => {
|
||||||
let lines = val
|
let lines = val
|
||||||
.split(SPLIT_CHAR)
|
.split(SPLIT_CHAR)
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
@ -50,7 +50,7 @@ impl Command for Lines {
|
|||||||
|
|
||||||
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream, ..) => {
|
||||||
let iter = stream
|
let iter = stream
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|value| {
|
.filter_map(|value| {
|
||||||
@ -78,7 +78,7 @@ impl Command for Lines {
|
|||||||
|
|
||||||
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||||
}
|
}
|
||||||
PipelineData::Value(val) => Err(ShellError::UnsupportedInput(
|
PipelineData::Value(val, ..) => Err(ShellError::UnsupportedInput(
|
||||||
format!("Not supported input: {}", val.as_string()?),
|
format!("Not supported input: {}", val.as_string()?),
|
||||||
call.head,
|
call.head,
|
||||||
)),
|
)),
|
||||||
|
@ -57,7 +57,7 @@ impl Command for ParEach {
|
|||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::Range { val, .. }) => Ok(val
|
PipelineData::Value(Value::Range { val, .. }, ..) => Ok(val
|
||||||
.into_range_iter()?
|
.into_range_iter()?
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.par_bridge()
|
.par_bridge()
|
||||||
@ -98,7 +98,7 @@ impl Command for ParEach {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.into_pipeline_data(ctrlc)),
|
.into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Value(Value::List { vals: val, .. }) => Ok(val
|
PipelineData::Value(Value::List { vals: val, .. }, ..) => Ok(val
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.par_bridge()
|
.par_bridge()
|
||||||
@ -139,7 +139,7 @@ impl Command for ParEach {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.into_pipeline_data(ctrlc)),
|
.into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Stream(stream) => Ok(stream
|
PipelineData::Stream(stream, ..) => Ok(stream
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.par_bridge()
|
.par_bridge()
|
||||||
.map(move |(idx, x)| {
|
.map(move |(idx, x)| {
|
||||||
@ -179,7 +179,7 @@ impl Command for ParEach {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.into_pipeline_data(ctrlc)),
|
.into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }, ..) => {
|
||||||
let mut output_cols = vec![];
|
let mut output_cols = vec![];
|
||||||
let mut output_vals = vec![];
|
let mut output_vals = vec![];
|
||||||
|
|
||||||
@ -208,9 +208,12 @@ impl Command for ParEach {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
||||||
PipelineData::Value(Value::Record {
|
PipelineData::Value(
|
||||||
mut cols, mut vals, ..
|
Value::Record {
|
||||||
}) => {
|
mut cols, mut vals, ..
|
||||||
|
},
|
||||||
|
..,
|
||||||
|
) => {
|
||||||
// TODO check that the lengths match when traversing record
|
// TODO check that the lengths match when traversing record
|
||||||
output_cols.append(&mut cols);
|
output_cols.append(&mut cols);
|
||||||
output_vals.append(&mut vals);
|
output_vals.append(&mut vals);
|
||||||
@ -229,7 +232,7 @@ impl Command for ParEach {
|
|||||||
}
|
}
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
PipelineData::Value(x) => {
|
PipelineData::Value(x, ..) => {
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
|
|
||||||
if let Some(var) = block.signature.get_positional(0) {
|
if let Some(var) = block.signature.get_positional(0) {
|
||||||
|
@ -90,7 +90,10 @@ impl Command for Range {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if from > to {
|
if from > to {
|
||||||
Ok(PipelineData::Value(Value::Nothing { span: call.head }))
|
Ok(PipelineData::Value(
|
||||||
|
Value::Nothing { span: call.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(engine_state.ctrlc.clone()))
|
||||||
@ -100,7 +103,10 @@ impl Command for Range {
|
|||||||
let to = rows_to as usize;
|
let to = rows_to as usize;
|
||||||
|
|
||||||
if from > to {
|
if from > to {
|
||||||
Ok(PipelineData::Value(Value::Nothing { span: call.head }))
|
Ok(PipelineData::Value(
|
||||||
|
Value::Nothing { span: call.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(engine_state.ctrlc.clone()))
|
||||||
|
@ -68,10 +68,13 @@ fn select(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::List {
|
PipelineData::Value(
|
||||||
vals: input_vals,
|
Value::List {
|
||||||
span,
|
vals: input_vals,
|
||||||
}) => {
|
span,
|
||||||
|
},
|
||||||
|
..,
|
||||||
|
) => {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
for input_val in input_vals {
|
for input_val in input_vals {
|
||||||
@ -92,7 +95,7 @@ fn select(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone()))
|
.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => Ok(stream
|
PipelineData::Stream(stream, ..) => Ok(stream
|
||||||
.map(move |x| {
|
.map(move |x| {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
@ -113,7 +116,7 @@ fn select(
|
|||||||
Value::Record { cols, vals, span }
|
Value::Record { cols, vals, span }
|
||||||
})
|
})
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())),
|
.into_pipeline_data(engine_state.ctrlc.clone())),
|
||||||
PipelineData::Value(v) => {
|
PipelineData::Value(v, ..) => {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ impl Command for Wrap {
|
|||||||
let name: String = call.req(engine_state, stack, 0)?;
|
let name: String = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => Ok(vals
|
PipelineData::Value(Value::List { vals, .. }, ..) => Ok(vals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |x| Value::Record {
|
.map(move |x| Value::Record {
|
||||||
cols: vec![name.clone()],
|
cols: vec![name.clone()],
|
||||||
@ -43,14 +43,14 @@ impl Command for Wrap {
|
|||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())),
|
.into_pipeline_data(engine_state.ctrlc.clone())),
|
||||||
PipelineData::Stream(stream) => Ok(stream
|
PipelineData::Stream(stream, ..) => Ok(stream
|
||||||
.map(move |x| Value::Record {
|
.map(move |x| Value::Record {
|
||||||
cols: vec![name.clone()],
|
cols: vec![name.clone()],
|
||||||
vals: vec![x],
|
vals: vec![x],
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())),
|
.into_pipeline_data(engine_state.ctrlc.clone())),
|
||||||
PipelineData::Value(input) => Ok(Value::Record {
|
PipelineData::Value(input, ..) => Ok(Value::Record {
|
||||||
cols: vec![name],
|
cols: vec![name],
|
||||||
vals: vec![input],
|
vals: vec![input],
|
||||||
span,
|
span,
|
||||||
|
@ -230,10 +230,13 @@ fn from_eml(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::Value(Value::from(Spanned {
|
Ok(PipelineData::Value(
|
||||||
item: collected,
|
Value::from(Spanned {
|
||||||
span: head,
|
item: collected,
|
||||||
})))
|
span: head,
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -194,7 +194,7 @@ fn from_ods(
|
|||||||
span: head,
|
span: head,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(record))
|
Ok(PipelineData::Value(record, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -67,11 +67,14 @@ fn from_url(input: PipelineData, head: Span, config: &Config) -> Result<Pipeline
|
|||||||
vals.push(Value::String { val: v, span: head })
|
vals.push(Value::String { val: v, span: head })
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::Value(Value::Record {
|
Ok(PipelineData::Value(
|
||||||
cols,
|
Value::Record {
|
||||||
vals,
|
cols,
|
||||||
span: head,
|
vals,
|
||||||
}))
|
span: head,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::UnsupportedInput(
|
_ => Err(ShellError::UnsupportedInput(
|
||||||
"String not compatible with url-encoding".to_string(),
|
"String not compatible with url-encoding".to_string(),
|
||||||
|
@ -194,7 +194,7 @@ fn from_xlsx(
|
|||||||
span: head,
|
span: head,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PipelineData::Value(record))
|
Ok(PipelineData::Value(record, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -57,14 +57,14 @@ pub fn eval(
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
if let Some(expr) = spanned_expr {
|
if let Some(expr) = spanned_expr {
|
||||||
match parse(&expr.item, &expr.span) {
|
match parse(&expr.item, &expr.span) {
|
||||||
Ok(value) => Ok(PipelineData::Value(value)),
|
Ok(value) => Ok(PipelineData::Value(value, None)),
|
||||||
Err(err) => Err(ShellError::UnsupportedInput(
|
Err(err) => Err(ShellError::UnsupportedInput(
|
||||||
format!("Math evaluation error: {}", err),
|
format!("Math evaluation error: {}", err),
|
||||||
expr.span,
|
expr.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let PipelineData::Value(Value::Nothing { .. }) = input {
|
if let PipelineData::Value(Value::Nothing { .. }, ..) = input {
|
||||||
return Ok(input);
|
return Ok(input);
|
||||||
}
|
}
|
||||||
input.map(
|
input.map(
|
||||||
|
@ -62,12 +62,12 @@ pub fn calculate(
|
|||||||
mf: impl Fn(&[Value], &Span) -> Result<Value, ShellError>,
|
mf: impl Fn(&[Value], &Span) -> Result<Value, ShellError>,
|
||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
match values {
|
match values {
|
||||||
PipelineData::Stream(s) => helper_for_tables(&s.collect::<Vec<Value>>(), name, mf),
|
PipelineData::Stream(s, ..) => helper_for_tables(&s.collect::<Vec<Value>>(), name, mf),
|
||||||
PipelineData::Value(Value::List { ref vals, .. }) => match &vals[..] {
|
PipelineData::Value(Value::List { ref vals, .. }, ..) => match &vals[..] {
|
||||||
[Value::Record { .. }, _end @ ..] => helper_for_tables(vals, name, mf),
|
[Value::Record { .. }, _end @ ..] => helper_for_tables(vals, name, mf),
|
||||||
_ => mf(vals, &name),
|
_ => mf(vals, &name),
|
||||||
},
|
},
|
||||||
PipelineData::Value(Value::Record { vals, cols, span }) => {
|
PipelineData::Value(Value::Record { vals, cols, span }, ..) => {
|
||||||
let new_vals: Result<Vec<Value>, ShellError> =
|
let new_vals: Result<Vec<Value>, ShellError> =
|
||||||
vals.into_iter().map(|val| mf(&[val], &name)).collect();
|
vals.into_iter().map(|val| mf(&[val], &name)).collect();
|
||||||
match new_vals {
|
match new_vals {
|
||||||
@ -79,7 +79,7 @@ pub fn calculate(
|
|||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Range { val, .. }) => {
|
PipelineData::Value(Value::Range { val, .. }, ..) => {
|
||||||
let new_vals: Result<Vec<Value>, ShellError> = val
|
let new_vals: Result<Vec<Value>, ShellError> = val
|
||||||
.into_range_iter()?
|
.into_range_iter()?
|
||||||
.map(|val| mf(&[val], &name))
|
.map(|val| mf(&[val], &name))
|
||||||
@ -87,6 +87,6 @@ pub fn calculate(
|
|||||||
|
|
||||||
mf(&new_vals?, &name)
|
mf(&new_vals?, &name)
|
||||||
}
|
}
|
||||||
PipelineData::Value(val) => mf(&[val], &name),
|
PipelineData::Value(val, ..) => mf(&[val], &name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,13 @@ fn bool(
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let bool_result: bool = rng.gen_bool(probability);
|
let bool_result: bool = rng.gen_bool(probability);
|
||||||
|
|
||||||
Ok(PipelineData::Value(Value::Bool {
|
Ok(PipelineData::Value(
|
||||||
val: bool_result,
|
Value::Bool {
|
||||||
span,
|
val: bool_result,
|
||||||
}))
|
span,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -70,10 +70,13 @@ fn chars(
|
|||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
Ok(PipelineData::Value(Value::String {
|
Ok(PipelineData::Value(
|
||||||
val: random_string,
|
Value::String {
|
||||||
span,
|
val: random_string,
|
||||||
}))
|
span,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -125,7 +125,10 @@ fn format(
|
|||||||
// We can only handle a Record or a List of Record's
|
// We can only handle a Record or a List of Record's
|
||||||
match data_as_value {
|
match data_as_value {
|
||||||
Value::Record { .. } => match format_record(format_operations, &data_as_value) {
|
Value::Record { .. } => match format_record(format_operations, &data_as_value) {
|
||||||
Ok(value) => Ok(PipelineData::Value(Value::string(value, Span::unknown()))),
|
Ok(value) => Ok(PipelineData::Value(
|
||||||
|
Value::string(value, Span::unknown()),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
Err(value) => Err(value),
|
Err(value) => Err(value),
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -151,10 +154,10 @@ fn format(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::Stream(ValueStream::from_stream(
|
Ok(PipelineData::Stream(
|
||||||
list.into_iter(),
|
ValueStream::from_stream(list.into_iter(), None),
|
||||||
None,
|
None,
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::UnsupportedInput(
|
_ => Err(ShellError::UnsupportedInput(
|
||||||
"Input data is not supported by this command.".to_string(),
|
"Input data is not supported by this command.".to_string(),
|
||||||
|
@ -74,6 +74,7 @@ fn operate(
|
|||||||
let head = call.head;
|
let head = call.head;
|
||||||
let pattern: Spanned<String> = call.req(engine_state, stack, 0)?;
|
let pattern: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||||
let regex: bool = call.has_flag("regex");
|
let regex: bool = call.has_flag("regex");
|
||||||
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
|
||||||
let pattern_item = pattern.item;
|
let pattern_item = pattern.item;
|
||||||
let pattern_span = pattern.span;
|
let pattern_span = pattern.span;
|
||||||
@ -125,10 +126,10 @@ fn operate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::Stream(ValueStream::from_stream(
|
Ok(PipelineData::Stream(
|
||||||
parsed.into_iter(),
|
ValueStream::from_stream(parsed.into_iter(), ctrlc),
|
||||||
None,
|
None,
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_regex(input: &str, span: Span) -> Result<String, ShellError> {
|
fn build_regex(input: &str, span: Span) -> Result<String, ShellError> {
|
||||||
|
@ -94,7 +94,7 @@ impl ExternalCommand {
|
|||||||
|
|
||||||
// If there is an input from the pipeline. The stdin from the process
|
// If there is an input from the pipeline. The stdin from the process
|
||||||
// is piped so it can be used to send the input information
|
// is piped so it can be used to send the input information
|
||||||
if !matches!(input, PipelineData::Value(Value::Nothing { .. })) {
|
if !matches!(input, PipelineData::Value(Value::Nothing { .. }, ..)) {
|
||||||
process.stdin(Stdio::piped());
|
process.stdin(Stdio::piped());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ prints out the list properly."#
|
|||||||
let use_grid_icons = config.use_grid_icons;
|
let use_grid_icons = config.use_grid_icons;
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||||
// dbg!("value::list");
|
// dbg!("value::list");
|
||||||
let data = convert_to_list(vals, &config);
|
let data = convert_to_list(vals, &config);
|
||||||
if let Some(items) = data {
|
if let Some(items) = data {
|
||||||
@ -81,7 +81,7 @@ prints out the list properly."#
|
|||||||
Ok(PipelineData::new(call.head))
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream, ..) => {
|
||||||
// dbg!("value::stream");
|
// dbg!("value::stream");
|
||||||
let data = convert_to_list(stream, &config);
|
let data = convert_to_list(stream, &config);
|
||||||
if let Some(items) = data {
|
if let Some(items) = data {
|
||||||
@ -99,7 +99,7 @@ prints out the list properly."#
|
|||||||
Ok(PipelineData::new(call.head))
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }, ..) => {
|
||||||
// dbg!("value::record");
|
// dbg!("value::record");
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use super::color_config::style_primitive;
|
use super::color_config::style_primitive;
|
||||||
use crate::viewers::color_config::get_color_config;
|
use crate::viewers::color_config::get_color_config;
|
||||||
|
use lscolors::{LsColors, Style};
|
||||||
use nu_protocol::ast::{Call, PathMember};
|
use nu_protocol::ast::{Call, PathMember};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Config, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value,
|
Category, Config, DataSource, IntoPipelineData, PipelineData, PipelineMetadata, ShellError,
|
||||||
|
Signature, Span, Value, ValueStream,
|
||||||
};
|
};
|
||||||
use nu_table::{StyledString, TextStyle, Theme};
|
use nu_table::{StyledString, TextStyle, Theme};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -45,7 +47,7 @@ impl Command for Table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||||
let table = convert_to_table(vals, ctrlc, &config)?;
|
let table = convert_to_table(vals, ctrlc, &config)?;
|
||||||
|
|
||||||
if let Some(table) = table {
|
if let Some(table) = table {
|
||||||
@ -60,7 +62,84 @@ impl Command for Table {
|
|||||||
Ok(PipelineData::new(call.head))
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream, metadata) => {
|
||||||
|
let stream = match metadata {
|
||||||
|
Some(PipelineMetadata {
|
||||||
|
data_source: DataSource::Ls,
|
||||||
|
}) => {
|
||||||
|
let config = config.clone();
|
||||||
|
let ctrlc = ctrlc.clone();
|
||||||
|
|
||||||
|
let ls_colors = match stack.get_env_var("LS_COLORS") {
|
||||||
|
Some(s) => LsColors::from_string(&s),
|
||||||
|
None => LsColors::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
ValueStream::from_stream(
|
||||||
|
stream.map(move |mut x| match &mut x {
|
||||||
|
Value::Record { cols, vals, .. } => {
|
||||||
|
let mut idx = 0;
|
||||||
|
|
||||||
|
while idx < cols.len() {
|
||||||
|
if cols[idx] == "name" {
|
||||||
|
if let Some(Value::String { val: path, span }) =
|
||||||
|
vals.get(idx)
|
||||||
|
{
|
||||||
|
match std::fs::symlink_metadata(&path) {
|
||||||
|
Ok(metadata) => {
|
||||||
|
let style = ls_colors
|
||||||
|
.style_for_path_with_metadata(
|
||||||
|
path.clone(),
|
||||||
|
Some(&metadata),
|
||||||
|
);
|
||||||
|
let ansi_style = style
|
||||||
|
.map(Style::to_crossterm_style)
|
||||||
|
.unwrap_or_default();
|
||||||
|
let use_ls_colors = config.use_ls_colors;
|
||||||
|
|
||||||
|
if use_ls_colors {
|
||||||
|
vals[idx] = Value::String {
|
||||||
|
val: ansi_style
|
||||||
|
.apply(path)
|
||||||
|
.to_string(),
|
||||||
|
span: *span,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
let style =
|
||||||
|
ls_colors.style_for_path(path.clone());
|
||||||
|
let ansi_style = style
|
||||||
|
.map(Style::to_crossterm_style)
|
||||||
|
.unwrap_or_default();
|
||||||
|
let use_ls_colors = config.use_ls_colors;
|
||||||
|
|
||||||
|
if use_ls_colors {
|
||||||
|
vals[idx] = Value::String {
|
||||||
|
val: ansi_style
|
||||||
|
.apply(path)
|
||||||
|
.to_string(),
|
||||||
|
span: *span,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x
|
||||||
|
}
|
||||||
|
_ => x,
|
||||||
|
}),
|
||||||
|
ctrlc,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => stream,
|
||||||
|
};
|
||||||
|
|
||||||
let table = convert_to_table(stream, ctrlc, &config)?;
|
let table = convert_to_table(stream, ctrlc, &config)?;
|
||||||
|
|
||||||
if let Some(table) = table {
|
if let Some(table) = table {
|
||||||
@ -75,7 +154,7 @@ impl Command for Table {
|
|||||||
Ok(PipelineData::new(call.head))
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }, ..) => {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
for (c, v) in cols.into_iter().zip(vals.into_iter()) {
|
for (c, v) in cols.into_iter().zip(vals.into_iter()) {
|
||||||
@ -105,8 +184,8 @@ impl Command for Table {
|
|||||||
}
|
}
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Error { error }) => Err(error),
|
PipelineData::Value(Value::Error { error }, ..) => Err(error),
|
||||||
PipelineData::Value(Value::CustomValue { val, span }) => {
|
PipelineData::Value(Value::CustomValue { val, span }, ..) => {
|
||||||
let base_pipeline = val.to_base_value(span)?.into_pipeline_data();
|
let base_pipeline = val.to_base_value(span)?.into_pipeline_data();
|
||||||
self.run(engine_state, stack, call, base_pipeline)
|
self.run(engine_state, stack, call, base_pipeline)
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ mod test {
|
|||||||
assert!(call.has_flag("flag"));
|
assert!(call.has_flag("flag"));
|
||||||
|
|
||||||
let required: f64 = call.req(0).unwrap();
|
let required: f64 = call.req(0).unwrap();
|
||||||
assert_eq!(required, 1.0);
|
assert!((required - 1.0).abs() < f64::EPSILON);
|
||||||
|
|
||||||
let optional: Option<String> = call.opt(1).unwrap();
|
let optional: Option<String> = call.opt(1).unwrap();
|
||||||
assert_eq!(optional, Some("something".to_string()));
|
assert_eq!(optional, Some("something".to_string()));
|
||||||
|
@ -145,8 +145,8 @@ impl Command for PluginDeclaration {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let input = match input {
|
let input = match input {
|
||||||
PipelineData::Value(value) => value,
|
PipelineData::Value(value, ..) => value,
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream, ..) => {
|
||||||
let values = stream.collect::<Vec<Value>>();
|
let values = stream.collect::<Vec<Value>>();
|
||||||
|
|
||||||
Value::List {
|
Value::List {
|
||||||
@ -192,7 +192,9 @@ impl Command for PluginDeclaration {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
PluginResponse::Value(value) => Ok(PipelineData::Value(value.as_ref().clone())),
|
PluginResponse::Value(value) => {
|
||||||
|
Ok(PipelineData::Value(value.as_ref().clone(), None))
|
||||||
|
}
|
||||||
PluginResponse::Error(msg) => Err(ShellError::LabeledError(
|
PluginResponse::Error(msg) => Err(ShellError::LabeledError(
|
||||||
"Error received from plugin".into(),
|
"Error received from plugin".into(),
|
||||||
msg,
|
msg,
|
||||||
|
@ -363,8 +363,8 @@ impl EngineState {
|
|||||||
let decl = self.get_decl(decl_id);
|
let decl = self.get_decl(decl_id);
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Stream(_) => decl,
|
PipelineData::Stream(..) => decl,
|
||||||
PipelineData::Value(value) => match value {
|
PipelineData::Value(value, ..) => match value {
|
||||||
Value::CustomValue { val, .. } => {
|
Value::CustomValue { val, .. } => {
|
||||||
// This filter works because the custom definitions were declared
|
// This filter works because the custom definitions were declared
|
||||||
// before the default nushell declarations. This means that the custom
|
// before the default nushell declarations. This means that the custom
|
||||||
|
@ -33,19 +33,29 @@ use crate::{ast::PathMember, Config, ShellError, Span, Value, ValueStream};
|
|||||||
/// Nushell.
|
/// Nushell.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PipelineData {
|
pub enum PipelineData {
|
||||||
Value(Value),
|
Value(Value, Option<PipelineMetadata>),
|
||||||
Stream(ValueStream),
|
Stream(ValueStream, Option<PipelineMetadata>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PipelineMetadata {
|
||||||
|
pub data_source: DataSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DataSource {
|
||||||
|
Ls,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineData {
|
impl PipelineData {
|
||||||
pub fn new(span: Span) -> PipelineData {
|
pub fn new(span: Span) -> PipelineData {
|
||||||
PipelineData::Value(Value::Nothing { span })
|
PipelineData::Value(Value::Nothing { span }, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_value(self, span: Span) -> Value {
|
pub fn into_value(self, span: Span) -> Value {
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(v) => v,
|
PipelineData::Value(v, ..) => v,
|
||||||
PipelineData::Stream(s) => Value::List {
|
PipelineData::Stream(s, ..) => Value::List {
|
||||||
vals: s.collect(),
|
vals: s.collect(),
|
||||||
span, // FIXME?
|
span, // FIXME?
|
||||||
},
|
},
|
||||||
@ -55,7 +65,7 @@ impl PipelineData {
|
|||||||
pub fn into_interruptible_iter(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineIterator {
|
pub fn into_interruptible_iter(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineIterator {
|
||||||
let mut iter = self.into_iter();
|
let mut iter = self.into_iter();
|
||||||
|
|
||||||
if let PipelineIterator(PipelineData::Stream(s)) = &mut iter {
|
if let PipelineIterator(PipelineData::Stream(s, ..)) = &mut iter {
|
||||||
s.ctrlc = ctrlc;
|
s.ctrlc = ctrlc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,20 +74,20 @@ impl PipelineData {
|
|||||||
|
|
||||||
pub fn collect_string(self, separator: &str, config: &Config) -> String {
|
pub fn collect_string(self, separator: &str, config: &Config) -> String {
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(v) => v.into_string(separator, config),
|
PipelineData::Value(v, ..) => v.into_string(separator, config),
|
||||||
PipelineData::Stream(s) => s.into_string(separator, config),
|
PipelineData::Stream(s, ..) => s.into_string(separator, config),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn follow_cell_path(self, cell_path: &[PathMember]) -> Result<Value, ShellError> {
|
pub fn follow_cell_path(self, cell_path: &[PathMember]) -> Result<Value, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
// FIXME: there are probably better ways of doing this
|
// FIXME: there are probably better ways of doing this
|
||||||
PipelineData::Stream(stream) => Value::List {
|
PipelineData::Stream(stream, ..) => Value::List {
|
||||||
vals: stream.collect(),
|
vals: stream.collect(),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}
|
}
|
||||||
.follow_cell_path(cell_path),
|
.follow_cell_path(cell_path),
|
||||||
PipelineData::Value(v) => v.follow_cell_path(cell_path),
|
PipelineData::Value(v, ..) => v.follow_cell_path(cell_path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,12 +98,12 @@ impl PipelineData {
|
|||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
match self {
|
match self {
|
||||||
// FIXME: there are probably better ways of doing this
|
// FIXME: there are probably better ways of doing this
|
||||||
PipelineData::Stream(stream) => Value::List {
|
PipelineData::Stream(stream, ..) => Value::List {
|
||||||
vals: stream.collect(),
|
vals: stream.collect(),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}
|
}
|
||||||
.update_cell_path(cell_path, callback),
|
.update_cell_path(cell_path, callback),
|
||||||
PipelineData::Value(v) => v.update_cell_path(cell_path, callback),
|
PipelineData::Value(v, ..) => v.update_cell_path(cell_path, callback),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,14 +118,14 @@ impl PipelineData {
|
|||||||
F: FnMut(Value) -> Value + 'static + Send,
|
F: FnMut(Value) -> Value + 'static + Send,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||||
Ok(vals.into_iter().map(f).into_pipeline_data(ctrlc))
|
Ok(vals.into_iter().map(f).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => Ok(stream.map(f).into_pipeline_data(ctrlc)),
|
PipelineData::Stream(stream, ..) => Ok(stream.map(f).into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Value(Value::Range { val, .. }) => {
|
PipelineData::Value(Value::Range { val, .. }, ..) => {
|
||||||
Ok(val.into_range_iter()?.map(f).into_pipeline_data(ctrlc))
|
Ok(val.into_range_iter()?.map(f).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
PipelineData::Value(v) => match f(v) {
|
PipelineData::Value(v, ..) => match f(v) {
|
||||||
Value::Error { error } => Err(error),
|
Value::Error { error } => Err(error),
|
||||||
v => Ok(v.into_pipeline_data()),
|
v => Ok(v.into_pipeline_data()),
|
||||||
},
|
},
|
||||||
@ -135,15 +145,17 @@ impl PipelineData {
|
|||||||
F: FnMut(Value) -> U + 'static + Send,
|
F: FnMut(Value) -> U + 'static + Send,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||||
Ok(vals.into_iter().map(f).flatten().into_pipeline_data(ctrlc))
|
Ok(vals.into_iter().map(f).flatten().into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => Ok(stream.map(f).flatten().into_pipeline_data(ctrlc)),
|
PipelineData::Stream(stream, ..) => {
|
||||||
PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() {
|
Ok(stream.map(f).flatten().into_pipeline_data(ctrlc))
|
||||||
|
}
|
||||||
|
PipelineData::Value(Value::Range { val, .. }, ..) => match val.into_range_iter() {
|
||||||
Ok(iter) => Ok(iter.map(f).flatten().into_pipeline_data(ctrlc)),
|
Ok(iter) => Ok(iter.map(f).flatten().into_pipeline_data(ctrlc)),
|
||||||
Err(error) => Err(error),
|
Err(error) => Err(error),
|
||||||
},
|
},
|
||||||
PipelineData::Value(v) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)),
|
PipelineData::Value(v, ..) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,14 +169,14 @@ impl PipelineData {
|
|||||||
F: FnMut(&Value) -> bool + 'static + Send,
|
F: FnMut(&Value) -> bool + 'static + Send,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||||
Ok(vals.into_iter().filter(f).into_pipeline_data(ctrlc))
|
Ok(vals.into_iter().filter(f).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => Ok(stream.filter(f).into_pipeline_data(ctrlc)),
|
PipelineData::Stream(stream, ..) => Ok(stream.filter(f).into_pipeline_data(ctrlc)),
|
||||||
PipelineData::Value(Value::Range { val, .. }) => {
|
PipelineData::Value(Value::Range { val, .. }, ..) => {
|
||||||
Ok(val.into_range_iter()?.filter(f).into_pipeline_data(ctrlc))
|
Ok(val.into_range_iter()?.filter(f).into_pipeline_data(ctrlc))
|
||||||
}
|
}
|
||||||
PipelineData::Value(v) => {
|
PipelineData::Value(v, ..) => {
|
||||||
if f(&v) {
|
if f(&v) {
|
||||||
Ok(v.into_pipeline_data())
|
Ok(v.into_pipeline_data())
|
||||||
} else {
|
} else {
|
||||||
@ -190,22 +202,33 @@ impl IntoIterator for PipelineData {
|
|||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(Value::List { vals, .. }) => {
|
PipelineData::Value(Value::List { vals, .. }, metadata) => {
|
||||||
PipelineIterator(PipelineData::Stream(ValueStream {
|
PipelineIterator(PipelineData::Stream(
|
||||||
stream: Box::new(vals.into_iter()),
|
ValueStream {
|
||||||
ctrlc: None,
|
stream: Box::new(vals.into_iter()),
|
||||||
}))
|
ctrlc: None,
|
||||||
|
},
|
||||||
|
metadata,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
PipelineData::Value(Value::Range { val, .. }, metadata) => {
|
||||||
|
match val.into_range_iter() {
|
||||||
|
Ok(iter) => PipelineIterator(PipelineData::Stream(
|
||||||
|
ValueStream {
|
||||||
|
stream: Box::new(iter),
|
||||||
|
ctrlc: None,
|
||||||
|
},
|
||||||
|
metadata,
|
||||||
|
)),
|
||||||
|
Err(error) => PipelineIterator(PipelineData::Stream(
|
||||||
|
ValueStream {
|
||||||
|
stream: Box::new(std::iter::once(Value::Error { error })),
|
||||||
|
ctrlc: None,
|
||||||
|
},
|
||||||
|
metadata,
|
||||||
|
)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() {
|
|
||||||
Ok(iter) => PipelineIterator(PipelineData::Stream(ValueStream {
|
|
||||||
stream: Box::new(iter),
|
|
||||||
ctrlc: None,
|
|
||||||
})),
|
|
||||||
Err(error) => PipelineIterator(PipelineData::Stream(ValueStream {
|
|
||||||
stream: Box::new(std::iter::once(Value::Error { error })),
|
|
||||||
ctrlc: None,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
x => PipelineIterator(x),
|
x => PipelineIterator(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,9 +239,9 @@ impl Iterator for PipelineIterator {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
PipelineData::Value(Value::Nothing { .. }) => None,
|
PipelineData::Value(Value::Nothing { .. }, ..) => None,
|
||||||
PipelineData::Value(v) => Some(std::mem::take(v)),
|
PipelineData::Value(v, ..) => Some(std::mem::take(v)),
|
||||||
PipelineData::Stream(stream) => stream.next(),
|
PipelineData::Stream(stream, ..) => stream.next(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,12 +255,17 @@ where
|
|||||||
V: Into<Value>,
|
V: Into<Value>,
|
||||||
{
|
{
|
||||||
fn into_pipeline_data(self) -> PipelineData {
|
fn into_pipeline_data(self) -> PipelineData {
|
||||||
PipelineData::Value(self.into())
|
PipelineData::Value(self.into(), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoInterruptiblePipelineData {
|
pub trait IntoInterruptiblePipelineData {
|
||||||
fn into_pipeline_data(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineData;
|
fn into_pipeline_data(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineData;
|
||||||
|
fn into_pipeline_data_with_metadata(
|
||||||
|
self,
|
||||||
|
metadata: PipelineMetadata,
|
||||||
|
ctrlc: Option<Arc<AtomicBool>>,
|
||||||
|
) -> PipelineData;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> IntoInterruptiblePipelineData for I
|
impl<I> IntoInterruptiblePipelineData for I
|
||||||
@ -247,9 +275,26 @@ where
|
|||||||
<I::IntoIter as Iterator>::Item: Into<Value>,
|
<I::IntoIter as Iterator>::Item: Into<Value>,
|
||||||
{
|
{
|
||||||
fn into_pipeline_data(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineData {
|
fn into_pipeline_data(self, ctrlc: Option<Arc<AtomicBool>>) -> PipelineData {
|
||||||
PipelineData::Stream(ValueStream {
|
PipelineData::Stream(
|
||||||
stream: Box::new(self.into_iter().map(Into::into)),
|
ValueStream {
|
||||||
ctrlc,
|
stream: Box::new(self.into_iter().map(Into::into)),
|
||||||
})
|
ctrlc,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_pipeline_data_with_metadata(
|
||||||
|
self,
|
||||||
|
metadata: PipelineMetadata,
|
||||||
|
ctrlc: Option<Arc<AtomicBool>>,
|
||||||
|
) -> PipelineData {
|
||||||
|
PipelineData::Stream(
|
||||||
|
ValueStream {
|
||||||
|
stream: Box::new(self.into_iter().map(Into::into)),
|
||||||
|
ctrlc,
|
||||||
|
},
|
||||||
|
Some(metadata),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,14 +126,14 @@ fn test2(call: &EvaluatedCall, input: &Value) -> Result<Value, ShellError> {
|
|||||||
let vals = (0..3)
|
let vals = (0..3)
|
||||||
.map(|v| Value::Int {
|
.map(|v| Value::Int {
|
||||||
val: v * i,
|
val: v * i,
|
||||||
span: call.head.clone(),
|
span: call.head,
|
||||||
})
|
})
|
||||||
.collect::<Vec<Value>>();
|
.collect::<Vec<Value>>();
|
||||||
|
|
||||||
Value::Record {
|
Value::Record {
|
||||||
cols: cols.clone(),
|
cols: cols.clone(),
|
||||||
vals,
|
vals,
|
||||||
span: call.head.clone(),
|
span: call.head,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<Value>>();
|
.collect::<Vec<Value>>();
|
||||||
|
24
src/main.rs
24
src/main.rs
@ -19,7 +19,7 @@ use nu_parser::parse;
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
IntoPipelineData, PipelineData, ShellError, Span, Value, CONFIG_VARIABLE_ID,
|
PipelineData, ShellError, Span, Value, CONFIG_VARIABLE_ID,
|
||||||
};
|
};
|
||||||
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
|
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
|
||||||
|
|
||||||
@ -313,8 +313,8 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_value(
|
fn print_pipeline_data(
|
||||||
value: Value,
|
input: PipelineData,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
@ -325,15 +325,13 @@ fn print_value(
|
|||||||
|
|
||||||
let output = match engine_state.find_decl("table".as_bytes()) {
|
let output = match engine_state.find_decl("table".as_bytes()) {
|
||||||
Some(decl_id) => {
|
Some(decl_id) => {
|
||||||
let table = engine_state.get_decl(decl_id).run(
|
let table =
|
||||||
engine_state,
|
engine_state
|
||||||
stack,
|
.get_decl(decl_id)
|
||||||
&Call::new(),
|
.run(engine_state, stack, &Call::new(), input)?;
|
||||||
value.into_pipeline_data(),
|
|
||||||
)?;
|
|
||||||
table.collect_string("\n", &config)
|
table.collect_string("\n", &config)
|
||||||
}
|
}
|
||||||
None => value.into_string(", ", &config),
|
None => input.collect_string(", ", &config),
|
||||||
};
|
};
|
||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
@ -436,11 +434,7 @@ fn eval_source(
|
|||||||
PipelineData::new(Span::unknown()),
|
PipelineData::new(Span::unknown()),
|
||||||
) {
|
) {
|
||||||
Ok(pipeline_data) => {
|
Ok(pipeline_data) => {
|
||||||
if let Err(err) = print_value(
|
if let Err(err) = print_pipeline_data(pipeline_data, engine_state, stack) {
|
||||||
pipeline_data.into_value(Span::unknown()),
|
|
||||||
engine_state,
|
|
||||||
stack,
|
|
||||||
) {
|
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
|
Loading…
Reference in New Issue
Block a user