forked from extern/nushell
Removing async_stream! from some commands (#1940)
* Removing async_stream! from some commands * Revert row.rs code * Simplify logic for first.rs and skip.rs
This commit is contained in:
parent
2a8ea88413
commit
ba6370621f
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct First;
|
pub struct First;
|
||||||
@ -35,7 +35,7 @@ impl WholeStreamCommand for First {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
first(args, registry)
|
first(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -57,27 +57,16 @@ impl WholeStreamCommand for First {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let (FirstArgs { rows }, input) = args.process(®istry).await?;
|
||||||
let (FirstArgs { rows }, mut input) = args.process(®istry).await?;
|
let rows_desired = if let Some(quantity) = rows {
|
||||||
let mut rows_desired = if let Some(quantity) = rows {
|
*quantity
|
||||||
*quantity
|
} else {
|
||||||
} else {
|
1
|
||||||
1
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(input) = input.next().await {
|
|
||||||
if rows_desired > 0 {
|
|
||||||
yield ReturnSuccess::value(input);
|
|
||||||
rows_desired -= 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(input.take(rows_desired).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -27,7 +27,7 @@ impl WholeStreamCommand for FromBSON {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_bson(args, registry)
|
from_bson(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -208,30 +208,27 @@ pub fn from_bson_bytes_to_value(bytes: Vec<u8>, tag: impl Into<Tag>) -> Result<V
|
|||||||
convert_bson_value_to_nu_value(&Bson::Array(docs), tag)
|
convert_bson_value_to_nu_value(&Bson::Array(docs), tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_bson(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let bytes = input.collect_binary(tag.clone()).await?;
|
let bytes = input.collect_binary(tag.clone()).await?;
|
||||||
|
|
||||||
match from_bson_bytes_to_value(bytes.item, tag.clone()) {
|
match from_bson_bytes_to_value(bytes.item, tag.clone()) {
|
||||||
Ok(x) => yield ReturnSuccess::value(x),
|
Ok(x) => Ok(OutputStream::one(ReturnSuccess::value(x))),
|
||||||
Err(_) => {
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
"Could not parse as BSON",
|
||||||
"Could not parse as BSON",
|
"input cannot be parsed as BSON",
|
||||||
"input cannot be parsed as BSON",
|
tag.clone(),
|
||||||
tag.clone(),
|
"value originates from here",
|
||||||
"value originates from here",
|
bytes.tag,
|
||||||
bytes.tag,
|
)),
|
||||||
))
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -42,7 +42,7 @@ impl WholeStreamCommand for FromCSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_csv(args, registry)
|
from_csv(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -66,43 +66,44 @@ impl WholeStreamCommand for FromCSV {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_csv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_csv(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
|
||||||
let (FromCSVArgs { headerless, separator }, mut input) = args.process(®istry).await?;
|
let (
|
||||||
let sep = match separator {
|
FromCSVArgs {
|
||||||
Some(Value {
|
headerless,
|
||||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
separator,
|
||||||
tag,
|
},
|
||||||
..
|
input,
|
||||||
}) => {
|
) = args.process(®istry).await?;
|
||||||
if s == r"\t" {
|
let sep = match separator {
|
||||||
'\t'
|
Some(Value {
|
||||||
} else {
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
let vec_s: Vec<char> = s.chars().collect();
|
tag,
|
||||||
if vec_s.len() != 1 {
|
..
|
||||||
yield Err(ShellError::labeled_error(
|
}) => {
|
||||||
"Expected a single separator char from --separator",
|
if s == r"\t" {
|
||||||
"requires a single character string input",
|
'\t'
|
||||||
tag,
|
} else {
|
||||||
));
|
let vec_s: Vec<char> = s.chars().collect();
|
||||||
return;
|
if vec_s.len() != 1 {
|
||||||
};
|
return Err(ShellError::labeled_error(
|
||||||
vec_s[0]
|
"Expected a single separator char from --separator",
|
||||||
}
|
"requires a single character string input",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
vec_s[0]
|
||||||
}
|
}
|
||||||
_ => ',',
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = from_delimited_data(headerless, sep, "CSV", input, name)?;
|
|
||||||
while let Some(item) = result.next().await {
|
|
||||||
yield item;
|
|
||||||
}
|
}
|
||||||
|
_ => ',',
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
from_delimited_data(headerless, sep, "CSV", input, name).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use csv::{ErrorKind, ReaderBuilder};
|
use csv::{ErrorKind, ReaderBuilder};
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
|
||||||
|
|
||||||
fn from_delimited_string_to_value(
|
fn from_delimited_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
@ -41,7 +41,7 @@ fn from_delimited_string_to_value(
|
|||||||
Ok(UntaggedValue::Table(rows).into_value(&tag))
|
Ok(UntaggedValue::Table(rows).into_value(&tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_delimited_data(
|
pub async fn from_delimited_data(
|
||||||
headerless: bool,
|
headerless: bool,
|
||||||
sep: char,
|
sep: char,
|
||||||
format_name: &'static str,
|
format_name: &'static str,
|
||||||
@ -49,37 +49,32 @@ pub fn from_delimited_data(
|
|||||||
name: Tag,
|
name: Tag,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_tag = name;
|
let name_tag = name;
|
||||||
|
let concat_string = input.collect_string(name_tag.clone()).await?;
|
||||||
|
|
||||||
let stream = async_stream! {
|
match from_delimited_string_to_value(concat_string.item, headerless, sep, name_tag.clone()) {
|
||||||
let concat_string = input.collect_string(name_tag.clone()).await?;
|
Ok(x) => match x {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Table(list),
|
||||||
|
..
|
||||||
|
} => Ok(futures::stream::iter(list).to_output_stream()),
|
||||||
|
x => Ok(OutputStream::one(x)),
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
let line_one = match pretty_csv_error(err) {
|
||||||
|
Some(pretty) => format!("Could not parse as {} ({})", format_name, pretty),
|
||||||
|
None => format!("Could not parse as {}", format_name),
|
||||||
|
};
|
||||||
|
let line_two = format!("input cannot be parsed as {}", format_name);
|
||||||
|
|
||||||
match from_delimited_string_to_value(concat_string.item, headerless, sep, name_tag.clone()) {
|
Err(ShellError::labeled_error_with_secondary(
|
||||||
Ok(x) => match x {
|
line_one,
|
||||||
Value { value: UntaggedValue::Table(list), .. } => {
|
line_two,
|
||||||
for l in list {
|
name_tag.clone(),
|
||||||
yield ReturnSuccess::value(l);
|
"value originates from here",
|
||||||
}
|
concat_string.tag,
|
||||||
}
|
))
|
||||||
x => yield ReturnSuccess::value(x),
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let line_one = match pretty_csv_error(err) {
|
|
||||||
Some(pretty) => format!("Could not parse as {} ({})", format_name,pretty),
|
|
||||||
None => format!("Could not parse as {}", format_name),
|
|
||||||
};
|
|
||||||
let line_two = format!("input cannot be parsed as {}", format_name);
|
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
|
||||||
line_one,
|
|
||||||
line_two,
|
|
||||||
name_tag.clone(),
|
|
||||||
"value originates from here",
|
|
||||||
concat_string.tag,
|
|
||||||
))
|
|
||||||
} ,
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pretty_csv_error(err: csv::Error) -> Option<String> {
|
fn pretty_csv_error(err: csv::Error) -> Option<String> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct FromINI;
|
pub struct FromINI;
|
||||||
@ -25,7 +25,7 @@ impl WholeStreamCommand for FromINI {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_ini(args, registry)
|
from_ini(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,36 +64,32 @@ pub fn from_ini_string_to_value(
|
|||||||
Ok(convert_ini_top_to_nu_value(&v, tag))
|
Ok(convert_ini_top_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_ini(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
|
||||||
|
|
||||||
match from_ini_string_to_value(concat_string.item, tag.clone()) {
|
match from_ini_string_to_value(concat_string.item, tag.clone()) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Value { value: UntaggedValue::Table(list), .. } => {
|
Value {
|
||||||
for l in list {
|
value: UntaggedValue::Table(list),
|
||||||
yield ReturnSuccess::value(l);
|
..
|
||||||
}
|
} => Ok(futures::stream::iter(list).to_output_stream()),
|
||||||
}
|
x => Ok(OutputStream::one(x)),
|
||||||
x => yield ReturnSuccess::value(x),
|
},
|
||||||
},
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
Err(_) => {
|
"Could not parse as INI",
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
"input cannot be parsed as INI",
|
||||||
"Could not parse as INI",
|
&tag,
|
||||||
"input cannot be parsed as INI",
|
"value originates from here",
|
||||||
&tag,
|
concat_string.tag,
|
||||||
"value originates from here",
|
)),
|
||||||
concat_string.tag,
|
}
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||||
use rusqlite::{types::ValueRef, Connection, Row, NO_PARAMS};
|
use rusqlite::{types::ValueRef, Connection, Row, NO_PARAMS};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -27,7 +27,7 @@ impl WholeStreamCommand for FromSQLite {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_sqlite(args, registry)
|
from_sqlite(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ impl WholeStreamCommand for FromDB {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_sqlite(args, registry)
|
from_sqlite(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +65,7 @@ pub fn convert_sqlite_file_to_nu_value(
|
|||||||
let mut meta_out = Vec::new();
|
let mut meta_out = Vec::new();
|
||||||
let mut meta_stmt = conn.prepare("select name from sqlite_master where type='table'")?;
|
let mut meta_stmt = conn.prepare("select name from sqlite_master where type='table'")?;
|
||||||
let mut meta_rows = meta_stmt.query(NO_PARAMS)?;
|
let mut meta_rows = meta_stmt.query(NO_PARAMS)?;
|
||||||
|
|
||||||
while let Some(meta_row) = meta_rows.next()? {
|
while let Some(meta_row) = meta_rows.next()? {
|
||||||
let table_name: String = meta_row.get(0)?;
|
let table_name: String = meta_row.get(0)?;
|
||||||
let mut meta_dict = TaggedDictBuilder::new(tag.clone());
|
let mut meta_dict = TaggedDictBuilder::new(tag.clone());
|
||||||
@ -134,37 +135,37 @@ pub fn from_sqlite_bytes_to_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_sqlite(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let bytes = input.collect_binary(tag.clone()).await?;
|
let bytes = input.collect_binary(tag.clone()).await?;
|
||||||
match from_sqlite_bytes_to_value(bytes.item, tag.clone()) {
|
|
||||||
Ok(x) => match x {
|
match from_sqlite_bytes_to_value(bytes.item, tag.clone()) {
|
||||||
Value { value: UntaggedValue::Table(list), .. } => {
|
Ok(x) => match x {
|
||||||
for l in list {
|
Value {
|
||||||
yield ReturnSuccess::value(l);
|
value: UntaggedValue::Table(list),
|
||||||
}
|
..
|
||||||
}
|
} => Ok(futures::stream::iter(list).to_output_stream()),
|
||||||
_ => yield ReturnSuccess::value(x),
|
_ => Ok(OutputStream::one(x)),
|
||||||
}
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("{:?}", err);
|
println!("{:?}", err);
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
|
||||||
"Could not parse as SQLite",
|
Err(ShellError::labeled_error_with_secondary(
|
||||||
"input cannot be parsed as SQLite",
|
"Could not parse as SQLite",
|
||||||
&tag,
|
"input cannot be parsed as SQLite",
|
||||||
"value originates from here",
|
&tag,
|
||||||
bytes.tag,
|
"value originates from here",
|
||||||
))
|
bytes.tag,
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -34,23 +34,19 @@ impl WholeStreamCommand for FromTSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_tsv(args, registry)
|
from_tsv(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_tsv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_tsv(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let (FromTSVArgs { headerless }, input) = args.process(®istry).await?;
|
||||||
let (FromTSVArgs { headerless }, mut input) = args.process(®istry).await?;
|
|
||||||
let mut result = from_delimited_data(headerless, '\t', "TSV", input, name)?;
|
|
||||||
|
|
||||||
while let Some(output) = result.next().await {
|
from_delimited_data(headerless, '\t', "TSV", input, name).await
|
||||||
yield output;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -24,44 +24,41 @@ impl WholeStreamCommand for FromURL {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_url(args, registry)
|
from_url(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_url(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item);
|
let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
let mut row = TaggedDictBuilder::new(tag);
|
let mut row = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
for (k,v) in result {
|
for (k, v) in result {
|
||||||
row.insert_untagged(k, UntaggedValue::string(v));
|
row.insert_untagged(k, UntaggedValue::string(v));
|
||||||
}
|
|
||||||
|
|
||||||
yield ReturnSuccess::value(row.into_value());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
|
||||||
"String not compatible with url-encoding",
|
|
||||||
"input not url-encoded",
|
|
||||||
tag,
|
|
||||||
"value originates from here",
|
|
||||||
concat_string.tag,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(OutputStream::one(ReturnSuccess::value(row.into_value())))
|
||||||
}
|
}
|
||||||
};
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"String not compatible with url-encoding",
|
||||||
Ok(stream.to_output_stream())
|
"input not url-encoded",
|
||||||
|
tag,
|
||||||
|
"value originates from here",
|
||||||
|
concat_string.tag,
|
||||||
|
)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -28,35 +28,42 @@ impl WholeStreamCommand for FromVcf {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_vcf(args, registry)
|
from_vcf(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_vcf(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_vcf(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let input_string = input.collect_string(tag.clone()).await?.item;
|
let input_string = input.collect_string(tag.clone()).await?.item;
|
||||||
let input_bytes = input_string.as_bytes();
|
let input_bytes = input_string.as_bytes();
|
||||||
let buf_reader = BufReader::new(input_bytes);
|
let buf_reader = BufReader::new(input_bytes);
|
||||||
let parser = ical::VcardParser::new(buf_reader);
|
let parser = ical::VcardParser::new(buf_reader);
|
||||||
|
|
||||||
for contact in parser {
|
let mut values_vec_deque = VecDeque::new();
|
||||||
match contact {
|
|
||||||
Ok(c) => yield ReturnSuccess::value(contact_to_value(c, tag.clone())),
|
for contact in parser {
|
||||||
Err(_) => yield Err(ShellError::labeled_error(
|
match contact {
|
||||||
|
Ok(c) => {
|
||||||
|
values_vec_deque.push_back(ReturnSuccess::value(contact_to_value(c, tag.clone())))
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
"Could not parse as .vcf",
|
"Could not parse as .vcf",
|
||||||
"input cannot be parsed as .vcf",
|
"input cannot be parsed as .vcf",
|
||||||
tag.clone()
|
tag.clone(),
|
||||||
)),
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(futures::stream::iter(values_vec_deque).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contact_to_value(contact: VcardContact, tag: Tag) -> Value {
|
fn contact_to_value(contact: VcardContact, tag: Tag) -> Value {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct FromYAML;
|
pub struct FromYAML;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ impl WholeStreamCommand for FromYAML {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_yaml(args, registry)
|
from_yaml(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ impl WholeStreamCommand for FromYML {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
from_yaml(args, registry)
|
from_yaml(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,37 +120,33 @@ pub fn from_yaml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value
|
|||||||
Ok(convert_yaml_value_to_nu_value(&v, tag)?)
|
Ok(convert_yaml_value_to_nu_value(&v, tag)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn from_yaml(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let args = args.evaluate_once(®istry).await?;
|
||||||
let args = args.evaluate_once(®istry).await?;
|
let tag = args.name_tag();
|
||||||
let tag = args.name_tag();
|
let input = args.input;
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
match from_yaml_string_to_value(concat_string.item, tag.clone()) {
|
match from_yaml_string_to_value(concat_string.item, tag.clone()) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Value { value: UntaggedValue::Table(list), .. } => {
|
Value {
|
||||||
for l in list {
|
value: UntaggedValue::Table(list),
|
||||||
yield ReturnSuccess::value(l);
|
..
|
||||||
}
|
} => Ok(futures::stream::iter(list).to_output_stream()),
|
||||||
}
|
x => Ok(OutputStream::one(x)),
|
||||||
x => yield ReturnSuccess::value(x),
|
},
|
||||||
},
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
Err(_) => {
|
"Could not parse as YAML",
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
"input cannot be parsed as YAML",
|
||||||
"Could not parse as YAML",
|
&tag,
|
||||||
"input cannot be parsed as YAML",
|
"value originates from here",
|
||||||
&tag,
|
&concat_string.tag,
|
||||||
"value originates from here",
|
)),
|
||||||
&concat_string.tag,
|
}
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -35,7 +35,7 @@ impl WholeStreamCommand for Last {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
last(args, registry)
|
last(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -58,28 +58,30 @@ impl WholeStreamCommand for Last {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let (LastArgs { rows }, input) = args.process(®istry).await?;
|
||||||
let (LastArgs { rows }, mut input) = args.process(®istry).await?;
|
let v: Vec<_> = input.into_vec().await;
|
||||||
let v: Vec<_> = input.into_vec().await;
|
|
||||||
|
|
||||||
let rows_desired = if let Some(quantity) = rows {
|
let rows_desired = if let Some(quantity) = rows {
|
||||||
*quantity
|
*quantity
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
};
|
|
||||||
|
|
||||||
let count = (rows_desired as usize);
|
|
||||||
if count < v.len() {
|
|
||||||
let k = v.len() - count;
|
|
||||||
for x in v[k..].iter() {
|
|
||||||
let y: Value = x.clone();
|
|
||||||
yield ReturnSuccess::value(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
|
let mut values_vec_deque = VecDeque::new();
|
||||||
|
|
||||||
|
let count = rows_desired as usize;
|
||||||
|
|
||||||
|
if count < v.len() {
|
||||||
|
let k = v.len() - count;
|
||||||
|
|
||||||
|
for x in v[k..].iter() {
|
||||||
|
values_vec_deque.push_back(ReturnSuccess::value(x.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(futures::stream::iter(values_vec_deque).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -24,7 +24,7 @@ impl WholeStreamCommand for Pwd {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
pwd(args, registry)
|
pwd(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -36,20 +36,15 @@ impl WholeStreamCommand for Pwd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub async fn pwd(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let stream = async_stream! {
|
shell_manager.pwd(args)
|
||||||
let shell_manager = args.shell_manager.clone();
|
|
||||||
let args = args.evaluate_once(®istry).await?;
|
|
||||||
let mut out = shell_manager.pwd(args)?;
|
|
||||||
|
|
||||||
while let Some(l) = out.next().await {
|
|
||||||
yield l;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -37,42 +37,37 @@ impl WholeStreamCommand for ReduceBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
reduce_by(args, registry)
|
reduce_by(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce_by(
|
pub async fn reduce_by(
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let (ReduceByArgs { reduce_with }, mut input) = args.process(®istry).await?;
|
||||||
let (ReduceByArgs { reduce_with }, mut input) = args.process(®istry).await?;
|
let values: Vec<Value> = input.collect().await;
|
||||||
let values: Vec<Value> = input.collect().await;
|
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
yield Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected table from pipeline",
|
"Expected table from pipeline",
|
||||||
"requires a table input",
|
"requires a table input",
|
||||||
name
|
name,
|
||||||
))
|
));
|
||||||
} else {
|
}
|
||||||
|
|
||||||
let reduce_with = if let Some(reducer) = reduce_with {
|
let reduce_with = if let Some(reducer) = reduce_with {
|
||||||
Some(reducer.item().clone())
|
Some(reducer.item().clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
|
||||||
|
|
||||||
match reduce(&values[0], reduce_with, name) {
|
|
||||||
Ok(reduced) => yield ReturnSuccess::value(reduced),
|
|
||||||
Err(err) => yield Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
match reduce(&values[0], reduce_with, name) {
|
||||||
|
Ok(reduced) => Ok(OutputStream::one(ReturnSuccess::value(reduced))),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Skip;
|
pub struct Skip;
|
||||||
@ -31,7 +31,7 @@ impl WholeStreamCommand for Skip {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
skip(args, registry)
|
skip(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -46,27 +46,16 @@ impl WholeStreamCommand for Skip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn skip(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let (SkipArgs { rows }, input) = args.process(®istry).await?;
|
||||||
let (SkipArgs { rows }, mut input) = args.process(®istry).await?;
|
let rows_desired = if let Some(quantity) = rows {
|
||||||
let mut rows_desired = if let Some(quantity) = rows {
|
*quantity
|
||||||
*quantity
|
} else {
|
||||||
} else {
|
1
|
||||||
1
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(input) = input.next().await {
|
|
||||||
if rows_desired == 0 {
|
|
||||||
yield ReturnSuccess::value(input);
|
|
||||||
}
|
|
||||||
if rows_desired > 0{
|
|
||||||
rows_desired -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(input.skip(rows_desired).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user