1
0
mirror of https://github.com/nushell/nushell.git synced 2025-08-15 13:53:13 +02:00

Parity and anchor carrying for str command suite. ()

Bring the majority of str sub commands to parity supporting their actions
by column paths. Ensuring they carry over anchor meta data as well.
This commit is contained in:
Andrés N. Robalino
2021-01-22 18:13:30 -05:00
committed by GitHub
parent 5a471aa1d0
commit 42b1287759
4 changed files with 113 additions and 25 deletions
crates/nu-command/src

@ -307,7 +307,7 @@ mod tests {
whole_stream_command(StrUpcase), whole_stream_command(StrUpcase),
whole_stream_command(StrCapitalize), whole_stream_command(StrCapitalize),
whole_stream_command(StrFindReplace), whole_stream_command(StrFindReplace),
// whole_stream_command(StrFrom), whole_stream_command(StrFrom),
whole_stream_command(StrSubstring), whole_stream_command(StrSubstring),
whole_stream_command(StrToDatetime), whole_stream_command(StrToDatetime),
whole_stream_command(StrContains), whole_stream_command(StrContains),
@ -318,9 +318,9 @@ mod tests {
whole_stream_command(StrStartsWith), whole_stream_command(StrStartsWith),
whole_stream_command(StrEndsWith), whole_stream_command(StrEndsWith),
//whole_stream_command(StrCollect), //whole_stream_command(StrCollect),
//whole_stream_command(StrLength), whole_stream_command(StrLength),
whole_stream_command(StrLPad), whole_stream_command(StrLPad),
//whole_stream_command(StrReverse), whole_stream_command(StrReverse),
whole_stream_command(StrRPad), whole_stream_command(StrRPad),
whole_stream_command(StrCamelCase), whole_stream_command(StrCamelCase),
whole_stream_command(StrPascalCase), whole_stream_command(StrPascalCase),

@ -63,7 +63,7 @@ impl WholeStreamCommand for SubCommand {
vec![ vec![
Example { Example {
description: "round to nearest integer", description: "round to nearest integer",
example: "= 1.7 | str from -d 0", example: "echo 1.7 | str from -d 0",
result: Some(vec![UntaggedValue::string("2").into_untagged_value()]), result: Some(vec![UntaggedValue::string("2").into_untagged_value()]),
}, },
/* /*

@ -1,10 +1,18 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::ShellTypeName;
use nu_protocol::{
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
};
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
rest: Vec<ColumnPath>,
}
#[async_trait] #[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -12,7 +20,10 @@ impl WholeStreamCommand for SubCommand {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("str length") Signature::build("str length").rest(
SyntaxShape::ColumnPath,
"optionally find length of text by column paths",
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -20,13 +31,7 @@ impl WholeStreamCommand for SubCommand {
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args operate(args).await
.input
.map(move |x| match x.as_string() {
Ok(s) => ReturnSuccess::value(UntaggedValue::int(s.len()).into_untagged_value()),
Err(err) => Err(err),
})
.to_output_stream())
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -48,6 +53,47 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rest }, input) = args.process().await?;
let column_paths: Vec<_> = rest;
Ok(input
.map(move |v| {
if column_paths.is_empty() {
ReturnSuccess::value(action(&v, v.tag())?)
} else {
let mut ret = v;
for path in &column_paths {
ret = ret.swap_data_by_column_path(
path,
Box::new(move |old| action(old, old.tag())),
)?;
}
ReturnSuccess::value(ret)
}
})
.to_output_stream())
}
fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
match &input.value {
UntaggedValue::Primitive(Primitive::String(s)) => {
Ok(UntaggedValue::int(s.len()).into_value(tag))
}
other => {
let got = format!("got {}", other.type_name());
Err(ShellError::labeled_error(
"value is not string",
got,
tag.into().span,
))
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::ShellError; use super::ShellError;

@ -1,10 +1,18 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::ShellTypeName;
use nu_protocol::{
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
};
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
rest: Vec<ColumnPath>,
}
#[async_trait] #[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -12,7 +20,10 @@ impl WholeStreamCommand for SubCommand {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("str reverse") Signature::build("str reverse").rest(
SyntaxShape::ColumnPath,
"optionally reverse text by column paths",
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -20,16 +31,7 @@ impl WholeStreamCommand for SubCommand {
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args operate(args).await
.input
.map(move |x| match x.as_string() {
Ok(s) => ReturnSuccess::value(
UntaggedValue::string(s.chars().rev().collect::<String>())
.into_untagged_value(),
),
Err(err) => Err(err),
})
.to_output_stream())
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -41,6 +43,46 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rest }, input) = args.process().await?;
let column_paths: Vec<_> = rest;
Ok(input
.map(move |v| {
if column_paths.is_empty() {
ReturnSuccess::value(action(&v, v.tag())?)
} else {
let mut ret = v;
for path in &column_paths {
ret = ret.swap_data_by_column_path(
path,
Box::new(move |old| action(old, old.tag())),
)?;
}
ReturnSuccess::value(ret)
}
})
.to_output_stream())
}
fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
match &input.value {
UntaggedValue::Primitive(Primitive::String(s)) => {
Ok(UntaggedValue::string(s.chars().rev().collect::<String>()).into_value(tag))
}
other => {
let got = format!("got {}", other.type_name());
Err(ShellError::labeled_error(
"value is not string",
got,
tag.into().span,
))
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::ShellError; use super::ShellError;