Move command changes. Refactorings. (#2683)

Continuing on anchoring and improvements on Nu's overall internal commands (#2635).
`move column` sub command has been turned into the command `move` since
we use it to move exclusively columns. Examples added as well.

Fixed it to carry along any anchor locations that might be in place if
table to be moved originates from other sources.
This commit is contained in:
Andrés N. Robalino 2020-10-20 04:07:13 -05:00 committed by GitHub
parent bc6c884a14
commit b6d19cc9fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 516 additions and 625 deletions

3
Cargo.lock generated
View File

@ -3067,6 +3067,7 @@ dependencies = [
"nu-errors", "nu-errors",
"nu-protocol", "nu-protocol",
"nu-source", "nu-source",
"nu-test-support",
"nu-value-ext", "nu-value-ext",
"num-bigint 0.3.0", "num-bigint 0.3.0",
"serde 1.0.115", "serde 1.0.115",
@ -3119,6 +3120,7 @@ dependencies = [
name = "nu-test-support" name = "nu-test-support"
version = "0.21.0" version = "0.21.0"
dependencies = [ dependencies = [
"bigdecimal",
"chrono", "chrono",
"dunce", "dunce",
"getset", "getset",
@ -3227,6 +3229,7 @@ dependencies = [
"nu-plugin", "nu-plugin",
"nu-protocol", "nu-protocol",
"nu-source", "nu-source",
"nu-test-support",
"nu-value-ext", "nu-value-ext",
"semver 0.10.0", "semver 0.10.0",
] ]

View File

@ -159,7 +159,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Ansi), whole_stream_command(Ansi),
whole_stream_command(Char), whole_stream_command(Char),
// Column manipulation // Column manipulation
whole_stream_command(MoveColumn), whole_stream_command(Move),
whole_stream_command(Reject), whole_stream_command(Reject),
whole_stream_command(Select), whole_stream_command(Select),
whole_stream_command(Get), whole_stream_command(Get),

View File

@ -213,7 +213,7 @@ pub(crate) use math::{
}; };
pub(crate) use merge::Merge; pub(crate) use merge::Merge;
pub(crate) use mkdir::Mkdir; pub(crate) use mkdir::Mkdir;
pub(crate) use move_::{Move, MoveColumn, Mv}; pub(crate) use move_::{Move, Mv};
pub(crate) use next::Next; pub(crate) use next::Next;
pub(crate) use nth::Nth; pub(crate) use nth::Nth;
pub(crate) use open::Open; pub(crate) use open::Open;
@ -285,6 +285,7 @@ mod tests {
whole_stream_command(Append), whole_stream_command(Append),
whole_stream_command(GroupBy), whole_stream_command(GroupBy),
whole_stream_command(Insert), whole_stream_command(Insert),
whole_stream_command(Move),
whole_stream_command(Update), whole_stream_command(Update),
whole_stream_command(Empty), whole_stream_command(Empty),
] ]

View File

@ -175,8 +175,8 @@ async fn from_yaml(
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::*; use super::*;
use nu_plugin::row; use nu_protocol::row;
use nu_plugin::test_helpers::value::string; use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -51,30 +51,30 @@ impl WholeStreamCommand for Command {
result: Some(vec![UntaggedValue::row(indexmap! { result: Some(vec![UntaggedValue::row(indexmap! {
"File".to_string() => UntaggedValue::Table(vec![ "File".to_string() => UntaggedValue::Table(vec![
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Andrés.txt").into(), "name".to_string() => UntaggedValue::string("Andrés.txt").into(),
"type".to_string() => UntaggedValue::string("File").into(), "type".to_string() => UntaggedValue::string("File").into(),
"chickens".to_string() => UntaggedValue::int(10).into(), "chickens".to_string() => UntaggedValue::int(10).into(),
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
}).into(), }).into(),
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Andrés.txt").into(), "name".to_string() => UntaggedValue::string("Andrés.txt").into(),
"type".to_string() => UntaggedValue::string("File").into(), "type".to_string() => UntaggedValue::string("File").into(),
"chickens".to_string() => UntaggedValue::int(20).into(), "chickens".to_string() => UntaggedValue::int(20).into(),
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
}).into(), }).into(),
]).into(), ]).into(),
"Dir".to_string() => UntaggedValue::Table(vec![ "Dir".to_string() => UntaggedValue::Table(vec![
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Jonathan").into(), "name".to_string() => UntaggedValue::string("Jonathan").into(),
"type".to_string() => UntaggedValue::string("Dir").into(), "type".to_string() => UntaggedValue::string("Dir").into(),
"chickens".to_string() => UntaggedValue::int(5).into(), "chickens".to_string() => UntaggedValue::int(5).into(),
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
}).into(), }).into(),
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Yehuda").into(), "name".to_string() => UntaggedValue::string("Yehuda").into(),
"type".to_string() => UntaggedValue::string("Dir").into(), "type".to_string() => UntaggedValue::string("Dir").into(),
"chickens".to_string() => UntaggedValue::int(4).into(), "chickens".to_string() => UntaggedValue::int(4).into(),
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
}).into(), }).into(),
]).into(), ]).into(),
}) })
@ -278,9 +278,10 @@ pub fn group(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::group; use super::group;
use nu_data::utils::helpers::{committers, date, int, row, string, table}; use nu_data::utils::helpers::committers;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_source::*; use nu_source::*;
use nu_test_support::value::{date, int, row, string, table};
#[test] #[test]
fn groups_table_by_date_column() -> Result<(), ShellError> { fn groups_table_by_date_column() -> Result<(), ShellError> {

View File

@ -38,9 +38,8 @@ mod tests {
avg::average, max::maximum, median::median, min::minimum, mode::mode, stddev::stddev, avg::average, max::maximum, median::median, min::minimum, mode::mode, stddev::stddev,
sum::summation, utils::calculate, utils::MathFunction, variance::variance, sum::summation, utils::calculate, utils::MathFunction, variance::variance,
}; };
use nu_plugin::row; use nu_protocol::{row, Value};
use nu_plugin::test_helpers::value::{decimal, decimal_from_float, int, table}; use nu_test_support::value::{decimal, decimal_from_float, int, table};
use nu_protocol::Value;
use std::str::FromStr; use std::str::FromStr;
#[test] #[test]
@ -71,14 +70,14 @@ mod tests {
values: vec![int(10)], values: vec![int(10)],
expected_err: None, expected_err: None,
expected_res: vec![ expected_res: vec![
Ok(decimal(10)), Ok(decimal_from_float(10.0)),
Ok(int(10)), Ok(int(10)),
Ok(int(10)), Ok(int(10)),
Ok(int(10)), Ok(int(10)),
Ok(table(&[int(10)])), Ok(table(&[int(10)])),
Ok(decimal(0)), Ok(decimal_from_float(0.0)),
Ok(int(10)), Ok(int(10)),
Ok(decimal(0)), Ok(decimal_from_float(0.0)),
], ],
}, },
TestCase { TestCase {
@ -86,7 +85,7 @@ mod tests {
values: vec![int(10), int(20), int(30)], values: vec![int(10), int(20), int(30)],
expected_err: None, expected_err: None,
expected_res: vec![ expected_res: vec![
Ok(decimal(20)), Ok(decimal_from_float(20.0)),
Ok(int(10)), Ok(int(10)),
Ok(int(30)), Ok(int(30)),
Ok(int(20)), Ok(int(20)),
@ -101,13 +100,13 @@ mod tests {
values: vec![int(10), decimal_from_float(26.5), decimal_from_float(26.5)], values: vec![int(10), decimal_from_float(26.5), decimal_from_float(26.5)],
expected_err: None, expected_err: None,
expected_res: vec![ expected_res: vec![
Ok(decimal(21)), Ok(decimal_from_float(21.0)),
Ok(int(10)), Ok(int(10)),
Ok(decimal_from_float(26.5)), Ok(decimal_from_float(26.5)),
Ok(decimal_from_float(26.5)), Ok(decimal_from_float(26.5)),
Ok(table(&[decimal_from_float(26.5)])), Ok(table(&[decimal_from_float(26.5)])),
Ok(decimal(BigDecimal::from_str("7.77817459305202276840928798315333943213319531457321440247173855894902863154158871367713143880202865").expect("Could not convert to decimal from string"))), Ok(decimal(BigDecimal::from_str("7.77817459305202276840928798315333943213319531457321440247173855894902863154158871367713143880202865").expect("Could not convert to decimal from string"))),
Ok(decimal(63)), Ok(decimal_from_float(63.0)),
Ok(decimal_from_float(60.5)), Ok(decimal_from_float(60.5)),
], ],
}, },
@ -116,14 +115,14 @@ mod tests {
values: vec![int(-14), int(-11), int(10)], values: vec![int(-14), int(-11), int(10)],
expected_err: None, expected_err: None,
expected_res: vec![ expected_res: vec![
Ok(decimal(-5)), Ok(decimal_from_float(-5.0)),
Ok(int(-14)), Ok(int(-14)),
Ok(int(10)), Ok(int(10)),
Ok(int(-11)), Ok(int(-11)),
Ok(table(&[int(-14), int(-11), int(10)])), Ok(table(&[int(-14), int(-11), int(10)])),
Ok(decimal(BigDecimal::from_str("10.67707825203131121081152396559571062628228776946058011397810604284900898365140801704064843595778374").expect("Could not convert to decimal from string"))), Ok(decimal(BigDecimal::from_str("10.67707825203131121081152396559571062628228776946058011397810604284900898365140801704064843595778374").expect("Could not convert to decimal from string"))),
Ok(int(-15)), Ok(int(-15)),
Ok(decimal(114)), Ok(decimal_from_float(114.0)),
], ],
}, },
TestCase { TestCase {
@ -131,13 +130,13 @@ mod tests {
values: vec![decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)], values: vec![decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)],
expected_err: None, expected_err: None,
expected_res: vec![ expected_res: vec![
Ok(decimal(-5)), Ok(decimal_from_float(-5.0)),
Ok(decimal_from_float(-13.5)), Ok(decimal_from_float(-13.5)),
Ok(int(10)), Ok(int(10)),
Ok(decimal_from_float(-11.5)), Ok(decimal_from_float(-11.5)),
Ok(table(&[decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)])), Ok(table(&[decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)])),
Ok(decimal(BigDecimal::from_str("10.63798226482196513098036125801342585449179971588207816421068645273754903468375890632981926875247027").expect("Could not convert to decimal from string"))), Ok(decimal(BigDecimal::from_str("10.63798226482196513098036125801342585449179971588207816421068645273754903468375890632981926875247027").expect("Could not convert to decimal from string"))),
Ok(decimal(-15)), Ok(decimal_from_float(-15.0)),
Ok(decimal(BigDecimal::from_str("113.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))), Ok(decimal(BigDecimal::from_str("113.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))),
], ],
}, },

View File

@ -1,328 +0,0 @@
use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_data::base::select_fields;
use nu_errors::ShellError;
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, Value};
use nu_source::HasFallibleSpan;
pub struct SubCommand;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<ColumnPath>,
after: Option<ColumnPath>,
before: Option<ColumnPath>,
}
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"move column"
}
fn signature(&self) -> Signature {
Signature::build("move column")
.rest(SyntaxShape::ColumnPath, "the columns to move")
.named(
"after",
SyntaxShape::ColumnPath,
"the column that will precede the columns moved",
None,
)
.named(
"before",
SyntaxShape::ColumnPath,
"the column that will be next the columns moved",
None,
)
}
fn usage(&self) -> &str {
"Move columns."
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
operate(args, registry).await
}
}
async fn operate(
raw_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let name = raw_args.call_info.name_tag.clone();
let registry = registry.clone();
let (
Arguments {
rest: mut columns,
before,
after,
},
input,
) = raw_args.process(&registry).await?;
if columns.is_empty() {
return Err(ShellError::labeled_error(
"expected columns",
"expected columns",
name,
));
}
if columns.iter().any(|c| c.members().len() > 1) {
return Err(ShellError::labeled_error(
"expected columns",
"expected columns",
name,
));
}
if vec![&after, &before]
.iter()
.map(|o| if o.is_some() { 1 } else { 0 })
.sum::<usize>()
> 1
{
return Err(ShellError::labeled_error(
"can't move column(s)",
"pick exactly one (before, after)",
name,
));
}
if let Some(after) = after {
let member = columns.remove(0);
Ok(input
.map(move |item| {
let member = vec![member.clone()];
let column_paths = vec![&member, &columns]
.into_iter()
.flatten()
.collect::<Vec<&ColumnPath>>();
let after_span = after.maybe_span().unwrap_or_else(Span::unknown);
if after.members().len() == 1 {
let keys = column_paths
.iter()
.filter_map(|c| c.last())
.map(|c| c.as_string())
.collect::<Vec<_>>();
if let Some(column) = after.last() {
if !keys.contains(&column.as_string()) {
ReturnSuccess::value(move_after(&item, &keys, &after, &name)?)
} else {
let msg =
format!("can't move column {} after itself", column.as_string());
Err(ShellError::labeled_error(
"can't move column",
msg,
after_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
after_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
after_span,
))
}
})
.to_output_stream())
} else if let Some(before) = before {
let member = columns.remove(0);
Ok(input
.map(move |item| {
let member = vec![member.clone()];
let column_paths = vec![&member, &columns]
.into_iter()
.flatten()
.collect::<Vec<&ColumnPath>>();
let before_span = before.maybe_span().unwrap_or_else(Span::unknown);
if before.members().len() == 1 {
let keys = column_paths
.iter()
.filter_map(|c| c.last())
.map(|c| c.as_string())
.collect::<Vec<_>>();
if let Some(column) = before.last() {
if !keys.contains(&column.as_string()) {
ReturnSuccess::value(move_before(&item, &keys, &before, &name)?)
} else {
let msg =
format!("can't move column {} before itself", column.as_string());
Err(ShellError::labeled_error(
"can't move column",
msg,
before_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
before_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
before_span,
))
}
})
.to_output_stream())
} else {
Err(ShellError::labeled_error(
"no columns given",
"no columns given",
name,
))
}
}
fn move_after(
table: &Value,
columns: &[String],
from: &ColumnPath,
tag: impl Into<Tag>,
) -> Result<Value, ShellError> {
let tag = tag.into();
let from_fields = from.maybe_span().unwrap_or_else(Span::unknown);
let from = if let Some((last, _)) = from.split_last() {
last.as_string()
} else {
return Err(ShellError::labeled_error(
"unknown column",
"unknown column",
from_fields,
));
};
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut insert = false;
let mut inserted = false;
for name in columns_moved.into_iter() {
if let Some(name) = name {
reordered_columns.push(Some(name.clone()));
if !inserted && name == from {
insert = true;
}
} else {
reordered_columns.push(None);
}
if insert {
for column in columns {
reordered_columns.push(Some(column.clone()));
}
inserted = true;
}
}
Ok(select_fields(
table,
&reordered_columns
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
&tag,
))
}
fn move_before(
table: &Value,
columns: &[String],
from: &ColumnPath,
tag: impl Into<Tag>,
) -> Result<Value, ShellError> {
let tag = tag.into();
let from_fields = from.maybe_span().unwrap_or_else(Span::unknown);
let from = if let Some((last, _)) = from.split_last() {
last.as_string()
} else {
return Err(ShellError::labeled_error(
"unknown column",
"unknown column",
from_fields,
));
};
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut inserted = false;
for name in columns_moved.into_iter() {
if let Some(name) = name {
if !inserted && name == from {
for column in columns {
reordered_columns.push(Some(column.clone()));
}
inserted = true;
}
reordered_columns.push(Some(name.clone()));
} else {
reordered_columns.push(None);
}
}
Ok(select_fields(
table,
&reordered_columns
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
&tag,
))
}
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -1,11 +1,20 @@
use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use nu_data::base::select_fields;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, Value};
use nu_source::HasFallibleSpan;
#[derive(Clone)]
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<ColumnPath>,
after: Option<ColumnPath>,
before: Option<ColumnPath>,
}
#[async_trait] #[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -14,34 +23,318 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("move") Signature::build("move")
.rest(SyntaxShape::ColumnPath, "the columns to move")
.named(
"after",
SyntaxShape::ColumnPath,
"the column that will precede the columns moved",
None,
)
.named(
"before",
SyntaxShape::ColumnPath,
"the column that will be next the columns moved",
None,
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
"Moves across desired subcommand." "Move columns."
} }
async fn run( async fn run(
&self, &self,
_args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let registry = registry.clone(); operate(args, registry).await
Ok(OutputStream::one(Ok(ReturnSuccess::Value( }
UntaggedValue::string(crate::commands::help::get_help(&Command, &registry))
.into_value(Tag::unknown()), fn examples(&self) -> Vec<Example> {
)))) use nu_test_support::value::*;
vec![
Example {
description: "Move the column \"type\" before the column \"name\"",
example: r#"ls | move type --before name | first"#,
result: Some(vec![row! {
"type".into() => string("File"),
"name".into() => string("Andrés.txt"),
"chickens".into() => int(10),
"modified".into() => date("2019-07-23")
}]),
},
Example {
description: "or move the column \"chickens\" after \"name\"",
example: r#"ls | move chickens --after name | first"#,
result: Some(vec![row! {
"name".into() => string("Andrés.txt"),
"chickens".into() => int(10),
"type".into() => string("File"),
"modified".into() => date("2019-07-23")
}]),
},
Example {
description: "you can selectively move many columns in either direction",
example: r#"ls | move name chickens --after type | first"#,
result: Some(vec![row! {
"type".into() => string("File"),
"name".into() => string("Andrés.txt"),
"chickens".into() => int(10),
"modified".into() => date("2019-07-23")
}]),
},
]
} }
} }
#[cfg(test)] async fn operate(
mod tests { raw_args: CommandArgs,
use super::Command; registry: &CommandRegistry,
use super::ShellError; ) -> Result<OutputStream, ShellError> {
let name = raw_args.call_info.name_tag.clone();
let registry = registry.clone();
let (
Arguments {
rest: mut columns,
before,
after,
},
input,
) = raw_args.process(&registry).await?;
#[test] if columns.is_empty() {
fn examples_work_as_expected() -> Result<(), ShellError> { return Err(ShellError::labeled_error(
use crate::examples::test as test_examples; "expected columns",
"expected columns",
name,
));
}
Ok(test_examples(Command {})?) if columns.iter().any(|c| c.members().len() > 1) {
return Err(ShellError::labeled_error(
"expected columns",
"expected columns",
name,
));
}
if vec![&after, &before]
.iter()
.map(|o| if o.is_some() { 1 } else { 0 })
.sum::<usize>()
> 1
{
return Err(ShellError::labeled_error(
"can't move column(s)",
"pick exactly one (before, after)",
name,
));
}
if let Some(after) = after {
let member = columns.remove(0);
Ok(input
.map(move |item| {
let member = vec![member.clone()];
let column_paths = vec![&member, &columns]
.into_iter()
.flatten()
.collect::<Vec<&ColumnPath>>();
let after_span = after.maybe_span().unwrap_or_else(Span::unknown);
if after.members().len() == 1 {
let keys = column_paths
.iter()
.filter_map(|c| c.last())
.map(|c| c.as_string())
.collect::<Vec<_>>();
if let Some(column) = after.last() {
if !keys.contains(&column.as_string()) {
ReturnSuccess::value(move_after(&item, &keys, &after)?)
} else {
let msg =
format!("can't move column {} after itself", column.as_string());
Err(ShellError::labeled_error(
"can't move column",
msg,
after_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
after_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
after_span,
))
}
})
.to_output_stream())
} else if let Some(before) = before {
let member = columns.remove(0);
Ok(input
.map(move |item| {
let member = vec![member.clone()];
let column_paths = vec![&member, &columns]
.into_iter()
.flatten()
.collect::<Vec<&ColumnPath>>();
let before_span = before.maybe_span().unwrap_or_else(Span::unknown);
if before.members().len() == 1 {
let keys = column_paths
.iter()
.filter_map(|c| c.last())
.map(|c| c.as_string())
.collect::<Vec<_>>();
if let Some(column) = before.last() {
if !keys.contains(&column.as_string()) {
ReturnSuccess::value(move_before(&item, &keys, &before)?)
} else {
let msg =
format!("can't move column {} before itself", column.as_string());
Err(ShellError::labeled_error(
"can't move column",
msg,
before_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
before_span,
))
}
} else {
Err(ShellError::labeled_error(
"expected column",
"expected column",
before_span,
))
}
})
.to_output_stream())
} else {
Err(ShellError::labeled_error(
"no columns given",
"no columns given",
name,
))
} }
} }
fn move_after(table: &Value, columns: &[String], from: &ColumnPath) -> Result<Value, ShellError> {
let from_fields = from.maybe_span().unwrap_or_else(Span::unknown);
let from = if let Some((last, _)) = from.split_last() {
last.as_string()
} else {
return Err(ShellError::labeled_error(
"unknown column",
"unknown column",
from_fields,
));
};
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut insert = false;
let mut inserted = false;
for name in columns_moved.into_iter() {
if let Some(name) = name {
reordered_columns.push(Some(name.clone()));
if !inserted && name == from {
insert = true;
}
} else {
reordered_columns.push(None);
}
if insert {
for column in columns {
reordered_columns.push(Some(column.clone()));
}
inserted = true;
}
}
Ok(select_fields(
table,
&reordered_columns
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
&table.tag,
))
}
fn move_before(table: &Value, columns: &[String], from: &ColumnPath) -> Result<Value, ShellError> {
let from_fields = from.maybe_span().unwrap_or_else(Span::unknown);
let from = if let Some((last, _)) = from.split_last() {
last.as_string()
} else {
return Err(ShellError::labeled_error(
"unknown column",
"unknown column",
from_fields,
));
};
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut inserted = false;
for name in columns_moved.into_iter() {
if let Some(name) = name {
if !inserted && name == from {
for column in columns {
reordered_columns.push(Some(column.clone()));
}
inserted = true;
}
reordered_columns.push(Some(name.clone()));
} else {
reordered_columns.push(None);
}
}
Ok(select_fields(
table,
&reordered_columns
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
&table.tag,
))
}

View File

@ -1,7 +1,5 @@
mod column;
mod command; mod command;
pub mod mv; pub mod mv;
pub use column::SubCommand as MoveColumn;
pub use command::Command as Move; pub use command::Command as Move;
pub use mv::Mv; pub use mv::Mv;

View File

@ -101,9 +101,10 @@ pub fn split(
mod tests { mod tests {
use super::split; use super::split;
use super::ShellError; use super::ShellError;
use nu_data::utils::helpers::{committers_grouped_by_date, date, int, row, string, table}; use nu_data::utils::helpers::committers_grouped_by_date;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::*; use nu_source::*;
use nu_test_support::value::{date, int, row, string, table};
#[test] #[test]
fn splits_inner_tables_by_key() { fn splits_inner_tables_by_key() {

View File

@ -112,8 +112,8 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -46,8 +46,8 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{to_camel_case, SubCommand}; use super::{to_camel_case, SubCommand};
use crate::commands::str_::case::action; use crate::commands::str_::case::action;
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -46,8 +46,8 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{to_kebab_case, SubCommand}; use super::{to_kebab_case, SubCommand};
use crate::commands::str_::case::action; use crate::commands::str_::case::action;
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -46,8 +46,8 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{to_pascal_case, SubCommand}; use super::{to_pascal_case, SubCommand};
use crate::commands::str_::case::action; use crate::commands::str_::case::action;
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -46,8 +46,8 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{to_screaming_snake_case, SubCommand}; use super::{to_screaming_snake_case, SubCommand};
use crate::commands::str_::case::action; use crate::commands::str_::case::action;
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -46,8 +46,8 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{to_snake_case, SubCommand}; use super::{to_snake_case, SubCommand};
use crate::commands::str_::case::action; use crate::commands::str_::case::action;
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -130,9 +130,9 @@ fn action(
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -100,8 +100,8 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -104,9 +104,9 @@ fn action(input: &Value, pattern: &str, tag: impl Into<Tag>) -> Result<Value, Sh
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -149,8 +149,8 @@ fn action(
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, FindReplace, SubCommand}; use super::{action, FindReplace, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -248,9 +248,9 @@ fn process_range(input: &Value, range: &Value) -> Result<IndexOfOptionalBounds,
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_protocol::{Primitive, UntaggedValue}; use nu_protocol::{Primitive, UntaggedValue};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -145,9 +145,9 @@ fn action(
mod tests { mod tests {
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_plugin::test_helpers::value::string;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -145,9 +145,9 @@ fn action(
mod tests { mod tests {
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_plugin::test_helpers::value::string;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -101,8 +101,8 @@ fn action(_input: &Value, options: &Replace, tag: impl Into<Tag>) -> Result<Valu
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, Replace, SubCommand}; use super::{action, Replace, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -104,9 +104,9 @@ fn action(input: &Value, pattern: &str, tag: impl Into<Tag>) -> Result<Value, Sh
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_protocol::UntaggedValue; use nu_protocol::UntaggedValue;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -285,8 +285,8 @@ fn process_arguments(range: Value, name: impl Into<Tag>) -> Result<(isize, isize
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand, Substring}; use super::{action, SubCommand, Substring};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -176,9 +176,9 @@ fn action(
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, DatetimeFormat, SubCommand}; use super::{action, DatetimeFormat, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_protocol::{Primitive, UntaggedValue}; use nu_protocol::{Primitive, UntaggedValue};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -114,8 +114,8 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::{decimal_from_float, string};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::{decimal_from_float, string};
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -114,8 +114,8 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::{int, string};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::{int, string};
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -65,11 +65,9 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{trim, SubCommand}; use super::{trim, SubCommand};
use crate::commands::str_::trim::{action, ActionMode}; use crate::commands::str_::trim::{action, ActionMode};
use nu_plugin::{ use nu_protocol::row;
row,
test_helpers::value::{int, string, table},
};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::{int, string, table};
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -66,11 +66,9 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{trim_left, SubCommand}; use super::{trim_left, SubCommand};
use crate::commands::str_::trim::{action, ActionMode}; use crate::commands::str_::trim::{action, ActionMode};
use nu_plugin::{ use nu_protocol::row;
row,
test_helpers::value::{int, string, table},
};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::{int, string, table};
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -66,11 +66,9 @@ mod tests {
use super::ShellError; use super::ShellError;
use super::{trim_right, SubCommand}; use super::{trim_right, SubCommand};
use crate::commands::str_::trim::{action, ActionMode}; use crate::commands::str_::trim::{action, ActionMode};
use nu_plugin::{ use nu_protocol::row;
row,
test_helpers::value::{int, string, table},
};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::{int, string, table};
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -100,8 +100,8 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
mod tests { mod tests {
use super::ShellError; use super::ShellError;
use super::{action, SubCommand}; use super::{action, SubCommand};
use nu_plugin::test_helpers::value::string;
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::string;
#[test] #[test]
fn examples_work_as_expected() -> Result<(), ShellError> { fn examples_work_as_expected() -> Result<(), ShellError> {

View File

@ -7,11 +7,8 @@ use nu_source::{AnchorLocation, TaggedItem};
use crate::prelude::*; use crate::prelude::*;
use indexmap::indexmap;
use num_bigint::BigInt; use num_bigint::BigInt;
use indexmap::IndexMap;
use crate::command_registry::CommandRegistry; use crate::command_registry::CommandRegistry;
use crate::commands::classified::block::run_block; use crate::commands::classified::block::run_block;
use crate::commands::command::CommandArgs; use crate::commands::command::CommandArgs;
@ -450,10 +447,6 @@ fn string(input: impl Into<String>) -> Value {
UntaggedValue::string(input.into()).into_untagged_value() UntaggedValue::string(input.into()).into_untagged_value()
} }
fn row(entries: IndexMap<String, Value>) -> Value {
UntaggedValue::row(entries).into_untagged_value()
}
fn date(input: impl Into<String>) -> Value { fn date(input: impl Into<String>) -> Value {
let key = input.into().tagged_unknown(); let key = input.into().tagged_unknown();
crate::value::Date::naive_from_str(key.borrow_tagged()) crate::value::Date::naive_from_str(key.borrow_tagged())
@ -463,30 +456,30 @@ fn date(input: impl Into<String>) -> Value {
fn file_listing() -> Vec<Value> { fn file_listing() -> Vec<Value> {
vec![ vec![
row(indexmap! { row! {
"modified".to_string() => date("2019-07-23"),
"name".to_string() => string("Andrés.txt"), "name".to_string() => string("Andrés.txt"),
"type".to_string() => string("File"), "type".to_string() => string("File"),
"chickens".to_string() => int(10), "chickens".to_string() => int(10),
}), "modified".to_string() => date("2019-07-23")
row(indexmap! { },
"modified".to_string() => date("2019-07-23"), row! {
"name".to_string() => string("Jonathan"), "name".to_string() => string("Jonathan"),
"type".to_string() => string("Dir"), "type".to_string() => string("Dir"),
"chickens".to_string() => int(5), "chickens".to_string() => int(5),
}), "modified".to_string() => date("2019-07-23")
row(indexmap! { },
"modified".to_string() => date("2019-09-24"), row! {
"name".to_string() => string("Andrés.txt"), "name".to_string() => string("Andrés.txt"),
"type".to_string() => string("File"), "type".to_string() => string("File"),
"chickens".to_string() => int(20), "chickens".to_string() => int(20),
}), "modified".to_string() => date("2019-09-24")
row(indexmap! { },
"modified".to_string() => date("2019-09-24"), row! {
"name".to_string() => string("Yehuda"), "name".to_string() => string("Yehuda"),
"type".to_string() => string("Dir"), "type".to_string() => string("Dir"),
"chickens".to_string() => int(4), "chickens".to_string() => int(4),
}), "modified".to_string() => date("2019-09-24")
},
] ]
} }

View File

@ -68,7 +68,7 @@ macro_rules! trace_out_stream {
}}; }};
} }
pub(crate) use nu_protocol::{errln, out, outln}; pub(crate) use nu_protocol::{errln, out, outln, row};
use nu_source::HasFallibleSpan; use nu_source::HasFallibleSpan;
pub(crate) use crate::command_registry::CommandRegistry; pub(crate) use crate::command_registry::CommandRegistry;

View File

@ -22,7 +22,7 @@ fn moves_a_column_before() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open sample.csv open sample.csv
| move column column99 --before column1 | move column99 --before column1
| rename chars | rename chars
| get chars | get chars
| str trim | str trim
@ -57,7 +57,7 @@ fn moves_columns_before() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open sample.csv open sample.csv
| move column column99 column3 --before column2 | move column99 column3 --before column2
| rename _ chars_1 chars_2 | rename _ chars_1 chars_2
| get chars_2 chars_1 | get chars_2 chars_1
| str trim | str trim
@ -92,8 +92,8 @@ fn moves_a_column_after() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open sample.csv open sample.csv
| move column letters --after and_more | move letters --after and_more
| move column letters and_more --before column2 | move letters and_more --before column2
| rename _ chars_1 chars_2 | rename _ chars_1 chars_2
| get chars_1 chars_2 | get chars_1 chars_2
| str trim | str trim
@ -128,7 +128,7 @@ fn moves_columns_after() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open sample.csv open sample.csv
| move column letters and_more --after column1 | move letters and_more --after column1
| get | get
| nth 1 2 | nth 1 2
| str collect | str collect

View File

@ -191,7 +191,7 @@ mod tests {
#[test] #[test]
fn gets_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> { fn gets_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> {
let field_path = column_path("package.version"); let field_path = column_path("package.version").as_column_path()?;
let (version, tag) = string("0.4.0").into_parts(); let (version, tag) = string("0.4.0").into_parts();
@ -205,7 +205,7 @@ mod tests {
assert_eq!( assert_eq!(
*value.into_value(tag).get_data_by_column_path( *value.into_value(tag).get_data_by_column_path(
&field_path?.item, &field_path.item,
Box::new(error_callback("package.version")) Box::new(error_callback("package.version"))
)?, )?,
version version
@ -217,7 +217,7 @@ mod tests {
#[test] #[test]
fn gets_first_matching_field_from_rows_with_same_field_inside_a_table() -> Result<(), ShellError> fn gets_first_matching_field_from_rows_with_same_field_inside_a_table() -> Result<(), ShellError>
{ {
let field_path = column_path("package.authors.name"); let field_path = column_path("package.authors.name").as_column_path()?;
let (_, tag) = string("Andrés N. Robalino").into_parts(); let (_, tag) = string("Andrés N. Robalino").into_parts();
@ -235,7 +235,7 @@ mod tests {
assert_eq!( assert_eq!(
value.into_value(tag).get_data_by_column_path( value.into_value(tag).get_data_by_column_path(
&field_path?.item, &field_path.item,
Box::new(error_callback("package.authors.name")) Box::new(error_callback("package.authors.name"))
)?, )?,
table(&[ table(&[
@ -250,7 +250,7 @@ mod tests {
#[test] #[test]
fn column_path_that_contains_just_a_number_gets_a_row_from_a_table() -> Result<(), ShellError> { fn column_path_that_contains_just_a_number_gets_a_row_from_a_table() -> Result<(), ShellError> {
let field_path = column_path("package.authors.0"); let field_path = column_path("package.authors.0").as_column_path()?;
let (_, tag) = string("Andrés N. Robalino").into_parts(); let (_, tag) = string("Andrés N. Robalino").into_parts();
@ -268,7 +268,7 @@ mod tests {
assert_eq!( assert_eq!(
*value.into_value(tag).get_data_by_column_path( *value.into_value(tag).get_data_by_column_path(
&field_path?.item, &field_path.item,
Box::new(error_callback("package.authors.0")) Box::new(error_callback("package.authors.0"))
)?, )?,
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
@ -281,7 +281,7 @@ mod tests {
#[test] #[test]
fn column_path_that_contains_just_a_number_gets_a_row_from_a_row() -> Result<(), ShellError> { fn column_path_that_contains_just_a_number_gets_a_row_from_a_row() -> Result<(), ShellError> {
let field_path = column_path(r#"package.authors."0""#); let field_path = column_path(r#"package.authors."0""#).as_column_path()?;
let (_, tag) = string("Andrés N. Robalino").into_parts(); let (_, tag) = string("Andrés N. Robalino").into_parts();
@ -299,7 +299,7 @@ mod tests {
assert_eq!( assert_eq!(
*value.into_value(tag).get_data_by_column_path( *value.into_value(tag).get_data_by_column_path(
&field_path?.item, &field_path.item,
Box::new(error_callback("package.authors.\"0\"")) Box::new(error_callback("package.authors.\"0\""))
)?, )?,
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {
@ -312,7 +312,7 @@ mod tests {
#[test] #[test]
fn replaces_matching_field_from_a_row() -> Result<(), ShellError> { fn replaces_matching_field_from_a_row() -> Result<(), ShellError> {
let field_path = column_path("amigos"); let field_path = column_path("amigos").as_column_path()?;
let sample = UntaggedValue::row(indexmap! { let sample = UntaggedValue::row(indexmap! {
"amigos".into() => table(&[ "amigos".into() => table(&[
@ -326,7 +326,7 @@ mod tests {
let actual = sample let actual = sample
.into_untagged_value() .into_untagged_value()
.replace_data_at_column_path(&field_path?.item, replacement) .replace_data_at_column_path(&field_path.item, replacement)
.ok_or_else(|| ShellError::untagged_runtime_error("Could not replace column"))?; .ok_or_else(|| ShellError::untagged_runtime_error("Could not replace column"))?;
assert_eq!(actual, row(indexmap! {"amigos".into() => string("jonas")})); assert_eq!(actual, row(indexmap! {"amigos".into() => string("jonas")}));
@ -336,7 +336,7 @@ mod tests {
#[test] #[test]
fn replaces_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> { fn replaces_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> {
let field_path = column_path(r#"package.authors."los.3.caballeros""#); let field_path = column_path(r#"package.authors."los.3.caballeros""#).as_column_path()?;
let sample = UntaggedValue::row(indexmap! { let sample = UntaggedValue::row(indexmap! {
"package".into() => row(indexmap! { "package".into() => row(indexmap! {
@ -353,7 +353,7 @@ mod tests {
let actual = sample let actual = sample
.into_value(&tag) .into_value(&tag)
.replace_data_at_column_path(&field_path?.item, replacement.clone()) .replace_data_at_column_path(&field_path.item, replacement.clone())
.ok_or_else(|| { .ok_or_else(|| {
ShellError::labeled_error( ShellError::labeled_error(
"Could not replace column", "Could not replace column",
@ -377,7 +377,8 @@ mod tests {
} }
#[test] #[test]
fn replaces_matching_field_from_rows_inside_a_table() -> Result<(), ShellError> { fn replaces_matching_field_from_rows_inside_a_table() -> Result<(), ShellError> {
let field_path = column_path(r#"shell_policy.releases."nu.version.arepa""#); let field_path =
column_path(r#"shell_policy.releases."nu.version.arepa""#).as_column_path()?;
let sample = UntaggedValue::row(indexmap! { let sample = UntaggedValue::row(indexmap! {
"shell_policy".into() => row(indexmap! { "shell_policy".into() => row(indexmap! {
@ -409,7 +410,7 @@ mod tests {
let actual = sample let actual = sample
.into_value(tag.clone()) .into_value(tag.clone())
.replace_data_at_column_path(&field_path?.item, replacement.clone()) .replace_data_at_column_path(&field_path.item, replacement.clone())
.ok_or_else(|| { .ok_or_else(|| {
ShellError::labeled_error( ShellError::labeled_error(
"Could not replace column", "Could not replace column",

View File

@ -97,99 +97,68 @@ pub fn report(
} }
pub mod helpers { pub mod helpers {
use super::Model;
use indexmap::indexmap;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{UntaggedValue, Value}; use nu_protocol::{row, Value};
use nu_source::{Span, Tag, TaggedItem}; use nu_source::{Tag, TaggedItem};
use nu_test_support::value::{date, int, string, table};
use nu_value_ext::ValueExt; use nu_value_ext::ValueExt;
use num_bigint::BigInt;
use indexmap::IndexMap;
pub fn int(s: impl Into<BigInt>) -> Value {
UntaggedValue::int(s).into_untagged_value()
}
pub fn decimal_from_float(f: f64, span: Span) -> Value {
UntaggedValue::decimal_from_float(f, span).into_untagged_value()
}
pub fn string(input: impl Into<String>) -> Value {
UntaggedValue::string(input.into()).into_untagged_value()
}
pub fn row(entries: IndexMap<String, Value>) -> Value {
UntaggedValue::row(entries).into_untagged_value()
}
pub fn table(list: &[Value]) -> Value {
UntaggedValue::table(list).into_untagged_value()
}
pub fn date(input: impl Into<String>) -> Value {
let key = input.into().tagged_unknown();
crate::value::Date::naive_from_str(key.borrow_tagged())
.expect("date from string failed")
.into_untagged_value()
}
pub fn committers() -> Vec<Value> { pub fn committers() -> Vec<Value> {
vec![ vec![
row(indexmap! { row! {
"date".into() => date("2019-07-23"), "date".into() => date("2019-07-23"),
"name".into() => string("AR"), "name".into() => string("AR"),
"country".into() => string("EC"), "country".into() => string("EC"),
"chickens".into() => int(10), "chickens".into() => int(10)
}), },
row(indexmap! { row! {
"date".into() => date("2019-07-23"), "date".into() => date("2019-07-23"),
"name".into() => string("JT"), "name".into() => string("JT"),
"country".into() => string("NZ"), "country".into() => string("NZ"),
"chickens".into() => int(5), "chickens".into() => int(5)
}), },
row(indexmap! { row! {
"date".into() => date("2019-10-10"), "date".into() => date("2019-10-10"),
"name".into() => string("YK"), "name".into() => string("YK"),
"country".into() => string("US"), "country".into() => string("US"),
"chickens".into() => int(6), "chickens".into() => int(6)
}), },
row(indexmap! { row! {
"date".into() => date("2019-09-24"), "date".into() => date("2019-09-24"),
"name".into() => string("AR"), "name".into() => string("AR"),
"country".into() => string("EC"), "country".into() => string("EC"),
"chickens".into() => int(20), "chickens".into() => int(20)
}), },
row(indexmap! { row! {
"date".into() => date("2019-10-10"), "date".into() => date("2019-10-10"),
"name".into() => string("JT"), "name".into() => string("JT"),
"country".into() => string("NZ"), "country".into() => string("NZ"),
"chickens".into() => int(15), "chickens".into() => int(15)
}), },
row(indexmap! { row! {
"date".into() => date("2019-09-24"), "date".into() => date("2019-09-24"),
"name".into() => string("YK"), "name".into() => string("YK"),
"country".into() => string("US"), "country".into() => string("US"),
"chickens".into() => int(4), "chickens".into() => int(4)
}), },
row(indexmap! { row! {
"date".into() => date("2019-10-10"), "date".into() => date("2019-10-10"),
"name".into() => string("AR"), "name".into() => string("AR"),
"country".into() => string("EC"), "country".into() => string("EC"),
"chickens".into() => int(30), "chickens".into() => int(30)
}), },
row(indexmap! { row! {
"date".into() => date("2019-09-24"), "date".into() => date("2019-09-24"),
"name".into() => string("JT"), "name".into() => string("JT"),
"country".into() => string("NZ"), "country".into() => string("NZ"),
"chickens".into() => int(10), "chickens".into() => int(10)
}), },
row(indexmap! { row! {
"date".into() => date("2019-07-23"), "date".into() => date("2019-07-23"),
"name".into() => string("YK"), "name".into() => string("YK"),
"country".into() => string("US"), "country".into() => string("US"),
"chickens".into() => int(2), "chickens".into() => int(2)
}), },
] ]
} }
@ -217,6 +186,17 @@ pub mod helpers {
date.format(&fmt) date.format(&fmt)
}) })
} }
}
#[cfg(test)]
mod tests {
use super::helpers::{committers, date_formatter};
use super::{report, Labels, Model, Operation, Range, Reduction};
use nu_errors::ShellError;
use nu_protocol::Value;
use nu_source::{Tag, TaggedItem};
use nu_test_support::value::{decimal_from_float, int, table};
use nu_value_ext::ValueExt;
pub fn assert_without_checking_percentages(report_a: Model, report_b: Model) { pub fn assert_without_checking_percentages(report_a: Model, report_b: Model) {
assert_eq!(report_a.labels.x, report_b.labels.x); assert_eq!(report_a.labels.x, report_b.labels.x);
@ -224,19 +204,6 @@ pub mod helpers {
assert_eq!(report_a.ranges, report_b.ranges); assert_eq!(report_a.ranges, report_b.ranges);
assert_eq!(report_a.data, report_b.data); assert_eq!(report_a.data, report_b.data);
} }
}
#[cfg(test)]
mod tests {
use super::helpers::{
assert_without_checking_percentages, committers, date_formatter, decimal_from_float, int,
table,
};
use super::{report, Labels, Model, Operation, Range, Reduction};
use nu_errors::ShellError;
use nu_protocol::Value;
use nu_source::{Span, Tag, TaggedItem};
use nu_value_ext::ValueExt;
#[test] #[test]
fn prepares_report_using_counting_value() { fn prepares_report_using_counting_value() {
@ -304,19 +271,19 @@ mod tests {
]), ]),
percentages: table(&[ percentages: table(&[
table(&[ table(&[
decimal_from_float(33.33, Span::unknown()), decimal_from_float(33.33),
decimal_from_float(66.66, Span::unknown()), decimal_from_float(66.66),
decimal_from_float(99.99, Span::unknown()), decimal_from_float(99.99),
]), ]),
table(&[ table(&[
decimal_from_float(16.66, Span::unknown()), decimal_from_float(16.66),
decimal_from_float(33.33, Span::unknown()), decimal_from_float(33.33),
decimal_from_float(49.99, Span::unknown()), decimal_from_float(49.99),
]), ]),
table(&[ table(&[
decimal_from_float(6.66, Span::unknown()), decimal_from_float(6.66),
decimal_from_float(13.33, Span::unknown()), decimal_from_float(13.33),
decimal_from_float(19.99, Span::unknown()), decimal_from_float(19.99),
]), ]),
]), ]),
}, },

View File

@ -14,6 +14,7 @@ nu-errors = {path = "../nu-errors", version = "0.21.0"}
nu-protocol = {path = "../nu-protocol", version = "0.21.0"} nu-protocol = {path = "../nu-protocol", version = "0.21.0"}
nu-source = {path = "../nu-source", version = "0.21.0"} nu-source = {path = "../nu-source", version = "0.21.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.21.0"} nu-value-ext = {path = "../nu-value-ext", version = "0.21.0"}
nu-test-support = {path = "../nu-test-support", version = "0.21.0"}
bigdecimal = {version = "0.2.0", features = ["serde"]} bigdecimal = {version = "0.2.0", features = ["serde"]}
indexmap = {version = "1.6.0", features = ["serde-1"]} indexmap = {version = "1.6.0", features = ["serde-1"]}
@ -21,4 +22,4 @@ num-bigint = {version = "0.3.0", features = ["serde"]}
serde = {version = "1.0.115", features = ["derive"]} serde = {version = "1.0.115", features = ["derive"]}
serde_json = "1.0.57" serde_json = "1.0.57"
[build-dependencies] [build-dependencies]

View File

@ -1,8 +1,12 @@
use crate::Plugin; use crate::Plugin;
use indexmap::IndexMap; use indexmap::IndexMap;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{CallInfo, EvaluatedArgs, ReturnSuccess, ReturnValue, UntaggedValue, Value}; use nu_protocol::{
CallInfo, EvaluatedArgs, Primitive, ReturnSuccess, ReturnValue, UntaggedValue, Value,
};
use nu_source::Tag; use nu_source::Tag;
use nu_test_support::value::column_path;
use nu_value_ext::ValueExt;
pub struct PluginTest<'a, T: Plugin> { pub struct PluginTest<'a, T: Plugin> {
plugin: &'a mut T, plugin: &'a mut T,
@ -112,12 +116,12 @@ impl CallStub {
} }
pub fn with_parameter(&mut self, name: &str) -> Result<&mut Self, ShellError> { pub fn with_parameter(&mut self, name: &str) -> Result<&mut Self, ShellError> {
let fields: Vec<Value> = name let cp = column_path(&name)
.split('.') .as_column_path()
.map(|s| UntaggedValue::string(s.to_string()).into_value(Tag::unknown())) .expect("Failed! Expected valid column path.");
.collect(); let cp = UntaggedValue::Primitive(Primitive::ColumnPath(cp.item)).into_value(cp.tag);
self.positionals.push(value::column_path(&fields)?); self.positionals.push(cp);
Ok(self) Ok(self)
} }
@ -157,62 +161,3 @@ pub fn expect_return_value_at(
return_values.len() - 1 return_values.len() - 1
)) ))
} }
pub mod value {
use bigdecimal::BigDecimal;
use nu_errors::ShellError;
use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value};
use nu_source::{Span, Tag};
use nu_value_ext::ValueExt;
use num_bigint::BigInt;
pub fn get_data(for_value: Value, key: &str) -> Value {
for_value.get_data(&key.to_string()).borrow().clone()
}
pub fn int(i: impl Into<BigInt>) -> Value {
UntaggedValue::Primitive(Primitive::Int(i.into())).into_untagged_value()
}
pub fn decimal(f: impl Into<BigDecimal>) -> Value {
UntaggedValue::decimal(f.into()).into_untagged_value()
}
pub fn decimal_from_float(f: f64) -> Value {
UntaggedValue::decimal_from_float(f, Span::unknown()).into_untagged_value()
}
pub fn string(input: impl Into<String>) -> Value {
UntaggedValue::string(input.into()).into_untagged_value()
}
pub fn structured_sample_record(key: &str, value: &str) -> Value {
let mut record = TaggedDictBuilder::new(Tag::unknown());
record.insert_untagged(key, UntaggedValue::string(value));
record.into_value()
}
pub fn unstructured_sample_record(value: &str) -> Value {
UntaggedValue::string(value).into_value(Tag::unknown())
}
pub fn table(list: &[Value]) -> Value {
UntaggedValue::table(list).into_untagged_value()
}
pub fn column_path(paths: &[Value]) -> Result<Value, ShellError> {
Ok(UntaggedValue::Primitive(Primitive::ColumnPath(
table(&paths.to_vec()).as_column_path()?.item,
))
.into_untagged_value())
}
#[macro_export]
macro_rules! row {
($( $key: expr => $val: expr ),*) => {{
let mut map = ::indexmap::IndexMap::new();
$( map.insert($key, $val); )*
::nu_protocol::UntaggedValue::row(map).into_untagged_value()
}}
}
}

View File

@ -24,3 +24,12 @@ macro_rules! outln {
macro_rules! errln { macro_rules! errln {
($($tokens:tt)*) => { eprintln!($($tokens)*) } ($($tokens:tt)*) => { eprintln!($($tokens)*) }
} }
#[macro_export]
macro_rules! row {
($( $key: expr => $val: expr ),*) => {{
let mut map = ::indexmap::IndexMap::new();
$( map.insert($key, $val); )*
::nu_protocol::UntaggedValue::row(map).into_untagged_value()
}}
}

View File

@ -169,8 +169,8 @@ impl UntaggedValue {
} }
/// Helper for creating column-path values /// Helper for creating column-path values
pub fn column_path(s: &str) -> UntaggedValue { pub fn column_path(s: &str, span: Span) -> UntaggedValue {
let s = s.to_string().spanned_unknown(); let s = s.to_string().spanned(span);
UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::build(&s))) UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::build(&s)))
} }
@ -196,8 +196,8 @@ impl UntaggedValue {
} }
/// Helper for creating decimal values /// Helper for creating decimal values
pub fn decimal(s: BigDecimal) -> UntaggedValue { pub fn decimal(s: impl Into<BigDecimal>) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Decimal(s)) UntaggedValue::Primitive(Primitive::Decimal(s.into()))
} }
/// Helper for creating decimal values /// Helper for creating decimal values

View File

@ -21,6 +21,7 @@ getset = "0.1.1"
glob = "0.3.0" glob = "0.3.0"
indexmap = {version = "1.6.0", features = ["serde-1"]} indexmap = {version = "1.6.0", features = ["serde-1"]}
num-bigint = {version = "0.3.0", features = ["serde"]} num-bigint = {version = "0.3.0", features = ["serde"]}
bigdecimal = {version = "0.2.0", features = ["serde"]}
tempfile = "3.1.0" tempfile = "3.1.0"
[build-dependencies] [build-dependencies]

View File

@ -1,16 +1,21 @@
use bigdecimal::BigDecimal;
use chrono::{DateTime, NaiveDate, Utc}; use chrono::{DateTime, NaiveDate, Utc};
use indexmap::IndexMap; use indexmap::IndexMap;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ColumnPath, PathMember, Primitive, UntaggedValue, Value}; use nu_protocol::{PathMember, Primitive, UntaggedValue, Value};
use nu_source::{Span, SpannedItem, Tagged, TaggedItem}; use nu_source::{Span, TaggedItem};
use num_bigint::BigInt; use num_bigint::BigInt;
pub fn int(s: impl Into<BigInt>) -> Value { pub fn int(s: impl Into<BigInt>) -> Value {
UntaggedValue::int(s).into_untagged_value() UntaggedValue::int(s).into_untagged_value()
} }
pub fn decimal_from_float(f: f64, span: Span) -> Value { pub fn decimal(s: BigDecimal) -> Value {
UntaggedValue::decimal_from_float(f, span).into_untagged_value() UntaggedValue::Primitive(Primitive::Decimal(s)).into_untagged_value()
}
pub fn decimal_from_float(f: f64) -> Value {
UntaggedValue::decimal_from_float(f, Span::unknown()).into_untagged_value()
} }
pub fn string(input: impl Into<String>) -> Value { pub fn string(input: impl Into<String>) -> Value {
@ -42,9 +47,8 @@ pub fn date(input: impl Into<String>) -> Value {
.into_untagged_value() .into_untagged_value()
} }
pub fn column_path(paths: &str) -> Result<Tagged<ColumnPath>, ShellError> { pub fn column_path(paths: &str) -> Value {
let paths = paths.to_string().spanned_unknown(); UntaggedValue::column_path(paths, Span::unknown()).into_untagged_value()
Ok(ColumnPath::build(&paths).tagged_unknown())
} }
pub fn error_callback( pub fn error_callback(

View File

@ -5,7 +5,7 @@ use indexmap::indexmap;
#[test] #[test]
fn forgiving_insertion_test_1() { fn forgiving_insertion_test_1() {
let field_path = column_path("crate.version").unwrap(); let field_path = column_path("crate.version").as_column_path().unwrap();
let version = string("nuno"); let version = string("nuno");
@ -20,7 +20,7 @@ fn forgiving_insertion_test_1() {
assert_eq!( assert_eq!(
*value *value
.into_untagged_value() .into_untagged_value()
.forgiving_insert_data_at_column_path(&field_path, version) .forgiving_insert_data_at_column_path(&field_path.item, version)
.unwrap() .unwrap()
.get_data_by_column_path(&field_path, Box::new(error_callback("crate.version"))) .get_data_by_column_path(&field_path, Box::new(error_callback("crate.version")))
.unwrap(), .unwrap(),
@ -30,7 +30,7 @@ fn forgiving_insertion_test_1() {
#[test] #[test]
fn forgiving_insertion_test_2() { fn forgiving_insertion_test_2() {
let field_path = column_path("things.0").unwrap(); let field_path = column_path("things.0").as_column_path().unwrap();
let version = string("arepas"); let version = string("arepas");
@ -47,7 +47,7 @@ fn forgiving_insertion_test_2() {
assert_eq!( assert_eq!(
*value *value
.into_untagged_value() .into_untagged_value()
.forgiving_insert_data_at_column_path(&field_path, version) .forgiving_insert_data_at_column_path(&field_path.item, version)
.unwrap() .unwrap()
.get_data_by_column_path(&field_path, Box::new(error_callback("things.0"))) .get_data_by_column_path(&field_path, Box::new(error_callback("things.0")))
.unwrap(), .unwrap(),
@ -57,8 +57,10 @@ fn forgiving_insertion_test_2() {
#[test] #[test]
fn forgiving_insertion_test_3() { fn forgiving_insertion_test_3() {
let field_path = column_path("color_config.arepa_color").unwrap(); let field_path = column_path("color_config.arepa_color")
let pizza_path = column_path("things.0").unwrap(); .as_column_path()
.unwrap();
let pizza_path = column_path("things.0").as_column_path().unwrap();
let entry = string("amarillo"); let entry = string("amarillo");
@ -79,7 +81,7 @@ fn forgiving_insertion_test_3() {
.forgiving_insert_data_at_column_path(&field_path, entry.clone()) .forgiving_insert_data_at_column_path(&field_path, entry.clone())
.unwrap() .unwrap()
.get_data_by_column_path( .get_data_by_column_path(
&field_path, &field_path.item,
Box::new(error_callback("color_config.arepa_color")) Box::new(error_callback("color_config.arepa_color"))
) )
.unwrap(), .unwrap(),
@ -89,7 +91,7 @@ fn forgiving_insertion_test_3() {
assert_eq!( assert_eq!(
*value *value
.into_untagged_value() .into_untagged_value()
.forgiving_insert_data_at_column_path(&field_path, entry) .forgiving_insert_data_at_column_path(&field_path.item, entry)
.unwrap() .unwrap()
.get_data_by_column_path(&pizza_path, Box::new(error_callback("things.0"))) .get_data_by_column_path(&pizza_path, Box::new(error_callback("things.0")))
.unwrap(), .unwrap(),

View File

@ -15,6 +15,7 @@ nu-plugin = {path = "../nu-plugin", version = "0.21.0"}
nu-protocol = {path = "../nu-protocol", version = "0.21.0"} nu-protocol = {path = "../nu-protocol", version = "0.21.0"}
nu-source = {path = "../nu-source", version = "0.21.0"} nu-source = {path = "../nu-source", version = "0.21.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.21.0"} nu-value-ext = {path = "../nu-value-ext", version = "0.21.0"}
nu-test-support = {path = "../nu-test-support", version = "0.21.0"}
semver = "0.10.0" semver = "0.10.0"

View File

@ -150,7 +150,7 @@ mod tests {
mod semver { mod semver {
use crate::inc::SemVerAction; use crate::inc::SemVerAction;
use crate::Inc; use crate::Inc;
use nu_plugin::test_helpers::value::string; use nu_test_support::value::string;
#[test] #[test]
fn major() -> Result<(), Box<dyn std::error::Error>> { fn major() -> Result<(), Box<dyn std::error::Error>> {

View File

@ -2,8 +2,10 @@ mod integration {
use crate::inc::{Action, SemVerAction}; use crate::inc::{Action, SemVerAction};
use crate::Inc; use crate::Inc;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_plugin::test_helpers::value::{column_path, string};
use nu_plugin::test_helpers::{plugin, CallStub}; use nu_plugin::test_helpers::{plugin, CallStub};
use nu_protocol::{Primitive, UntaggedValue};
use nu_test_support::value::column_path;
use nu_value_ext::ValueExt;
#[test] #[test]
fn picks_up_one_action_flag_only() { fn picks_up_one_action_flag_only() {
@ -58,21 +60,28 @@ mod integration {
.args(CallStub::new().with_parameter("package.version")?.create()) .args(CallStub::new().with_parameter("package.version")?.create())
.setup(|plugin, _| { .setup(|plugin, _| {
//FIXME: this will need to be updated //FIXME: this will need to be updated
if let Ok(column_path) = column_path(&[string("package"), string("version")]) { if let Ok(column_path) = column_path("package.version").as_column_path() {
let column_path =
UntaggedValue::Primitive(Primitive::ColumnPath(column_path.item))
.into_value(column_path.tag);
plugin.expect_field(column_path) plugin.expect_field(column_path)
} }
}); });
Ok(()) Ok(())
} }
mod sem_ver { mod sem_ver {
use crate::Inc; use crate::Inc;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_plugin::test_helpers::value::{get_data, string, structured_sample_record};
use nu_plugin::test_helpers::{expect_return_value_at, plugin, CallStub}; use nu_plugin::test_helpers::{expect_return_value_at, plugin, CallStub};
use nu_protocol::TaggedDictBuilder;
use nu_source::Tag;
use nu_test_support::value::string;
use nu_value_ext::get_data;
fn cargo_sample_record(with_version: &str) -> nu_protocol::Value { fn cargo_sample_record(with_version: &str) -> nu_protocol::Value {
structured_sample_record("version", with_version) TaggedDictBuilder::build(Tag::unknown(), |row| {
row.insert_value("version".to_string(), string(with_version));
})
} }
#[test] #[test]
@ -90,7 +99,7 @@ mod integration {
let actual = expect_return_value_at(run, 0); let actual = expect_return_value_at(run, 0);
assert_eq!(get_data(actual, "version"), string("1.0.0")); assert_eq!(get_data(&actual, "version").borrow(), &string("1.0.0"));
Ok(()) Ok(())
} }
@ -109,7 +118,7 @@ mod integration {
let actual = expect_return_value_at(run, 0); let actual = expect_return_value_at(run, 0);
assert_eq!(get_data(actual, "version"), string("0.2.0")); assert_eq!(get_data(&actual, "version").borrow(), &string("0.2.0"));
Ok(()) Ok(())
} }
@ -128,7 +137,7 @@ mod integration {
let actual = expect_return_value_at(run, 0); let actual = expect_return_value_at(run, 0);
assert_eq!(get_data(actual, "version"), string("0.1.4")); assert_eq!(get_data(&actual, "version").borrow(), &string("0.1.4"));
Ok(()) Ok(())
} }
} }

View File

@ -127,7 +127,7 @@ fn build_xpath(xpath_str: &str) -> Result<sxd_xpath::XPath, ShellError> {
mod tests { mod tests {
use super::string_to_value as query; use super::string_to_value as query;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_source::{Span, TaggedItem}; use nu_source::TaggedItem;
use nu_test_support::value::{decimal_from_float, row}; use nu_test_support::value::{decimal_from_float, row};
use indexmap::indexmap; use indexmap::indexmap;
@ -140,9 +140,7 @@ mod tests {
assert_eq!( assert_eq!(
actual[0], actual[0],
row( row(indexmap! { "count(//a/*[posit...".into() => decimal_from_float(1.0) })
indexmap! { "count(//a/*[posit...".into() => decimal_from_float(1.0, Span::unknown()) }
)
); );
Ok(()) Ok(())
@ -156,9 +154,7 @@ mod tests {
assert_eq!( assert_eq!(
actual[0], actual[0],
row( row(indexmap! { "count(//*[contain...".into() => decimal_from_float(1.0) })
indexmap! { "count(//*[contain...".into() => decimal_from_float(1.0, Span::unknown()) }
)
); );
Ok(()) Ok(())