forked from extern/nushell
Declare input and output types of commands (#6796)
* Add failing test that list of ints and floats is List<Number> * Start defining subtype relation * Make it possible to declare input and output types for commands - Enforce them in tests * Declare input and output types of commands * Add formatted signatures to `help commands` table * Revert SyntaxShape::Table -> Type::Table change * Revert unnecessary derive(Hash) on SyntaxShape Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
This commit is contained in:
parent
f878276de7
commit
df94052180
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2743,6 +2743,8 @@ dependencies = [
|
||||
"num-format",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum 0.24.1",
|
||||
"strum_macros 0.24.3",
|
||||
"sys-locale",
|
||||
"thiserror",
|
||||
"typetag",
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits and")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required(
|
||||
"target",
|
||||
SyntaxShape::Int,
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits not")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.switch(
|
||||
"signed",
|
||||
"always treat input number as a signed number",
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits or")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required(
|
||||
"target",
|
||||
SyntaxShape::Int,
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
use num_traits::int::PrimInt;
|
||||
use std::fmt::Display;
|
||||
@ -18,6 +18,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits rol")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("bits", SyntaxShape::Int, "number of bits to rotate left")
|
||||
.switch(
|
||||
"signed",
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
use num_traits::int::PrimInt;
|
||||
use std::fmt::Display;
|
||||
@ -18,6 +18,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits ror")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("bits", SyntaxShape::Int, "number of bits to rotate right")
|
||||
.switch(
|
||||
"signed",
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
use num_traits::CheckedShl;
|
||||
use std::fmt::Display;
|
||||
@ -18,6 +18,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits shl")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("bits", SyntaxShape::Int, "number of bits to shift left")
|
||||
.switch(
|
||||
"signed",
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
use num_traits::CheckedShr;
|
||||
use std::fmt::Display;
|
||||
@ -18,6 +18,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits shr")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("bits", SyntaxShape::Int, "number of bits to shift right")
|
||||
.switch(
|
||||
"signed",
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bits xor")
|
||||
.input_output_types(vec![(Type::Int, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.required(
|
||||
"target",
|
||||
SyntaxShape::Int,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
struct Arguments {
|
||||
added_data: Vec<u8>,
|
||||
@ -30,6 +30,8 @@ impl Command for BytesAdd {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes add")
|
||||
.input_output_types(vec![(Type::Binary, Type::Binary)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("data", SyntaxShape::Binary, "the binary to add")
|
||||
.named(
|
||||
"index",
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
@ -115,6 +115,8 @@ impl Command for BytesAt {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes at")
|
||||
.input_output_types(vec![(Type::Binary, Type::Binary)])
|
||||
.vectorizes_over_list(true)
|
||||
.required("range", SyntaxShape::Any, "the indexes to get bytes")
|
||||
.rest(
|
||||
"rest",
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -24,6 +24,7 @@ impl Command for BytesBuild {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("bytes build")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Binary)])
|
||||
.rest("rest", SyntaxShape::Any, "list of bytes")
|
||||
.category(Category::Bytes)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@ -16,6 +16,7 @@ impl Command for BytesCollect {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes collect")
|
||||
.input_output_types(vec![(Type::List(Box::new(Type::Binary)), Type::Binary)])
|
||||
.optional(
|
||||
"separator",
|
||||
SyntaxShape::Binary,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
@ -28,6 +28,7 @@ impl Command for BytesEndsWith {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes ends-with")
|
||||
.input_output_types(vec![(Type::Binary, Type::Bool)])
|
||||
.required("pattern", SyntaxShape::Binary, "the pattern to match")
|
||||
.rest(
|
||||
"rest",
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
struct Arguments {
|
||||
@ -29,6 +29,10 @@ impl Command for BytesIndexOf {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes index-of")
|
||||
.input_output_types(vec![
|
||||
(Type::Binary, Type::Int),
|
||||
(Type::Binary, Type::List(Box::new(Type::Int))),
|
||||
])
|
||||
.required(
|
||||
"pattern",
|
||||
SyntaxShape::Binary,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BytesLen;
|
||||
@ -16,6 +16,8 @@ impl Command for BytesLen {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes length")
|
||||
.input_output_types(vec![(Type::Binary, Type::Int)])
|
||||
.vectorizes_over_list(true)
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
|
@ -3,7 +3,8 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
struct Arguments {
|
||||
@ -29,6 +30,7 @@ impl Command for BytesRemove {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes remove")
|
||||
.input_output_types(vec![(Type::Binary, Type::Binary)])
|
||||
.required("pattern", SyntaxShape::Binary, "the pattern to find")
|
||||
.rest(
|
||||
"rest",
|
||||
|
@ -3,7 +3,8 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
struct Arguments {
|
||||
@ -29,6 +30,7 @@ impl Command for BytesReplace {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes replace")
|
||||
.input_output_types(vec![(Type::Binary, Type::Binary)])
|
||||
.required("find", SyntaxShape::Binary, "the pattern to find")
|
||||
.required("replace", SyntaxShape::Binary, "the replacement pattern")
|
||||
.rest(
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
@ -17,6 +17,7 @@ impl Command for BytesReverse {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes reverse")
|
||||
.input_output_types(vec![(Type::Binary, Type::Binary)])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
@ -28,6 +28,7 @@ impl Command for BytesStartsWith {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("bytes starts-with")
|
||||
.input_output_types(vec![(Type::Binary, Type::Bool)])
|
||||
.required("pattern", SyntaxShape::Binary, "the pattern to match")
|
||||
.rest(
|
||||
"rest",
|
||||
|
@ -13,7 +13,7 @@ use std::hash::{Hash, Hasher};
|
||||
/// ```text
|
||||
/// assert_eq!(HashableValue::Bool {val: true, span: Span{start: 0, end: 1}}, HashableValue::Bool {val: true, span: Span{start: 90, end: 1000}})
|
||||
/// ```
|
||||
#[derive(Eq, Debug)]
|
||||
#[derive(Eq, Debug, Ord, PartialOrd)]
|
||||
pub enum HashableValue {
|
||||
Bool {
|
||||
val: bool,
|
||||
|
@ -1,10 +1,11 @@
|
||||
use super::hashable_value::HashableValue;
|
||||
use itertools::Itertools;
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::iter;
|
||||
@ -24,6 +25,7 @@ impl Command for Histogram {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("histogram")
|
||||
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Table(vec![])),])
|
||||
.optional("column-name", SyntaxShape::String, "column name to calc frequency, no need to provide if input is just a list")
|
||||
.optional("frequency-column-name", SyntaxShape::String, "histogram's frequency column, default to be frequency column output")
|
||||
.named("percentage-type", SyntaxShape::String, "percentage calculate method, can be 'normalize' or 'relative', in 'normalize', defaults to be 'normalize'", Some('t'))
|
||||
@ -36,23 +38,48 @@ impl Command for Histogram {
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get a histogram for the types of files",
|
||||
description: "Compute a histogram of file types",
|
||||
example: "ls | histogram type",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description:
|
||||
"Get a histogram for the types of files, with frequency column named freq",
|
||||
"Compute a histogram for the types of files, with frequency column named freq",
|
||||
example: "ls | histogram type freq",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Get a histogram for a list of numbers",
|
||||
example: "echo [1 2 3 1 1 1 2 2 1 1] | histogram",
|
||||
result: None,
|
||||
description: "Compute a histogram for a list of numbers",
|
||||
example: "echo [1 2 1] | histogram",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::Record {
|
||||
cols: vec!["value".to_string(), "count".to_string(), "quantile".to_string(), "percentage".to_string(), "frequency".to_string()],
|
||||
vals: vec![
|
||||
Value::test_int(1),
|
||||
Value::test_int(2),
|
||||
Value::test_float(0.6666666666666666),
|
||||
Value::test_string("66.67%"),
|
||||
Value::test_string("******************************************************************"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::Record {
|
||||
cols: vec!["value".to_string(), "count".to_string(), "quantile".to_string(), "percentage".to_string(), "frequency".to_string()],
|
||||
vals: vec![
|
||||
Value::test_int(2),
|
||||
Value::test_int(1),
|
||||
Value::test_float(0.3333333333333333),
|
||||
Value::test_string("33.33%"),
|
||||
Value::test_string("*********************************"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}],
|
||||
span: Span::test_data(),
|
||||
}
|
||||
),
|
||||
},
|
||||
Example {
|
||||
description: "Get a histogram for a list of numbers, and percentage is based on the maximum value",
|
||||
description: "Compute a histogram for a list of numbers, and percentage is based on the maximum value",
|
||||
example: "echo [1 2 3 1 1 1 2 2 1 1] | histogram --percentage-type relative",
|
||||
result: None,
|
||||
}
|
||||
@ -213,7 +240,7 @@ fn histogram_impl(
|
||||
freq_column.to_string(),
|
||||
];
|
||||
const MAX_FREQ_COUNT: f64 = 100.0;
|
||||
for (val, count) in counter.into_iter() {
|
||||
for (val, count) in counter.into_iter().sorted() {
|
||||
let quantile = match calc_method {
|
||||
PercentageCalcMethod::Normalize => count as f64 / total_cnt as f64,
|
||||
PercentageCalcMethod::Relative => count as f64 / max_cnt as f64,
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,7 +19,9 @@ impl Command for Fmt {
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("fmt").category(Category::Conversions)
|
||||
Signature::build("fmt")
|
||||
.input_output_types(vec![(Type::Number, Type::Record(vec![]))])
|
||||
.category(Category::Conversions)
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,16 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into binary")
|
||||
.input_output_types(vec![
|
||||
(Type::Binary, Type::Binary),
|
||||
(Type::Int, Type::Binary),
|
||||
(Type::Number, Type::Binary),
|
||||
(Type::String, Type::Binary),
|
||||
(Type::Bool, Type::Binary),
|
||||
(Type::Filesize, Type::Binary),
|
||||
(Type::Date, Type::Binary),
|
||||
])
|
||||
.allow_variants_without_examples(true) // TODO: supply exhaustive examples
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,13 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into bool")
|
||||
.input_output_types(vec![
|
||||
(Type::Int, Type::Bool),
|
||||
(Type::Number, Type::Bool),
|
||||
(Type::String, Type::Bool),
|
||||
(Type::Bool, Type::Bool),
|
||||
(Type::List(Box::new(Type::Any)), Type::Table(vec![])),
|
||||
])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
@ -89,6 +96,11 @@ impl Command for SubCommand {
|
||||
example: "1 | into bool",
|
||||
result: Some(Value::boolean(true, span)),
|
||||
},
|
||||
Example {
|
||||
description: "convert decimal to boolean",
|
||||
example: "0.3 | into bool",
|
||||
result: Some(Value::boolean(true, span)),
|
||||
},
|
||||
Example {
|
||||
description: "convert decimal string to boolean",
|
||||
example: "'0.0' | into bool",
|
||||
|
@ -7,7 +7,7 @@ use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
struct Arguments {
|
||||
@ -64,7 +64,11 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into datetime")
|
||||
.named(
|
||||
.input_output_types(vec![
|
||||
(Type::Int, Type::Date),
|
||||
(Type::String, Type::Date),
|
||||
])
|
||||
.named(
|
||||
"timezone",
|
||||
SyntaxShape::String,
|
||||
"Specify timezone if the input is a Unix timestamp. Valid options: 'UTC' ('u') or 'LOCAL' ('l')",
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,11 +15,16 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into decimal").rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
"optionally convert text into decimal by column paths",
|
||||
)
|
||||
Signature::build("into decimal")
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::Number),
|
||||
(Type::Bool, Type::Number),
|
||||
])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
"optionally convert text into decimal by column paths",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -3,7 +3,7 @@ use nu_parser::parse_duration_bytes;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath, Expr},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Unit,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Unit,
|
||||
Value,
|
||||
};
|
||||
|
||||
@ -17,6 +17,13 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into duration")
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::Duration),
|
||||
(Type::Duration, Type::Duration),
|
||||
// TODO: --convert option should be implemented as `format duration`
|
||||
(Type::String, Type::String),
|
||||
(Type::Duration, Type::String),
|
||||
])
|
||||
.named(
|
||||
"convert",
|
||||
SyntaxShape::String,
|
||||
@ -121,11 +128,19 @@ impl Command for SubCommand {
|
||||
span,
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Convert duration to duration",
|
||||
example: "420sec | into duration",
|
||||
result: Some(Value::Duration {
|
||||
val: 7 * 60 * 1000 * 1000 * 1000,
|
||||
span,
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Convert duration to the requested duration as a string",
|
||||
example: "420sec | into duration --convert min",
|
||||
example: "420sec | into duration --convert ms",
|
||||
result: Some(Value::String {
|
||||
val: "7 min".to_string(),
|
||||
val: "420000 ms".to_string(),
|
||||
span,
|
||||
}),
|
||||
},
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,12 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into filesize")
|
||||
.input_output_types(vec![
|
||||
(Type::Int, Type::Filesize),
|
||||
(Type::Number, Type::Filesize),
|
||||
(Type::String, Type::Filesize),
|
||||
(Type::Filesize, Type::Filesize),
|
||||
])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
struct Arguments {
|
||||
@ -28,6 +28,16 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into int")
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::Int),
|
||||
(Type::Number, Type::Int),
|
||||
(Type::Bool, Type::Int),
|
||||
// Unix timestamp in seconds
|
||||
(Type::Date, Type::Int),
|
||||
// TODO: Users should do this by dividing a Filesize by a Filesize explicitly
|
||||
(Type::Filesize, Type::Int),
|
||||
])
|
||||
.vectorizes_over_list(true)
|
||||
.named("radix", SyntaxShape::Number, "radix of integer", Some('r'))
|
||||
.switch("little-endian", "use little-endian byte decoding", None)
|
||||
.rest(
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
into_code, Category, Config, Example, IntoPipelineData, PipelineData, ShellError, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
use nu_utils::get_system_locale;
|
||||
use num_format::ToFormattedString;
|
||||
@ -32,6 +32,16 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into string")
|
||||
.input_output_types(vec![
|
||||
(Type::Binary, Type::String),
|
||||
(Type::Int, Type::String),
|
||||
(Type::Number, Type::String),
|
||||
(Type::String, Type::String),
|
||||
(Type::Bool, Type::String),
|
||||
(Type::Filesize, Type::String),
|
||||
(Type::Date, Type::String),
|
||||
])
|
||||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
||||
// FIXME - need to support column paths
|
||||
.rest(
|
||||
"rest",
|
||||
@ -135,11 +145,12 @@ impl Command for SubCommand {
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "convert date to string",
|
||||
example: "date now | into string",
|
||||
result: None,
|
||||
},
|
||||
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
||||
// Example {
|
||||
// description: "convert date to string",
|
||||
// example: "'2020-10-10 10:00:00 +02:00' | into datetime | into string",
|
||||
// result: Some(Value::test_string("Sat Oct 10 10:00:00 2020")),
|
||||
// },
|
||||
Example {
|
||||
description: "convert filepath to string",
|
||||
example: "ls Cargo.toml | get name | into string",
|
||||
@ -147,8 +158,8 @@ impl Command for SubCommand {
|
||||
},
|
||||
Example {
|
||||
description: "convert filesize to string",
|
||||
example: "ls Cargo.toml | get size | into string",
|
||||
result: None,
|
||||
example: "1KiB | into string",
|
||||
result: Some(Value::test_string("1,024 B")),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Alias;
|
||||
@ -16,6 +16,7 @@ impl Command for Alias {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("alias")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("name", SyntaxShape::String, "name of the alias")
|
||||
.required(
|
||||
"initial_value",
|
||||
@ -53,12 +54,12 @@ impl Command for Alias {
|
||||
Example {
|
||||
description: "Alias ll to ls -l",
|
||||
example: "alias ll = ls -l",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
},
|
||||
Example {
|
||||
description: "Make an alias that makes a list of all custom commands",
|
||||
example: "alias customs = ($nu.scope.commands | where is_custom | get command)",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use nu_parser::parse;
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +21,7 @@ impl Command for Ast {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("ast")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required(
|
||||
"pipeline",
|
||||
SyntaxShape::String,
|
||||
@ -50,17 +52,17 @@ impl Command for Ast {
|
||||
Example {
|
||||
description: "Print the ast of a string",
|
||||
example: "ast 'hello'",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
},
|
||||
Example {
|
||||
description: "Print the ast of a pipeline",
|
||||
example: "ast 'ls | where name =~ README'",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
},
|
||||
Example {
|
||||
description: "Print the ast of a pipeline with an error",
|
||||
example: "ast 'for x in 1..10 { echo $x '",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::engine::ReplOperation;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::IntoPipelineData;
|
||||
use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Commandline;
|
||||
@ -16,6 +16,7 @@ impl Command for Commandline {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("commandline")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.switch(
|
||||
"append",
|
||||
"appends the string to the end of the buffer",
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Debug;
|
||||
@ -15,11 +15,17 @@ impl Command for Debug {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("debug").category(Category::Core).switch(
|
||||
"raw",
|
||||
"Prints the raw value representation",
|
||||
Some('r'),
|
||||
)
|
||||
Signature::build("debug")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::String)),
|
||||
),
|
||||
(Type::Table(vec![]), Type::List(Box::new(Type::String))),
|
||||
(Type::Any, Type::String),
|
||||
])
|
||||
.category(Category::Core)
|
||||
.switch("raw", "Prints the raw value representation", Some('r'))
|
||||
}
|
||||
|
||||
fn run(
|
||||
@ -54,12 +60,20 @@ impl Command for Debug {
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Print the value of a string",
|
||||
description: "Debug print a string",
|
||||
example: "'hello' | debug",
|
||||
result: Some(Value::test_string("hello")),
|
||||
},
|
||||
Example {
|
||||
description: "Print the value of a table",
|
||||
description: "Debug print a list",
|
||||
example: "['hello'] | debug",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_string("hello")],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Debug print a table",
|
||||
example: "echo [[version patch]; [0.1.0 false] [0.1.1 true] [0.2.0 false]] | debug",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Def;
|
||||
@ -16,6 +16,7 @@ impl Command for Def {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("def")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("def_name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DefEnv;
|
||||
@ -16,6 +16,7 @@ impl Command for DefEnv {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("def-env")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("def_name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,7 +17,9 @@ impl Command for Describe {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("describe").category(Category::Core)
|
||||
Signature::build("describe")
|
||||
.input_output_types(vec![(Type::Any, Type::String)])
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
||||
fn run(
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, ListStream, PipelineData, RawStream, ShellError, Signature, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +20,7 @@ impl Command for Do {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("do")
|
||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||
.required("block", SyntaxShape::Any, "the block to run")
|
||||
.switch(
|
||||
"ignore-errors",
|
||||
@ -197,8 +198,13 @@ impl Command for Do {
|
||||
},
|
||||
Example {
|
||||
description: "Run the block, with a positional parameter",
|
||||
example: r#"do {|x| 100 + $x } 50"#,
|
||||
result: Some(Value::test_int(150)),
|
||||
example: r#"do {|x| 100 + $x } 77"#,
|
||||
result: Some(Value::test_int(177)),
|
||||
},
|
||||
Example {
|
||||
description: "Run the block, with input",
|
||||
example: r#"77 | do {|x| 100 + $in }"#,
|
||||
result: None, // TODO: returns 177
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, ListStream, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, ListStream, PipelineData, ShellError, Signature, Span, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,6 +20,7 @@ impl Command for Echo {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("echo")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Any)])
|
||||
.rest("rest", SyntaxShape::Any, "the values to echo")
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::get_full_help;
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, Span, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -14,7 +14,9 @@ impl Command for ExportCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("export").category(Category::Core)
|
||||
Signature::build("export")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportAlias;
|
||||
@ -16,6 +16,7 @@ impl Command for ExportAlias {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export alias")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("name", SyntaxShape::String, "name of the alias")
|
||||
.required(
|
||||
"initial_value",
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportDef;
|
||||
@ -16,6 +16,7 @@ impl Command for ExportDef {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export def")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportDefEnv;
|
||||
@ -16,6 +16,7 @@ impl Command for ExportDefEnv {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export def-env")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportExtern;
|
||||
@ -16,6 +16,7 @@ impl Command for ExportExtern {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export extern")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("def_name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.category(Category::Core)
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExportUse;
|
||||
@ -16,6 +16,7 @@ impl Command for ExportUse {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export use")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("pattern", SyntaxShape::ImportPattern, "import pattern")
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Extern;
|
||||
@ -16,6 +16,7 @@ impl Command for Extern {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("extern")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("def_name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.category(Category::Core)
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +20,7 @@ impl Command for For {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("for")
|
||||
.input_output_types(vec![(Type::Nothing, Type::List(Box::new(Type::Any)))])
|
||||
.required(
|
||||
"var_name",
|
||||
SyntaxShape::VarWithOptType,
|
||||
|
@ -1,4 +1,5 @@
|
||||
use fancy_regex::Regex;
|
||||
use itertools::Itertools;
|
||||
use nu_ansi_term::{
|
||||
Color::{Default, Red, White},
|
||||
Style,
|
||||
@ -9,7 +10,7 @@ use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Command, EngineState, Stack},
|
||||
span, Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||
ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
use std::borrow::Borrow;
|
||||
#[derive(Clone)]
|
||||
@ -22,6 +23,7 @@ impl Command for Help {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("help")
|
||||
.input_output_types(vec![(Type::Nothing, Type::String)])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::String,
|
||||
@ -162,6 +164,16 @@ fn help(
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("signatures".into());
|
||||
vals.push(Value::String {
|
||||
val: sig
|
||||
.input_output_types
|
||||
.iter()
|
||||
.map(|(i, o)| format!("{:?} => {:?}", i.to_shape(), o.to_shape()))
|
||||
.join("\n"),
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("search_terms".into());
|
||||
vals.push(if search_terms.is_empty() {
|
||||
Value::nothing(head)
|
||||
@ -259,6 +271,16 @@ fn help(
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("signatures".into());
|
||||
vals.push(Value::String {
|
||||
val: sig
|
||||
.input_output_types
|
||||
.iter()
|
||||
.map(|(i, o)| format!("{:?} => {:?}", i.to_shape(), o.to_shape()))
|
||||
.join("\n"),
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("search_terms".into());
|
||||
vals.push(if search_terms.is_empty() {
|
||||
Value::nothing(head)
|
||||
|
@ -1,7 +1,7 @@
|
||||
use nu_protocol::ast::{Call, Expr, Expression};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -14,6 +14,7 @@ impl Command for Hide {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("hide")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("pattern", SyntaxShape::ImportPattern, "import pattern")
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
did_you_mean, Category, Example, PipelineData, ShellError, Signature, Span, Spanned,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,7 @@ impl Command for HideEnv {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("hide-env")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.rest(
|
||||
"name",
|
||||
SyntaxShape::String,
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::{eval_block, eval_expression, eval_expression_with_input, CallExt
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, FromValue, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
||||
Category, Example, FromValue, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,6 +19,7 @@ impl Command for If {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("if")
|
||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||
.required("cond", SyntaxShape::Expression, "condition to check")
|
||||
.required(
|
||||
"then_block",
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Ignore;
|
||||
@ -15,7 +15,9 @@ impl Command for Ignore {
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("ignore").category(Category::Core)
|
||||
Signature::build("ignore")
|
||||
.input_output_types(vec![(Type::Any, Type::Nothing)])
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
@ -37,7 +39,7 @@ impl Command for Ignore {
|
||||
vec![Example {
|
||||
description: "Ignore the output of an echo command",
|
||||
example: "echo done | ignore",
|
||||
result: None,
|
||||
result: Some(Value::nothing(Span::test_data())),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use nu_engine::eval_expression_with_input;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Let;
|
||||
@ -17,6 +17,8 @@ impl Command for Let {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("let")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.allow_variants_without_examples(true)
|
||||
.required("var_name", SyntaxShape::VarWithOptType, "variable name")
|
||||
.required(
|
||||
"initial_value",
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::{Call, Expr, Expression};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, DataSource, Example, IntoPipelineData, PipelineData, PipelineMetadata, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +20,8 @@ impl Command for Metadata {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("metadata")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Record(vec![]))])
|
||||
.allow_variants_without_examples(true)
|
||||
.optional(
|
||||
"expression",
|
||||
SyntaxShape::Any,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Module;
|
||||
@ -16,6 +16,7 @@ impl Command for Module {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("module")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("module_name", SyntaxShape::String, "module name")
|
||||
.required(
|
||||
"block",
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Register;
|
||||
@ -16,6 +16,7 @@ impl Command for Register {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("register")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required(
|
||||
"plugin",
|
||||
SyntaxShape::Filepath,
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::{eval_block, find_in_dirs_env, redirect_env};
|
||||
use nu_protocol::ast::{Call, Expr, Expression};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,6 +19,7 @@ impl Command for Use {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("use")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required("pattern", SyntaxShape::ImportPattern, "import pattern")
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Example, IntoPipelineData, PipelineData, ShellError, Signature, Value};
|
||||
use nu_protocol::{Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value};
|
||||
|
||||
pub mod shadow {
|
||||
include!(concat!(env!("OUT_DIR"), "/shadow.rs"));
|
||||
@ -16,6 +16,8 @@ impl Command for Version {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("version")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Record(vec![]))])
|
||||
.allow_variants_without_examples(true)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -215,3 +217,13 @@ fn features_enabled() -> Vec<String> {
|
||||
|
||||
names
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use super::Version;
|
||||
use crate::test_examples;
|
||||
test_examples(Version {})
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,8 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
use nu_utils::locale::get_system_locale_string;
|
||||
use std::fmt::{Display, Write};
|
||||
@ -21,6 +22,11 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date format")
|
||||
.input_output_types(vec![
|
||||
(Type::Date, Type::String),
|
||||
(Type::String, Type::String),
|
||||
])
|
||||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
||||
.switch("list", "lists strftime cheatsheet", Some('l'))
|
||||
.optional(
|
||||
"format string",
|
||||
@ -66,8 +72,18 @@ impl Command for SubCommand {
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
||||
// Example {
|
||||
// description: "Format a given date-time using the default format (RFC 2822).",
|
||||
// example: r#"'2021-10-22 20:00:12 +01:00' | into datetime | date format"#,
|
||||
// result: Some(Value::String {
|
||||
// val: "Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
// span: Span::test_data(),
|
||||
// }),
|
||||
// },
|
||||
Example {
|
||||
description: "Format a given date using the default format (RFC 2822).",
|
||||
description:
|
||||
"Format a given date-time as a string using the default format (RFC 2822).",
|
||||
example: r#""2021-10-22 20:00:12 +01:00" | date format"#,
|
||||
result: Some(Value::String {
|
||||
val: "Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
@ -75,13 +91,13 @@ impl Command for SubCommand {
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Format a given date using a given format string.",
|
||||
example: "date format '%Y-%m-%d'",
|
||||
description: "Format the current date-time using a given format string.",
|
||||
example: r#"date now | date format "%Y-%m-%d %H:%M:%S""#,
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Format a given date using a given format string.",
|
||||
example: r#"date format "%Y-%m-%d %H:%M:%S""#,
|
||||
description: "Format the current date using a given format string.",
|
||||
example: r#"date now | date format "%Y-%m-%d %H:%M:%S""#,
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
|
@ -3,7 +3,7 @@ use chrono::{DateTime, FixedOffset, Local};
|
||||
use chrono_humanize::HumanTime;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Value};
|
||||
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -13,7 +13,13 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date humanize").category(Category::Date)
|
||||
Signature::build("date humanize")
|
||||
.input_output_types(vec![
|
||||
(Type::Date, Type::String),
|
||||
(Type::String, Type::String),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Date)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -45,21 +51,11 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Print a 'humanized' format for the date, relative to now.",
|
||||
example: "date humanize",
|
||||
result: Some(Value::String {
|
||||
val: "now".to_string(),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
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: None,
|
||||
},
|
||||
]
|
||||
vec![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: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use chrono_tz::TZ_VARIANTS;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, Signature, Span, Value,
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -14,7 +14,9 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date list-timezone").category(Category::Date)
|
||||
Signature::build("date list-timezone")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Table(vec![]))])
|
||||
.category(Category::Date)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use chrono::Local;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, IntoPipelineData, PipelineData, Signature, Value};
|
||||
use nu_protocol::{Category, Example, IntoPipelineData, PipelineData, Signature, Type, Value};
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -11,7 +11,9 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date now").category(Category::Date)
|
||||
Signature::build("date now")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Date)])
|
||||
.category(Category::Date)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -2,6 +2,7 @@ use crate::date::utils::parse_date_from_string;
|
||||
use chrono::{DateTime, Datelike, FixedOffset, Local, Timelike};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Type;
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError::DatetimeParseError, Signature, Span, Value,
|
||||
};
|
||||
@ -15,11 +16,17 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date to-record").category(Category::Date)
|
||||
Signature::build("date to-record")
|
||||
.input_output_types(vec![
|
||||
(Type::Date, Type::Record(vec![])),
|
||||
(Type::String, Type::Record(vec![])),
|
||||
])
|
||||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
||||
.category(Category::Date)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Convert the date into a structured table."
|
||||
"Convert the date into a record."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
@ -38,46 +45,54 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let example_result_1 = || {
|
||||
let span = Span::test_data();
|
||||
let cols = vec![
|
||||
"year".into(),
|
||||
"month".into(),
|
||||
"day".into(),
|
||||
"hour".into(),
|
||||
"minute".into(),
|
||||
"second".into(),
|
||||
"timezone".into(),
|
||||
];
|
||||
let vals = vec![
|
||||
Value::Int { val: 2020, span },
|
||||
Value::Int { val: 4, span },
|
||||
Value::Int { val: 12, span },
|
||||
Value::Int { val: 22, span },
|
||||
Value::Int { val: 10, span },
|
||||
Value::Int { val: 57, span },
|
||||
Value::String {
|
||||
val: "+02:00".to_string(),
|
||||
span,
|
||||
},
|
||||
];
|
||||
Some(Value::Record { cols, vals, span })
|
||||
};
|
||||
|
||||
vec![
|
||||
Example {
|
||||
description: "Convert the current date into a structured table.",
|
||||
example: "date to-table",
|
||||
description: "Convert the current date into a record.",
|
||||
example: "date to-record",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert the current date into a structured table.",
|
||||
description: "Convert the current date into a record.",
|
||||
example: "date now | date to-record",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert a given date into a structured table.",
|
||||
example: " '2020-04-12 22:10:57 +0200' | date to-record",
|
||||
result: {
|
||||
let span = Span::test_data();
|
||||
let cols = vec![
|
||||
"year".into(),
|
||||
"month".into(),
|
||||
"day".into(),
|
||||
"hour".into(),
|
||||
"minute".into(),
|
||||
"second".into(),
|
||||
"timezone".into(),
|
||||
];
|
||||
let vals = vec![
|
||||
Value::Int { val: 2020, span },
|
||||
Value::Int { val: 4, span },
|
||||
Value::Int { val: 12, span },
|
||||
Value::Int { val: 22, span },
|
||||
Value::Int { val: 10, span },
|
||||
Value::Int { val: 57, span },
|
||||
Value::String {
|
||||
val: "+02:00".to_string(),
|
||||
span,
|
||||
},
|
||||
];
|
||||
Some(Value::Record { cols, vals, span })
|
||||
},
|
||||
description: "Convert a date string into a record.",
|
||||
example: "'2020-04-12 22:10:57 +0200' | date to-record",
|
||||
result: example_result_1(),
|
||||
},
|
||||
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
||||
// Example {
|
||||
// description: "Convert a date into a record.",
|
||||
// example: "'2020-04-12 22:10:57 +0200' | into datetime | date to-record",
|
||||
// result: example_result_1(),
|
||||
// },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use crate::date::utils::parse_date_from_string;
|
||||
use chrono::{DateTime, Datelike, FixedOffset, Local, Timelike};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Type;
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError::DatetimeParseError, Signature, Span, Value,
|
||||
};
|
||||
@ -15,7 +16,13 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date to-table").category(Category::Date)
|
||||
Signature::build("date to-table")
|
||||
.input_output_types(vec![
|
||||
(Type::Date, Type::Table(vec![])),
|
||||
(Type::String, Type::Table(vec![])),
|
||||
])
|
||||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
||||
.category(Category::Date)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -38,49 +45,57 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let example_result_1 = || {
|
||||
let span = Span::test_data();
|
||||
let cols = vec![
|
||||
"year".into(),
|
||||
"month".into(),
|
||||
"day".into(),
|
||||
"hour".into(),
|
||||
"minute".into(),
|
||||
"second".into(),
|
||||
"timezone".into(),
|
||||
];
|
||||
let vals = vec![
|
||||
Value::Int { val: 2020, span },
|
||||
Value::Int { val: 4, span },
|
||||
Value::Int { val: 12, span },
|
||||
Value::Int { val: 22, span },
|
||||
Value::Int { val: 10, span },
|
||||
Value::Int { val: 57, span },
|
||||
Value::String {
|
||||
val: "+02:00".to_string(),
|
||||
span,
|
||||
},
|
||||
];
|
||||
Some(Value::List {
|
||||
vals: vec![Value::Record { cols, vals, span }],
|
||||
span,
|
||||
})
|
||||
};
|
||||
|
||||
vec![
|
||||
Example {
|
||||
description: "Convert the date into a structured table.",
|
||||
description: "Convert the current date into a table.",
|
||||
example: "date to-table",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert the date into a structured table.",
|
||||
description: "Convert the date into a table.",
|
||||
example: "date now | date to-table",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert a given date into a structured table.",
|
||||
example: " '2020-04-12 22:10:57 +0200' | date to-table",
|
||||
result: {
|
||||
let span = Span::test_data();
|
||||
let cols = vec![
|
||||
"year".into(),
|
||||
"month".into(),
|
||||
"day".into(),
|
||||
"hour".into(),
|
||||
"minute".into(),
|
||||
"second".into(),
|
||||
"timezone".into(),
|
||||
];
|
||||
let vals = vec![
|
||||
Value::Int { val: 2020, span },
|
||||
Value::Int { val: 4, span },
|
||||
Value::Int { val: 12, span },
|
||||
Value::Int { val: 22, span },
|
||||
Value::Int { val: 10, span },
|
||||
Value::Int { val: 57, span },
|
||||
Value::String {
|
||||
val: "+02:00".to_string(),
|
||||
span,
|
||||
},
|
||||
];
|
||||
Some(Value::List {
|
||||
vals: vec![Value::Record { cols, vals, span }],
|
||||
span,
|
||||
})
|
||||
},
|
||||
description: "Convert a given date into a table.",
|
||||
example: "'2020-04-12 22:10:57 +0200' | date to-table",
|
||||
result: example_result_1(),
|
||||
},
|
||||
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
||||
// Example {
|
||||
// description: "Convert a given date into a table.",
|
||||
// example: "'2020-04-12 22:10:57 +0200' | into datetime | date to-table",
|
||||
// result: example_result_1(),
|
||||
// },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
use chrono::{FixedOffset, TimeZone};
|
||||
@ -20,6 +20,8 @@ impl Command for SubCommand {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date to-timezone")
|
||||
.input_output_types(vec![(Type::Date, Type::Date), (Type::String, Type::Date)])
|
||||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
||||
.required("time zone", SyntaxShape::String, "time zone description")
|
||||
.category(Category::Date)
|
||||
}
|
||||
@ -62,6 +64,16 @@ impl Command for SubCommand {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let example_result_1 = || {
|
||||
let dt = FixedOffset::east(5 * 3600)
|
||||
.ymd(2020, 10, 10)
|
||||
.and_hms(13, 00, 00);
|
||||
Some(Value::Date {
|
||||
val: dt,
|
||||
span: Span::test_data(),
|
||||
})
|
||||
};
|
||||
|
||||
vec![
|
||||
Example {
|
||||
description: "Get the current date in UTC+05:00",
|
||||
@ -81,19 +93,14 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Get the current date in Hawaii",
|
||||
example: r#""2020-10-10 10:00:00 +02:00" | date to-timezone "+0500""#,
|
||||
// result: None
|
||||
// The following should be the result of the test, but it fails. Cannot figure it out why.
|
||||
result: {
|
||||
let dt = FixedOffset::east(5 * 3600)
|
||||
.ymd(2020, 10, 10)
|
||||
.and_hms(13, 00, 00);
|
||||
|
||||
Some(Value::Date {
|
||||
val: dt,
|
||||
span: Span::test_data(),
|
||||
})
|
||||
},
|
||||
result: example_result_1(),
|
||||
},
|
||||
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
||||
// Example {
|
||||
// description: "Get the current date in Hawaii, from a datetime object",
|
||||
// example: r#""2020-10-10 10:00:00 +02:00" | into datetime | date to-timezone "+0500""#,
|
||||
// result: example_result_1(),
|
||||
// },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
22
crates/nu-command/src/env/export_env.rs
vendored
22
crates/nu-command/src/env/export_env.rs
vendored
@ -2,7 +2,7 @@ use nu_engine::{eval_block, redirect_env, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,7 @@ impl Command for ExportEnv {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("export-env")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![])),
|
||||
@ -53,11 +54,20 @@ impl Command for ExportEnv {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Set an environment",
|
||||
example: r#"export-env { let-env SPAM = 'eggs' }; $env.SPAM"#,
|
||||
result: Some(Value::string("eggs", Span::test_data())),
|
||||
}]
|
||||
vec![
|
||||
Example {
|
||||
description: "Set an environment variable",
|
||||
example: r#"export-env { let-env SPAM = 'eggs' }"#,
|
||||
result: Some(Value::Nothing {
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Set an environment variable and examine its value",
|
||||
example: r#"export-env { let-env SPAM = 'eggs' }; $env.SPAM"#,
|
||||
result: Some(Value::string("eggs", Span::test_data())),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
3
crates/nu-command/src/env/with_env.rs
vendored
3
crates/nu-command/src/env/with_env.rs
vendored
@ -4,7 +4,7 @@ use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,7 @@ impl Command for WithEnv {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("with-env")
|
||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||
.required(
|
||||
"variable",
|
||||
SyntaxShape::Any,
|
||||
|
@ -1,75 +1,206 @@
|
||||
#[cfg(test)]
|
||||
use nu_engine::eval_block;
|
||||
#[cfg(test)]
|
||||
use nu_parser::parse;
|
||||
#[cfg(test)]
|
||||
use nu_protocol::{
|
||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||
PipelineData, Span, Value,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::To;
|
||||
|
||||
#[cfg(test)]
|
||||
use super::{
|
||||
Ansi, Date, From, If, Into, LetEnv, Math, Path, Random, Split, SplitColumn, SplitRow, Str,
|
||||
StrJoin, StrLength, StrReplace, Url, Wrap,
|
||||
};
|
||||
use nu_protocol::engine::Command;
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_examples(cmd: impl Command + 'static) {
|
||||
use crate::BuildString;
|
||||
test_examples::test_examples(cmd);
|
||||
}
|
||||
|
||||
let examples = cmd.examples();
|
||||
let mut engine_state = Box::new(EngineState::new());
|
||||
|
||||
let delta = {
|
||||
// Base functions that are needed for testing
|
||||
// Try to keep this working set small to keep tests running as fast as possible
|
||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||
working_set.add_decl(Box::new(Str));
|
||||
working_set.add_decl(Box::new(StrJoin));
|
||||
working_set.add_decl(Box::new(StrLength));
|
||||
working_set.add_decl(Box::new(StrReplace));
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(To));
|
||||
working_set.add_decl(Box::new(Into));
|
||||
working_set.add_decl(Box::new(Random));
|
||||
working_set.add_decl(Box::new(Split));
|
||||
working_set.add_decl(Box::new(SplitColumn));
|
||||
working_set.add_decl(Box::new(SplitRow));
|
||||
working_set.add_decl(Box::new(Math));
|
||||
working_set.add_decl(Box::new(Path));
|
||||
working_set.add_decl(Box::new(Date));
|
||||
working_set.add_decl(Box::new(Url));
|
||||
working_set.add_decl(Box::new(Ansi));
|
||||
working_set.add_decl(Box::new(Wrap));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
|
||||
use super::Echo;
|
||||
working_set.add_decl(Box::new(Echo));
|
||||
// Adding the command that is being tested to the working set
|
||||
working_set.add_decl(Box::new(cmd));
|
||||
|
||||
working_set.render()
|
||||
#[cfg(test)]
|
||||
mod test_examples {
|
||||
use super::super::{
|
||||
Ansi, BuildString, Date, Echo, From, If, Into, LetEnv, Math, Path, Random, Split,
|
||||
SplitColumn, SplitRow, Str, StrJoin, StrLength, StrReplace, Url, Wrap,
|
||||
};
|
||||
use crate::To;
|
||||
use itertools::Itertools;
|
||||
use nu_engine;
|
||||
use nu_parser;
|
||||
use nu_protocol::{
|
||||
ast::Block,
|
||||
engine::{Command, EngineState, Stack, StateDelta, StateWorkingSet},
|
||||
Example, PipelineData, Signature, Span, Type, Value,
|
||||
};
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
|
||||
let cwd = std::env::current_dir().expect("Could not get current working directory.");
|
||||
pub fn test_examples(cmd: impl Command + 'static) {
|
||||
let examples = cmd.examples();
|
||||
let signature = cmd.signature();
|
||||
let mut engine_state = make_engine_state(cmd.clone_box());
|
||||
|
||||
engine_state
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
let cwd = std::env::current_dir().expect("Could not get current working directory.");
|
||||
|
||||
for example in examples {
|
||||
// Skip tests that don't have results to compare to
|
||||
if example.result.is_none() {
|
||||
continue;
|
||||
let mut witnessed_type_transformations = HashSet::<(Type, Type)>::new();
|
||||
|
||||
for example in examples {
|
||||
if example.result.is_none() {
|
||||
continue;
|
||||
}
|
||||
witnessed_type_transformations.extend(
|
||||
check_example_input_and_output_types_match_command_signature(
|
||||
&example,
|
||||
&cwd,
|
||||
&mut make_engine_state(cmd.clone_box()),
|
||||
&signature.input_output_types,
|
||||
signature.operates_on_cell_paths(),
|
||||
signature.vectorizes_over_list,
|
||||
),
|
||||
);
|
||||
check_example_evaluates_to_expected_output(&example, &cwd, &mut engine_state);
|
||||
}
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
check_all_signature_input_output_types_entries_have_examples(
|
||||
signature,
|
||||
witnessed_type_transformations,
|
||||
);
|
||||
}
|
||||
|
||||
fn make_engine_state(cmd: Box<dyn Command>) -> Box<EngineState> {
|
||||
let mut engine_state = Box::new(EngineState::new());
|
||||
|
||||
let delta = {
|
||||
// Base functions that are needed for testing
|
||||
// Try to keep this working set small to keep tests running as fast as possible
|
||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||
working_set.add_decl(Box::new(Str));
|
||||
working_set.add_decl(Box::new(StrJoin));
|
||||
working_set.add_decl(Box::new(StrLength));
|
||||
working_set.add_decl(Box::new(StrReplace));
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(To));
|
||||
working_set.add_decl(Box::new(Into));
|
||||
working_set.add_decl(Box::new(Random));
|
||||
working_set.add_decl(Box::new(Split));
|
||||
working_set.add_decl(Box::new(SplitColumn));
|
||||
working_set.add_decl(Box::new(SplitRow));
|
||||
working_set.add_decl(Box::new(Math));
|
||||
working_set.add_decl(Box::new(Path));
|
||||
working_set.add_decl(Box::new(Date));
|
||||
working_set.add_decl(Box::new(Url));
|
||||
working_set.add_decl(Box::new(Ansi));
|
||||
working_set.add_decl(Box::new(Wrap));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
working_set.add_decl(Box::new(Echo));
|
||||
// Adding the command that is being tested to the working set
|
||||
working_set.add_decl(cmd);
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
|
||||
engine_state
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
engine_state
|
||||
}
|
||||
|
||||
fn check_example_input_and_output_types_match_command_signature<'a>(
|
||||
example: &Example,
|
||||
cwd: &PathBuf,
|
||||
engine_state: &mut Box<EngineState>,
|
||||
signature_input_output_types: &Vec<(Type, Type)>,
|
||||
signature_operates_on_cell_paths: bool,
|
||||
signature_vectorizes_over_list: bool,
|
||||
) -> HashSet<(Type, Type)> {
|
||||
let mut witnessed_type_transformations = HashSet::<(Type, Type)>::new();
|
||||
|
||||
// Skip tests that don't have results to compare to
|
||||
if let Some(example_output) = example.result.as_ref() {
|
||||
if let Some(example_input_type) =
|
||||
eval_pipeline_without_terminal_expression(example.example, &cwd, engine_state)
|
||||
{
|
||||
let example_input_type = example_input_type.get_type();
|
||||
let example_output_type = example_output.get_type();
|
||||
|
||||
let example_matches_signature =
|
||||
signature_input_output_types
|
||||
.iter()
|
||||
.any(|(sig_in_type, sig_out_type)| {
|
||||
example_input_type.is_subtype(sig_in_type)
|
||||
&& example_output_type.is_subtype(sig_out_type)
|
||||
&& {
|
||||
witnessed_type_transformations
|
||||
.insert((sig_in_type.clone(), sig_out_type.clone()));
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
// The example type checks as vectorization over an input list if both:
|
||||
// 1. The command is declared to vectorize over list input.
|
||||
// 2. There exists an entry t -> u in the type map such that the
|
||||
// example_input_type is a subtype of list<t> and the
|
||||
// example_output_type is a subtype of list<u>.
|
||||
let example_matches_signature_via_vectorization_over_list =
|
||||
signature_vectorizes_over_list
|
||||
&& match &example_input_type {
|
||||
Type::List(ex_in_type) => {
|
||||
match signature_input_output_types.iter().find_map(
|
||||
|(sig_in_type, sig_out_type)| {
|
||||
if ex_in_type.is_subtype(sig_in_type) {
|
||||
Some((sig_in_type, sig_out_type))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
) {
|
||||
Some((sig_in_type, sig_out_type)) => match &example_output_type
|
||||
{
|
||||
Type::List(ex_out_type)
|
||||
if ex_out_type.is_subtype(sig_out_type) =>
|
||||
{
|
||||
witnessed_type_transformations.insert((
|
||||
sig_in_type.clone(),
|
||||
sig_out_type.clone(),
|
||||
));
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// The example type checks as a cell path operation if both:
|
||||
// 1. The command is declared to operate on cell paths.
|
||||
// 2. The example_input_type is list or record or table, and the example
|
||||
// output shape is the same as the input shape.
|
||||
let example_matches_signature_via_cell_path_operation =
|
||||
signature_operates_on_cell_paths
|
||||
&& example_input_type.accepts_cell_paths()
|
||||
// TODO: This is too permissive; it should make use of the signature.input_output_types at least.
|
||||
&& example_output_type.to_shape() == example_input_type.to_shape();
|
||||
|
||||
if !(example_matches_signature
|
||||
|| example_matches_signature_via_vectorization_over_list
|
||||
|| example_matches_signature_via_cell_path_operation)
|
||||
{
|
||||
assert!(
|
||||
false,
|
||||
"The example `{}` demonstrates a transformation of type {:?} -> {:?}. \
|
||||
However, this does not match the declared signature: {:?}.{} \
|
||||
For this command, `vectorizes_over_list` is {} and `operates_on_cell_paths()` is {}.",
|
||||
example.example,
|
||||
example_input_type,
|
||||
example_output_type,
|
||||
signature_input_output_types,
|
||||
if signature_input_output_types.is_empty() { " (Did you forget to declare the input and output types for the command?)" } else { "" },
|
||||
signature_vectorizes_over_list,
|
||||
signature_operates_on_cell_paths
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
witnessed_type_transformations
|
||||
}
|
||||
|
||||
fn check_example_evaluates_to_expected_output(
|
||||
example: &Example,
|
||||
cwd: &PathBuf,
|
||||
engine_state: &mut Box<EngineState>,
|
||||
) {
|
||||
let mut stack = Stack::new();
|
||||
|
||||
// Set up PWD
|
||||
@ -85,30 +216,82 @@ pub fn test_examples(cmd: impl Command + 'static) {
|
||||
.merge_env(&mut stack, &cwd)
|
||||
.expect("Error merging environment");
|
||||
|
||||
let (block, delta) = {
|
||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||
let (output, err) = parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
example.example.as_bytes(),
|
||||
false,
|
||||
&[],
|
||||
let empty_input = PipelineData::new(Span::test_data());
|
||||
let result = eval(example.example, empty_input, &cwd, engine_state);
|
||||
|
||||
// Note. Value implements PartialEq for Bool, Int, Float, String and Block
|
||||
// If the command you are testing requires to compare another case, then
|
||||
// you need to define its equality in the Value struct
|
||||
if let Some(expected) = example.result.as_ref() {
|
||||
assert_eq!(
|
||||
&result, expected,
|
||||
"The example result differs from the expected value",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_all_signature_input_output_types_entries_have_examples(
|
||||
signature: Signature,
|
||||
witnessed_type_transformations: HashSet<(Type, Type)>,
|
||||
) {
|
||||
let declared_type_transformations =
|
||||
HashSet::from_iter(signature.input_output_types.into_iter());
|
||||
assert!(
|
||||
witnessed_type_transformations.is_subset(&declared_type_transformations),
|
||||
"This should not be possible (bug in test): the type transformations \
|
||||
collected in the course of matching examples to the signature type map \
|
||||
contain type transformations not present in the signature type map."
|
||||
);
|
||||
|
||||
if !signature.allow_variants_without_examples {
|
||||
assert_eq!(
|
||||
witnessed_type_transformations,
|
||||
declared_type_transformations,
|
||||
"There are entries in the signature type map which do not correspond to any example: \
|
||||
{:?}",
|
||||
declared_type_transformations
|
||||
.difference(&witnessed_type_transformations)
|
||||
.map(|(s1, s2)| format!("{} -> {}", s1, s2))
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(err) = err {
|
||||
panic!("test parse error in `{}`: {:?}", example.example, err)
|
||||
}
|
||||
fn eval(
|
||||
contents: &str,
|
||||
input: PipelineData,
|
||||
cwd: &PathBuf,
|
||||
engine_state: &mut Box<EngineState>,
|
||||
) -> Value {
|
||||
let (block, delta) = parse(contents, engine_state);
|
||||
eval_block(block, input, cwd, engine_state, delta)
|
||||
}
|
||||
|
||||
(output, working_set.render())
|
||||
};
|
||||
fn parse(contents: &str, engine_state: &Box<EngineState>) -> (Block, StateDelta) {
|
||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||
let (output, err) =
|
||||
nu_parser::parse(&mut working_set, None, contents.as_bytes(), false, &[]);
|
||||
|
||||
if let Some(err) = err {
|
||||
panic!("test parse error in `{}`: {:?}", contents, err)
|
||||
}
|
||||
|
||||
(output, working_set.render())
|
||||
}
|
||||
|
||||
fn eval_block(
|
||||
block: Block,
|
||||
input: PipelineData,
|
||||
cwd: &PathBuf,
|
||||
engine_state: &mut Box<EngineState>,
|
||||
delta: StateDelta,
|
||||
) -> Value {
|
||||
engine_state
|
||||
.merge_delta(delta)
|
||||
.expect("Error merging delta");
|
||||
|
||||
let mut stack = Stack::new();
|
||||
|
||||
// Set up PWD
|
||||
stack.add_env_var(
|
||||
"PWD".to_string(),
|
||||
Value::String {
|
||||
@ -117,33 +300,34 @@ pub fn test_examples(cmd: impl Command + 'static) {
|
||||
},
|
||||
);
|
||||
|
||||
match eval_block(
|
||||
&engine_state,
|
||||
&mut stack,
|
||||
&block,
|
||||
PipelineData::new(Span::test_data()),
|
||||
true,
|
||||
true,
|
||||
) {
|
||||
Err(err) => panic!("test eval error in `{}`: {:?}", example.example, err),
|
||||
Ok(result) => {
|
||||
let result = result.into_value(Span::test_data());
|
||||
println!("input: {}", example.example);
|
||||
println!("result: {:?}", result);
|
||||
println!("done: {:?}", start.elapsed());
|
||||
match nu_engine::eval_block(&engine_state, &mut stack, &block, input, true, true) {
|
||||
Err(err) => panic!("test eval error in `{}`: {:?}", "TODO", err),
|
||||
Ok(result) => result.into_value(Span::test_data()),
|
||||
}
|
||||
}
|
||||
|
||||
// Note. Value implements PartialEq for Bool, Int, Float, String and Block
|
||||
// If the command you are testing requires to compare another case, then
|
||||
// you need to define its equality in the Value struct
|
||||
if let Some(expected) = example.result {
|
||||
if result != expected {
|
||||
panic!(
|
||||
"the example result is different to expected value: {:?} != {:?}",
|
||||
result, expected
|
||||
)
|
||||
}
|
||||
fn eval_pipeline_without_terminal_expression(
|
||||
src: &str,
|
||||
cwd: &PathBuf,
|
||||
engine_state: &mut Box<EngineState>,
|
||||
) -> Option<Value> {
|
||||
let (mut block, delta) = parse(src, engine_state);
|
||||
match block.pipelines.len() {
|
||||
1 => {
|
||||
let n_expressions = block.pipelines[0].expressions.len();
|
||||
block.pipelines[0].expressions.truncate(&n_expressions - 1);
|
||||
|
||||
if !block.pipelines[0].expressions.is_empty() {
|
||||
let empty_input = PipelineData::new(Span::test_data());
|
||||
Some(eval_block(block, empty_input, &cwd, engine_state, delta))
|
||||
} else {
|
||||
Some(Value::nothing(Span::test_data()))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// E.g. multiple semicolon-separated statements
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +16,10 @@ impl Command for All {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Any)), Type::Bool),
|
||||
(Type::Table(vec![]), Type::Bool),
|
||||
])
|
||||
.required(
|
||||
"predicate",
|
||||
SyntaxShape::RowCondition,
|
||||
|
@ -2,7 +2,8 @@ use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +16,10 @@ impl Command for Any {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Any)), Type::Bool),
|
||||
(Type::Table(vec![]), Type::Bool),
|
||||
])
|
||||
.required(
|
||||
"predicate",
|
||||
SyntaxShape::RowCondition,
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,10 @@ impl Command for Append {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("append")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required("row", SyntaxShape::Any, "the row, list, or table to append")
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::{eval_block, redirect_env, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,7 @@ impl Command for Collect {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("collect")
|
||||
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Any)])
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||
Signature, Span, Value,
|
||||
Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,7 +15,12 @@ impl Command for Columns {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name()).category(Category::Filters)
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![(
|
||||
Type::Table(vec![]),
|
||||
Type::List(Box::new(Type::String)),
|
||||
)])
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::Call, engine::Command, engine::EngineState, engine::Stack, Category, Example,
|
||||
PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -14,6 +14,19 @@ impl Command for Compact {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("compact")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::Table(vec![]), Type::Table(vec![])),
|
||||
(
|
||||
// TODO: Should table be a subtype of List<Any>? If so then this
|
||||
// entry would be unnecessary.
|
||||
Type::Table(vec![]),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
])
|
||||
.rest(
|
||||
"columns",
|
||||
SyntaxShape::Any,
|
||||
|
@ -1,7 +1,9 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, Example, PipelineData, Signature, Span, Spanned, SyntaxShape, Value};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Default;
|
||||
@ -13,6 +15,9 @@ impl Command for Default {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("default")
|
||||
// TODO: Give more specific type signature?
|
||||
// TODO: Declare usage of cell paths in signature? (It seems to behave as if it uses cell paths)
|
||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||
.required(
|
||||
"default value",
|
||||
SyntaxShape::Any,
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||
ShellError, Signature, Span, SyntaxShape, Value,
|
||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,7 @@ impl Command for DropColumn {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![(Type::Table(vec![]), Type::Table(vec![]))])
|
||||
.optional(
|
||||
"columns",
|
||||
SyntaxShape::Int,
|
||||
@ -25,7 +26,7 @@ impl Command for DropColumn {
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Remove the last number of columns. If you want to remove columns by name, try 'reject'."
|
||||
"Remove N columns at the right-hand end of the input table. To remove columns by name, use 'reject'."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,16 +17,19 @@ impl Command for Drop {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("drop")
|
||||
.optional(
|
||||
"rows",
|
||||
SyntaxShape::Int,
|
||||
"starting from the back, the number of rows to remove",
|
||||
)
|
||||
.input_output_types(vec![
|
||||
(Type::Table(vec![]), Type::Table(vec![])),
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
])
|
||||
.optional("rows", SyntaxShape::Int, "The number of items to remove")
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Remove the last several rows of the input. Counterpart of 'skip'. Opposite of 'last'."
|
||||
"Remove items/rows from the end of the input list/table. Counterpart of 'skip'. Opposite of 'last'."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
@ -37,7 +40,7 @@ impl Command for Drop {
|
||||
vec![
|
||||
Example {
|
||||
example: "[0,1,2,3] | drop",
|
||||
description: "Remove the last item of a list/table",
|
||||
description: "Remove the last item of a list",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_int(0), Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
@ -45,7 +48,7 @@ impl Command for Drop {
|
||||
},
|
||||
Example {
|
||||
example: "[0,1,2,3] | drop 0",
|
||||
description: "Remove zero item of a list/table",
|
||||
description: "Remove zero item of a list",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::test_int(0),
|
||||
@ -58,12 +61,24 @@ impl Command for Drop {
|
||||
},
|
||||
Example {
|
||||
example: "[0,1,2,3] | drop 2",
|
||||
description: "Remove the last two items of a list/table",
|
||||
description: "Remove the last two items of a list",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_int(0), Value::test_int(1)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Remove the last row in a table",
|
||||
example: "[[a, b]; [1, 2] [3, 4]] | drop 1",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::Record {
|
||||
cols: vec!["a".to_string(), "b".to_string()],
|
||||
vals: vec![Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
}],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::{Call, RangeInclusion};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, FromValue, IntoInterruptiblePipelineData, PipelineData, PipelineIterator,
|
||||
Range, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Range, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,10 @@ impl Command for DropNth {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("drop nth")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"row number or row range",
|
||||
// FIXME: we can make this accept either Int or Range when we can compose SyntaxShapes
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -35,6 +35,10 @@ with 'transpose' first."#
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("each")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -24,6 +24,10 @@ impl Command for EachWhile {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
||||
|
@ -2,7 +2,7 @@ use nu_engine::CallExt;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -15,6 +15,7 @@ impl Command for Empty {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("is-empty")
|
||||
.input_output_types(vec![(Type::Any, Type::Bool)])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,10 @@ impl Command for Every {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("every")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"stride",
|
||||
SyntaxShape::Int,
|
||||
|
@ -9,7 +9,7 @@ use nu_protocol::{
|
||||
ast::Call,
|
||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||
Category, Config, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, ShellError,
|
||||
Signature, Span, SyntaxShape, Value,
|
||||
Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
use nu_utils::get_ls_colors;
|
||||
|
||||
@ -23,6 +23,20 @@ impl Command for Find {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![
|
||||
(
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter it would be List<T> -> List<T>.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::String, Type::String),
|
||||
(
|
||||
// For find -p
|
||||
Type::Table(vec![]),
|
||||
Type::Table(vec![]),
|
||||
),
|
||||
])
|
||||
.named(
|
||||
"predicate",
|
||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
||||
|
@ -16,6 +16,24 @@ impl Command for First {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("first")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
// TODO: This variant duplicates the functionality of
|
||||
// `take`. See #6611, #6611, #6893
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter style it would be List<T> ->
|
||||
// List<T>.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter it would be List<T> -> T.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::Any,
|
||||
),
|
||||
(Type::Binary, Type::Binary),
|
||||
])
|
||||
.optional(
|
||||
"rows",
|
||||
SyntaxShape::Int,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,13 @@ impl Command for Flatten {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("flatten")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::Record(vec![]), Type::Table(vec![])),
|
||||
])
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::String,
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||
SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +20,15 @@ impl Command for Get {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("get")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter it would be List<T> -> T.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::Any,
|
||||
),
|
||||
(Type::Table(vec![]), Type::Any),
|
||||
])
|
||||
.required(
|
||||
"cell_path",
|
||||
SyntaxShape::CellPath,
|
||||
@ -92,6 +101,24 @@ impl Command for Get {
|
||||
}
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get an item from a list",
|
||||
example: "[0 1 2] | get 1",
|
||||
result: Some(Value::test_int(1)),
|
||||
},
|
||||
Example {
|
||||
description: "Get a column from a table",
|
||||
example: "[{A: A0}] | get A",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_string("A0")],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
description: "Get a cell from a table",
|
||||
example: "[{A: A0}] | get 0.A",
|
||||
result: Some(Value::test_string("A0")),
|
||||
},
|
||||
Example {
|
||||
description: "Extract the name of files as a list",
|
||||
example: "ls | get name",
|
||||
@ -125,3 +152,15 @@ impl Command for Get {
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(Get)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, Signature, Span, Spanned,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,14 @@ impl Command for Group {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("group")
|
||||
// TODO: It accepts Table also, but currently there is no Table
|
||||
// example. Perhaps Table should be a subtype of List, in which case
|
||||
// the current signature would suffice even when a Table example
|
||||
// exists.
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::List(Box::new(Type::Any)))),
|
||||
)])
|
||||
.required("group_size", SyntaxShape::Int, "the size of each group")
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
|
||||
Value,
|
||||
Type, Value,
|
||||
};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
@ -17,15 +17,20 @@ impl Command for GroupBy {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("group-by").optional(
|
||||
"grouper",
|
||||
SyntaxShape::Any,
|
||||
"the grouper value to use",
|
||||
)
|
||||
Signature::build("group-by")
|
||||
// TODO: It accepts Table also, but currently there is no Table
|
||||
// example. Perhaps Table should be a subtype of List, in which case
|
||||
// the current signature would suffice even when a Table example
|
||||
// exists.
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::Record(vec![]),
|
||||
)])
|
||||
.optional("grouper", SyntaxShape::Any, "the grouper value to use")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Split a table into groups based on one column's values, and return a record with those groups."
|
||||
"Splits a list or table into groups, and returns a record containing those groups."
|
||||
}
|
||||
|
||||
fn run(
|
||||
@ -47,7 +52,7 @@ impl Command for GroupBy {
|
||||
},
|
||||
Example {
|
||||
description: "You can also group by raw values by leaving out the argument",
|
||||
example: "echo ['1' '3' '1' '3' '2' '1' '1'] | group-by",
|
||||
example: "['1' '3' '1' '3' '2' '1' '1'] | group-by",
|
||||
result: Some(Value::Record {
|
||||
cols: vec!["1".to_string(), "3".to_string(), "2".to_string()],
|
||||
vals: vec![
|
||||
|
@ -1,7 +1,8 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Config, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value,
|
||||
Category, Config, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -13,7 +14,16 @@ impl Command for Headers {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name()).category(Category::Filters)
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![
|
||||
(Type::Table(vec![]), Type::Table(vec![])),
|
||||
(
|
||||
// Tables with missing values are List<Any>
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::Table(vec![]),
|
||||
),
|
||||
])
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::{Call, CellPath, PathMember};
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||
ShellError, Signature, Span, SyntaxShape, Value,
|
||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,14 @@ impl Command for Insert {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("insert")
|
||||
.input_output_types(vec![
|
||||
(Type::Record(vec![]), Type::Record(vec![])),
|
||||
// TODO: It accepts table input also (in which case it repeats
|
||||
// the value across all table rows) but currently there is no
|
||||
// example of the table variant so it cannot be in the
|
||||
// signature.
|
||||
// (Type::Table(vec![]), Type::Table(vec![])),
|
||||
])
|
||||
.required(
|
||||
"field",
|
||||
SyntaxShape::CellPath,
|
||||
@ -49,8 +57,8 @@ impl Command for Insert {
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Insert a new value",
|
||||
example: "echo {'name': 'nu', 'stars': 5} | insert alias 'Nushell'",
|
||||
description: "Insert a new entry into a record",
|
||||
example: "{'name': 'nu', 'stars': 5} | insert alias 'Nushell'",
|
||||
result: Some(Value::Record {
|
||||
cols: vec!["name".into(), "stars".into(), "alias".into()],
|
||||
vals: vec![
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||
Signature, Span, SyntaxShape, Value,
|
||||
Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,23 @@ impl Command for Last {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("last")
|
||||
.input_output_types(vec![
|
||||
(
|
||||
// TODO: This variant duplicates the functionality of
|
||||
// `take`. See #6611, #6611, #6893
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter style it would be List<T> ->
|
||||
// List<T>.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(
|
||||
// TODO: This is too permissive; if we could express this
|
||||
// using a type parameter it would be List<T> -> T.
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::Any,
|
||||
),
|
||||
])
|
||||
.optional(
|
||||
"rows",
|
||||
SyntaxShape::Int,
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||
Signature, Span, Value,
|
||||
Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -20,6 +20,10 @@ impl Command for Length {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("length")
|
||||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Any)), Type::Int),
|
||||
(Type::Table(vec![]), Type::Int),
|
||||
])
|
||||
.switch("column", "Show the number of columns in a table", Some('c'))
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, RawStream, ShellError,
|
||||
Signature, Span, Value,
|
||||
Signature, Span, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,6 +19,7 @@ impl Command for Lines {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("lines")
|
||||
.input_output_types(vec![(Type::String, Type::List(Box::new(Type::String)))])
|
||||
.switch("skip-empty", "skip empty lines", Some('s'))
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, FromValue, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
|
||||
ShellError, Signature, Span, SyntaxShape, Value,
|
||||
ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -29,6 +29,10 @@ repeating this process with row 1, and so on."#
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("merge")
|
||||
.input_output_types(vec![
|
||||
(Type::Record(vec![]), Type::Record(vec![])),
|
||||
(Type::Table(vec![]), Type::Table(vec![])),
|
||||
])
|
||||
.required(
|
||||
"block",
|
||||
// Both this and `update` should have a shape more like <record> | <table> | <block> than just <any>. -Leon 2022-10-27
|
||||
@ -64,10 +68,11 @@ repeating this process with row 1, and so on."#
|
||||
Example {
|
||||
example: "{a: 1, b: 2} | merge {c: 3}",
|
||||
description: "Merge two records",
|
||||
result: Some(Value::test_record(
|
||||
vec!["a", "b", "c"],
|
||||
vec![Value::test_int(1), Value::test_int(2), Value::test_int(3)],
|
||||
)),
|
||||
result: Some(Value::Record {
|
||||
cols: vec!["a".to_string(), "b".to_string(), "c".to_string()],
|
||||
vals: vec![Value::test_int(1), Value::test_int(2), Value::test_int(3)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
example: "{a: 1, b: 3} | merge { { b: 2 } | merge { c: 4 } }",
|
||||
@ -77,6 +82,17 @@ repeating this process with row 1, and so on."#
|
||||
vec![Value::test_int(1), Value::test_int(2), Value::test_int(4)],
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
example: "[{columnA: A0 columnB: B0}] | merge [{columnA: 'A0*'}]",
|
||||
description: "Merge two tables, overwriting overlapping columns",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(
|
||||
vec!["columnA", "columnB"],
|
||||
vec![Value::test_string("A0*"), Value::test_string("B0")],
|
||||
)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||
Signature, Span, Spanned, SyntaxShape, Value,
|
||||
Signature, Span, Spanned, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -26,6 +26,10 @@ impl Command for Move {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("move")
|
||||
.input_output_types(vec![
|
||||
(Type::Table(vec![]), Type::Table(vec![])),
|
||||
(Type::Record(vec![]), Type::Record(vec![])),
|
||||
])
|
||||
.rest("columns", SyntaxShape::String, "the columns to move")
|
||||
.named(
|
||||
"after",
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
|
||||
@ -23,6 +23,10 @@ impl Command for ParEach {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("par-each")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![SyntaxShape::Any])),
|
||||
|
@ -3,7 +3,7 @@ use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -16,6 +16,10 @@ impl Command for Prepend {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("prepend")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"row",
|
||||
SyntaxShape::Any,
|
||||
|
@ -4,7 +4,7 @@ use nu_protocol::ast::{Call, RangeInclusion};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -17,6 +17,10 @@ impl Command for Range {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("range")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required(
|
||||
"rows",
|
||||
SyntaxShape::Range,
|
||||
|
@ -5,7 +5,7 @@ use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
|
||||
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -18,6 +18,7 @@ impl Command for Reduce {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("reduce")
|
||||
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Any)])
|
||||
.named(
|
||||
"fold",
|
||||
SyntaxShape::Any,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user