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

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -81,15 +81,11 @@ impl Command for FromCsv {
Example {
description: "Convert comma-separated data to a table",
example: "\"ColA,ColB\n1,2\" | from csv",
result: Some(Value::list (
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![
Value::test_int(1),
Value::test_int(2),
],
result: Some(Value::test_list (
vec![Value::test_record(record! {
"ColA" => Value::test_int(1),
"ColB" => Value::test_int(2),
})],
Span::test_data(),
))
},
Example {

View File

@ -1,7 +1,7 @@
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Record,
record, Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
ShellError, Signature, Span, Type, Value,
};
@ -29,23 +29,16 @@ impl Command for FromJson {
Example {
example: r#"'{ "a": 1 }' | from json"#,
description: "Converts json formatted string to table",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string()],
vals: vec![Value::test_int(1)],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
})),
},
Example {
example: r#"'{ "a": 1, "b": [1, 2] }' | from json"#,
description: "Converts json formatted string to table",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![
Value::test_int(1),
Value::list(
vec![Value::test_int(1), Value::test_int(2)],
Span::test_data(),
),
],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
"b" => Value::test_list(vec![Value::test_int(1), Value::test_int(2)]),
})),
},
]

View File

@ -1,8 +1,8 @@
use nu_protocol::ast::{Call, Expr, Expression, PipelineElement};
use nu_protocol::engine::{Command, EngineState, Stack, StateWorkingSet};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, Range, Record, ShellError, Signature, Span,
Type, Unit, Value,
record, Category, Example, IntoPipelineData, PipelineData, Range, Record, ShellError,
Signature, Span, Type, Unit, Value,
};
#[derive(Clone)]
pub struct FromNuon;
@ -27,23 +27,16 @@ impl Command for FromNuon {
Example {
example: "'{ a:1 }' | from nuon",
description: "Converts nuon formatted string to table",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string()],
vals: vec![Value::test_int(1)],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
})),
},
Example {
example: "'{ a:1, b: [1, 2] }' | from nuon",
description: "Converts nuon formatted string to table",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![
Value::test_int(1),
Value::list(
vec![Value::test_int(1), Value::test_int(2)],
Span::test_data(),
),
],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
"b" => Value::test_list(vec![Value::test_int(1), Value::test_int(2)]),
})),
},
]

View File

@ -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, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span,
record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span,
Spanned, SyntaxShape, Type, Value,
};
@ -44,30 +44,28 @@ impl Command for FromSsv {
example: r#"'FOO BAR
1 2' | from ssv"#,
description: "Converts ssv formatted string to table",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["FOO".to_string(), "BAR".to_string()],
vals: vec![Value::test_string("1"), Value::test_string("2")],
result: Some(Value::test_list(
vec![Value::test_record(record! {
"FOO" => Value::test_string("1"),
"BAR" => Value::test_string("2"),
})],
Span::test_data(),
)),
}, Example {
example: r#"'FOO BAR
1 2' | from ssv --noheaders"#,
description: "Converts ssv formatted string to table but not treating the first row as column names",
result: Some(
Value::list(
Value::test_list(
vec![
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("FOO"), Value::test_string("BAR")],
Value::test_record(record! {
"column1" => Value::test_string("FOO"),
"column2" => Value::test_string("BAR"),
}),
Value::test_record(Record {
cols: vec!["column1".to_string(), "column2".to_string()],
vals: vec![Value::test_string("1"), Value::test_string("2")],
Value::test_record(record! {
"column1" => Value::test_string("1"),
"column2" => Value::test_string("2"),
}),
],
Span::test_data(),
)
),
}]

View File

@ -1,7 +1,7 @@
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span, Type,
record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type,
Value,
};
@ -28,24 +28,19 @@ impl Command for FromToml {
Example {
example: "'a = 1' | from toml",
description: "Converts toml formatted string to record",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string()],
vals: vec![Value::test_int(1)],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
})),
},
Example {
example: "'a = 1
b = [1, 2]' | from toml",
description: "Converts toml formatted string to record",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
"b" => Value::test_list(vec![
Value::test_int(1),
Value::list(
vec![Value::test_int(1), Value::test_int(2)],
Span::test_data(),
),
],
Value::test_int(2)],),
})),
},
]

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -75,15 +75,11 @@ impl Command for FromTsv {
Example {
description: "Convert tab-separated data to a table",
example: "\"ColA\tColB\n1\t2\" | from tsv",
result: Some(Value::list (
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string()],
vals: vec![
Value::test_int(1),
Value::test_int(2),
],
result: Some(Value::test_list (
vec![Value::test_record(record! {
"ColA" => Value::test_int(1),
"ColB" => Value::test_int(2),
})],
Span::test_data(),
))
},
Example {

View File

@ -3,8 +3,8 @@ use indexmap::map::IndexMap;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span, Type,
Value,
record, Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span,
Type, Value,
};
use roxmltree::NodeType;
@ -69,45 +69,22 @@ string. This way content of every tag is always a table and is easier to parse"#
<remember>Event</remember>
</note>' | from xml"#,
description: "Converts xml formatted string to record",
result: Some(Value::test_record(Record {
cols: vec![
COLUMN_TAG_NAME.to_string(),
COLUMN_ATTRS_NAME.to_string(),
COLUMN_CONTENT_NAME.to_string(),
],
vals: vec![
Value::test_string("note"),
Value::test_record(Record::new()),
Value::list(
vec![Value::test_record(Record {
cols: vec![
COLUMN_TAG_NAME.to_string(),
COLUMN_ATTRS_NAME.to_string(),
COLUMN_CONTENT_NAME.to_string(),
],
vals: vec![
Value::test_string("remember"),
Value::test_record(Record::new()),
Value::list(
vec![Value::test_record(Record {
cols: vec![
COLUMN_TAG_NAME.to_string(),
COLUMN_ATTRS_NAME.to_string(),
COLUMN_CONTENT_NAME.to_string(),
],
vals: vec![
Value::test_nothing(),
Value::test_nothing(),
Value::test_string("Event"),
],
})],
Span::test_data(),
),
],
result: Some(Value::test_record(record! {
COLUMN_TAG_NAME => Value::test_string("note"),
COLUMN_ATTRS_NAME => Value::test_record(Record::new()),
COLUMN_CONTENT_NAME => Value::test_list(vec![
Value::test_record(record! {
COLUMN_TAG_NAME => Value::test_string("remember"),
COLUMN_ATTRS_NAME => Value::test_record(Record::new()),
COLUMN_CONTENT_NAME => Value::test_list(vec![
Value::test_record(record! {
COLUMN_TAG_NAME => Value::test_nothing(),
COLUMN_ATTRS_NAME => Value::test_nothing(),
COLUMN_CONTENT_NAME => Value::test_string("Event"),
})],
Span::test_data(),
),
],
})],
),
})),
}]
}
@ -344,28 +321,18 @@ mod tests {
attrs: IndexMap<&str, &str>,
content: &[Value],
) -> Value {
Value::test_record(Record {
cols: vec![
COLUMN_TAG_NAME.into(),
COLUMN_ATTRS_NAME.into(),
COLUMN_CONTENT_NAME.into(),
],
vals: vec![string(tag), attributes(attrs), table(content)],
Value::test_record(record! {
COLUMN_TAG_NAME => string(tag),
COLUMN_ATTRS_NAME => attributes(attrs),
COLUMN_CONTENT_NAME => table(content),
})
}
fn content_string(value: impl Into<String>) -> Value {
Value::test_record(Record {
cols: vec![
COLUMN_TAG_NAME.into(),
COLUMN_ATTRS_NAME.into(),
COLUMN_CONTENT_NAME.into(),
],
vals: vec![
Value::nothing(Span::test_data()),
Value::nothing(Span::test_data()),
string(value),
],
Value::test_record(record! {
COLUMN_TAG_NAME => Value::nothing(Span::test_data()),
COLUMN_ATTRS_NAME => Value::nothing(Span::test_data()),
COLUMN_CONTENT_NAME => string(value),
})
}

View File

@ -3,7 +3,7 @@ use itertools::Itertools;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span, Type,
record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type,
Value,
};
use serde::de::Deserialize;
@ -221,30 +221,22 @@ pub fn get_examples() -> Vec<Example<'static>> {
Example {
example: "'a: 1' | from yaml",
description: "Converts yaml formatted string to table",
result: Some(Value::test_record(Record {
cols: vec!["a".to_string()],
vals: vec![Value::test_int(1)],
result: Some(Value::test_record(record! {
"a" => Value::test_int(1),
})),
},
Example {
example: "'[ a: 1, b: [1, 2] ]' | from yaml",
description: "Converts yaml formatted string to table",
result: Some(Value::list(
vec![
Value::test_record(Record {
cols: vec!["a".to_string()],
vals: vec![Value::test_int(1)],
}),
Value::test_record(Record {
cols: vec!["b".to_string()],
vals: vec![Value::list(
vec![Value::test_int(1), Value::test_int(2)],
Span::test_data(),
)],
}),
],
Span::test_data(),
)),
result: Some(Value::test_list(vec![
Value::test_record(record! {
"a" => Value::test_int(1),
}),
Value::test_record(record! {
"b" => Value::test_list(
vec![Value::test_int(1), Value::test_int(2)],),
}),
])),
},
]
}
@ -274,17 +266,15 @@ mod test {
TestCase {
description: "Double Curly Braces With Quotes",
input: r#"value: "{{ something }}""#,
expected: Ok(Value::test_record(Record {
cols: vec!["value".to_string()],
vals: vec![Value::test_string("{{ something }}")],
expected: Ok(Value::test_record(record! {
"value" => Value::test_string("{{ something }}"),
})),
},
TestCase {
description: "Double Curly Braces Without Quotes",
input: r#"value: {{ something }}"#,
expected: Ok(Value::test_record(Record {
cols: vec!["value".to_string()],
vals: vec![Value::test_string("{{ something }}")],
expected: Ok(Value::test_record(record! {
"value" => Value::test_string("{{ something }}"),
})),
},
];
@ -335,19 +325,16 @@ mod test {
Span::test_data(),
);
let expected: Result<Value, ShellError> = Ok(Value::list(
vec![
Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![Value::test_string("b"), Value::test_string("c")],
}),
Value::test_record(Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![Value::test_string("g"), Value::test_string("h")],
}),
],
Span::test_data(),
));
let expected: Result<Value, ShellError> = Ok(Value::test_list(vec![
Value::test_record(record! {
"a" => Value::test_string("b"),
"b" => Value::test_string("c"),
}),
Value::test_record(record! {
"a" => Value::test_string("g"),
"b" => Value::test_string("h"),
}),
]));
// Unfortunately the eq function for Value doesn't compare well enough to detect
// ordering errors in List columns or values.
@ -388,37 +375,32 @@ mod test {
let test_cases: Vec<TestCase> = vec![
TestCase {
input: "Key: !Value ${TEST}-Test-role",
expected: Ok(Value::test_record(Record {
cols: vec!["Key".to_string()],
vals: vec![Value::test_string("!Value ${TEST}-Test-role")],
expected: Ok(Value::test_record(record! {
"Key" => Value::test_string("!Value ${TEST}-Test-role"),
})),
},
TestCase {
input: "Key: !Value test-${TEST}",
expected: Ok(Value::test_record(Record {
cols: vec!["Key".to_string()],
vals: vec![Value::test_string("!Value test-${TEST}")],
expected: Ok(Value::test_record(record! {
"Key" => Value::test_string("!Value test-${TEST}"),
})),
},
TestCase {
input: "Key: !Value",
expected: Ok(Value::test_record(Record {
cols: vec!["Key".to_string()],
vals: vec![Value::test_string("!Value")],
expected: Ok(Value::test_record(record! {
"Key" => Value::test_string("!Value"),
})),
},
TestCase {
input: "Key: !True",
expected: Ok(Value::test_record(Record {
cols: vec!["Key".to_string()],
vals: vec![Value::test_string("!True")],
expected: Ok(Value::test_record(record! {
"Key" => Value::test_string("!True"),
})),
},
TestCase {
input: "Key: !123",
expected: Ok(Value::test_record(Record {
cols: vec!["Key".to_string()],
vals: vec![Value::test_string("!123")],
expected: Ok(Value::test_record(record! {
"Key" => Value::test_string("!123"),
})),
},
];

View File

@ -320,7 +320,7 @@ fn get_padded_string(text: String, desired_length: usize, padding_character: cha
#[cfg(test)]
mod tests {
use super::*;
use nu_protocol::{Config, IntoPipelineData, Record, Span, Value};
use nu_protocol::{record, Config, IntoPipelineData, Value};
fn one(string: &str) -> String {
string
@ -342,9 +342,8 @@ mod tests {
#[test]
fn render_h1() {
let value = Value::test_record(Record {
cols: vec!["H1".to_string()],
vals: vec![Value::test_string("Ecuador")],
let value = Value::test_record(record! {
"H1" => Value::test_string("Ecuador"),
});
assert_eq!(fragment(value, false, &Config::default()), "# Ecuador\n");
@ -352,9 +351,8 @@ mod tests {
#[test]
fn render_h2() {
let value = Value::test_record(Record {
cols: vec!["H2".to_string()],
vals: vec![Value::test_string("Ecuador")],
let value = Value::test_record(record! {
"H2" => Value::test_string("Ecuador"),
});
assert_eq!(fragment(value, false, &Config::default()), "## Ecuador\n");
@ -362,9 +360,8 @@ mod tests {
#[test]
fn render_h3() {
let value = Value::test_record(Record {
cols: vec!["H3".to_string()],
vals: vec![Value::test_string("Ecuador")],
let value = Value::test_record(record! {
"H3" => Value::test_string("Ecuador"),
});
assert_eq!(fragment(value, false, &Config::default()), "### Ecuador\n");
@ -372,9 +369,8 @@ mod tests {
#[test]
fn render_blockquote() {
let value = Value::test_record(Record {
cols: vec!["BLOCKQUOTE".to_string()],
vals: vec![Value::test_string("Ecuador")],
let value = Value::test_record(record! {
"BLOCKQUOTE" => Value::test_string("Ecuador"),
});
assert_eq!(fragment(value, false, &Config::default()), "> Ecuador\n");
@ -382,23 +378,17 @@ mod tests {
#[test]
fn render_table() {
let value = Value::list(
vec![
Value::test_record(Record {
cols: vec!["country".to_string()],
vals: vec![Value::test_string("Ecuador")],
}),
Value::test_record(Record {
cols: vec!["country".to_string()],
vals: vec![Value::test_string("New Zealand")],
}),
Value::test_record(Record {
cols: vec!["country".to_string()],
vals: vec![Value::test_string("USA")],
}),
],
Span::test_data(),
);
let value = Value::test_list(vec![
Value::test_record(record! {
"country" => Value::test_string("Ecuador"),
}),
Value::test_record(record! {
"country" => Value::test_string("New Zealand"),
}),
Value::test_record(record! {
"country" => Value::test_string("USA"),
}),
]);
assert_eq!(
table(