mirror of
https://github.com/nushell/nushell.git
synced 2024-11-29 03:44:19 +01:00
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(Cal),
|
||||||
whole_stream_command(Calc),
|
whole_stream_command(Calc),
|
||||||
whole_stream_command(Mkdir),
|
whole_stream_command(Mkdir),
|
||||||
whole_stream_command(Move),
|
whole_stream_command(Mv),
|
||||||
whole_stream_command(Kill),
|
whole_stream_command(Kill),
|
||||||
whole_stream_command(Version),
|
whole_stream_command(Version),
|
||||||
whole_stream_command(Clear),
|
whole_stream_command(Clear),
|
||||||
@ -310,6 +310,7 @@ pub fn create_default_context(
|
|||||||
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(Reject),
|
whole_stream_command(Reject),
|
||||||
whole_stream_command(Select),
|
whole_stream_command(Select),
|
||||||
whole_stream_command(Get),
|
whole_stream_command(Get),
|
||||||
@ -345,6 +346,7 @@ pub fn create_default_context(
|
|||||||
whole_stream_command(Each),
|
whole_stream_command(Each),
|
||||||
whole_stream_command(IsEmpty),
|
whole_stream_command(IsEmpty),
|
||||||
// Table manipulation
|
// Table manipulation
|
||||||
|
whole_stream_command(Move),
|
||||||
whole_stream_command(Merge),
|
whole_stream_command(Merge),
|
||||||
whole_stream_command(Shuffle),
|
whole_stream_command(Shuffle),
|
||||||
whole_stream_command(Wrap),
|
whole_stream_command(Wrap),
|
||||||
|
@ -79,7 +79,7 @@ pub(crate) mod map_max_by;
|
|||||||
pub(crate) mod math;
|
pub(crate) mod math;
|
||||||
pub(crate) mod merge;
|
pub(crate) mod merge;
|
||||||
pub(crate) mod mkdir;
|
pub(crate) mod mkdir;
|
||||||
pub(crate) mod mv;
|
pub(crate) mod move_;
|
||||||
pub(crate) mod next;
|
pub(crate) mod next;
|
||||||
pub(crate) mod nth;
|
pub(crate) mod nth;
|
||||||
pub(crate) mod open;
|
pub(crate) mod open;
|
||||||
@ -219,7 +219,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 mv::Move;
|
pub(crate) use move_::{Move, MoveColumn, 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;
|
||||||
@ -246,10 +246,7 @@ pub(crate) use skip::Skip;
|
|||||||
pub(crate) use skip_until::SkipUntil;
|
pub(crate) use skip_until::SkipUntil;
|
||||||
pub(crate) use skip_while::SkipWhile;
|
pub(crate) use skip_while::SkipWhile;
|
||||||
pub(crate) use sort_by::SortBy;
|
pub(crate) use sort_by::SortBy;
|
||||||
pub(crate) use split::Split;
|
pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow};
|
||||||
pub(crate) use split::SplitChars;
|
|
||||||
pub(crate) use split::SplitColumn;
|
|
||||||
pub(crate) use split::SplitRow;
|
|
||||||
pub(crate) use split_by::SplitBy;
|
pub(crate) use split_by::SplitBy;
|
||||||
pub(crate) use str_::{
|
pub(crate) use str_::{
|
||||||
Str, StrCapitalize, StrCollect, StrDowncase, StrFindReplace, StrLength, StrSet, StrSubstring,
|
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 nu_source::Tagged;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub struct Move;
|
pub struct Mv;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct MoveArgs {
|
pub struct Arguments {
|
||||||
pub src: Tagged<PathBuf>,
|
pub src: Tagged<PathBuf>,
|
||||||
pub dst: Tagged<PathBuf>,
|
pub dst: Tagged<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WholeStreamCommand for Move {
|
impl WholeStreamCommand for Mv {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"mv"
|
"mv"
|
||||||
}
|
}
|
||||||
@ -78,12 +78,12 @@ async fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Move;
|
use super::Mv;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn examples_work_as_expected() {
|
fn examples_work_as_expected() {
|
||||||
use crate::examples::test as test_examples;
|
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::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
use crate::commands::mkdir::MkdirArgs;
|
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::commands::rm::RemoveArgs;
|
||||||
use crate::data::dir_entry_dict;
|
use crate::data::dir_entry_dict;
|
||||||
use crate::path::canonicalize;
|
use crate::path::canonicalize;
|
||||||
@ -441,7 +441,7 @@ impl Shell for FilesystemShell {
|
|||||||
|
|
||||||
fn mv(
|
fn mv(
|
||||||
&self,
|
&self,
|
||||||
MoveArgs { src, dst }: MoveArgs,
|
MvArgs { src, dst }: MvArgs,
|
||||||
_name: Tag,
|
_name: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
|||||||
use crate::commands::cp::CopyArgs;
|
use crate::commands::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
use crate::commands::mkdir::MkdirArgs;
|
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::commands::rm::RemoveArgs;
|
||||||
use crate::data::command_dict;
|
use crate::data::command_dict;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -185,7 +185,7 @@ impl Shell for HelpShell {
|
|||||||
Ok(OutputStream::empty())
|
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())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
|||||||
use crate::commands::cp::CopyArgs;
|
use crate::commands::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
use crate::commands::mkdir::MkdirArgs;
|
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::commands::rm::RemoveArgs;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::stream::OutputStream;
|
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 cd(&self, args: CdArgs, name: Tag) -> Result<OutputStream, ShellError>;
|
||||||
fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> 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 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 rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||||
fn path(&self) -> String;
|
fn path(&self) -> String;
|
||||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
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::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
use crate::commands::mkdir::MkdirArgs;
|
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::commands::rm::RemoveArgs;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::shell::filesystem_shell::FilesystemShell;
|
use crate::shell::filesystem_shell::FilesystemShell;
|
||||||
@ -170,7 +170,7 @@ impl ShellManager {
|
|||||||
shells[self.current_shell()].mkdir(args, name, &path)
|
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 shells = self.shells.lock();
|
||||||
|
|
||||||
let path = shells[self.current_shell()].path();
|
let path = shells[self.current_shell()].path();
|
||||||
|
@ -3,7 +3,7 @@ use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
|||||||
use crate::commands::cp::CopyArgs;
|
use crate::commands::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
use crate::commands::mkdir::MkdirArgs;
|
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::commands::rm::RemoveArgs;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::shell::shell::Shell;
|
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(
|
Err(ShellError::labeled_error(
|
||||||
"mv not currently supported on values",
|
"mv not currently supported on values",
|
||||||
"not currently supported",
|
"not currently supported",
|
||||||
|
@ -31,7 +31,7 @@ mod ls;
|
|||||||
mod math;
|
mod math;
|
||||||
mod merge;
|
mod merge;
|
||||||
mod mkdir;
|
mod mkdir;
|
||||||
mod mv;
|
mod move_;
|
||||||
mod open;
|
mod open;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod prepend;
|
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
|
| lines
|
||||||
| trim
|
| trim
|
||||||
| split column ","
|
| split column ","
|
||||||
| pivot
|
| get Column2
|
||||||
| nth 1
|
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
@ -61,6 +61,11 @@ impl ColumnPath {
|
|||||||
pub fn split_last(&self) -> Option<(&PathMember, &[PathMember])> {
|
pub fn split_last(&self) -> Option<(&PathMember, &[PathMember])> {
|
||||||
self.members.split_last()
|
self.members.split_last()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the last member
|
||||||
|
pub fn last(&self) -> Option<&PathMember> {
|
||||||
|
self.iter().last()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrettyDebug for ColumnPath {
|
impl PrettyDebug for ColumnPath {
|
||||||
@ -99,6 +104,13 @@ impl PathMember {
|
|||||||
pub fn int(int: impl Into<BigInt>, span: impl Into<Span>) -> PathMember {
|
pub fn int(int: impl Into<BigInt>, span: impl Into<Span>) -> PathMember {
|
||||||
UnspannedPathMember::Int(int.into()).into_path_member(span)
|
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
|
/// Prepares a list of "sounds like" matches for the string you're trying to find
|
||||||
|
Loading…
Reference in New Issue
Block a user