Convert more examples and tests to record! macro (#10840)

# Description
Use `record!` macro instead of defining two separate `vec!` for `cols`
and `vals` when appropriate.
This visually aligns the key with the value.
Further more you don't have to deal with the construction of `Record {
cols, vals }` so we can hide the implementation details in the future.

## State

Not covering all possible commands yet, also some tests/examples are
better expressed by creating cols and vals separately.

# User/Developer-Facing Changes
The examples and tests should read more natural. No relevant functional
change

# Bycatch

Where I noticed it I replaced usage of `Value` constructors with
`Span::test_data()` or `Span::unknown()` to the `Value::test_...`
constructors. This should make things more readable and also simplify
changes to the `Span` system in the future.
This commit is contained in:
Stefan Holderbach
2023-10-28 14:52:31 +02:00
committed by GitHub
parent 7d67ca3652
commit 4b301710d3
99 changed files with 1592 additions and 2540 deletions

View File

@ -6,8 +6,8 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, Range, Record, ShellError,
Signature, Span, Spanned, SyntaxShape, Type, Value,
record, Category, Example, IntoInterruptiblePipelineData, PipelineData, Range, Record,
ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
};
type Input<'t> = Peekable<CharIndices<'t>>;
@ -58,26 +58,15 @@ impl Command for DetectColumns {
}
fn examples(&self) -> Vec<Example> {
let span = Span::test_data();
vec![
Example {
description: "Splits string across multiple columns",
example: "'a b c' | detect columns --no-headers",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec![
"column0".to_string(),
"column1".to_string(),
"column2".to_string(),
],
vals: vec![
Value::test_string("a"),
Value::test_string("b"),
Value::test_string("c"),
],
})],
span,
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"column0" => Value::test_string("a"),
"column1" => Value::test_string("b"),
"column2" => Value::test_string("c"),
})])),
},
Example {
description: "",

View File

@ -6,7 +6,7 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, ListStream, PipelineData, Record, ShellError, Signature, Span, Spanned,
record, Category, Example, ListStream, PipelineData, ShellError, Signature, Span, Spanned,
SyntaxShape, Type, Value,
};
@ -43,13 +43,10 @@ impl Command for Parse {
}
fn examples(&self) -> Vec<Example> {
let result = Value::list(
vec![Value::test_record(Record {
cols: vec!["foo".to_string(), "bar".to_string()],
vals: vec![Value::test_string("hi"), Value::test_string("there")],
})],
Span::test_data(),
);
let result = Value::test_list(vec![Value::test_record(record! {
"foo" => Value::test_string("hi"),
"bar" => Value::test_string("there"),
})]);
vec![
Example {
@ -65,55 +62,46 @@ impl Command for Parse {
Example {
description: "Parse a string using fancy-regex named capture group pattern",
example: "\"foo bar.\" | parse --regex '\\s*(?<name>\\w+)(?=\\.)'",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["name".to_string()],
vals: vec![Value::test_string("bar")],
result: Some(Value::test_list(
vec![Value::test_record(record! {
"name" => Value::test_string("bar"),
})],
Span::test_data(),
)),
},
Example {
description: "Parse a string using fancy-regex capture group pattern",
example: "\"foo! bar.\" | parse --regex '(\\w+)(?=\\.)|(\\w+)(?=!)'",
result: Some(Value::list(
result: Some(Value::test_list(
vec![
Value::test_record(Record {
cols: vec!["capture0".to_string(), "capture1".to_string()],
vals: vec![Value::test_string(""), Value::test_string("foo")],
Value::test_record(record! {
"capture0" => Value::test_string(""),
"capture1" => Value::test_string("foo"),
}),
Value::test_record(Record {
cols: vec!["capture0".to_string(), "capture1".to_string()],
vals: vec![Value::test_string("bar"), Value::test_string("")],
Value::test_record(record! {
"capture0" => Value::test_string("bar"),
"capture1" => Value::test_string(""),
}),
],
Span::test_data(),
)),
},
Example {
description: "Parse a string using fancy-regex look behind pattern",
example:
"\" @another(foo bar) \" | parse --regex '\\s*(?<=[() ])(@\\w+)(\\([^)]*\\))?\\s*'",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["capture0".to_string(), "capture1".to_string()],
vals: vec![
Value::test_string("@another"),
Value::test_string("(foo bar)"),
],
result: Some(Value::test_list(
vec![Value::test_record(record! {
"capture0" => Value::test_string("@another"),
"capture1" => Value::test_string("(foo bar)"),
})],
Span::test_data(),
)),
},
Example {
description: "Parse a string using fancy-regex look ahead atomic group pattern",
example: "\"abcd\" | parse --regex '^a(bc(?=d)|b)cd$'",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["capture0".to_string()],
vals: vec![Value::test_string("b")],
result: Some(Value::test_list(
vec![Value::test_record(record! {
"capture0" => Value::test_string("b"),
})],
Span::test_data(),
)),
},
]

View File

@ -2,7 +2,7 @@ use fancy_regex::Regex;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
record, Category, Example, PipelineData, Record, ShellError, Signature, Span, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use std::collections::BTreeMap;
use std::{fmt, str};
@ -58,61 +58,34 @@ impl Command for Size {
Example {
description: "Count the number of words in a string",
example: r#""There are seven words in this sentence" | size"#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(7),
Value::test_int(38),
Value::test_int(38),
Value::test_int(38),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(7),
"bytes" => Value::test_int(38),
"chars" => Value::test_int(38),
"graphemes" => Value::test_int(38),
})),
},
Example {
description: "Counts unicode characters",
example: r#"'今天天气真好' | size "#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(6),
Value::test_int(18),
Value::test_int(6),
Value::test_int(6),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(6),
"bytes" => Value::test_int(18),
"chars" => Value::test_int(6),
"graphemes" => Value::test_int(6),
})),
},
Example {
description: "Counts Unicode characters correctly in a string",
example: r#""Amélie Amelie" | size"#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(2),
Value::test_int(15),
Value::test_int(14),
Value::test_int(13),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(2),
"bytes" => Value::test_int(15),
"chars" => Value::test_int(14),
"graphemes" => Value::test_int(13),
})),
},
]

View File

@ -2,8 +2,8 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, Record, ShellError, Signature, Span, Spanned, SyntaxShape,
Type, Value,
record, Category, Example, PipelineData, Record, ShellError, Signature, Span, Spanned,
SyntaxShape, Type, Value,
};
use regex::Regex;
@ -63,74 +63,48 @@ impl Command for SubCommand {
Example {
description: "Split a string into columns by the specified separator",
example: "'a--b--c' | split column '--'",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec![
"column1".to_string(),
"column2".to_string(),
"column3".to_string(),
],
vals: vec![
Value::test_string("a"),
Value::test_string("b"),
Value::test_string("c"),
],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"column1" => Value::test_string("a"),
"column2" => Value::test_string("b"),
"column3" => Value::test_string("c"),
})])),
},
Example {
description: "Split a string into columns of char and remove the empty columns",
example: "'abc' | split column --collapse-empty ''",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec![
"column1".to_string(),
"column2".to_string(),
"column3".to_string(),
],
vals: vec![
Value::test_string("a"),
Value::test_string("b"),
Value::test_string("c"),
],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"column1" => Value::test_string("a"),
"column2" => Value::test_string("b"),
"column3" => Value::test_string("c"),
})])),
},
Example {
description: "Split a list of strings into a table",
example: "['a-b' 'c-d'] | split column -",
result: Some(Value::list(
vec![
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("a"), Value::test_string("b")],
}),
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("c"), Value::test_string("d")],
}),
],
Span::test_data(),
)),
result: Some(Value::test_list(vec![
Value::test_record(record! {
"column1" => Value::test_string("a"),
"column2" => Value::test_string("b"),
}),
Value::test_record(record! {
"column1" => Value::test_string("c"),
"column2" => Value::test_string("d"),
}),
])),
},
Example {
description: "Split a list of strings into a table, ignoring padding",
example: r"['a - b' 'c - d'] | split column --regex '\s*-\s*'",
result: Some(Value::list(
vec![
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("a"), Value::test_string("b")],
}),
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("c"), Value::test_string("d")],
}),
],
Span::test_data(),
)),
result: Some(Value::test_list(vec![
Value::test_record(record! {
"column1" => Value::test_string("a"),
"column2" => Value::test_string("b"),
}),
Value::test_record(record! {
"column1" => Value::test_string("c"),
"column2" => Value::test_string("d"),
}),
])),
},
]
}

View File

@ -2,10 +2,9 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::record;
use nu_protocol::Category;
use nu_protocol::{
Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
#[derive(Clone)]
pub struct SubCommand;
@ -68,13 +67,10 @@ impl Command for SubCommand {
Example {
description: "Capitalize a column in a table",
example: "[[lang, gems]; [nu_test, 100]] | str capitalize lang",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["lang".to_string(), "gems".to_string()],
vals: vec![Value::test_string("Nu_test"), Value::test_int(100)],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"lang" => Value::test_string("Nu_test"),
"gems" => Value::test_int(100),
})])),
},
]
}

View File

@ -2,10 +2,9 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::record;
use nu_protocol::Category;
use nu_protocol::{
Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value};
#[derive(Clone)]
pub struct SubCommand;
@ -68,24 +67,18 @@ impl Command for SubCommand {
Example {
description: "Downcase contents",
example: "[[ColA ColB]; [Test ABC]] | str downcase ColA",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![Value::test_string("test"), Value::test_string("ABC")],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"ColA" => Value::test_string("test"),
"ColB" => Value::test_string("ABC"),
})])),
},
Example {
description: "Downcase contents",
example: "[[ColA ColB]; [Test ABC]] | str downcase ColA ColB",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![Value::test_string("test"), Value::test_string("abc")],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"ColA" => Value::test_string("test"),
"ColB" => Value::test_string("abc"),
})])),
},
]
}

View File

@ -3,8 +3,9 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::ast::CellPath;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::record;
use nu_protocol::{
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -89,32 +90,26 @@ impl Command for SubCommand {
Example {
description: "Check if input contains string in a record",
example: "{ ColA: test, ColB: 100 } | str contains 'e' ColA",
result: Some(Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![Value::test_bool(true), Value::test_int(100)],
result: Some(Value::test_record(record! {
"ColA" => Value::test_bool(true),
"ColB" => Value::test_int(100),
})),
},
Example {
description: "Check if input contains string in a table",
example: " [[ColA ColB]; [test 100]] | str contains --ignore-case 'E' ColA",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![Value::test_bool(true), Value::test_int(100)],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"ColA" => Value::test_bool(true),
"ColB" => Value::test_int(100),
})])),
},
Example {
description: "Check if input contains string in a table",
example: " [[ColA ColB]; [test hello]] | str contains 'e' ColA ColB",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![Value::test_bool(true), Value::test_bool(true)],
})],
Span::test_data(),
)),
result: Some(Value::test_list(vec![Value::test_record(record! {
"ColA" => Value::test_bool(true),
"ColB" => Value::test_bool(true),
})])),
},
Example {
description: "Check if input string contains 'banana'",
@ -124,26 +119,20 @@ impl Command for SubCommand {
Example {
description: "Check if list contains string",
example: "[one two three] | str contains o",
result: Some(Value::list(
vec![
Value::test_bool(true),
Value::test_bool(true),
Value::test_bool(false),
],
Span::test_data(),
)),
result: Some(Value::test_list(vec![
Value::test_bool(true),
Value::test_bool(true),
Value::test_bool(false),
])),
},
Example {
description: "Check if list does not contain string",
example: "[one two three] | str contains --not o",
result: Some(Value::list(
vec![
Value::test_bool(false),
Value::test_bool(false),
Value::test_bool(true),
],
Span::test_data(),
)),
result: Some(Value::test_list(vec![
Value::test_bool(false),
Value::test_bool(false),
Value::test_bool(true),
])),
},
]
}

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
levenshtein_distance, Category, Example, PipelineData, Record, ShellError, Signature, Span,
levenshtein_distance, record, Category, Example, PipelineData, ShellError, Signature, Span,
SyntaxShape, Type, Value,
};
@ -80,25 +80,21 @@ impl Command for SubCommand {
Example {
description: "Compute edit distance between strings in table and another string, using cell paths",
example: "[{a: 'nutshell' b: 'numetal'}] | str distance 'nushell' 'a' 'b'",
result: Some(Value::list (
result: Some(Value::test_list (
vec![
Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![Value::test_int(1), Value::test_int(4)],
})
],
Span::test_data(),
)),
Value::test_record(record! {
"a" => Value::test_int(1),
"b" => Value::test_int(4),
})])),
},
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::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![Value::test_int(1), Value::test_int(4)],
})
),
Value::test_record(record! {
"a" => Value::test_int(1),
"b" => Value::test_int(4),
})),
}]
}
}

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, Record, ShellError, Signature, Span, Spanned, SyntaxShape,
record, Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape,
Type, Value,
};
@ -132,29 +132,22 @@ impl Command for SubCommand {
description: "Find and replace all occurrences of find string in table using regular expression",
example:
"[[ColA ColB ColC]; [abc abc ads]] | str replace --all --regex 'b' 'z' ColA ColC",
result: Some(Value::list (
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string(), "ColC".to_string()],
vals: vec![
Value::test_string("azc"),
Value::test_string("abc"),
Value::test_string("ads"),
],
result: Some(Value::test_list (
vec![Value::test_record(record! {
"ColA" => Value::test_string("azc"),
"ColB" => Value::test_string("abc"),
"ColC" => Value::test_string("ads"),
})],
Span::test_data(),
)),
},
Example {
description: "Find and replace all occurrences of find string in record using regular expression",
example:
"{ KeyA: abc, KeyB: abc, KeyC: ads } | str replace --all --regex 'b' 'z' KeyA KeyC",
result: Some(Value::test_record(Record {
cols: vec!["KeyA".to_string(), "KeyB".to_string(), "KeyC".to_string()],
vals: vec![
Value::test_string("azc"),
Value::test_string("abc"),
Value::test_string("ads"),
],
result: Some(Value::test_record(record! {
"KeyA" => Value::test_string("azc"),
"KeyB" => Value::test_string("abc"),
"KeyC" => Value::test_string("ads"),
})),
},
Example {

View File

@ -2,7 +2,7 @@ use fancy_regex::Regex;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
record, Category, Example, PipelineData, Record, ShellError, Signature, Span, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use std::collections::BTreeMap;
use std::{fmt, str};
@ -48,61 +48,34 @@ impl Command for SubCommand {
Example {
description: "Count the number of words in a string",
example: r#""There are seven words in this sentence" | str stats"#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(7),
Value::test_int(38),
Value::test_int(38),
Value::test_int(38),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(7),
"bytes" => Value::test_int(38),
"chars" => Value::test_int(38),
"graphemes" => Value::test_int(38),
})),
},
Example {
description: "Counts unicode characters",
example: r#"'今天天气真好' | str stats "#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(6),
Value::test_int(18),
Value::test_int(6),
Value::test_int(6),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(6),
"bytes" => Value::test_int(18),
"chars" => Value::test_int(6),
"graphemes" => Value::test_int(6),
})),
},
Example {
description: "Counts Unicode characters correctly in a string",
example: r#""Amélie Amelie" | str stats"#,
result: Some(Value::test_record(Record {
cols: vec![
"lines".into(),
"words".into(),
"bytes".into(),
"chars".into(),
"graphemes".into(),
],
vals: vec![
Value::test_int(1),
Value::test_int(2),
Value::test_int(15),
Value::test_int(14),
Value::test_int(13),
],
result: Some(Value::test_record(record! {
"lines" => Value::test_int(1),
"words" => Value::test_int(2),
"bytes" => Value::test_int(15),
"chars" => Value::test_int(14),
"graphemes" => Value::test_int(13),
})),
},
]