forked from extern/nushell
Add "move column" command. (#2123)
This commit is contained in:
parent
c3ba1e476f
commit
34e1e6e426
@ -260,7 +260,7 @@ pub fn create_default_context(
|
||||
whole_stream_command(Cal),
|
||||
whole_stream_command(Calc),
|
||||
whole_stream_command(Mkdir),
|
||||
whole_stream_command(Move),
|
||||
whole_stream_command(Mv),
|
||||
whole_stream_command(Kill),
|
||||
whole_stream_command(Version),
|
||||
whole_stream_command(Clear),
|
||||
@ -310,6 +310,7 @@ pub fn create_default_context(
|
||||
whole_stream_command(Ansi),
|
||||
whole_stream_command(Char),
|
||||
// Column manipulation
|
||||
whole_stream_command(MoveColumn),
|
||||
whole_stream_command(Reject),
|
||||
whole_stream_command(Select),
|
||||
whole_stream_command(Get),
|
||||
@ -345,6 +346,7 @@ pub fn create_default_context(
|
||||
whole_stream_command(Each),
|
||||
whole_stream_command(IsEmpty),
|
||||
// Table manipulation
|
||||
whole_stream_command(Move),
|
||||
whole_stream_command(Merge),
|
||||
whole_stream_command(Shuffle),
|
||||
whole_stream_command(Wrap),
|
||||
|
@ -79,7 +79,7 @@ pub(crate) mod map_max_by;
|
||||
pub(crate) mod math;
|
||||
pub(crate) mod merge;
|
||||
pub(crate) mod mkdir;
|
||||
pub(crate) mod mv;
|
||||
pub(crate) mod move_;
|
||||
pub(crate) mod next;
|
||||
pub(crate) mod nth;
|
||||
pub(crate) mod open;
|
||||
@ -219,7 +219,7 @@ pub(crate) use math::{
|
||||
};
|
||||
pub(crate) use merge::Merge;
|
||||
pub(crate) use mkdir::Mkdir;
|
||||
pub(crate) use mv::Move;
|
||||
pub(crate) use move_::{Move, MoveColumn, Mv};
|
||||
pub(crate) use next::Next;
|
||||
pub(crate) use nth::Nth;
|
||||
pub(crate) use open::Open;
|
||||
@ -246,10 +246,7 @@ pub(crate) use skip::Skip;
|
||||
pub(crate) use skip_until::SkipUntil;
|
||||
pub(crate) use skip_while::SkipWhile;
|
||||
pub(crate) use sort_by::SortBy;
|
||||
pub(crate) use split::Split;
|
||||
pub(crate) use split::SplitChars;
|
||||
pub(crate) use split::SplitColumn;
|
||||
pub(crate) use split::SplitRow;
|
||||
pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow};
|
||||
pub(crate) use split_by::SplitBy;
|
||||
pub(crate) use str_::{
|
||||
Str, StrCapitalize, StrCollect, StrDowncase, StrFindReplace, StrLength, StrSet, StrSubstring,
|
||||
|
335
crates/nu-cli/src/commands/move_/column.rs
Normal file
335
crates/nu-cli/src/commands/move_/column.rs
Normal file
@ -0,0 +1,335 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::base::select_fields;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, Value};
|
||||
use nu_source::span_for_spanned_list;
|
||||
|
||||
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(®istry).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 = span_for_spanned_list(after.members().iter().map(|p| p.span));
|
||||
|
||||
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 = span_for_spanned_list(before.members().iter().map(|p| p.span));
|
||||
|
||||
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 = span_for_spanned_list(from.members().iter().map(|p| p.span));
|
||||
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)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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 = span_for_spanned_list(from.members().iter().map(|p| p.span));
|
||||
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)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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::SubCommand;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
}
|
||||
}
|
46
crates/nu-cli/src/commands/move_/command.rs
Normal file
46
crates/nu-cli/src/commands/move_/command.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Command;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"move"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("move")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"moves across desired subcommand."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
_args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
Ok(OutputStream::one(Ok(ReturnSuccess::Value(
|
||||
UntaggedValue::string(crate::commands::help::get_help(&Command, ®istry))
|
||||
.into_value(Tag::unknown()),
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Command;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Command {})
|
||||
}
|
||||
}
|
7
crates/nu-cli/src/commands/move_/mod.rs
Normal file
7
crates/nu-cli/src/commands/move_/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
mod column;
|
||||
mod command;
|
||||
pub mod mv;
|
||||
|
||||
pub use column::SubCommand as MoveColumn;
|
||||
pub use command::Command as Move;
|
||||
pub use mv::Mv;
|
@ -6,16 +6,16 @@ use nu_protocol::{Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Move;
|
||||
pub struct Mv;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MoveArgs {
|
||||
pub struct Arguments {
|
||||
pub src: Tagged<PathBuf>,
|
||||
pub dst: Tagged<PathBuf>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Move {
|
||||
impl WholeStreamCommand for Mv {
|
||||
fn name(&self) -> &str {
|
||||
"mv"
|
||||
}
|
||||
@ -78,12 +78,12 @@ async fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Move;
|
||||
use super::Mv;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Move {})
|
||||
test_examples(Mv {})
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::mv::MoveArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::data::dir_entry_dict;
|
||||
use crate::path::canonicalize;
|
||||
@ -441,7 +441,7 @@ impl Shell for FilesystemShell {
|
||||
|
||||
fn mv(
|
||||
&self,
|
||||
MoveArgs { src, dst }: MoveArgs,
|
||||
MvArgs { src, dst }: MvArgs,
|
||||
_name: Tag,
|
||||
path: &str,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::mv::MoveArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::data::command_dict;
|
||||
use crate::prelude::*;
|
||||
@ -185,7 +185,7 @@ impl Shell for HelpShell {
|
||||
Ok(OutputStream::empty())
|
||||
}
|
||||
|
||||
fn mv(&self, _args: MoveArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||
fn mv(&self, _args: MvArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||
Ok(OutputStream::empty())
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::mv::MoveArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::prelude::*;
|
||||
use crate::stream::OutputStream;
|
||||
@ -23,7 +23,7 @@ pub trait Shell: std::fmt::Debug {
|
||||
fn cd(&self, args: CdArgs, name: Tag) -> Result<OutputStream, ShellError>;
|
||||
fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||
fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||
fn mv(&self, args: MoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||
fn mv(&self, args: MvArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||
fn rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||
fn path(&self) -> String;
|
||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::mv::MoveArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::filesystem_shell::FilesystemShell;
|
||||
@ -170,7 +170,7 @@ impl ShellManager {
|
||||
shells[self.current_shell()].mkdir(args, name, &path)
|
||||
}
|
||||
|
||||
pub fn mv(&self, args: MoveArgs, name: Tag) -> Result<OutputStream, ShellError> {
|
||||
pub fn mv(&self, args: MvArgs, name: Tag) -> Result<OutputStream, ShellError> {
|
||||
let shells = self.shells.lock();
|
||||
|
||||
let path = shells[self.current_shell()].path();
|
||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::mv::MoveArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::shell::Shell;
|
||||
@ -189,7 +189,7 @@ impl Shell for ValueShell {
|
||||
))
|
||||
}
|
||||
|
||||
fn mv(&self, _args: MoveArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||
fn mv(&self, _args: MvArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||
Err(ShellError::labeled_error(
|
||||
"mv not currently supported on values",
|
||||
"not currently supported",
|
||||
|
@ -31,7 +31,7 @@ mod ls;
|
||||
mod math;
|
||||
mod merge;
|
||||
mod mkdir;
|
||||
mod mv;
|
||||
mod move_;
|
||||
mod open;
|
||||
mod parse;
|
||||
mod prepend;
|
||||
|
141
crates/nu-cli/tests/commands/move_/column.rs
Normal file
141
crates/nu-cli/tests/commands/move_/column.rs
Normal file
@ -0,0 +1,141 @@
|
||||
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
|
||||
use nu_test_support::playground::Playground;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn moves_a_column_before() {
|
||||
Playground::setup("move_column_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"sample.csv",
|
||||
r#"
|
||||
column1,column2,column3,...,column98,column99,column100
|
||||
-------,-------,-------,---,--------, A ,---------
|
||||
-------,-------,-------,---,--------, N ,---------
|
||||
-------,-------,-------,---,--------, D ,---------
|
||||
-------,-------,-------,---,--------, R ,---------
|
||||
-------,-------,-------,---,--------, E ,---------
|
||||
-------,-------,-------,---,--------, S ,---------
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open sample.csv
|
||||
| move column column99 --before column1
|
||||
| rename chars
|
||||
| get chars
|
||||
| trim
|
||||
| str collect
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.out.contains("ANDRES"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn moves_columns_before() {
|
||||
Playground::setup("move_column_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"sample.csv",
|
||||
r#"
|
||||
column1,column2,column3,...,column98,column99,column100
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
-------,-------, D ,---,--------, R ,---------
|
||||
-------,-------, E ,---,--------, S ,---------
|
||||
-------,-------, : ,---,--------, : ,---------
|
||||
-------,-------, J ,---,--------, O ,---------
|
||||
-------,-------, N ,---,--------, A ,---------
|
||||
-------,-------, T ,---,--------, H ,---------
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open sample.csv
|
||||
| move column column99 column3 --before column2
|
||||
| rename _ chars_1 chars_2
|
||||
| get chars_2 chars_1
|
||||
| trim
|
||||
| str collect
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.out.contains("ANDRES::JONATHAN"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn moves_a_column_after() {
|
||||
Playground::setup("move_column_test_3", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"sample.csv",
|
||||
r#"
|
||||
column1,column2,letters,...,column98,and_more,column100
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
-------,-------, D ,---,--------, R ,---------
|
||||
-------,-------, E ,---,--------, S ,---------
|
||||
-------,-------, : ,---,--------, : ,---------
|
||||
-------,-------, J ,---,--------, O ,---------
|
||||
-------,-------, N ,---,--------, A ,---------
|
||||
-------,-------, T ,---,--------, H ,---------
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open sample.csv
|
||||
| move column letters --after and_more
|
||||
| move column letters and_more --before column2
|
||||
| rename _ chars_1 chars_2
|
||||
| get chars_1 chars_2
|
||||
| trim
|
||||
| str collect
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.out.contains("ANDRES::JONATHAN"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn moves_columns_after() {
|
||||
Playground::setup("move_column_test_4", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"sample.csv",
|
||||
r#"
|
||||
column1,column2,letters,...,column98,and_more,column100
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
-------,-------, D ,---,--------, R ,---------
|
||||
-------,-------, E ,---,--------, S ,---------
|
||||
-------,-------, : ,---,--------, : ,---------
|
||||
-------,-------, J ,---,--------, O ,---------
|
||||
-------,-------, N ,---,--------, A ,---------
|
||||
-------,-------, T ,---,--------, H ,---------
|
||||
-------,-------, A ,---,--------, N ,---------
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open sample.csv
|
||||
| move column letters and_more --after column1
|
||||
| get
|
||||
| nth 1 2
|
||||
| str collect
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.out.contains("lettersand_more"));
|
||||
})
|
||||
}
|
2
crates/nu-cli/tests/commands/move_/mod.rs
Normal file
2
crates/nu-cli/tests/commands/move_/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
mod column;
|
||||
mod mv;
|
@ -19,8 +19,7 @@ fn to_column() {
|
||||
| lines
|
||||
| trim
|
||||
| split column ","
|
||||
| pivot
|
||||
| nth 1
|
||||
| get Column2
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
@ -61,6 +61,11 @@ impl ColumnPath {
|
||||
pub fn split_last(&self) -> Option<(&PathMember, &[PathMember])> {
|
||||
self.members.split_last()
|
||||
}
|
||||
|
||||
/// Returns the last member
|
||||
pub fn last(&self) -> Option<&PathMember> {
|
||||
self.iter().last()
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for ColumnPath {
|
||||
@ -99,6 +104,13 @@ impl PathMember {
|
||||
pub fn int(int: impl Into<BigInt>, span: impl Into<Span>) -> PathMember {
|
||||
UnspannedPathMember::Int(int.into()).into_path_member(span)
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> String {
|
||||
match &self.unspanned {
|
||||
UnspannedPathMember::String(string) => string.clone(),
|
||||
UnspannedPathMember::Int(int) => format!("{}", int),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares a list of "sounds like" matches for the string you're trying to find
|
||||
|
Loading…
Reference in New Issue
Block a user