Another batch of removing async_stream (#1970)

This commit is contained in:
Jonathan Turner 2020-06-12 01:34:41 -07:00 committed by GitHub
parent 731aa6bbdd
commit 935a5f6b9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 217 additions and 204 deletions

View file

@ -45,8 +45,7 @@ impl WholeStreamCommand for Alias {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
// args.process(registry, alias)?.run() alias(args, registry).await
alias(args, registry)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -65,63 +64,78 @@ impl WholeStreamCommand for Alias {
} }
} }
// <<<<<<< HEAD pub async fn alias(
// pub fn alias(alias_args: AliasArgs, ctx: RunnableContext) -> Result<OutputStream, ShellError> { args: CommandArgs,
// ======= registry: &CommandRegistry,
pub fn alias(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let registry = registry.clone(); let registry = registry.clone();
let stream = async_stream! { let mut raw_input = args.raw_input.clone();
let mut raw_input = args.raw_input.clone(); let (
let (AliasArgs { name, args: list, block, save}, ctx) = args.process(&registry).await?; AliasArgs {
let mut processed_args: Vec<String> = vec![]; name,
args: list,
block,
save,
},
_ctx,
) = args.process(&registry).await?;
let mut processed_args: Vec<String> = vec![];
if let Some(true) = save { if let Some(true) = save {
let mut result = crate::data::config::read(name.clone().tag, &None)?; let mut result = crate::data::config::read(name.clone().tag, &None)?;
// process the alias to remove the --save flag // process the alias to remove the --save flag
let left_brace = raw_input.find('{').unwrap_or(0); let left_brace = raw_input.find('{').unwrap_or(0);
let right_brace = raw_input.rfind('}').unwrap_or(raw_input.len()); let right_brace = raw_input.rfind('}').unwrap_or_else(|| raw_input.len());
let mut left = raw_input[..left_brace].replace("--save", "").replace("-s", ""); let left = raw_input[..left_brace]
let mut right = raw_input[right_brace..].replace("--save", "").replace("-s", ""); .replace("--save", "")
raw_input = format!("{}{}{}", left, &raw_input[left_brace..right_brace], right); .replace("-s", "");
let right = raw_input[right_brace..]
.replace("--save", "")
.replace("-s", "");
raw_input = format!("{}{}{}", left, &raw_input[left_brace..right_brace], right);
// create a value from raw_input alias // create a value from raw_input alias
let alias: Value = raw_input.trim().to_string().into(); let alias: Value = raw_input.trim().to_string().into();
let alias_start = raw_input.find("[").unwrap_or(0); // used to check if the same alias already exists let alias_start = raw_input.find('[').unwrap_or(0); // used to check if the same alias already exists
// add to startup if alias doesn't exist and replce if it does // add to startup if alias doesn't exist and replce if it does
match result.get_mut("startup") { match result.get_mut("startup") {
Some(startup) => { Some(startup) => {
if let UntaggedValue::Table(ref mut commands) = startup.value { if let UntaggedValue::Table(ref mut commands) = startup.value {
if let Some(command) = commands.iter_mut().find(|command| { if let Some(command) = commands.iter_mut().find(|command| {
let cmd_str = command.as_string().unwrap_or_default(); let cmd_str = command.as_string().unwrap_or_default();
cmd_str.starts_with(&raw_input[..alias_start]) cmd_str.starts_with(&raw_input[..alias_start])
}) { }) {
*command = alias; *command = alias;
} else { } else {
commands.push(alias); commands.push(alias);
}
} }
} }
None => {
let mut table = UntaggedValue::table(&[alias]);
result.insert("startup".to_string(), table.into_value(Tag::default()));
}
} }
config::write(&result, &None)?; None => {
} let table = UntaggedValue::table(&[alias]);
result.insert("startup".to_string(), table.into_value(Tag::default()));
for item in list.iter() {
if let Ok(string) = item.as_string() {
processed_args.push(format!("${}", string));
} else {
yield Err(ShellError::labeled_error("Expected a string", "expected a string", item.tag()));
} }
} }
yield ReturnSuccess::action(CommandAction::AddAlias(name.to_string(), processed_args, block.clone())) config::write(&result, &None)?;
}; }
Ok(stream.to_output_stream()) for item in list.iter() {
if let Ok(string) = item.as_string() {
processed_args.push(format!("${}", string));
} else {
return Err(ShellError::labeled_error(
"Expected a string",
"expected a string",
item.tag(),
));
}
}
Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::AddAlias(name.to_string(), processed_args, block),
)))
} }
#[cfg(test)] #[cfg(test)]

View file

@ -4,9 +4,7 @@ use crate::utils::data_processing::{reducer_for, Reduce};
use bigdecimal::FromPrimitive; use bigdecimal::FromPrimitive;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::hir::{convert_number_to_u64, Number, Operator}; use nu_protocol::hir::{convert_number_to_u64, Number, Operator};
use nu_protocol::{ use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
Dictionary, Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value,
};
use num_traits::identities::Zero; use num_traits::identities::Zero;
use indexmap::map::IndexMap; use indexmap::map::IndexMap;
@ -42,6 +40,7 @@ impl WholeStreamCommand for Average {
name: args.call_info.name_tag, name: args.call_info.name_tag,
raw_input: args.raw_input, raw_input: args.raw_input,
}) })
.await
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -53,53 +52,48 @@ impl WholeStreamCommand for Average {
} }
} }
fn average( async fn average(
RunnableContext { RunnableContext {
mut input, name, .. mut input, name, ..
}: RunnableContext, }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let stream = async_stream! { let values: Vec<Value> = input.drain_vec().await;
let mut values: Vec<Value> = input.drain_vec().await;
let action = reducer_for(Reduce::Sum);
if values.iter().all(|v| if let UntaggedValue::Primitive(_) = v.value {true} else {false}) { if values.iter().all(|v| v.is_primitive()) {
match avg(&values, name) { match avg(&values, name) {
Ok(result) => yield ReturnSuccess::value(result), Ok(result) => Ok(OutputStream::one(ReturnSuccess::value(result))),
Err(err) => yield Err(err), Err(err) => Err(err),
} }
} else { } else {
let mut column_values = IndexMap::new(); let mut column_values = IndexMap::new();
for value in values { for value in values {
match value.value { if let UntaggedValue::Row(row_dict) = value.value {
UntaggedValue::Row(row_dict) => { for (key, value) in row_dict.entries.iter() {
for (key, value) in row_dict.entries.iter() { column_values
column_values .entry(key.clone())
.entry(key.clone()) .and_modify(|v: &mut Vec<Value>| v.push(value.clone()))
.and_modify(|v: &mut Vec<Value>| v.push(value.clone())) .or_insert(vec![value.clone()]);
.or_insert(vec![value.clone()]);
}
},
table => {},
};
}
let mut column_totals = IndexMap::new();
for (col_name, col_vals) in column_values {
match avg(&col_vals, &name) {
Ok(result) => {
column_totals.insert(col_name, result);
}
Err(err) => yield Err(err),
} }
} }
yield ReturnSuccess::value(
UntaggedValue::Row(Dictionary {entries: column_totals}).into_untagged_value())
} }
};
let stream: BoxStream<'static, ReturnValue> = stream.boxed(); let mut column_totals = IndexMap::new();
for (col_name, col_vals) in column_values {
match avg(&col_vals, &name) {
Ok(result) => {
column_totals.insert(col_name, result);
}
Err(err) => return Err(err),
}
}
Ok(stream.to_output_stream()) Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(Dictionary {
entries: column_totals,
})
.into_untagged_value(),
)))
}
} }
fn avg(values: &[Value], name: impl Into<Tag>) -> Result<Value, ShellError> { fn avg(values: &[Value], name: impl Into<Tag>) -> Result<Value, ShellError> {

View file

@ -54,7 +54,7 @@ documentation link at https://docs.rs/encoding_rs/0.8.23/encoding_rs/#statics"#
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
enter(args, registry) enter(args, registry).await
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -78,121 +78,122 @@ documentation link at https://docs.rs/encoding_rs/0.8.23/encoding_rs/#statics"#
} }
} }
fn enter(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { async fn enter(
raw_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone(); let registry = registry.clone();
let stream = async_stream! { let scope = raw_args.call_info.scope.clone();
let scope = raw_args.call_info.scope.clone(); let shell_manager = raw_args.shell_manager.clone();
let shell_manager = raw_args.shell_manager.clone(); let head = raw_args.call_info.args.head.clone();
let head = raw_args.call_info.args.head.clone(); let ctrl_c = raw_args.ctrl_c.clone();
let ctrl_c = raw_args.ctrl_c.clone(); let current_errors = raw_args.current_errors.clone();
let current_errors = raw_args.current_errors.clone(); let host = raw_args.host.clone();
let host = raw_args.host.clone(); let tag = raw_args.call_info.name_tag.clone();
let tag = raw_args.call_info.name_tag.clone(); let (EnterArgs { location, encoding }, _) = raw_args.process(&registry).await?;
let (EnterArgs { location, encoding }, _) = raw_args.process(&registry).await?; let location_string = location.display().to_string();
let location_string = location.display().to_string(); let location_clone = location_string.clone();
let location_clone = location_string.clone();
if location_string.starts_with("help") { if location_string.starts_with("help") {
let spec = location_string.split(':').collect::<Vec<&str>>(); let spec = location_string.split(':').collect::<Vec<&str>>();
if spec.len() == 2 { if spec.len() == 2 {
let (_, command) = (spec[0], spec[1]); let (_, command) = (spec[0], spec[1]);
if registry.has(command) { if registry.has(command) {
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( return Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterHelpShell(
UntaggedValue::string(command).into_value(Tag::unknown()), UntaggedValue::string(command).into_value(Tag::unknown()),
))); ),
return; )));
}
}
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
UntaggedValue::nothing().into_value(Tag::unknown()),
)));
} else if location.is_dir() {
yield Ok(ReturnSuccess::Action(CommandAction::EnterShell(
location_clone,
)));
} else {
// If it's a file, attempt to open the file as a value and enter it
let cwd = shell_manager.path();
let full_path = std::path::PathBuf::from(cwd);
let (file_extension, contents, contents_tag) =
crate::commands::open::fetch(
&full_path,
&PathBuf::from(location_clone),
tag.span,
match encoding {
Some(e) => e.to_string(),
_ => "".to_string()
}
).await?;
match contents {
UntaggedValue::Primitive(Primitive::String(_)) => {
let tagged_contents = contents.into_value(&contents_tag);
if let Some(extension) = file_extension {
let command_name = format!("from {}", extension);
if let Some(converter) =
registry.get_command(&command_name)
{
let new_args = RawCommandArgs {
host,
ctrl_c,
current_errors,
shell_manager,
call_info: UnevaluatedCallInfo {
args: nu_protocol::hir::Call {
head,
positional: None,
named: None,
span: Span::unknown(),
is_last: false,
},
name_tag: tag.clone(),
scope: scope.clone()
},
};
let mut result = converter.run(
new_args.with_input(vec![tagged_contents]),
&registry,
).await;
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
for res in result_vec {
match res {
Ok(ReturnSuccess::Value(Value {
value,
..
})) => {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
Value {
value,
tag: contents_tag.clone(),
})));
}
x => yield x,
}
}
} else {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
}
} else {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
}
}
_ => {
let tagged_contents = contents.into_value(contents_tag);
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
}
} }
} }
}; Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterHelpShell(UntaggedValue::nothing().into_value(Tag::unknown())),
)))
} else if location.is_dir() {
Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterShell(location_clone),
)))
} else {
// If it's a file, attempt to open the file as a value and enter it
let cwd = shell_manager.path();
Ok(stream.to_output_stream()) let full_path = std::path::PathBuf::from(cwd);
let (file_extension, contents, contents_tag) = crate::commands::open::fetch(
&full_path,
&PathBuf::from(location_clone),
tag.span,
match encoding {
Some(e) => e.to_string(),
_ => "".to_string(),
},
)
.await?;
match contents {
UntaggedValue::Primitive(Primitive::String(_)) => {
let tagged_contents = contents.into_value(&contents_tag);
if let Some(extension) = file_extension {
let command_name = format!("from {}", extension);
if let Some(converter) = registry.get_command(&command_name) {
let new_args = RawCommandArgs {
host,
ctrl_c,
current_errors,
shell_manager,
call_info: UnevaluatedCallInfo {
args: nu_protocol::hir::Call {
head,
positional: None,
named: None,
span: Span::unknown(),
is_last: false,
},
name_tag: tag.clone(),
scope: scope.clone(),
},
};
let mut result = converter
.run(new_args.with_input(vec![tagged_contents]), &registry)
.await;
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
Ok(futures::stream::iter(result_vec.into_iter().map(
move |res| match res {
Ok(ReturnSuccess::Value(Value { value, .. })) => Ok(
ReturnSuccess::Action(CommandAction::EnterValueShell(Value {
value,
tag: contents_tag.clone(),
})),
),
x => x,
},
))
.to_output_stream())
} else {
Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterValueShell(tagged_contents),
)))
}
} else {
Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterValueShell(tagged_contents),
)))
}
}
_ => {
let tagged_contents = contents.into_value(contents_tag);
Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterValueShell(tagged_contents),
)))
}
}
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -25,14 +25,10 @@ impl WholeStreamCommand for From {
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let registry = registry.clone(); let registry = registry.clone();
let stream = async_stream! { Ok(OutputStream::one(ReturnSuccess::value(
yield Ok(ReturnSuccess::Value( UntaggedValue::string(crate::commands::help::get_help(&From, &registry))
UntaggedValue::string(crate::commands::help::get_help(&From, &registry)) .into_value(Tag::unknown()),
.into_value(Tag::unknown()), )))
));
};
Ok(stream.to_output_stream())
} }
} }

View file

@ -339,6 +339,14 @@ impl Value {
} }
} }
/// View the Value as a Primitive value, if possible
pub fn is_primitive(&self) -> bool {
match &self.value {
UntaggedValue::Primitive(_) => true,
_ => false,
}
}
/// View the Value as unsigned 64-bit, if possible /// View the Value as unsigned 64-bit, if possible
pub fn as_u64(&self) -> Result<u64, ShellError> { pub fn as_u64(&self) -> Result<u64, ShellError> {
match &self.value { match &self.value {