mirror of
https://github.com/nushell/nushell
synced 2024-11-15 01:17:07 +00:00
Fix it expansion and add collect (#2065)
This commit is contained in:
parent
05781607f4
commit
4e2a4236f8
7 changed files with 133 additions and 34 deletions
|
@ -303,6 +303,7 @@ pub fn create_default_context(
|
|||
whole_stream_command(StrSet),
|
||||
whole_stream_command(StrToDatetime),
|
||||
whole_stream_command(StrTrim),
|
||||
whole_stream_command(StrCollect),
|
||||
whole_stream_command(BuildString),
|
||||
whole_stream_command(Ansi),
|
||||
// Column manipulation
|
||||
|
@ -657,10 +658,12 @@ pub async fn cli(
|
|||
|
||||
if let Ok(result) = nu_parser::lite_parse(&prompt_line, 0).map_err(ShellError::from)
|
||||
{
|
||||
let prompt_block = nu_parser::classify_block(&result, context.registry());
|
||||
let mut prompt_block = nu_parser::classify_block(&result, context.registry());
|
||||
|
||||
let env = context.get_env();
|
||||
|
||||
prompt_block.block.expand_it_usage();
|
||||
|
||||
match run_block(
|
||||
&prompt_block.block,
|
||||
&mut context,
|
||||
|
|
|
@ -240,8 +240,8 @@ pub(crate) use split::SplitColumn;
|
|||
pub(crate) use split::SplitRow;
|
||||
pub(crate) use split_by::SplitBy;
|
||||
pub(crate) use str_::{
|
||||
Str, StrCapitalize, StrDowncase, StrFindReplace, StrSet, StrSubstring, StrToDatetime,
|
||||
StrToDecimal, StrToInteger, StrTrim, StrUpcase,
|
||||
Str, StrCapitalize, StrCollect, StrDowncase, StrFindReplace, StrSet, StrSubstring,
|
||||
StrToDatetime, StrToDecimal, StrToInteger, StrTrim, StrUpcase,
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use t_sort_by::TSortBy;
|
||||
|
|
56
crates/nu-cli/src/commands/str_/collect.rs
Normal file
56
crates/nu-cli/src/commands/str_/collect.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"str collect"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("str collect")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"collects a list of strings into a string"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
_registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let output = args
|
||||
.input
|
||||
.collect_string(args.call_info.name_tag.clone())
|
||||
.await?;
|
||||
|
||||
Ok(OutputStream::one(ReturnSuccess::value(
|
||||
UntaggedValue::string(output.item).into_value(output.tag),
|
||||
)))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Collect a list of string",
|
||||
example: "echo ['a' 'b' 'c'] | str collect",
|
||||
result: Some(vec![Value::from("abc")]),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SubCommand;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod capitalize;
|
||||
mod collect;
|
||||
mod command;
|
||||
mod downcase;
|
||||
mod find_replace;
|
||||
|
@ -11,6 +12,7 @@ mod trim;
|
|||
mod upcase;
|
||||
|
||||
pub use capitalize::SubCommand as StrCapitalize;
|
||||
pub use collect::SubCommand as StrCollect;
|
||||
pub use command::Command as Str;
|
||||
pub use downcase::SubCommand as StrDowncase;
|
||||
pub use find_replace::SubCommand as StrFindReplace;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
use futures::stream::{iter, once};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, UntaggedValue, Value};
|
||||
use nu_protocol::{Primitive, Type, UntaggedValue, Value};
|
||||
use nu_source::{Tagged, TaggedItem};
|
||||
|
||||
pub struct InputStream {
|
||||
|
@ -74,12 +74,18 @@ impl InputStream {
|
|||
value_tag = value_t;
|
||||
bytes.extend_from_slice(&b);
|
||||
}
|
||||
Some(Value { tag: value_tag, .. }) => {
|
||||
Some(Value {
|
||||
tag: value_tag,
|
||||
value,
|
||||
}) => {
|
||||
return Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
tag,
|
||||
"value originates from here",
|
||||
format!(
|
||||
"{} originates from here",
|
||||
Type::from_value(&value).plain_string(100000)
|
||||
),
|
||||
value_tag,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -44,6 +44,14 @@ impl InternalCommand {
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_it_usage(&mut self) {
|
||||
if let Some(positionals) = &mut self.args.positional {
|
||||
for arg in positionals {
|
||||
arg.expand_it_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
|
@ -109,34 +117,8 @@ impl ClassifiedCommand {
|
|||
|
||||
pub fn expand_it_usage(&mut self) {
|
||||
match self {
|
||||
ClassifiedCommand::Internal(command) => {
|
||||
if let Some(positionals) = &mut command.args.positional {
|
||||
for arg in positionals {
|
||||
if let SpannedExpression {
|
||||
expr: Expression::Block(block),
|
||||
..
|
||||
} = arg
|
||||
{
|
||||
block.expand_it_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClassifiedCommand::Expr(expr) => {
|
||||
if let SpannedExpression {
|
||||
expr: Expression::Block(ref block),
|
||||
span,
|
||||
} = **expr
|
||||
{
|
||||
let mut block = block.clone();
|
||||
block.expand_it_usage();
|
||||
*expr = Box::new(SpannedExpression {
|
||||
expr: Expression::Block(block),
|
||||
span,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ClassifiedCommand::Internal(command) => command.expand_it_usage(),
|
||||
ClassifiedCommand::Expr(expr) => expr.expand_it_usage(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -588,6 +570,44 @@ impl SpannedExpression {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_it_usage(&mut self) {
|
||||
match self {
|
||||
SpannedExpression {
|
||||
expr: Expression::Block(block),
|
||||
..
|
||||
} => {
|
||||
block.expand_it_usage();
|
||||
}
|
||||
SpannedExpression {
|
||||
expr: Expression::Invocation(block),
|
||||
..
|
||||
} => {
|
||||
block.expand_it_usage();
|
||||
}
|
||||
SpannedExpression {
|
||||
expr: Expression::List(list),
|
||||
..
|
||||
} => {
|
||||
for item in list.iter_mut() {
|
||||
item.expand_it_usage();
|
||||
}
|
||||
}
|
||||
SpannedExpression {
|
||||
expr: Expression::Path(path),
|
||||
..
|
||||
} => {
|
||||
if let SpannedExpression {
|
||||
expr: Expression::Invocation(block),
|
||||
..
|
||||
} = &mut path.head
|
||||
{
|
||||
block.expand_it_usage();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for SpannedExpression {
|
||||
|
|
|
@ -72,6 +72,18 @@ fn it_expansion_of_list() {
|
|||
assert_eq!(actual.out, "[\"bar\",\"foo\"]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_expansion_of_invocation() {
|
||||
let actual = nu!(
|
||||
cwd: ".",
|
||||
r#"
|
||||
echo $(echo "4" | echo $it | str to-int )
|
||||
"#
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argument_invocation() {
|
||||
let actual = nu!(
|
||||
|
|
Loading…
Reference in a new issue