Add zip command

This commit is contained in:
JT 2021-11-02 18:28:28 +13:00
parent bc8d90672e
commit 25846d3c1e
7 changed files with 88 additions and 75 deletions

View File

@ -1,5 +1,4 @@
use crate::date::utils::parse_date_from_string;
use chrono::prelude::*;
use chrono::{DateTime, FixedOffset, Local};
use chrono_humanize::HumanTime;
use nu_protocol::ast::Call;
@ -45,13 +44,7 @@ impl Command for SubCommand {
Example {
description: "Print a 'humanized' format for the date, relative to now.",
example: r#""2021-10-22 20:00:12 +01:00" | date humanize"#,
result: {
let s = Local.ymd(2021, 10, 22).and_hms(20, 00, 12);
Some(Value::String {
val: HumanTime::from(s).to_string(),
span: Span::unknown(),
})
},
result: None,
},
]
}

View File

@ -87,7 +87,8 @@ pub fn create_default_context() -> EngineState {
Touch,
Use,
Where,
Wrap
Wrap,
Zip
);
// This is a WIP proof of concept

View File

@ -73,40 +73,9 @@ impl Command for Each {
let span = call.head;
match input {
PipelineData::Value(Value::Range { val, .. }) => Ok(val
.into_range_iter()?
.enumerate()
.map(move |(idx, x)| {
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
if numbered {
stack.add_var(
*var_id,
Value::Record {
cols: vec!["index".into(), "item".into()],
vals: vec![
Value::Int {
val: idx as i64,
span,
},
x,
],
span,
},
);
} else {
stack.add_var(*var_id, x);
}
}
}
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
Ok(v) => v.into_value(),
Err(error) => Value::Error { error },
}
})
.into_pipeline_data(ctrlc)),
PipelineData::Value(Value::List { vals: val, .. }) => Ok(val
PipelineData::Value(Value::Range { .. })
| PipelineData::Value(Value::List { .. })
| PipelineData::Stream { .. } => Ok(input
.into_iter()
.enumerate()
.map(move |(idx, x)| {
@ -139,38 +108,6 @@ impl Command for Each {
}
})
.into_pipeline_data(ctrlc)),
PipelineData::Stream(stream) => Ok(stream
.enumerate()
.map(move |(idx, x)| {
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
if numbered {
stack.add_var(
*var_id,
Value::Record {
cols: vec!["index".into(), "item".into()],
vals: vec![
Value::Int {
val: idx as i64,
span,
},
x,
],
span,
},
);
} else {
stack.add_var(*var_id, x);
}
}
}
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
Ok(v) => v.into_value(),
Err(error) => Value::Error { error },
}
})
.into_pipeline_data(ctrlc)),
PipelineData::Value(Value::Record { cols, vals, .. }) => {
let mut output_cols = vec![];
let mut output_vals = vec![];

View File

@ -8,6 +8,7 @@ mod range;
mod select;
mod where_;
mod wrap;
mod zip;
pub use each::Each;
pub use get::Get;
@ -19,3 +20,4 @@ pub use range::Range;
pub use select::Select;
pub use where_::Where;
pub use wrap::Wrap;
pub use zip::Zip;

View File

@ -0,0 +1,65 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature, SyntaxShape,
Value,
};
#[derive(Clone)]
pub struct Zip;
impl Command for Zip {
fn name(&self) -> &str {
"zip"
}
fn usage(&self) -> &str {
"Combine a stream with the input"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("zip").required("other", SyntaxShape::Any, "the other input")
}
fn examples(&self) -> Vec<Example> {
vec![Example {
example: "1..3 | zip 4..6",
description: "Zip multiple streams and get one of the results",
result: None,
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let other: Value = call.req(engine_state, stack, 0)?;
let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
Ok(input
.into_iter()
.zip(other.into_pipeline_data().into_iter())
.map(move |(x, y)| Value::List {
vals: vec![x, y],
span: head,
})
.into_pipeline_data(ctrlc))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(Zip {})
}
}

View File

@ -116,6 +116,16 @@ impl IntoIterator for PipelineData {
ctrlc: None,
}))
}
PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() {
Ok(val) => PipelineIterator(PipelineData::Stream(ValueStream {
stream: Box::new(val),
ctrlc: None,
})),
Err(e) => PipelineIterator(PipelineData::Stream(ValueStream {
stream: Box::new(vec![Value::Error { error: e }].into_iter()),
ctrlc: None,
})),
},
x => PipelineIterator(x),
}
}

View File

@ -806,3 +806,8 @@ fn help_works_with_missing_requirements() -> TestResult {
fn scope_variable() -> TestResult {
run_test(r"let x = 3; $scope.vars.0", "$x")
}
#[test]
fn zip_ranges() -> TestResult {
run_test(r"1..3 | zip 4..6 | get 2.1", "6")
}