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:
Dan Davison
2022-11-09 16:55:05 -05:00
committed by GitHub
parent f878276de7
commit df94052180
238 changed files with 2315 additions and 756 deletions

View File

@ -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)]
@ -25,6 +25,7 @@ impl Command for BuildString {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("build-string")
.rest("rest", SyntaxShape::String, "list of string")
.input_output_types(vec![(Type::Nothing, Type::String)])
.category(Category::Strings)
}

View File

@ -4,7 +4,7 @@ use lazy_static::lazy_static;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call, engine::Command, Category, Example, IntoInterruptiblePipelineData, IntoPipelineData,
PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
// Character used to separate directories in a Path Environment variable on windows is ";"
@ -156,6 +156,7 @@ impl Command for Char {
fn signature(&self) -> Signature {
Signature::build("char")
.input_output_types(vec![(Type::Nothing, Type::String)])
.optional(
"character",
SyntaxShape::Any,

View File

@ -6,7 +6,7 @@ use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
Spanned, SyntaxShape, Value,
Spanned, SyntaxShape, Type, Value,
};
type Input<'t> = Peekable<CharIndices<'t>>;
@ -27,6 +27,7 @@ impl Command for DetectColumns {
"number of rows to skip before detecting",
Some('s'),
)
.input_output_types(vec![(Type::String, Type::Table(vec![]))])
.switch("no-headers", "don't detect headers", Some('n'))
.category(Category::Strings)
}

View File

@ -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, Spanned,
SyntaxShape, Value,
SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -24,6 +24,7 @@ impl Command for Decode {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("decode")
.input_output_types(vec![(Type::Binary, Type::String)])
.required("encoding", SyntaxShape::String, "the text encoding to use")
.category(Category::Strings)
}

View File

@ -2,7 +2,7 @@ use super::base64::{operate, ActionType, CHARACTER_SET_DESC};
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,11 @@ impl Command for DecodeBase64 {
fn signature(&self) -> Signature {
Signature::build("decode base64")
.input_output_types(vec![
(Type::String, Type::String),
(Type::String, Type::Binary),
])
.vectorizes_over_list(true)
.named(
"character-set",
SyntaxShape::String,

View File

@ -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, Spanned,
SyntaxShape, Value,
SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -24,6 +24,7 @@ impl Command for Encode {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("encode")
.input_output_types(vec![(Type::String, Type::Binary)])
.required("encoding", SyntaxShape::String, "the text encoding to use")
.category(Category::Strings)
}

View File

@ -15,6 +15,8 @@ impl Command for EncodeBase64 {
fn signature(&self) -> Signature {
Signature::build("encode base64")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.named(
"character-set",
SyntaxShape::String,

View File

@ -2,9 +2,9 @@ use nu_engine::{eval_expression, CallExt};
use nu_parser::parse_expression;
use nu_protocol::ast::{Call, PathMember};
use nu_protocol::engine::{Command, EngineState, Stack, StateWorkingSet};
use nu_protocol::Type;
use nu_protocol::{
Category, Example, ListStream, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, ListStream, PipelineData, ShellError, Signature, Span, SyntaxShape, Type,
Value,
};
#[derive(Clone)]
@ -17,6 +17,10 @@ impl Command for Format {
fn signature(&self) -> Signature {
Signature::build("format")
.input_output_types(vec![(
Type::Table(vec![]),
Type::List(Box::new(Type::String)),
)])
.required(
"pattern",
SyntaxShape::String,

View File

@ -4,7 +4,7 @@ use nu_protocol::ast::{Call, CellPath};
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
format_filesize, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape,
Value,
Type, Value,
};
struct Arguments {
@ -28,6 +28,7 @@ impl Command for FileSize {
fn signature(&self) -> Signature {
Signature::build("format filesize")
.input_output_types(vec![(Type::Filesize, Type::String)])
.required(
"format value",
SyntaxShape::String,
@ -36,7 +37,7 @@ impl Command for FileSize {
.rest(
"rest",
SyntaxShape::CellPath,
"optinally find and replace text by column paths",
"Optionally find and replace text by column paths",
)
.category(Category::Strings)
}
@ -78,19 +79,19 @@ impl Command for FileSize {
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert the size row to KB",
description: "Convert the size column to KB",
example: "ls | format filesize KB size",
result: None,
},
Example {
description: "Convert the apparent row to B",
description: "Convert the apparent column to B",
example: "du | format filesize B apparent",
result: None,
},
Example {
description: "Convert the size data to MB",
example: "4Gb | format filesize MB",
result: None,
result: Some(Value::test_string("4000.0 MB")),
},
]
}

View File

@ -4,7 +4,7 @@ use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, ListStream, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
Value,
Type, Value,
};
#[derive(Clone)]
@ -30,6 +30,7 @@ impl Command for Parse {
SyntaxShape::String,
"the pattern to match. Eg) \"{foo}: {bar}\"",
)
.input_output_types(vec![(Type::String, Type::Table(vec![]))])
.switch("regex", "use full regex syntax for patterns", Some('r'))
.category(Category::Strings)
}

View File

@ -1,7 +1,7 @@
use fancy_regex::Regex;
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};
use std::collections::BTreeMap;
use std::{fmt, str};
use unicode_segmentation::UnicodeSegmentation;
@ -18,7 +18,9 @@ impl Command for Size {
}
fn signature(&self) -> Signature {
Signature::build("size").category(Category::Strings)
Signature::build("size")
.category(Category::Strings)
.input_output_types(vec![(Type::String, Type::Record(vec![]))])
}
fn usage(&self) -> &str {

View File

@ -1,7 +1,7 @@
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -13,11 +13,14 @@ impl Command for SubCommand {
}
fn signature(&self) -> Signature {
Signature::build("split chars").category(Category::Strings)
Signature::build("split chars")
.input_output_types(vec![(Type::String, Type::List(Box::new(Type::String)))])
.vectorizes_over_list(true)
.category(Category::Strings)
}
fn usage(&self) -> &str {
"Split a string's characters into separate rows"
"Split a string into a list of characters"
}
fn search_terms(&self) -> Vec<&str> {
@ -26,7 +29,7 @@ impl Command for SubCommand {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Split the string's characters into separate rows",
description: "Split the string into a list of characters",
example: "'hello' | split chars",
result: Some(Value::List {
vals: vec![

View File

@ -2,7 +2,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,
};
#[derive(Clone)]
@ -15,6 +16,14 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("split column")
.input_output_types(vec![
(Type::String, Type::Table(vec![])),
(
// TODO: no test coverage (is this behavior a bug or a feature?)
Type::List(Box::new(Type::String)),
Type::Table(vec![]),
),
])
.required(
"separator",
SyntaxShape::String,
@ -71,7 +80,7 @@ impl Command for SubCommand {
},
Example {
description: "Split a string into columns of char and remove the empty columns",
example: "echo 'abc' | split column -c ''",
example: "'abc' | split column -c ''",
result: Some(Value::List {
vals: vec![Value::Record {
cols: vec![
@ -89,6 +98,25 @@ impl Command for SubCommand {
span: Span::test_data(),
}),
},
Example {
description: "Split a list of strings into a table",
example: "['a-b' 'c-d'] | split column -",
result: Some(Value::List {
vals: vec![
Value::Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("a"), Value::test_string("b")],
span: Span::test_data(),
},
Value::Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("c"), Value::test_string("d")],
span: Span::test_data(),
},
],
span: Span::test_data(),
}),
},
]
}
}
@ -161,15 +189,14 @@ fn split_column_helper(
}
}
// #[cfg(test)]
// mod tests {
// use super::ShellError;
// use super::SubCommand;
#[cfg(test)]
mod test {
use super::*;
// #[test]
// fn examples_work_as_expected() -> Result<(), ShellError> {
// use crate::examples::test as test_examples;
#[test]
fn test_examples() {
use crate::test_examples;
// test_examples(SubCommand {})
// }
// }
test_examples(SubCommand {})
}
}

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value,
Category, Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -15,6 +15,10 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("split list")
.input_output_types(vec![(
Type::List(Box::new(Type::Any)),
Type::List(Box::new(Type::List(Box::new(Type::Any)))),
)])
.required(
"separator",
SyntaxShape::Any,
@ -128,3 +132,15 @@ fn split_list(
}
.into_pipeline_data())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(SubCommand {})
}
}

View File

@ -2,7 +2,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,
};
#[derive(Clone)]
@ -15,6 +16,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("split row")
.input_output_types(vec![(Type::String, Type::List(Box::new(Type::String)))])
.vectorizes_over_list(true)
.required(
"separator",
SyntaxShape::String,
@ -133,15 +136,14 @@ fn split_row_helper(
}
}
// #[cfg(test)]
// mod tests {
// use super::ShellError;
// use super::SubCommand;
#[cfg(test)]
mod test {
use super::*;
// #[test]
// fn examples_work_as_expected() -> Result<(), ShellError> {
// use crate::examples::test as test_examples;
#[test]
fn test_examples() {
use crate::test_examples;
// test_examples(SubCommand {})
// }
// }
test_examples(SubCommand {})
}
}

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
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,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("split words")
.input_output_types(vec![(Type::String, Type::List(Box::new(Type::String)))])
.vectorizes_over_list(true)
.category(Category::Strings)
// .switch(
// "ignore-hyphenated",

View File

@ -2,7 +2,7 @@ use inflector::cases::camelcase::to_camel_case;
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,
};
use crate::operate;
@ -17,6 +17,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str camel-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -3,7 +3,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 SubCommand;
@ -15,6 +15,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str capitalize")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -3,7 +3,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 SubCommand;
@ -15,6 +15,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str downcase")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use inflector::cases::kebabcase::to_kebab_case;
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,
};
use crate::operate;
@ -17,6 +17,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str kebab-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use inflector::cases::pascalcase::to_pascal_case;
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,
};
use crate::operate;
@ -17,6 +17,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str pascal-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use inflector::cases::screamingsnakecase::to_screaming_snake_case;
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,
};
use crate::operate;
@ -16,6 +16,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str screaming-snake-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use inflector::cases::snakecase::to_snake_case;
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,
};
use crate::operate;
@ -16,6 +16,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str snake-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use inflector::cases::titlecase::to_title_case;
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,
};
use crate::operate;
@ -17,6 +17,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str title-case")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
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 SubCommand;
@ -13,11 +13,14 @@ impl Command for SubCommand {
}
fn signature(&self) -> Signature {
Signature::build("str upcase").rest(
"rest",
SyntaxShape::CellPath,
"optionally upcase text by column paths",
)
Signature::build("str upcase")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,
"optionally upcase text by column paths",
)
}
fn usage(&self) -> &str {

View File

@ -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)]
@ -16,6 +16,7 @@ impl Command for StrCollect {
fn signature(&self) -> Signature {
Signature::build("str collect")
.input_output_types(vec![(Type::List(Box::new(Type::String)), Type::String)])
.optional(
"separator",
SyntaxShape::String,

View File

@ -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 SubCommand;
@ -29,6 +29,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str contains")
.input_output_types(vec![(Type::String, Type::Bool)])
.vectorizes_over_list(true)
.required("string", SyntaxShape::String, "the string to find")
.rest(
"rest",

View File

@ -4,7 +4,7 @@ use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
levenshtein_distance, Category, Example, PipelineData, ShellError, Signature, Span,
SyntaxShape, Value,
SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -28,6 +28,7 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str distance")
.input_output_types(vec![(Type::String, Type::Int)])
.required(
"compare-string",
SyntaxShape::String,
@ -42,11 +43,11 @@ impl Command for SubCommand {
}
fn usage(&self) -> &str {
"compare two strings and return the edit distance/levenshtein distance"
"Compare two strings and return the edit distance/Levenshtein distance"
}
fn search_terms(&self) -> Vec<&str> {
vec!["edit", "match", "score", "levenshtein"]
vec!["edit", "levenshtein"]
}
fn run(
@ -70,8 +71,19 @@ impl Command for SubCommand {
vec![Example {
description: "get the edit distance between two strings",
example: "'nushell' | str distance 'nutshell'",
result: Some(Value::Int {
val: 1,
result: Some(Value::test_int(1)),
},
Example {
description: "Compute edit distance between strings in record and another string, using cell paths",
example: "[{a: 'nutshell' b: 'numetal'}] | str distance 'nushell' 'a' 'b'",
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(4)],
span: Span::test_data(),
}
],
span: Span::test_data(),
}),
}]

View File

@ -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 {
substring: String,
@ -27,11 +27,13 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str ends-with")
.input_output_types(vec![(Type::String, Type::Bool)])
.vectorizes_over_list(true)
.required("string", SyntaxShape::String, "the string to match")
.rest(
"rest",
SyntaxShape::CellPath,
"optionally matches suffix of text by column paths",
"optionally matches suffix of text by cell paths",
)
.category(Category::Strings)
}

View File

@ -5,7 +5,7 @@ use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::Category;
use nu_protocol::Spanned;
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
struct Arguments {
end: bool,
@ -33,6 +33,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str index-of")
.input_output_types(vec![(Type::String, Type::Int)])
.vectorizes_over_list(true) // TODO: no test coverage
.required("string", SyntaxShape::String, "the string to find index of")
.rest(
"rest",

View File

@ -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)]
@ -16,6 +16,7 @@ impl Command for StrJoin {
fn signature(&self) -> Signature {
Signature::build("str join")
.input_output_types(vec![(Type::List(Box::new(Type::String)), Type::String)])
.optional(
"separator",
SyntaxShape::String,

View File

@ -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 SubCommand;
@ -15,6 +15,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str length")
.input_output_types(vec![(Type::String, Type::Int)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -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 {
length: Option<i64>,
@ -28,6 +28,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str lpad")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.required_named("length", SyntaxShape::Int, "length to pad to", Some('l'))
.required_named(
"character",

View File

@ -4,7 +4,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 {
@ -32,6 +33,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str replace")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.required("find", SyntaxShape::String, "the pattern to find")
.required("replace", SyntaxShape::String, "the replacement pattern")
.rest(

View File

@ -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 SubCommand;
@ -16,6 +16,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str reverse")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,

View File

@ -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 {
length: Option<i64>,
@ -28,6 +28,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str rpad")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.required_named("length", SyntaxShape::Int, "length to pad to", Some('l'))
.required_named(
"character",

View File

@ -5,7 +5,7 @@ use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::Category;
use nu_protocol::Spanned;
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
struct Arguments {
substring: String,
@ -29,6 +29,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str starts-with")
.input_output_types(vec![(Type::String, Type::Bool)])
.vectorizes_over_list(true)
.required("string", SyntaxShape::String, "the string to match")
.rest(
"rest",

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
use std::cmp::Ordering;
#[derive(Clone)]
@ -38,6 +38,8 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str substring")
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.required(
"range",
SyntaxShape::Any,

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -39,7 +39,9 @@ impl Command for SubCommand {
fn signature(&self) -> Signature {
Signature::build("str trim")
.rest(
.input_output_types(vec![(Type::String, Type::String)])
.vectorizes_over_list(true)
.rest(
"rest",
SyntaxShape::CellPath,
"optionally trim text by column paths",