Switch to "engine-p" (#3270)

* WIP

* WIP

* first builds

* Tests pass
This commit is contained in:
Jonathan Turner 2021-04-07 04:19:43 +12:00 committed by GitHub
parent ad1c4f5e39
commit 073e5727c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
262 changed files with 2269 additions and 2660 deletions

4
Cargo.lock generated
View file

@ -3241,8 +3241,6 @@ version = "0.29.1"
dependencies = [ dependencies = [
"Inflector", "Inflector",
"arboard", "arboard",
"async-recursion",
"async-trait",
"base64 0.13.0", "base64 0.13.0",
"bigdecimal", "bigdecimal",
"byte-unit", "byte-unit",
@ -3265,8 +3263,6 @@ dependencies = [
"filesize", "filesize",
"fs_extra", "fs_extra",
"futures 0.3.13", "futures 0.3.13",
"futures-util",
"futures_codec",
"getset", "getset",
"glob", "glob",
"hamcrest2", "hamcrest2",

View file

@ -123,13 +123,13 @@ pub fn search_paths() -> Vec<std::path::PathBuf> {
search_paths search_paths
} }
pub async fn run_script_file(options: Options) -> Result<(), Box<dyn Error>> { pub fn run_script_file(options: Options) -> Result<(), Box<dyn Error>> {
let context = create_default_context(false)?; let context = create_default_context(false)?;
if let Some(cfg) = options.config { if let Some(cfg) = options.config {
load_cfg_as_global_cfg(&context, PathBuf::from(cfg)).await; load_cfg_as_global_cfg(&context, PathBuf::from(cfg));
} else { } else {
load_global_cfg(&context).await; load_global_cfg(&context);
} }
let _ = register_plugins(&context); let _ = register_plugins(&context);
@ -140,22 +140,22 @@ pub async fn run_script_file(options: Options) -> Result<(), Box<dyn Error>> {
.get(0) .get(0)
.ok_or_else(|| ShellError::unexpected("Nu source code not available"))?; .ok_or_else(|| ShellError::unexpected("Nu source code not available"))?;
run_script_standalone(script.get_code().to_string(), options.stdin, &context, true).await?; run_script_standalone(script.get_code().to_string(), options.stdin, &context, true)?;
Ok(()) Ok(())
} }
#[cfg(feature = "rustyline-support")] #[cfg(feature = "rustyline-support")]
pub async fn cli(context: EvaluationContext, options: Options) -> Result<(), Box<dyn Error>> { pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box<dyn Error>> {
let _ = configure_ctrl_c(&context); let _ = configure_ctrl_c(&context);
// start time for running startup scripts (this metric includes loading of the cfg, but w/e) // start time for running startup scripts (this metric includes loading of the cfg, but w/e)
let startup_commands_start_time = std::time::Instant::now(); let startup_commands_start_time = std::time::Instant::now();
if let Some(cfg) = options.config { if let Some(cfg) = options.config {
load_cfg_as_global_cfg(&context, PathBuf::from(cfg)).await; load_cfg_as_global_cfg(&context, PathBuf::from(cfg));
} else { } else {
load_global_cfg(&context).await; load_global_cfg(&context);
} }
// Store cmd duration in an env var // Store cmd duration in an env var
context.scope.add_env_var( context.scope.add_env_var(
@ -196,7 +196,7 @@ pub async fn cli(context: EvaluationContext, options: Options) -> Result<(), Box
}; };
//Check whether dir we start in contains local cfg file and if so load it. //Check whether dir we start in contains local cfg file and if so load it.
load_local_cfg_if_present(&context).await; load_local_cfg_if_present(&context);
// Give ourselves a scope to work in // Give ourselves a scope to work in
context.scope.enter_scope(); context.scope.enter_scope();
@ -240,11 +240,11 @@ pub async fn cli(context: EvaluationContext, options: Options) -> Result<(), Box
format!("\x1b[32m{}{}\x1b[m> ", cwd, current_branch()) format!("\x1b[32m{}{}\x1b[m> ", cwd, current_branch())
} else { } else {
let run_result = run_block(&prompt_block, &context, InputStream::empty()).await; let run_result = run_block(&prompt_block, &context, InputStream::empty());
context.scope.exit_scope(); context.scope.exit_scope();
match run_result { match run_result {
Ok(result) => match result.collect_string(Tag::unknown()).await { Ok(result) => match result.collect_string(Tag::unknown()) {
Ok(string_result) => { Ok(string_result) => {
let errors = context.get_errors(); let errors = context.get_errors();
maybe_print_errors(&context, Text::from(prompt_line)); maybe_print_errors(&context, Text::from(prompt_line));
@ -302,16 +302,13 @@ pub async fn cli(context: EvaluationContext, options: Options) -> Result<(), Box
let cmd_start_time = std::time::Instant::now(); let cmd_start_time = std::time::Instant::now();
let line = match convert_rustyline_result_to_string(readline) { let line = match convert_rustyline_result_to_string(readline) {
LineResult::Success(_) => { LineResult::Success(_) => process_script(
process_script( &session_text[line_start..],
&session_text[line_start..], &context,
&context, false,
false, line_start,
line_start, true,
true, ),
)
.await
}
x => x, x => x,
}; };
@ -404,11 +401,11 @@ pub async fn cli(context: EvaluationContext, options: Options) -> Result<(), Box
Ok(()) Ok(())
} }
pub async fn load_local_cfg_if_present(context: &EvaluationContext) { pub fn load_local_cfg_if_present(context: &EvaluationContext) {
trace!("Loading local cfg if present"); trace!("Loading local cfg if present");
match config::loadable_cfg_exists_in_dir(PathBuf::from(context.shell_manager.path())) { match config::loadable_cfg_exists_in_dir(PathBuf::from(context.shell_manager.path())) {
Ok(Some(cfg_path)) => { Ok(Some(cfg_path)) => {
if let Err(err) = context.load_config(&ConfigPath::Local(cfg_path)).await { if let Err(err) = context.load_config(&ConfigPath::Local(cfg_path)) {
context.host.lock().print_err(err, &Text::from("")) context.host.lock().print_err(err, &Text::from(""))
} }
} }
@ -422,8 +419,8 @@ pub async fn load_local_cfg_if_present(context: &EvaluationContext) {
} }
} }
async fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) { fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) {
if let Err(err) = context.load_config(&ConfigPath::Global(path.clone())).await { if let Err(err) = context.load_config(&ConfigPath::Global(path.clone())) {
context.host.lock().print_err(err, &Text::from("")); context.host.lock().print_err(err, &Text::from(""));
} else { } else {
//TODO current commands assume to find path to global cfg file under config-path //TODO current commands assume to find path to global cfg file under config-path
@ -435,10 +432,10 @@ async fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) {
} }
} }
pub async fn load_global_cfg(context: &EvaluationContext) { pub fn load_global_cfg(context: &EvaluationContext) {
match config::default_path() { match config::default_path() {
Ok(path) => { Ok(path) => {
load_cfg_as_global_cfg(context, path).await; load_cfg_as_global_cfg(context, path);
} }
Err(e) => { Err(e) => {
context.host.lock().print_err(e, &Text::from("")); context.host.lock().print_err(e, &Text::from(""));
@ -459,7 +456,7 @@ pub fn register_plugins(context: &EvaluationContext) -> Result<(), ShellError> {
Ok(()) Ok(())
} }
pub async fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<String, ShellError> { pub fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<String, ShellError> {
// FIXME: do we still need this? // FIXME: do we still need this?
let line = if let Some(s) = line.strip_suffix('\n') { let line = if let Some(s) = line.strip_suffix('\n') {
s s
@ -477,10 +474,10 @@ pub async fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<Strin
let input_stream = InputStream::empty(); let input_stream = InputStream::empty();
let result = run_block(&classified_block, ctx, input_stream).await; let result = run_block(&classified_block, ctx, input_stream);
ctx.scope.exit_scope(); ctx.scope.exit_scope();
result?.collect_string(Tag::unknown()).await.map(|x| x.item) result?.collect_string(Tag::unknown()).map(|x| x.item)
} }
#[allow(dead_code)] #[allow(dead_code)]

View file

@ -25,8 +25,6 @@ macro_rules! stream {
macro_rules! trace_out_stream { macro_rules! trace_out_stream {
(target: $target:tt, $desc:tt = $expr:expr) => {{ (target: $target:tt, $desc:tt = $expr:expr) => {{
if log::log_enabled!(target: $target, log::Level::Trace) { if log::log_enabled!(target: $target, log::Level::Trace) {
use futures::stream::StreamExt;
let objects = $expr.inspect(move |o| { let objects = $expr.inspect(move |o| {
trace!( trace!(
target: $target, target: $target,
@ -46,7 +44,6 @@ macro_rules! trace_out_stream {
}}; }};
} }
pub(crate) use futures::{Stream, StreamExt};
pub(crate) use nu_engine::Host; pub(crate) use nu_engine::Host;
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use nu_errors::ShellError; pub(crate) use nu_errors::ShellError;
@ -65,11 +62,11 @@ pub trait FromInputStream {
impl<T> FromInputStream for T impl<T> FromInputStream for T
where where
T: Stream<Item = nu_protocol::Value> + Send + 'static, T: Iterator<Item = nu_protocol::Value> + Send + Sync + 'static,
{ {
fn from_input_stream(self) -> OutputStream { fn from_input_stream(self) -> OutputStream {
OutputStream { OutputStream {
values: self.map(nu_protocol::ReturnSuccess::value).boxed(), values: Box::new(self.map(nu_protocol::ReturnSuccess::value)),
} }
} }
} }
@ -81,12 +78,12 @@ pub trait ToOutputStream {
impl<T, U> ToOutputStream for T impl<T, U> ToOutputStream for T
where where
T: Stream<Item = U> + Send + 'static, T: Iterator<Item = U> + Send + Sync + 'static,
U: Into<nu_protocol::ReturnValue>, U: Into<nu_protocol::ReturnValue>,
{ {
fn to_output_stream(self) -> OutputStream { fn to_output_stream(self) -> OutputStream {
OutputStream { OutputStream {
values: self.map(|item| item.into()).boxed(), values: Box::new(self.map(|item| item.into())),
} }
} }
} }

View file

@ -27,8 +27,6 @@ nu-ansi-term = { version = "0.29.1", path = "../nu-ansi-term" }
Inflector = "0.11" Inflector = "0.11"
arboard = { version = "1.1.0", optional = true } arboard = { version = "1.1.0", optional = true }
async-recursion = "0.3.2"
async-trait = "0.1.42"
base64 = "0.13.0" base64 = "0.13.0"
bigdecimal = { version = "0.2.0", features = ["serde"] } bigdecimal = { version = "0.2.0", features = ["serde"] }
byte-unit = "4.0.9" byte-unit = "4.0.9"
@ -51,8 +49,6 @@ encoding_rs = "0.8.28"
filesize = "0.2.0" filesize = "0.2.0"
fs_extra = "1.2.0" fs_extra = "1.2.0"
futures = { version = "0.3.12", features = ["compat", "io-compat"] } futures = { version = "0.3.12", features = ["compat", "io-compat"] }
futures-util = "0.3.12"
futures_codec = "0.4.1"
getset = "0.1.1" getset = "0.1.1"
glob = "0.3.0" glob = "0.3.0"
htmlescape = "0.3.1" htmlescape = "0.3.1"

View file

@ -13,7 +13,6 @@ pub struct Arguments {
block: CapturedBlock, block: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"all?" "all?"
@ -31,8 +30,8 @@ impl WholeStreamCommand for Command {
"Find if the table rows matches the condition." "Find if the table rows matches the condition."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
all(args).await all(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -53,10 +52,10 @@ impl WholeStreamCommand for Command {
} }
} }
async fn all(args: CommandArgs) -> Result<OutputStream, ShellError> { fn all(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = Arc::new(EvaluationContext::from_args(&args)); let ctx = Arc::new(EvaluationContext::from_args(&args));
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { block }, input) = args.process().await?; let (Arguments { block }, input) = args.process()?;
let condition = { let condition = {
if block.block.block.len() != 1 { if block.block.block.len() != 1 {
@ -99,28 +98,25 @@ async fn all(args: CommandArgs) -> Result<OutputStream, ShellError> {
ctx.scope.add_vars(&block.captured.entries); ctx.scope.add_vars(&block.captured.entries);
ctx.scope.add_var("$it", row); ctx.scope.add_var("$it", row);
async move { let condition = evaluate_baseline_expr(&condition, &*ctx);
let condition = evaluate_baseline_expr(&condition, &*ctx).await.clone(); ctx.scope.exit_scope();
ctx.scope.exit_scope();
let curr = acc?.drain_vec().await; let curr = acc?.drain_vec();
let curr = curr let curr = curr
.get(0) .get(0)
.ok_or_else(|| ShellError::unexpected("No value to check with"))?; .ok_or_else(|| ShellError::unexpected("No value to check with"))?;
let cond = curr.as_bool()?; let cond = curr.as_bool()?;
match condition { match condition {
Ok(condition) => match condition.as_bool() { Ok(condition) => match condition.as_bool() {
Ok(b) => Ok(InputStream::one( Ok(b) => Ok(InputStream::one(
UntaggedValue::boolean(cond && b).into_value(&curr.tag), UntaggedValue::boolean(cond && b).into_value(&curr.tag),
)), )),
Err(e) => Err(e),
},
Err(e) => Err(e), Err(e) => Err(e),
} },
Err(e) => Err(e),
} }
}) })?
.await?
.to_output_stream()) .to_output_stream())
} }

View file

@ -14,7 +14,6 @@ struct AnsiArgs {
osc: Option<Tagged<String>>, osc: Option<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"ansi" "ansi"
@ -120,8 +119,8 @@ Format: #
] ]
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let (AnsiArgs { code, escape, osc }, _) = args.process().await?; let (AnsiArgs { code, escape, osc }, _) = args.process()?;
if let Some(e) = escape { if let Some(e) = escape {
let esc_vec: Vec<char> = e.item.chars().collect(); let esc_vec: Vec<char> = e.item.chars().collect();

View file

@ -15,7 +15,6 @@ struct Arguments {
rest: Vec<ColumnPath>, rest: Vec<ColumnPath>,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"ansi strip" "ansi strip"
@ -32,8 +31,8 @@ impl WholeStreamCommand for SubCommand {
"strip ansi escape sequences from string" "strip ansi escape sequences from string"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
operate(args).await operate(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -45,8 +44,8 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> { fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rest }, input) = args.process().await?; let (Arguments { rest }, input) = args.process()?;
let column_paths: Vec<_> = rest; let column_paths: Vec<_> = rest;
Ok(input Ok(input

View file

@ -13,7 +13,6 @@ pub struct Arguments {
block: CapturedBlock, block: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"any?" "any?"
@ -31,8 +30,8 @@ impl WholeStreamCommand for Command {
"Find if the table rows matches the condition." "Find if the table rows matches the condition."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
any(args).await any(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -53,10 +52,10 @@ impl WholeStreamCommand for Command {
} }
} }
async fn any(args: CommandArgs) -> Result<OutputStream, ShellError> { fn any(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = Arc::new(EvaluationContext::from_args(&args)); let ctx = Arc::new(EvaluationContext::from_args(&args));
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { block }, input) = args.process().await?; let (Arguments { block }, input) = args.process()?;
let condition = { let condition = {
if block.block.block.len() != 1 { if block.block.block.len() != 1 {
@ -99,28 +98,25 @@ async fn any(args: CommandArgs) -> Result<OutputStream, ShellError> {
ctx.scope.add_vars(&block.captured.entries); ctx.scope.add_vars(&block.captured.entries);
ctx.scope.add_var("$it", row); ctx.scope.add_var("$it", row);
async move { let condition = evaluate_baseline_expr(&condition, &*ctx);
let condition = evaluate_baseline_expr(&condition, &*ctx).await.clone(); ctx.scope.exit_scope();
ctx.scope.exit_scope();
let curr = cond?.drain_vec().await; let curr = cond?.drain_vec();
let curr = curr let curr = curr
.get(0) .get(0)
.ok_or_else(|| ShellError::unexpected("No value to check with"))?; .ok_or_else(|| ShellError::unexpected("No value to check with"))?;
let cond = curr.as_bool()?; let cond = curr.as_bool()?;
match condition { match condition {
Ok(condition) => match condition.as_bool() { Ok(condition) => match condition.as_bool() {
Ok(b) => Ok(InputStream::one( Ok(b) => Ok(InputStream::one(
UntaggedValue::boolean(cond || b).into_value(&curr.tag), UntaggedValue::boolean(cond || b).into_value(&curr.tag),
)), )),
Err(e) => Err(e),
},
Err(e) => Err(e), Err(e) => Err(e),
} },
Err(e) => Err(e),
} }
}) })?
.await?
.to_output_stream()) .to_output_stream())
} }

View file

@ -10,7 +10,6 @@ struct Arguments {
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"append" "append"
@ -28,10 +27,10 @@ impl WholeStreamCommand for Command {
"Append a row to the table." "Append a row to the table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { mut value }, input) = args.process().await?; let (Arguments { mut value }, input) = args.process()?;
let input: Vec<Value> = input.collect().await; let input: Vec<Value> = input.collect();
if let Some(first) = input.get(0) { if let Some(first) = input.get(0) {
value.tag = first.tag(); value.tag = first.tag();
@ -48,18 +47,14 @@ impl WholeStreamCommand for Command {
} }
} }
Ok(futures::stream::iter( Ok(input
input .into_iter()
.into_iter() .chain(vec![value])
.chain(vec![value]) .map(ReturnSuccess::value)
.map(ReturnSuccess::value), .to_output_stream())
)
.to_output_stream())
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
use nu_protocol::row;
vec![ vec![
Example { Example {
description: "Add values to the end of the table", description: "Add values to the end of the table",

View file

@ -4,7 +4,6 @@ use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
pub struct Autoenv; pub struct Autoenv;
#[async_trait]
impl WholeStreamCommand for Autoenv { impl WholeStreamCommand for Autoenv {
fn name(&self) -> &str { fn name(&self) -> &str {
"autoenv" "autoenv"
@ -26,7 +25,7 @@ The .nu-env file has the same format as your $HOME/nu/config.toml file. By loadi
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("autoenv") Signature::build("autoenv")
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(get_full_help(&Autoenv, &args.scope)).into_value(Tag::unknown()), UntaggedValue::string(get_full_help(&Autoenv, &args.scope)).into_value(Tag::unknown()),
))) )))

View file

@ -8,7 +8,6 @@ use sha2::{Digest, Sha256};
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
pub struct AutoenvTrust; pub struct AutoenvTrust;
#[async_trait]
impl WholeStreamCommand for AutoenvTrust { impl WholeStreamCommand for AutoenvTrust {
fn name(&self) -> &str { fn name(&self) -> &str {
"autoenv trust" "autoenv trust"
@ -22,11 +21,11 @@ impl WholeStreamCommand for AutoenvTrust {
"Trust a .nu-env file in the current or given directory" "Trust a .nu-env file in the current or given directory"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let file_to_trust = match args.call_info.evaluate(&ctx).await?.args.nth(0) { let file_to_trust = match args.call_info.evaluate(&ctx)?.args.nth(0) {
Some(Value { Some(Value {
value: UntaggedValue::Primitive(Primitive::String(ref path)), value: UntaggedValue::Primitive(Primitive::String(ref path)),
tag: _, tag: _,

View file

@ -8,7 +8,6 @@ use std::io::Read;
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
pub struct AutoenvUnTrust; pub struct AutoenvUnTrust;
#[async_trait]
impl WholeStreamCommand for AutoenvUnTrust { impl WholeStreamCommand for AutoenvUnTrust {
fn name(&self) -> &str { fn name(&self) -> &str {
"autoenv untrust" "autoenv untrust"
@ -26,10 +25,10 @@ impl WholeStreamCommand for AutoenvUnTrust {
"Untrust a .nu-env file in the current or given directory" "Untrust a .nu-env file in the current or given directory"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let file_to_untrust = match args.call_info.evaluate(&ctx).await?.args.nth(0) { let file_to_untrust = match args.call_info.evaluate(&ctx)?.args.nth(0) {
Some(Value { Some(Value {
value: UntaggedValue::Primitive(Primitive::String(ref path)), value: UntaggedValue::Primitive(Primitive::String(ref path)),
tag: _, tag: _,

View file

@ -12,7 +12,6 @@ use std::sync::atomic::AtomicBool;
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"autoview" "autoview"
@ -26,8 +25,8 @@ impl WholeStreamCommand for Command {
"View the contents of the pipeline as a table or list." "View the contents of the pipeline as a table or list."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
autoview(RunnableContext::from_command_args(args)).await autoview(RunnableContext::from_command_args(args))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -71,7 +70,7 @@ impl RunnableContextWithoutInput {
} }
} }
pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellError> { pub fn autoview(context: RunnableContext) -> Result<OutputStream, ShellError> {
let configuration = AutoViewConfiguration::new(); let configuration = AutoViewConfiguration::new();
let binary = context.get_command("binaryview"); let binary = context.get_command("binaryview");
@ -84,21 +83,19 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
let term_width = context.host.lock().width(); let term_width = context.host.lock().width();
let color_hm = get_color_config(); let color_hm = get_color_config();
if let Some(x) = input_stream.next().await { if let Some(x) = input_stream.next() {
match input_stream.next().await { match input_stream.next() {
Some(y) => { Some(y) => {
let ctrl_c = context.ctrl_c.clone(); let ctrl_c = context.ctrl_c.clone();
let xy = vec![x, y]; let xy = vec![x, y];
let xy_stream = futures::stream::iter(xy) let xy_stream = xy.into_iter().chain(input_stream).interruptible(ctrl_c);
.chain(input_stream)
.interruptible(ctrl_c);
let stream = InputStream::from_stream(xy_stream); let stream = InputStream::from_stream(xy_stream);
if let Some(table) = table { if let Some(table) = table {
let command_args = create_default_command_args(&context).with_input(stream); let command_args = create_default_command_args(&context).with_input(stream);
let result = table.run(command_args).await?; let result = table.run(command_args)?;
result.collect::<Vec<_>>().await; let _ = result.collect::<Vec<_>>();
} }
} }
_ => { _ => {
@ -114,8 +111,8 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
); );
let command_args = let command_args =
create_default_command_args(&context).with_input(stream); create_default_command_args(&context).with_input(stream);
let result = text.run(command_args).await?; let result = text.run(command_args)?;
result.collect::<Vec<_>>().await; let _ = result.collect::<Vec<_>>();
} else { } else {
out!("{}", s); out!("{}", s);
} }
@ -196,8 +193,8 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
stream.push_back(x); stream.push_back(x);
let command_args = let command_args =
create_default_command_args(&context).with_input(stream); create_default_command_args(&context).with_input(stream);
let result = binary.run(command_args).await?; let result = binary.run(command_args)?;
result.collect::<Vec<_>>().await; let _ = result.collect::<Vec<_>>();
} else { } else {
use pretty_hex::*; use pretty_hex::*;
out!("{:?}", b.hex_dump()); out!("{:?}", b.hex_dump());
@ -262,8 +259,8 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
stream.push_back(x); stream.push_back(x);
let command_args = let command_args =
create_default_command_args(&context).with_input(stream); create_default_command_args(&context).with_input(stream);
let result = table.run(command_args).await?; let result = table.run(command_args)?;
result.collect::<Vec<_>>().await; let _ = result.collect::<Vec<_>>();
} else { } else {
out!("{:?}", item); out!("{:?}", item);
} }

View file

@ -23,7 +23,6 @@ struct BenchmarkArgs {
passthrough: Option<CapturedBlock>, passthrough: Option<CapturedBlock>,
} }
#[async_trait]
impl WholeStreamCommand for Benchmark { impl WholeStreamCommand for Benchmark {
fn name(&self) -> &str { fn name(&self) -> &str {
"benchmark" "benchmark"
@ -48,8 +47,8 @@ impl WholeStreamCommand for Benchmark {
"Runs a block and returns the time it took to execute it." "Runs a block and returns the time it took to execute it."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
benchmark(args).await benchmark(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -68,11 +67,11 @@ impl WholeStreamCommand for Benchmark {
} }
} }
async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = raw_args.call_info.args.span; let tag = raw_args.call_info.args.span;
let mut context = EvaluationContext::from_args(&raw_args); let mut context = EvaluationContext::from_args(&raw_args);
let scope = raw_args.scope.clone(); let scope = raw_args.scope.clone();
let (BenchmarkArgs { block, passthrough }, input) = raw_args.process().await?; let (BenchmarkArgs { block, passthrough }, input) = raw_args.process()?;
let env = scope.get_env_vars(); let env = scope.get_env_vars();
let name = generate_free_name(&env); let name = generate_free_name(&env);
@ -82,15 +81,15 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let start_time = Instant::now(); let start_time = Instant::now();
// #[cfg(feature = "rich-benchmark")] // #[cfg(feature = "rich-benchmark")]
// let start = time().await; // let start = time();
context.scope.enter_scope(); context.scope.enter_scope();
let result = run_block(&block.block, &context, input).await; let result = run_block(&block.block, &context, input);
context.scope.exit_scope(); context.scope.exit_scope();
let output = result?.into_vec().await; let output = result?.into_vec();
// #[cfg(feature = "rich-benchmark")] // #[cfg(feature = "rich-benchmark")]
// let end = time().await; // let end = time();
let end_time = Instant::now(); let end_time = Instant::now();
context.clear_errors(); context.clear_errors();
@ -102,7 +101,7 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let real_time = into_big_int(end_time - start_time); let real_time = into_big_int(end_time - start_time);
indexmap.insert("real time".to_string(), real_time); indexmap.insert("real time".to_string(), real_time);
benchmark_output(indexmap, output, passthrough, &tag, &mut context).await benchmark_output(indexmap, output, passthrough, &tag, &mut context)
} }
// return advanced stats // return advanced stats
// #[cfg(feature = "rich-benchmark")] // #[cfg(feature = "rich-benchmark")]
@ -121,7 +120,7 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
// let idle_time = into_big_int(end.idle() - start.idle()); // let idle_time = into_big_int(end.idle() - start.idle());
// indexmap.insert("idle time".to_string(), idle_time); // indexmap.insert("idle time".to_string(), idle_time);
// benchmark_output(indexmap, output, passthrough, &tag, &mut context).await // benchmark_output(indexmap, output, passthrough, &tag, &mut context)
// } else { // } else {
// Err(ShellError::untagged_runtime_error( // Err(ShellError::untagged_runtime_error(
// "Could not retrieve CPU time", // "Could not retrieve CPU time",
@ -129,7 +128,7 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
// } // }
} }
async fn benchmark_output<T, Output>( fn benchmark_output<T, Output>(
indexmap: IndexMap<String, BigInt>, indexmap: IndexMap<String, BigInt>,
block_output: Output, block_output: Output,
passthrough: Option<CapturedBlock>, passthrough: Option<CapturedBlock>,
@ -155,7 +154,7 @@ where
let time_block = add_implicit_autoview(time_block.block); let time_block = add_implicit_autoview(time_block.block);
context.scope.enter_scope(); context.scope.enter_scope();
let result = run_block(&time_block, context, benchmark_output).await; let result = run_block(&time_block, context, benchmark_output);
context.scope.exit_scope(); context.scope.exit_scope();
result?; result?;
context.clear_errors(); context.clear_errors();

View file

@ -12,7 +12,6 @@ pub struct BuildStringArgs {
pub struct BuildString; pub struct BuildString;
#[async_trait]
impl WholeStreamCommand for BuildString { impl WholeStreamCommand for BuildString {
fn name(&self) -> &str { fn name(&self) -> &str {
"build-string" "build-string"
@ -27,9 +26,9 @@ impl WholeStreamCommand for BuildString {
"Builds a string from the arguments." "Builds a string from the arguments."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (BuildStringArgs { rest }, _) = args.process().await?; let (BuildStringArgs { rest }, _) = args.process()?;
let mut output_string = String::new(); let mut output_string = String::new();

View file

@ -7,7 +7,6 @@ use nu_protocol::{Dictionary, Signature, SyntaxShape, UntaggedValue, Value};
pub struct Cal; pub struct Cal;
#[async_trait]
impl WholeStreamCommand for Cal { impl WholeStreamCommand for Cal {
fn name(&self) -> &str { fn name(&self) -> &str {
"cal" "cal"
@ -41,8 +40,8 @@ impl WholeStreamCommand for Cal {
"Display a calendar." "Display a calendar."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
cal(args).await cal(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -66,8 +65,8 @@ impl WholeStreamCommand for Cal {
} }
} }
pub async fn cal(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn cal(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let mut calendar_vec_deque = VecDeque::new(); let mut calendar_vec_deque = VecDeque::new();
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
@ -102,7 +101,7 @@ pub async fn cal(args: CommandArgs) -> Result<OutputStream, ShellError> {
current_day_option, current_day_option,
)?; )?;
Ok(futures::stream::iter(calendar_vec_deque).to_output_stream()) Ok(calendar_vec_deque.into_iter().to_output_stream())
} }
fn get_invalid_year_shell_error(year_tag: &Tag) -> ShellError { fn get_invalid_year_shell_error(year_tag: &Tag) -> ShellError {

View file

@ -7,7 +7,6 @@ use nu_protocol::{Signature, SyntaxShape};
pub struct Cd; pub struct Cd;
#[async_trait]
impl WholeStreamCommand for Cd { impl WholeStreamCommand for Cd {
fn name(&self) -> &str { fn name(&self) -> &str {
"cd" "cd"
@ -25,10 +24,10 @@ impl WholeStreamCommand for Cd {
"Change to a new path." "Change to a new path."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let shell_manager = args.shell_manager.clone(); let shell_manager = args.shell_manager.clone();
let (args, _): (CdArgs, _) = args.process().await?; let (args, _): (CdArgs, _) = args.process()?;
shell_manager.cd(args, name) shell_manager.cd(args, name)
} }

View file

@ -13,7 +13,6 @@ struct CharArgs {
unicode: bool, unicode: bool,
} }
#[async_trait]
impl WholeStreamCommand for Char { impl WholeStreamCommand for Char {
fn name(&self) -> &str { fn name(&self) -> &str {
"char" "char"
@ -65,7 +64,7 @@ impl WholeStreamCommand for Char {
] ]
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let ( let (
CharArgs { CharArgs {
name, name,
@ -73,7 +72,7 @@ impl WholeStreamCommand for Char {
unicode, unicode,
}, },
_, _,
) = args.process().await?; ) = args.process()?;
if unicode { if unicode {
if !rest.is_empty() { if !rest.is_empty() {

View file

@ -6,7 +6,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
#[derive(Clone)] #[derive(Clone)]
pub struct Chart; pub struct Chart;
#[async_trait]
impl WholeStreamCommand for Chart { impl WholeStreamCommand for Chart {
fn name(&self) -> &str { fn name(&self) -> &str {
"chart" "chart"
@ -20,7 +19,7 @@ impl WholeStreamCommand for Chart {
"Displays charts." "Displays charts."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.scope.get_command("chart bar").is_none() { if args.scope.get_command("chart bar").is_none() {
return Err(ShellError::untagged_runtime_error( return Err(ShellError::untagged_runtime_error(
"nu_plugin_chart not installed.", "nu_plugin_chart not installed.",

View file

@ -1,16 +1,14 @@
use crate::futures::ThreadedReceiver; use crate::futures::ThreadedReceiver;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::evaluate_baseline_expr; use nu_engine::{evaluate_baseline_expr, BufCodecReader};
use nu_engine::{MaybeTextCodec, StringOrBinary}; use nu_engine::{MaybeTextCodec, StringOrBinary};
use std::borrow::Cow;
use std::io::Write; use std::io::Write;
use std::ops::Deref; use std::ops::Deref;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::mpsc; use std::sync::mpsc;
use std::{borrow::Cow, io::BufReader};
use futures::executor::block_on_stream;
use futures_codec::FramedRead;
use log::trace; use log::trace;
use nu_errors::ShellError; use nu_errors::ShellError;
@ -18,9 +16,8 @@ use nu_protocol::hir::Expression;
use nu_protocol::hir::{ExternalCommand, ExternalRedirection}; use nu_protocol::hir::{ExternalCommand, ExternalRedirection};
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value}; use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
use nu_source::Tag; use nu_source::Tag;
use nu_stream::trace_stream;
pub(crate) async fn run_external_command( pub(crate) fn run_external_command(
command: ExternalCommand, command: ExternalCommand,
context: &mut EvaluationContext, context: &mut EvaluationContext,
input: InputStream, input: InputStream,
@ -36,10 +33,10 @@ pub(crate) async fn run_external_command(
)); ));
} }
run_with_stdin(command, context, input, external_redirection).await run_with_stdin(command, context, input, external_redirection)
} }
async fn run_with_stdin( fn run_with_stdin(
command: ExternalCommand, command: ExternalCommand,
context: &mut EvaluationContext, context: &mut EvaluationContext,
input: InputStream, input: InputStream,
@ -47,12 +44,10 @@ async fn run_with_stdin(
) -> Result<InputStream, ShellError> { ) -> Result<InputStream, ShellError> {
let path = context.shell_manager.path(); let path = context.shell_manager.path();
let input = trace_stream!(target: "nu::trace_stream::external::stdin", "input" = input);
let mut command_args = vec![]; let mut command_args = vec![];
for arg in command.args.iter() { for arg in command.args.iter() {
let is_literal = matches!(arg.expr, Expression::Literal(_)); let is_literal = matches!(arg.expr, Expression::Literal(_));
let value = evaluate_baseline_expr(arg, context).await?; let value = evaluate_baseline_expr(arg, context)?;
// Skip any arguments that don't really exist, treating them as optional // Skip any arguments that don't really exist, treating them as optional
// FIXME: we may want to preserve the gap in the future, though it's hard to say // FIXME: we may want to preserve the gap in the future, though it's hard to say
@ -219,7 +214,7 @@ fn spawn(
.take() .take()
.expect("Internal error: could not get stdin pipe for external command"); .expect("Internal error: could not get stdin pipe for external command");
for value in block_on_stream(input) { for value in input {
match &value.value { match &value.value {
UntaggedValue::Primitive(Primitive::Nothing) => continue, UntaggedValue::Primitive(Primitive::Nothing) => continue,
UntaggedValue::Primitive(Primitive::String(s)) => { UntaggedValue::Primitive(Primitive::String(s)) => {
@ -274,10 +269,12 @@ fn spawn(
return Err(()); return Err(());
}; };
let file = futures::io::AllowStdIo::new(stdout); // let file = futures::io::AllowStdIo::new(stdout);
let stream = FramedRead::new(file, MaybeTextCodec::default()); // let stream = FramedRead::new(file, MaybeTextCodec::default());
let buf_read = BufReader::new(stdout);
let buf_codec = BufCodecReader::new(buf_read, MaybeTextCodec::default());
for line in block_on_stream(stream) { for line in buf_codec {
match line { match line {
Ok(line) => match line { Ok(line) => match line {
StringOrBinary::String(s) => { StringOrBinary::String(s) => {
@ -345,10 +342,12 @@ fn spawn(
return Err(()); return Err(());
}; };
let file = futures::io::AllowStdIo::new(stderr); // let file = futures::io::AllowStdIo::new(stderr);
let stream = FramedRead::new(file, MaybeTextCodec::default()); // let stream = FramedRead::new(file, MaybeTextCodec::default());
let buf_reader = BufReader::new(stderr);
let buf_codec = BufCodecReader::new(buf_reader, MaybeTextCodec::default());
for line in block_on_stream(stream) { for line in buf_codec {
match line { match line {
Ok(line) => match line { Ok(line) => match line {
StringOrBinary::String(s) => { StringOrBinary::String(s) => {
@ -506,16 +505,13 @@ mod tests {
#[cfg(feature = "which")] #[cfg(feature = "which")]
use super::{run_external_command, InputStream}; use super::{run_external_command, InputStream};
#[cfg(feature = "which")]
use futures::executor::block_on;
#[cfg(feature = "which")] #[cfg(feature = "which")]
use nu_engine::basic_evaluation_context; use nu_engine::basic_evaluation_context;
#[cfg(feature = "which")]
use nu_errors::ShellError;
#[cfg(feature = "which")] #[cfg(feature = "which")]
use nu_test_support::commands::ExternalBuilder; use nu_test_support::commands::ExternalBuilder;
// async fn read(mut stream: OutputStream) -> Option<Value> { // fn read(mut stream: OutputStream) -> Option<Value> {
// match stream.try_next().await { // match stream.try_next() {
// Ok(val) => { // Ok(val) => {
// if let Some(val) = val { // if let Some(val) = val {
// val.raw_value() // val.raw_value()
@ -528,7 +524,7 @@ mod tests {
// } // }
#[cfg(feature = "which")] #[cfg(feature = "which")]
async fn non_existent_run() -> Result<(), ShellError> { fn non_existent_run() {
use nu_protocol::hir::ExternalRedirection; use nu_protocol::hir::ExternalRedirection;
let cmd = ExternalBuilder::for_name("i_dont_exist.exe").build(); let cmd = ExternalBuilder::for_name("i_dont_exist.exe").build();
@ -536,24 +532,18 @@ mod tests {
let mut ctx = let mut ctx =
basic_evaluation_context().expect("There was a problem creating a basic context."); basic_evaluation_context().expect("There was a problem creating a basic context.");
assert!( assert!(run_external_command(cmd, &mut ctx, input, ExternalRedirection::Stdout).is_err());
run_external_command(cmd, &mut ctx, input, ExternalRedirection::Stdout)
.await
.is_err()
);
Ok(())
} }
// async fn failure_run() -> Result<(), ShellError> { // fn failure_run() -> Result<(), ShellError> {
// let cmd = ExternalBuilder::for_name("fail").build(); // let cmd = ExternalBuilder::for_name("fail").build();
// let mut ctx = crate::cli::basic_evaluation_context().expect("There was a problem creating a basic context."); // let mut ctx = crate::cli::basic_evaluation_context().expect("There was a problem creating a basic context.");
// let stream = run_external_command(cmd, &mut ctx, None, false) // let stream = run_external_command(cmd, &mut ctx, None, false)
// .await? // ?
// .expect("There was a problem running the external command."); // .expect("There was a problem running the external command.");
// match read(stream.into()).await { // match read(stream.into()) {
// Some(Value { // Some(Value {
// value: UntaggedValue::Error(_), // value: UntaggedValue::Error(_),
// .. // ..
@ -571,8 +561,8 @@ mod tests {
#[cfg(feature = "which")] #[cfg(feature = "which")]
#[test] #[test]
fn identifies_command_not_found() -> Result<(), ShellError> { fn identifies_command_not_found() {
block_on(non_existent_run()) non_existent_run()
} }
#[test] #[test]

View file

@ -6,7 +6,6 @@ use std::process::Command;
pub struct Clear; pub struct Clear;
#[async_trait]
impl WholeStreamCommand for Clear { impl WholeStreamCommand for Clear {
fn name(&self) -> &str { fn name(&self) -> &str {
"clear" "clear"
@ -20,7 +19,7 @@ impl WholeStreamCommand for Clear {
"Clears the terminal." "Clears the terminal."
} }
async fn run(&self, _: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, _: CommandArgs) -> Result<OutputStream, ShellError> {
if cfg!(windows) { if cfg!(windows) {
Command::new("cmd") Command::new("cmd")
.args(&["/C", "cls"]) .args(&["/C", "cls"])

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use futures::stream::StreamExt;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, Value}; use nu_protocol::{Signature, Value};
@ -8,7 +8,6 @@ use arboard::Clipboard;
pub struct Clip; pub struct Clip;
#[async_trait]
impl WholeStreamCommand for Clip { impl WholeStreamCommand for Clip {
fn name(&self) -> &str { fn name(&self) -> &str {
"clip" "clip"
@ -22,8 +21,8 @@ impl WholeStreamCommand for Clip {
"Copy the contents of the pipeline to the copy/paste buffer." "Copy the contents of the pipeline to the copy/paste buffer."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
clip(args).await clip(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -42,10 +41,10 @@ impl WholeStreamCommand for Clip {
} }
} }
pub async fn clip(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn clip(args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let values: Vec<Value> = input.collect().await; let values: Vec<Value> = input.collect();
if let Ok(mut clip_context) = Clipboard::new() { if let Ok(mut clip_context) = Clipboard::new() {
let mut new_copy_data = String::new(); let mut new_copy_data = String::new();

View file

@ -1,6 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use futures::future;
use futures::stream::StreamExt;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
@ -13,7 +12,6 @@ pub struct CompactArgs {
rest: Vec<Tagged<String>>, rest: Vec<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Compact { impl WholeStreamCommand for Compact {
fn name(&self) -> &str { fn name(&self) -> &str {
"compact" "compact"
@ -27,8 +25,8 @@ impl WholeStreamCommand for Compact {
"Creates a table with non-empty rows." "Creates a table with non-empty rows."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
compact(args).await compact(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -40,11 +38,11 @@ impl WholeStreamCommand for Compact {
} }
} }
pub async fn compact(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn compact(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (CompactArgs { rest: columns }, input) = args.process().await?; let (CompactArgs { rest: columns }, input) = args.process()?;
Ok(input Ok(input
.filter_map(move |item| { .filter_map(move |item| {
future::ready(if columns.is_empty() { if columns.is_empty() {
if !item.is_empty() { if !item.is_empty() {
Some(ReturnSuccess::value(item)) Some(ReturnSuccess::value(item))
} else { } else {
@ -67,7 +65,7 @@ pub async fn compact(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
_ => None, _ => None,
} }
}) }
}) })
.to_output_stream()) .to_output_stream())
} }

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config clear" "config clear"
@ -19,8 +18,8 @@ impl WholeStreamCommand for SubCommand {
"clear the config" "clear the config"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
clear(args).await clear(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -32,7 +31,7 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn clear(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn clear(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name_span = args.call_info.name_tag.clone(); let name_span = args.call_info.name_tag.clone();
let path = match args.scope.get_var("config-path") { let path = match args.scope.get_var("config-path") {

View file

@ -7,7 +7,6 @@ use nu_stream::OutputStream;
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"config" "config"
@ -21,22 +20,22 @@ impl WholeStreamCommand for Command {
"Configuration management." "Configuration management."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag; let name = args.call_info.name_tag;
if let Some(global_cfg) = &args.configs.lock().global_config { if let Some(global_cfg) = &args.configs.lock().global_config {
let result = global_cfg.vars.clone(); let result = global_cfg.vars.clone();
Ok(futures::stream::iter(vec![ReturnSuccess::value( Ok(vec![ReturnSuccess::value(
UntaggedValue::Row(result.into()).into_value(name), UntaggedValue::Row(result.into()).into_value(name),
)]) )]
.into_iter()
.to_output_stream()) .to_output_stream())
} else { } else {
Ok( Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
futures::stream::iter(vec![ReturnSuccess::value(UntaggedValue::Error( ShellError::untagged_runtime_error("No global config found!"),
ShellError::untagged_runtime_error("No global config found!"), ))]
))]) .into_iter()
.to_output_stream(), .to_output_stream())
)
} }
} }
} }

View file

@ -12,7 +12,6 @@ pub struct Arguments {
column_path: ColumnPath, column_path: ColumnPath,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config get" "config get"
@ -30,8 +29,8 @@ impl WholeStreamCommand for SubCommand {
"Gets a value from the config" "Gets a value from the config"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
get(args).await get(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -43,10 +42,10 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn get(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let scope = args.scope.clone(); let scope = args.scope.clone();
let (Arguments { column_path }, _) = args.process().await?; let (Arguments { column_path }, _) = args.process()?;
let path = match scope.get_var("config-path") { let path = match scope.get_var("config-path") {
Some(Value { Some(Value {
@ -70,7 +69,7 @@ pub async fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
.map(|x| ReturnSuccess::value(x.clone())) .map(|x| ReturnSuccess::value(x.clone()))
.collect(); .collect();
futures::stream::iter(list).to_output_stream() list.into_iter().to_output_stream()
} }
x => OutputStream::one(ReturnSuccess::value(x)), x => OutputStream::one(ReturnSuccess::value(x)),
}) })

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config path" "config path"
@ -19,8 +18,8 @@ impl WholeStreamCommand for SubCommand {
"return the path to the config file" "return the path to the config file"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
path(args).await path(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -32,7 +31,7 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn path(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn path(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
match args.scope.get_var("config-path") { match args.scope.get_var("config-path") {
Some( Some(

View file

@ -11,7 +11,6 @@ pub struct Arguments {
remove: Tagged<String>, remove: Tagged<String>,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config remove" "config remove"
@ -29,8 +28,8 @@ impl WholeStreamCommand for SubCommand {
"Removes a value from the config" "Removes a value from the config"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
remove(args).await remove(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -42,10 +41,10 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name_span = args.call_info.name_tag.clone(); let name_span = args.call_info.name_tag.clone();
let scope = args.scope.clone(); let scope = args.scope.clone();
let (Arguments { remove }, _) = args.process().await?; let (Arguments { remove }, _) = args.process()?;
let path = match scope.get_var("config-path") { let path = match scope.get_var("config-path") {
Some(Value { Some(Value {
@ -62,9 +61,10 @@ pub async fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
if result.contains_key(&key) { if result.contains_key(&key) {
result.swap_remove(&key); result.swap_remove(&key);
config::write(&result, &path)?; config::write(&result, &path)?;
Ok(futures::stream::iter(vec![ReturnSuccess::value( Ok(vec![ReturnSuccess::value(
UntaggedValue::Row(result.into()).into_value(remove.tag()), UntaggedValue::Row(result.into()).into_value(remove.tag()),
)]) )]
.into_iter()
.to_output_stream()) .to_output_stream())
} else { } else {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(

View file

@ -13,7 +13,6 @@ pub struct Arguments {
value: Value, value: Value,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config set" "config set"
@ -29,8 +28,8 @@ impl WholeStreamCommand for SubCommand {
"Sets a value in the config" "Sets a value in the config"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
set(args).await set(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -59,7 +58,7 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn set(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let scope = args.scope.clone(); let scope = args.scope.clone();
@ -69,7 +68,7 @@ pub async fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
mut value, mut value,
}, },
_, _,
) = args.process().await?; ) = args.process()?;
let path = match scope.get_var("config-path") { let path = match scope.get_var("config-path") {
Some(Value { Some(Value {
@ -96,8 +95,7 @@ pub async fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
config::write(&changes.entries, &path)?; config::write(&changes.entries, &path)?;
ctx.reload_config(&ConfigPath::Global( ctx.reload_config(&ConfigPath::Global(
path.expect("Global config path is always some"), path.expect("Global config path is always some"),
)) ))?;
.await?;
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(changes).into_value(name), UntaggedValue::Row(changes).into_value(name),

View file

@ -13,7 +13,6 @@ pub struct Arguments {
set_into: Tagged<String>, set_into: Tagged<String>,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"config set_into" "config set_into"
@ -31,8 +30,8 @@ impl WholeStreamCommand for SubCommand {
"Sets a value in the config" "Sets a value in the config"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
set_into(args).await set_into(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -44,11 +43,11 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub async fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let scope = args.scope.clone(); let scope = args.scope.clone();
let (Arguments { set_into: v }, input) = args.process().await?; let (Arguments { set_into: v }, input) = args.process()?;
let path = match scope.get_var("config-path") { let path = match scope.get_var("config-path") {
Some(Value { Some(Value {
@ -60,7 +59,7 @@ pub async fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut result = nu_data::config::read(&name, &path)?; let mut result = nu_data::config::read(&name, &path)?;
let rows: Vec<Value> = input.collect().await; let rows: Vec<Value> = input.collect();
let key = v.to_string(); let key = v.to_string();
Ok(if rows.is_empty() { Ok(if rows.is_empty() {
@ -78,8 +77,7 @@ pub async fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
config::write(&result, &path)?; config::write(&result, &path)?;
ctx.reload_config(&ConfigPath::Global( ctx.reload_config(&ConfigPath::Global(
path.expect("Global config path is always some"), path.expect("Global config path is always some"),
)) ))?;
.await?;
OutputStream::one(ReturnSuccess::value( OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(result.into()).into_value(name), UntaggedValue::Row(result.into()).into_value(name),
@ -93,8 +91,7 @@ pub async fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
config::write(&result, &path)?; config::write(&result, &path)?;
ctx.reload_config(&ConfigPath::Global( ctx.reload_config(&ConfigPath::Global(
path.expect("Global config path is always some"), path.expect("Global config path is always some"),
)) ))?;
.await?;
OutputStream::one(ReturnSuccess::value( OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(result.into()).into_value(name), UntaggedValue::Row(result.into()).into_value(name),

View file

@ -5,7 +5,6 @@ use nu_protocol::{Signature, SyntaxShape};
pub struct Cpy; pub struct Cpy;
#[async_trait]
impl WholeStreamCommand for Cpy { impl WholeStreamCommand for Cpy {
fn name(&self) -> &str { fn name(&self) -> &str {
"cp" "cp"
@ -26,10 +25,10 @@ impl WholeStreamCommand for Cpy {
"Copy files." "Copy files."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let shell_manager = args.shell_manager.clone(); let shell_manager = args.shell_manager.clone();
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (args, _) = args.process().await?; let (args, _) = args.process()?;
shell_manager.cp(args, name) shell_manager.cp(args, name)
} }

View file

@ -5,7 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"date" "date"
@ -19,7 +18,7 @@ impl WholeStreamCommand for Command {
"Apply date function." "Apply date function."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()), UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()),
))) )))

View file

@ -15,7 +15,6 @@ pub struct FormatArgs {
table: bool, table: bool,
} }
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date format" "date format"
@ -31,8 +30,8 @@ impl WholeStreamCommand for Date {
"Format a given date using the given format string." "Format a given date using the given format string."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
format(args).await format(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -51,9 +50,9 @@ impl WholeStreamCommand for Date {
} }
} }
pub async fn format(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn format(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (FormatArgs { format, table }, input) = args.process().await?; let (FormatArgs { format, table }, input) = args.process()?;
Ok(input Ok(input
.map(move |value| match value { .map(move |value| match value {

View file

@ -7,7 +7,6 @@ use nu_protocol::{Dictionary, ReturnSuccess, Signature, UntaggedValue};
pub struct Date; pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date list-timezone" "date list-timezone"
@ -21,8 +20,8 @@ impl WholeStreamCommand for Date {
"List supported time zones." "List supported time zones."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
list_timezone(args).await list_timezone(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -41,8 +40,8 @@ impl WholeStreamCommand for Date {
} }
} }
async fn list_timezone(args: CommandArgs) -> Result<OutputStream, ShellError> { fn list_timezone(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let list = TZ_VARIANTS.iter().map(move |tz| { let list = TZ_VARIANTS.iter().map(move |tz| {
@ -58,7 +57,7 @@ async fn list_timezone(args: CommandArgs) -> Result<OutputStream, ShellError> {
)) ))
}); });
Ok(futures::stream::iter(list).to_output_stream()) Ok(list.into_iter().to_output_stream())
} }
#[cfg(test)] #[cfg(test)]

View file

@ -6,7 +6,6 @@ use nu_protocol::{Signature, UntaggedValue};
pub struct Date; pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date now" "date now"
@ -20,13 +19,13 @@ impl WholeStreamCommand for Date {
"Get the current date." "Get the current date."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
now(args).await now(args)
} }
} }
pub async fn now(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn now(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let now: DateTime<Local> = Local::now(); let now: DateTime<Local> = Local::now();

View file

@ -7,7 +7,6 @@ use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue
pub struct Date; pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date to-table" "date to-table"
@ -21,8 +20,8 @@ impl WholeStreamCommand for Date {
"Print the date in a structured table." "Print the date in a structured table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
to_table(args).await to_table(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -34,8 +33,8 @@ impl WholeStreamCommand for Date {
} }
} }
async fn to_table(args: CommandArgs) -> Result<OutputStream, ShellError> { fn to_table(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let input = args.input; let input = args.input;

View file

@ -12,7 +12,6 @@ struct DateToTimeZoneArgs {
timezone: Tagged<String>, timezone: Tagged<String>,
} }
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date to-timezone" "date to-timezone"
@ -34,8 +33,8 @@ impl WholeStreamCommand for Date {
"Use 'date list-timezone' to list all supported time zones." "Use 'date list-timezone' to list all supported time zones."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
to_timezone(args).await to_timezone(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -59,9 +58,9 @@ impl WholeStreamCommand for Date {
} }
} }
async fn to_timezone(args: CommandArgs) -> Result<OutputStream, ShellError> { fn to_timezone(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (DateToTimeZoneArgs { timezone }, input) = args.process().await?; let (DateToTimeZoneArgs { timezone }, input) = args.process()?;
Ok(input Ok(input
.map(move |value| match value { .map(move |value| match value {

View file

@ -8,7 +8,6 @@ use nu_protocol::Signature;
pub struct Date; pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str { fn name(&self) -> &str {
"date utc" "date utc"
@ -22,13 +21,13 @@ impl WholeStreamCommand for Date {
"return the current date in utc." "return the current date in utc."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
utc(args).await utc(args)
} }
} }
pub async fn utc(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn utc(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let no_fmt = "".to_string(); let no_fmt = "".to_string();

View file

@ -10,7 +10,6 @@ pub struct DebugArgs {
raw: bool, raw: bool,
} }
#[async_trait]
impl WholeStreamCommand for Debug { impl WholeStreamCommand for Debug {
fn name(&self) -> &str { fn name(&self) -> &str {
"debug" "debug"
@ -24,13 +23,13 @@ impl WholeStreamCommand for Debug {
"Print the Rust debug representation of the values." "Print the Rust debug representation of the values."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
debug_value(args).await debug_value(args)
} }
} }
async fn debug_value(args: CommandArgs) -> Result<OutputStream, ShellError> { fn debug_value(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (DebugArgs { raw }, input) = args.process().await?; let (DebugArgs { raw }, input) = args.process()?;
Ok(input Ok(input
.map(move |v| { .map(move |v| {
if raw { if raw {

View file

@ -14,7 +14,6 @@ pub struct DefArgs {
pub block: CapturedBlock, pub block: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for Def { impl WholeStreamCommand for Def {
fn name(&self) -> &str { fn name(&self) -> &str {
"def" "def"
@ -35,7 +34,7 @@ impl WholeStreamCommand for Def {
"Create a command and set it to a definition." "Create a command and set it to a definition."
} }
async fn run(&self, _args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, _args: CommandArgs) -> Result<OutputStream, ShellError> {
// Currently, we don't do anything here because we should have already // Currently, we don't do anything here because we should have already
// installed the definition as we entered the scope // installed the definition as we entered the scope
// We just create a command so that we can get proper coloring // We just create a command so that we can get proper coloring

View file

@ -13,7 +13,6 @@ struct DefaultArgs {
pub struct Default; pub struct Default;
#[async_trait]
impl WholeStreamCommand for Default { impl WholeStreamCommand for Default {
fn name(&self) -> &str { fn name(&self) -> &str {
"default" "default"
@ -33,8 +32,8 @@ impl WholeStreamCommand for Default {
"Sets a default row's column if missing." "Sets a default row's column if missing."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
default(args).await default(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -46,8 +45,8 @@ impl WholeStreamCommand for Default {
} }
} }
async fn default(args: CommandArgs) -> Result<OutputStream, ShellError> { fn default(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (DefaultArgs { column, value }, input) = args.process().await?; let (DefaultArgs { column, value }, input) = args.process()?;
Ok(input Ok(input
.map(move |item| { .map(move |item| {

View file

@ -9,7 +9,6 @@ pub struct Describe;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct DescribeArgs {} pub struct DescribeArgs {}
#[async_trait]
impl WholeStreamCommand for Describe { impl WholeStreamCommand for Describe {
fn name(&self) -> &str { fn name(&self) -> &str {
"describe" "describe"
@ -23,12 +22,12 @@ impl WholeStreamCommand for Describe {
"Describes the objects in the stream." "Describes the objects in the stream."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
describe(args).await describe(args)
} }
} }
pub async fn describe(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn describe(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args Ok(args
.input .input
.map(|row| { .map(|row| {

View file

@ -12,7 +12,6 @@ struct DoArgs {
ignore_errors: bool, ignore_errors: bool,
} }
#[async_trait]
impl WholeStreamCommand for Do { impl WholeStreamCommand for Do {
fn name(&self) -> &str { fn name(&self) -> &str {
"do" "do"
@ -32,8 +31,8 @@ impl WholeStreamCommand for Do {
"Runs a block, optionally ignoring errors." "Runs a block, optionally ignoring errors."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
do_(args).await do_(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -52,7 +51,7 @@ impl WholeStreamCommand for Do {
} }
} }
async fn do_(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn do_(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let external_redirection = raw_args.call_info.args.external_redirection; let external_redirection = raw_args.call_info.args.external_redirection;
let context = EvaluationContext::from_args(&raw_args); let context = EvaluationContext::from_args(&raw_args);
@ -62,7 +61,7 @@ async fn do_(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
mut block, mut block,
}, },
input, input,
) = raw_args.process().await?; ) = raw_args.process()?;
let block_redirection = match external_redirection { let block_redirection = match external_redirection {
ExternalRedirection::None => { ExternalRedirection::None => {
@ -84,7 +83,7 @@ async fn do_(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
block.block.set_redirect(block_redirection); block.block.set_redirect(block_redirection);
context.scope.enter_scope(); context.scope.enter_scope();
let result = run_block(&block.block, &context, input).await; let result = run_block(&block.block, &context, input);
context.scope.exit_scope(); context.scope.exit_scope();
if ignore_errors { if ignore_errors {
@ -93,9 +92,9 @@ async fn do_(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
match result { match result {
Ok(mut stream) => { Ok(mut stream) => {
let output = stream.drain_vec().await; let output = stream.drain_vec();
context.clear_errors(); context.clear_errors();
Ok(futures::stream::iter(output).to_output_stream()) Ok(output.into_iter().to_output_stream())
} }
Err(_) => Ok(OutputStream::empty()), Err(_) => Ok(OutputStream::empty()),
} }

View file

@ -12,7 +12,6 @@ pub struct Arguments {
columns: Option<Tagged<u64>>, columns: Option<Tagged<u64>>,
} }
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"drop column" "drop column"
@ -30,12 +29,12 @@ impl WholeStreamCommand for SubCommand {
"Remove the last number of columns. If you want to remove columns by name, try 'reject'." "Remove the last number of columns. If you want to remove columns by name, try 'reject'."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
drop(args).await drop(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
use nu_protocol::{row, Value}; use nu_protocol::Value;
vec![Example { vec![Example {
description: "Remove the last column of a table", description: "Remove the last column of a table",
@ -48,8 +47,8 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> { fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { columns }, input) = args.process().await?; let (Arguments { columns }, input) = args.process()?;
let to_drop = if let Some(quantity) = columns { let to_drop = if let Some(quantity) = columns {
*quantity as usize *quantity as usize

View file

@ -11,7 +11,6 @@ pub struct Arguments {
rows: Option<Tagged<u64>>, rows: Option<Tagged<u64>>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"drop" "drop"
@ -29,8 +28,8 @@ impl WholeStreamCommand for Command {
"Remove the last number of rows or columns." "Remove the last number of rows or columns."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
drop(args).await drop(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -52,9 +51,9 @@ impl WholeStreamCommand for Command {
} }
} }
async fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> { fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rows }, input) = args.process().await?; let (Arguments { rows }, input) = args.process()?;
let v: Vec<_> = input.into_vec().await; let v: Vec<_> = input.into_vec();
let rows_to_drop = if let Some(quantity) = rows { let rows_to_drop = if let Some(quantity) = rows {
*quantity as usize *quantity as usize
@ -63,7 +62,7 @@ async fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> {
}; };
Ok(if rows_to_drop == 0 { Ok(if rows_to_drop == 0 {
futures::stream::iter(v).to_output_stream() v.into_iter().to_output_stream()
} else { } else {
let k = if v.len() < rows_to_drop { let k = if v.len() < rows_to_drop {
0 0
@ -73,6 +72,6 @@ async fn drop(args: CommandArgs) -> Result<OutputStream, ShellError> {
let iter = v.into_iter().take(k); let iter = v.into_iter().take(k);
futures::stream::iter(iter).to_output_stream() iter.to_output_stream()
}) })
} }

View file

@ -28,7 +28,6 @@ pub struct DuArgs {
min_size: Option<Tagged<u64>>, min_size: Option<Tagged<u64>>,
} }
#[async_trait]
impl WholeStreamCommand for Du { impl WholeStreamCommand for Du {
fn name(&self) -> &str { fn name(&self) -> &str {
NAME NAME
@ -71,8 +70,8 @@ impl WholeStreamCommand for Du {
"Find disk usage sizes of specified items." "Find disk usage sizes of specified items."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
du(args).await du(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -84,12 +83,12 @@ impl WholeStreamCommand for Du {
} }
} }
async fn du(args: CommandArgs) -> Result<OutputStream, ShellError> { fn du(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctrl_c = args.ctrl_c.clone(); let ctrl_c = args.ctrl_c.clone();
let ctrl_c_copy = ctrl_c.clone(); let ctrl_c_copy = ctrl_c.clone();
let (args, _): (DuArgs, _) = args.process().await?; let (args, _): (DuArgs, _) = args.process()?;
let exclude = args.exclude.map_or(Ok(None), move |x| { let exclude = args.exclude.map_or(Ok(None), move |x| {
Pattern::new(&x.item) Pattern::new(&x.item)
.map(Option::Some) .map(Option::Some)
@ -131,7 +130,7 @@ async fn du(args: CommandArgs) -> Result<OutputStream, ShellError> {
all, all,
}; };
let inp = futures::stream::iter(paths); let inp = paths;
Ok(inp Ok(inp
.flat_map(move |path| match path { .flat_map(move |path| match path {
@ -146,9 +145,9 @@ async fn du(args: CommandArgs) -> Result<OutputStream, ShellError> {
output.push(Ok(ReturnSuccess::Value(v.into()))); output.push(Ok(ReturnSuccess::Value(v.into())));
} }
} }
futures::stream::iter(output) output
} }
Err(e) => futures::stream::iter(vec![Err(e)]), Err(e) => vec![Err(e)],
}) })
.interruptible(ctrl_c_copy) .interruptible(ctrl_c_copy)
.to_output_stream()) .to_output_stream())

View file

@ -2,7 +2,6 @@ use crate::prelude::*;
use nu_engine::run_block; use nu_engine::run_block;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use futures::stream::once;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ use nu_protocol::{
hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
@ -17,7 +16,6 @@ pub struct EachArgs {
numbered: Tagged<bool>, numbered: Tagged<bool>,
} }
#[async_trait]
impl WholeStreamCommand for Each { impl WholeStreamCommand for Each {
fn name(&self) -> &str { fn name(&self) -> &str {
"each" "each"
@ -37,8 +35,8 @@ impl WholeStreamCommand for Each {
"Run a block on each row of the table." "Run a block on each row of the table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
each(args).await each(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -67,7 +65,7 @@ impl WholeStreamCommand for Each {
} }
} }
pub async fn process_row( pub fn process_row(
captured_block: Arc<Box<CapturedBlock>>, captured_block: Arc<Box<CapturedBlock>>,
context: Arc<EvaluationContext>, context: Arc<EvaluationContext>,
input: Value, input: Value,
@ -80,7 +78,7 @@ pub async fn process_row(
let input_stream = if !captured_block.block.params.positional.is_empty() { let input_stream = if !captured_block.block.params.positional.is_empty() {
InputStream::empty() InputStream::empty()
} else { } else {
once(async { Ok(input_clone) }).to_input_stream() vec![Ok(input_clone)].into_iter().to_input_stream()
}; };
context.scope.enter_scope(); context.scope.enter_scope();
@ -95,7 +93,7 @@ pub async fn process_row(
context.scope.add_var("$it", input); context.scope.add_var("$it", input);
} }
let result = run_block(&captured_block.block, &*context, input_stream).await; let result = run_block(&captured_block.block, &*context, input_stream);
context.scope.exit_scope(); context.scope.exit_scope();
@ -110,40 +108,36 @@ pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value {
dict.into_value() dict.into_value()
} }
async fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&raw_args));
let (each_args, input): (EachArgs, _) = raw_args.process().await?; let (each_args, input): (EachArgs, _) = raw_args.process()?;
let block = Arc::new(Box::new(each_args.block)); let block = Arc::new(Box::new(each_args.block));
if each_args.numbered.item { if each_args.numbered.item {
Ok(input Ok(input
.enumerate() .enumerate()
.then(move |input| { .map(move |input| {
let block = block.clone(); let block = block.clone();
let context = context.clone(); let context = context.clone();
let row = make_indexed_item(input.0, input.1); let row = make_indexed_item(input.0, input.1);
async { match process_row(block, context, row) {
match process_row(block, context, row).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()
.to_output_stream()) .to_output_stream())
} else { } else {
Ok(input Ok(input
.then(move |input| { .map(move |input| {
let block = block.clone(); let block = block.clone();
let context = context.clone(); let context = context.clone();
async { match process_row(block, context, input) {
match process_row(block, context, input).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()

View file

@ -17,7 +17,6 @@ pub struct EachGroupArgs {
//numbered: Tagged<bool>, //numbered: Tagged<bool>,
} }
#[async_trait]
impl WholeStreamCommand for EachGroup { impl WholeStreamCommand for EachGroup {
fn name(&self) -> &str { fn name(&self) -> &str {
"each group" "each group"
@ -45,16 +44,54 @@ impl WholeStreamCommand for EachGroup {
}] }]
} }
async fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&raw_args));
let (each_args, input): (EachGroupArgs, _) = raw_args.process().await?; let (each_args, input): (EachGroupArgs, _) = raw_args.process()?;
let block = Arc::new(Box::new(each_args.block)); let block = Arc::new(Box::new(each_args.block));
Ok(input let each_group_iterator = EachGroupIterator {
.chunks(each_args.group_size.item) block,
.then(move |input| run_block_on_vec(input, block.clone(), context.clone())) context,
.flatten() group_size: each_args.group_size.item,
.to_output_stream()) input,
};
Ok(each_group_iterator.flatten().to_output_stream())
}
}
struct EachGroupIterator {
block: Arc<Box<CapturedBlock>>,
context: Arc<EvaluationContext>,
group_size: usize,
input: InputStream,
}
impl Iterator for EachGroupIterator {
type Item = OutputStream;
fn next(&mut self) -> Option<Self::Item> {
let mut group = vec![];
let mut current_count = 0;
while let Some(next) = self.input.next() {
group.push(next);
current_count += 1;
if current_count >= self.group_size {
break;
}
}
if group.is_empty() {
return None;
}
Some(run_block_on_vec(
group,
self.block.clone(),
self.context.clone(),
))
} }
} }
@ -62,43 +99,43 @@ pub(crate) fn run_block_on_vec(
input: Vec<Value>, input: Vec<Value>,
block: Arc<Box<CapturedBlock>>, block: Arc<Box<CapturedBlock>>,
context: Arc<EvaluationContext>, context: Arc<EvaluationContext>,
) -> impl Future<Output = OutputStream> { ) -> OutputStream {
let value = Value { let value = Value {
value: UntaggedValue::Table(input), value: UntaggedValue::Table(input),
tag: Tag::unknown(), tag: Tag::unknown(),
}; };
async { match process_row(block, context, value) {
match process_row(block, context, value).await { Ok(s) => {
Ok(s) => { // We need to handle this differently depending on whether process_row
// We need to handle this differently depending on whether process_row // returned just 1 value or if it returned multiple as a stream.
// returned just 1 value or if it returned multiple as a stream. let vec = s.collect::<Vec<_>>();
let vec = s.collect::<Vec<_>>().await;
// If it returned just one value, just take that value // If it returned just one value, just take that value
if vec.len() == 1 { if vec.len() == 1 {
return OutputStream::one(vec.into_iter().next().expect( return OutputStream::one(
"This should be impossible, we just checked that vec.len() == 1.", vec.into_iter()
)); .next()
} .expect("This should be impossible, we just checked that vec.len() == 1."),
);
// If it returned multiple values, we need to put them into a table and
// return that.
let result = vec.into_iter().collect::<Result<Vec<ReturnSuccess>, _>>();
let result_table = match result {
Ok(t) => t,
Err(e) => return OutputStream::one(Err(e)),
};
let table = result_table
.into_iter()
.filter_map(|x| x.raw_value())
.collect();
OutputStream::one(Ok(ReturnSuccess::Value(UntaggedValue::Table(table).into())))
} }
Err(e) => OutputStream::one(Err(e)),
// If it returned multiple values, we need to put them into a table and
// return that.
let result = vec.into_iter().collect::<Result<Vec<ReturnSuccess>, _>>();
let result_table = match result {
Ok(t) => t,
Err(e) => return OutputStream::one(Err(e)),
};
let table = result_table
.into_iter()
.filter_map(|x| x.raw_value())
.collect();
OutputStream::one(Ok(ReturnSuccess::Value(UntaggedValue::Table(table).into())))
} }
Err(e) => OutputStream::one(Err(e)),
} }
} }

View file

@ -16,7 +16,6 @@ pub struct EachWindowArgs {
stride: Option<Tagged<usize>>, stride: Option<Tagged<usize>>,
} }
#[async_trait]
impl WholeStreamCommand for EachWindow { impl WholeStreamCommand for EachWindow {
fn name(&self) -> &str { fn name(&self) -> &str {
"each window" "each window"
@ -50,16 +49,15 @@ impl WholeStreamCommand for EachWindow {
}] }]
} }
async fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&raw_args));
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process().await?; let (each_args, mut input): (EachWindowArgs, _) = raw_args.process()?;
let block = Arc::new(Box::new(each_args.block)); let block = Arc::new(Box::new(each_args.block));
let mut window: Vec<_> = input let mut window: Vec<_> = input
.by_ref() .by_ref()
.take(*each_args.window_size - 1) .take(*each_args.window_size - 1)
.collect::<Vec<_>>() .collect::<Vec<_>>();
.await;
// `window` must start with dummy values, which will be removed on the first iteration // `window` must start with dummy values, which will be removed on the first iteration
let stride = each_args.stride.map(|x| *x).unwrap_or(1); let stride = each_args.stride.map(|x| *x).unwrap_or(1);
@ -67,7 +65,7 @@ impl WholeStreamCommand for EachWindow {
Ok(input Ok(input
.enumerate() .enumerate()
.then(move |(i, input)| { .map(move |(i, input)| {
// This would probably be more efficient if `last` was a VecDeque // This would probably be more efficient if `last` was a VecDeque
// But we can't have that because it needs to be put into a Table // But we can't have that because it needs to be put into a Table
window.remove(0); window.remove(0);
@ -77,15 +75,13 @@ impl WholeStreamCommand for EachWindow {
let context = context.clone(); let context = context.clone();
let local_window = window.clone(); let local_window = window.clone();
async move { if i % stride == 0 {
if i % stride == 0 { Some(run_block_on_vec(local_window, block, context))
Some(run_block_on_vec(local_window, block, context).await) } else {
} else { None
None
}
} }
}) })
.filter_map(|x| async { x }) .filter_map(|x| x)
.flatten() .flatten()
.to_output_stream()) .to_output_stream())
} }

View file

@ -13,7 +13,6 @@ pub struct EchoArgs {
pub rest: Vec<Value>, pub rest: Vec<Value>,
} }
#[async_trait]
impl WholeStreamCommand for Echo { impl WholeStreamCommand for Echo {
fn name(&self) -> &str { fn name(&self) -> &str {
"echo" "echo"
@ -27,8 +26,8 @@ impl WholeStreamCommand for Echo {
"Echo the arguments back to the user." "Echo the arguments back to the user."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
echo(args).await echo(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -47,8 +46,8 @@ impl WholeStreamCommand for Echo {
} }
} }
async fn echo(args: CommandArgs) -> Result<OutputStream, ShellError> { fn echo(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (args, _): (EchoArgs, _) = args.process().await?; let (args, _): (EchoArgs, _) = args.process()?;
let stream = args.rest.into_iter().map(|i| match i.as_string() { let stream = args.rest.into_iter().map(|i| match i.as_string() {
Ok(s) => OutputStream::one(Ok(ReturnSuccess::Value( Ok(s) => OutputStream::one(Ok(ReturnSuccess::Value(
@ -58,17 +57,19 @@ async fn echo(args: CommandArgs) -> Result<OutputStream, ShellError> {
Value { Value {
value: UntaggedValue::Table(table), value: UntaggedValue::Table(table),
.. ..
} => futures::stream::iter(table.into_iter().map(ReturnSuccess::value)) } => table
.into_iter()
.map(ReturnSuccess::value)
.to_output_stream(), .to_output_stream(),
Value { Value {
value: UntaggedValue::Primitive(Primitive::Range(range)), value: UntaggedValue::Primitive(Primitive::Range(range)),
tag, tag,
} => futures::stream::iter(RangeIterator::new(*range, tag)).to_output_stream(), } => RangeIterator::new(*range, tag).to_output_stream(),
x => OutputStream::one(Ok(ReturnSuccess::Value(x))), x => OutputStream::one(Ok(ReturnSuccess::Value(x))),
}, },
}); });
Ok(futures::stream::iter(stream).flatten().to_output_stream()) Ok(stream.flatten().to_output_stream())
} }
struct RangeIterator { struct RangeIterator {

View file

@ -8,7 +8,6 @@ use nu_protocol::{
}; };
use crate::utils::arguments::arguments; use crate::utils::arguments::arguments;
use futures::stream::once;
use nu_value_ext::{as_string, ValueExt}; use nu_value_ext::{as_string, ValueExt};
#[derive(Deserialize)] #[derive(Deserialize)]
@ -18,7 +17,6 @@ pub struct Arguments {
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"empty?" "empty?"
@ -35,8 +33,8 @@ impl WholeStreamCommand for Command {
"Check for empty values." "Check for empty values."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
is_empty(args).await is_empty(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -81,32 +79,28 @@ impl WholeStreamCommand for Command {
} }
} }
async fn is_empty(args: CommandArgs) -> Result<OutputStream, ShellError> { fn is_empty(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let name_tag = Arc::new(args.call_info.name_tag.clone()); let name_tag = Arc::new(args.call_info.name_tag.clone());
let context = Arc::new(EvaluationContext::from_args(&args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (Arguments { mut rest }, input) = args.process().await?; let (Arguments { mut rest }, input) = args.process()?;
let (columns, default_block): (Vec<ColumnPath>, Option<Box<CapturedBlock>>) = let (columns, default_block): (Vec<ColumnPath>, Option<Box<CapturedBlock>>) =
arguments(&mut rest)?; arguments(&mut rest)?;
let default_block = Arc::new(default_block); let default_block = Arc::new(default_block);
if input.is_empty() { if input.is_empty() {
let stream = futures::stream::iter(vec![ let stream = vec![UntaggedValue::Primitive(Primitive::Nothing).into_value(tag)].into_iter();
UntaggedValue::Primitive(Primitive::Nothing).into_value(tag)
]);
return Ok(InputStream::from_stream(stream) return Ok(InputStream::from_stream(stream)
.then(move |input| { .map(move |input| {
let tag = name_tag.clone(); let tag = name_tag.clone();
let context = context.clone(); let context = context.clone();
let block = default_block.clone(); let block = default_block.clone();
let columns = vec![]; let columns = vec![];
async { match process_row(context, input, block, columns, tag) {
match process_row(context, input, block, columns, tag).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()
@ -114,24 +108,22 @@ async fn is_empty(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
Ok(input Ok(input
.then(move |input| { .map(move |input| {
let tag = name_tag.clone(); let tag = name_tag.clone();
let context = context.clone(); let context = context.clone();
let block = default_block.clone(); let block = default_block.clone();
let columns = columns.clone(); let columns = columns.clone();
async { match process_row(context, input, block, columns, tag) {
match process_row(context, input, block, columns, tag).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()
.to_output_stream()) .to_output_stream())
} }
async fn process_row( fn process_row(
context: Arc<EvaluationContext>, context: Arc<EvaluationContext>,
input: Value, input: Value,
default_block: Arc<Option<Box<CapturedBlock>>>, default_block: Arc<Option<Box<CapturedBlock>>>,
@ -144,18 +136,18 @@ async fn process_row(
if let Some(default_block) = &*default_block { if let Some(default_block) = &*default_block {
let for_block = input.clone(); let for_block = input.clone();
let input_stream = once(async { Ok(for_block) }).to_input_stream(); let input_stream = vec![Ok(for_block)].into_iter().to_input_stream();
context.scope.enter_scope(); context.scope.enter_scope();
context.scope.add_vars(&default_block.captured.entries); context.scope.add_vars(&default_block.captured.entries);
context.scope.add_var("$it", input.clone()); context.scope.add_var("$it", input.clone());
let stream = run_block(&default_block.block, &*context, input_stream).await; let stream = run_block(&default_block.block, &*context, input_stream);
context.scope.exit_scope(); context.scope.exit_scope();
let mut stream = stream?; let mut stream = stream?;
*results = Some({ *results = Some({
let values = stream.drain_vec().await; let values = stream.drain_vec();
let errors = context.get_errors(); let errors = context.get_errors();

View file

@ -17,7 +17,6 @@ pub struct EnterArgs {
encoding: Option<Tagged<String>>, encoding: Option<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Enter { impl WholeStreamCommand for Enter {
fn name(&self) -> &str { fn name(&self) -> &str {
"enter" "enter"
@ -51,8 +50,8 @@ For a more complete list of encodings please refer to the encoding_rs
documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"# documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"#
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
enter(args).await enter(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -76,7 +75,7 @@ documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"#
} }
} }
async fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let scope = raw_args.scope.clone(); let scope = raw_args.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();
@ -85,13 +84,12 @@ async fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
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().await?; let (EnterArgs { location, encoding }, _) = raw_args.process()?;
let location_string = location.display().to_string(); let location_string = location.display().to_string();
let location_clone = location_string.clone();
if location.is_dir() { if location.is_dir() {
Ok(OutputStream::one(ReturnSuccess::action( Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterShell(location_clone), CommandAction::EnterShell(location_string),
))) )))
} else { } else {
// If it's a file, attempt to open the file as a value and enter it // If it's a file, attempt to open the file as a value and enter it
@ -102,11 +100,10 @@ async fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let (file_extension, tagged_contents) = crate::commands::open::fetch( let (file_extension, tagged_contents) = crate::commands::open::fetch(
&full_path, &full_path,
&PathBuf::from(location_clone), &PathBuf::from(location_string),
span, span,
encoding, encoding,
) )?;
.await?;
match tagged_contents.value { match tagged_contents.value {
UntaggedValue::Primitive(Primitive::String(_)) => { UntaggedValue::Primitive(Primitive::String(_)) => {
@ -127,18 +124,17 @@ async fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
span: Span::unknown(), span: Span::unknown(),
external_redirection: ExternalRedirection::Stdout, external_redirection: ExternalRedirection::Stdout,
}, },
name_tag: tag.clone(), name_tag: tag,
}, },
scope: scope.clone(), scope,
}; };
let tag = tagged_contents.tag.clone(); let tag = tagged_contents.tag.clone();
let mut result = converter let mut result =
.run(new_args.with_input(vec![tagged_contents])) converter.run(new_args.with_input(vec![tagged_contents]))?;
.await?; let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec();
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = Ok(result_vec
result.drain_vec().await; .into_iter()
Ok(futures::stream::iter(result_vec.into_iter().map( .map(move |res| match res {
move |res| match res {
Ok(ReturnSuccess::Value(Value { value, .. })) => Ok( Ok(ReturnSuccess::Value(Value { value, .. })) => Ok(
ReturnSuccess::Action(CommandAction::EnterValueShell(Value { ReturnSuccess::Action(CommandAction::EnterValueShell(Value {
value, value,
@ -146,9 +142,8 @@ async fn enter(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
})), })),
), ),
x => x, x => x,
}, })
)) .to_output_stream())
.to_output_stream())
} else { } else {
Ok(OutputStream::one(ReturnSuccess::action( Ok(OutputStream::one(ReturnSuccess::action(
CommandAction::EnterValueShell(tagged_contents), CommandAction::EnterValueShell(tagged_contents),

View file

@ -12,7 +12,6 @@ pub struct EveryArgs {
skip: Tagged<bool>, skip: Tagged<bool>,
} }
#[async_trait]
impl WholeStreamCommand for Every { impl WholeStreamCommand for Every {
fn name(&self) -> &str { fn name(&self) -> &str {
"every" "every"
@ -36,8 +35,8 @@ impl WholeStreamCommand for Every {
"Show (or skip) every n-th row, starting from the first one." "Show (or skip) every n-th row, starting from the first one."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
every(args).await every(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -63,15 +62,15 @@ impl WholeStreamCommand for Every {
} }
} }
async fn every(args: CommandArgs) -> Result<OutputStream, ShellError> { fn every(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (EveryArgs { stride, skip }, input) = args.process().await?; let (EveryArgs { stride, skip }, input) = args.process()?;
let stride = stride.item; let stride = stride.item;
let skip = skip.item; let skip = skip.item;
Ok(input Ok(input
.enumerate() .enumerate()
.filter_map(move |(i, value)| async move { .filter_map(move |(i, value)| {
let stride_desired = if stride < 1 { 1 } else { stride } as usize; let stride_desired = if stride < 1 { 1 } else { stride } as usize;
let should_include = skip == (i % stride_desired != 0); let should_include = skip == (i % stride_desired != 0);

View file

@ -13,7 +13,6 @@ pub struct ExecArgs {
pub rest: Vec<Tagged<String>>, pub rest: Vec<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Exec { impl WholeStreamCommand for Exec {
fn name(&self) -> &str { fn name(&self) -> &str {
"exec" "exec"
@ -32,8 +31,8 @@ impl WholeStreamCommand for Exec {
"Execute command." "Execute command."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
exec(args).await exec(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -53,12 +52,12 @@ impl WholeStreamCommand for Exec {
} }
#[cfg(unix)] #[cfg(unix)]
async fn exec(args: CommandArgs) -> Result<OutputStream, ShellError> { fn exec(args: CommandArgs) -> Result<OutputStream, ShellError> {
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
use std::process::Command; use std::process::Command;
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (args, _): (ExecArgs, _) = args.process().await?; let (args, _): (ExecArgs, _) = args.process()?;
let mut command = Command::new(args.command.item); let mut command = Command::new(args.command.item);
for tagged_arg in args.rest { for tagged_arg in args.rest {
@ -75,7 +74,7 @@ async fn exec(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
#[cfg(not(unix))] #[cfg(not(unix))]
async fn exec(args: CommandArgs) -> Result<OutputStream, ShellError> { fn exec(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"Error on exec", "Error on exec",
"exec is not supported on your platform", "exec is not supported on your platform",

View file

@ -4,7 +4,6 @@ use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape};
pub struct Exit; pub struct Exit;
#[async_trait]
impl WholeStreamCommand for Exit { impl WholeStreamCommand for Exit {
fn name(&self) -> &str { fn name(&self) -> &str {
"exit" "exit"
@ -24,8 +23,8 @@ impl WholeStreamCommand for Exit {
"Exit the current shell (or all shells)." "Exit the current shell (or all shells)."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
exit(args).await exit(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -44,8 +43,8 @@ impl WholeStreamCommand for Exit {
} }
} }
pub async fn exit(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn exit(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let code = if let Some(value) = args.call_info.args.nth(0) { let code = if let Some(value) = args.call_info.args.nth(0) {
value.as_i32()? value.as_i32()?

View file

@ -11,7 +11,6 @@ pub struct FirstArgs {
rows: Option<Tagged<usize>>, rows: Option<Tagged<usize>>,
} }
#[async_trait]
impl WholeStreamCommand for First { impl WholeStreamCommand for First {
fn name(&self) -> &str { fn name(&self) -> &str {
"first" "first"
@ -29,8 +28,8 @@ impl WholeStreamCommand for First {
"Show only the first number of rows." "Show only the first number of rows."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
first(args).await first(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -52,8 +51,8 @@ impl WholeStreamCommand for First {
} }
} }
async fn first(args: CommandArgs) -> Result<OutputStream, ShellError> { fn first(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (FirstArgs { rows }, input) = args.process().await?; let (FirstArgs { rows }, input) = args.process()?;
let rows_desired = if let Some(quantity) = rows { let rows_desired = if let Some(quantity) = rows {
*quantity *quantity
} else { } else {

View file

@ -13,7 +13,6 @@ pub struct Arguments {
rest: Vec<Tagged<String>>, rest: Vec<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"flatten" "flatten"
@ -27,8 +26,8 @@ impl WholeStreamCommand for Command {
"Flatten the table." "Flatten the table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
flatten(args).await flatten(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -52,12 +51,12 @@ impl WholeStreamCommand for Command {
} }
} }
async fn flatten(args: CommandArgs) -> Result<OutputStream, ShellError> { fn flatten(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { rest: columns }, input) = args.process().await?; let (Arguments { rest: columns }, input) = args.process()?;
Ok(input Ok(input
.map(move |item| futures::stream::iter(flat_value(&columns, &item, &tag).into_iter())) .map(move |item| flat_value(&columns, &item, &tag).into_iter())
.flatten() .flatten()
.to_output_stream()) .to_output_stream())
} }

View file

@ -13,7 +13,6 @@ pub struct FormatArgs {
pattern: Tagged<String>, pattern: Tagged<String>,
} }
#[async_trait]
impl WholeStreamCommand for Format { impl WholeStreamCommand for Format {
fn name(&self) -> &str { fn name(&self) -> &str {
"format" "format"
@ -31,8 +30,8 @@ impl WholeStreamCommand for Format {
"Format columns into a string using a simple pattern." "Format columns into a string using a simple pattern."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
format_command(args).await format_command(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -44,49 +43,46 @@ impl WholeStreamCommand for Format {
} }
} }
async fn format_command(args: CommandArgs) -> Result<OutputStream, ShellError> { fn format_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = Arc::new(EvaluationContext::from_args(&args)); let ctx = Arc::new(EvaluationContext::from_args(&args));
let (FormatArgs { pattern }, input) = args.process().await?; let (FormatArgs { pattern }, input) = args.process()?;
let format_pattern = format(&pattern); let format_pattern = format(&pattern);
let commands = Arc::new(format_pattern); let commands = Arc::new(format_pattern);
Ok(input Ok(input
.then(move |value| { .map(move |value| {
let mut output = String::new(); let mut output = String::new();
let commands = commands.clone(); let commands = commands.clone();
let ctx = ctx.clone(); let ctx = ctx.clone();
async move { for command in &*commands {
for command in &*commands { match command {
match command { FormatCommand::Text(s) => {
FormatCommand::Text(s) => { output.push_str(&s);
output.push_str(&s); }
} FormatCommand::Column(c) => {
FormatCommand::Column(c) => { // FIXME: use the correct spans
// FIXME: use the correct spans let full_column_path = nu_parser::parse_full_column_path(
let full_column_path = nu_parser::parse_full_column_path( &(c.to_string()).spanned(Span::unknown()),
&(c.to_string()).spanned(Span::unknown()), &ctx.scope,
&ctx.scope, );
);
ctx.scope.enter_scope(); ctx.scope.enter_scope();
ctx.scope.add_var("$it", value.clone()); ctx.scope.add_var("$it", value.clone());
let result = evaluate_baseline_expr(&full_column_path.0, &*ctx).await; let result = evaluate_baseline_expr(&full_column_path.0, &*ctx);
ctx.scope.exit_scope(); ctx.scope.exit_scope();
if let Ok(c) = result { if let Ok(c) = result {
output output.push_str(&value::format_leaf(c.borrow()).plain_string(100_000))
.push_str(&value::format_leaf(c.borrow()).plain_string(100_000)) } else {
} else { // That column doesn't match, so don't emit anything
// That column doesn't match, so don't emit anything
}
} }
} }
} }
ReturnSuccess::value(UntaggedValue::string(output).into_untagged_value())
} }
ReturnSuccess::value(UntaggedValue::string(output).into_untagged_value())
}) })
.to_output_stream()) .to_output_stream())
} }

View file

@ -16,7 +16,6 @@ pub struct Arguments {
format: Tagged<String>, format: Tagged<String>,
} }
#[async_trait]
impl WholeStreamCommand for FileSize { impl WholeStreamCommand for FileSize {
fn name(&self) -> &str { fn name(&self) -> &str {
"format filesize" "format filesize"
@ -40,8 +39,8 @@ impl WholeStreamCommand for FileSize {
"Converts a column of filesizes to some specified format" "Converts a column of filesizes to some specified format"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
filesize(args).await filesize(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -60,7 +59,7 @@ impl WholeStreamCommand for FileSize {
} }
} }
async fn process_row( fn process_row(
input: Value, input: Value,
format: Tagged<String>, format: Tagged<String>,
field: Arc<ColumnPath>, field: Arc<ColumnPath>,
@ -92,20 +91,18 @@ async fn process_row(
}) })
} }
async fn filesize(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn filesize(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { field, format }, input) = raw_args.process().await?; let (Arguments { field, format }, input) = raw_args.process()?;
let field = Arc::new(field); let field = Arc::new(field);
Ok(input Ok(input
.then(move |input| { .map(move |input| {
let format = format.clone(); let format = format.clone();
let field = field.clone(); let field = field.clone();
async { match process_row(input, format, field) {
match process_row(input, format, field).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()

View file

@ -5,7 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
pub struct From; pub struct From;
#[async_trait]
impl WholeStreamCommand for From { impl WholeStreamCommand for From {
fn name(&self) -> &str { fn name(&self) -> &str {
"from" "from"
@ -19,7 +18,7 @@ impl WholeStreamCommand for From {
"Parse content (string or binary) as a table (input format based on subcommand, like csv, ini, json, toml)." "Parse content (string or binary) as a table (input format based on subcommand, like csv, ini, json, toml)."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(get_full_help(&From, &args.scope)).into_value(Tag::unknown()), UntaggedValue::string(get_full_help(&From, &args.scope)).into_value(Tag::unknown()),
))) )))

View file

@ -12,7 +12,6 @@ pub struct FromCsvArgs {
separator: Option<Value>, separator: Option<Value>,
} }
#[async_trait]
impl WholeStreamCommand for FromCsv { impl WholeStreamCommand for FromCsv {
fn name(&self) -> &str { fn name(&self) -> &str {
"from csv" "from csv"
@ -37,8 +36,8 @@ impl WholeStreamCommand for FromCsv {
"Parse text as .csv and create table." "Parse text as .csv and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_csv(args).await from_csv(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -67,7 +66,7 @@ impl WholeStreamCommand for FromCsv {
} }
} }
async fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ( let (
@ -76,7 +75,7 @@ async fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
separator, separator,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
let sep = match separator { let sep = match separator {
Some(Value { Some(Value {
value: UntaggedValue::Primitive(Primitive::String(s)), value: UntaggedValue::Primitive(Primitive::String(s)),
@ -100,7 +99,7 @@ async fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
_ => ',', _ => ',',
}; };
from_delimited_data(noheaders, sep, "CSV", input, name).await from_delimited_data(noheaders, sep, "CSV", input, name)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -45,7 +45,7 @@ fn from_delimited_string_to_value(
Ok(UntaggedValue::Table(rows).into_value(&tag)) Ok(UntaggedValue::Table(rows).into_value(&tag))
} }
pub async fn from_delimited_data( pub fn from_delimited_data(
noheaders: bool, noheaders: bool,
sep: char, sep: char,
format_name: &'static str, format_name: &'static str,
@ -53,7 +53,7 @@ pub async 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 concat_string = input.collect_string(name_tag.clone())?;
let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n"); let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n");
match from_delimited_string_to_value(concat_string.item, noheaders, sep, name_tag.clone()) { match from_delimited_string_to_value(concat_string.item, noheaders, sep, name_tag.clone()) {
@ -61,7 +61,7 @@ pub async fn from_delimited_data(
Value { Value {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => Ok(futures::stream::iter(list).to_output_stream()), } => Ok(list.into_iter().to_output_stream()),
x => Ok(OutputStream::one(x)), x => Ok(OutputStream::one(x)),
}, },
Err(err) => { Err(err) => {
@ -80,7 +80,7 @@ pub async fn from_delimited_data(
Err(ShellError::labeled_error_with_secondary( Err(ShellError::labeled_error_with_secondary(
line_one, line_one,
line_two, line_two,
name_tag.clone(), name_tag,
"value originates from here", "value originates from here",
concat_string.tag, concat_string.tag,
)) ))

View file

@ -16,7 +16,6 @@ pub struct FromEmlArgs {
preview_body: Option<Tagged<usize>>, preview_body: Option<Tagged<usize>>,
} }
#[async_trait]
impl WholeStreamCommand for FromEml { impl WholeStreamCommand for FromEml {
fn name(&self) -> &str { fn name(&self) -> &str {
"from eml" "from eml"
@ -35,8 +34,8 @@ impl WholeStreamCommand for FromEml {
"Parse text as .eml and create table." "Parse text as .eml and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_eml(args).await from_eml(args)
} }
} }
@ -73,10 +72,10 @@ fn headerfieldvalue_to_value(tag: &Tag, value: &HeaderFieldValue) -> UntaggedVal
} }
} }
async fn from_eml(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_eml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (eml_args, input): (FromEmlArgs, _) = args.process().await?; let (eml_args, input): (FromEmlArgs, _) = args.process()?;
let value = input.collect_string(tag.clone()).await?; let value = input.collect_string(tag.clone())?;
let body_preview = eml_args let body_preview = eml_args
.preview_body .preview_body

View file

@ -9,7 +9,6 @@ use std::io::BufReader;
pub struct FromIcs; pub struct FromIcs;
#[async_trait]
impl WholeStreamCommand for FromIcs { impl WholeStreamCommand for FromIcs {
fn name(&self) -> &str { fn name(&self) -> &str {
"from ics" "from ics"
@ -23,17 +22,17 @@ impl WholeStreamCommand for FromIcs {
"Parse text as .ics and create table." "Parse text as .ics and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_ics(args).await from_ics(args)
} }
} }
async fn from_ics(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_ics(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?.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::IcalParser::new(buf_reader); let parser = ical::IcalParser::new(buf_reader);
@ -53,7 +52,7 @@ async fn from_ics(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
} }
Ok(futures::stream::iter(output).to_output_stream()) Ok(output.into_iter().to_output_stream())
} }
fn calendar_to_value(calendar: IcalCalendar, tag: Tag) -> Value { fn calendar_to_value(calendar: IcalCalendar, tag: Tag) -> Value {

View file

@ -6,7 +6,6 @@ use std::collections::HashMap;
pub struct FromIni; pub struct FromIni;
#[async_trait]
impl WholeStreamCommand for FromIni { impl WholeStreamCommand for FromIni {
fn name(&self) -> &str { fn name(&self) -> &str {
"from ini" "from ini"
@ -20,8 +19,8 @@ impl WholeStreamCommand for FromIni {
"Parse text as .ini and create table" "Parse text as .ini and create table"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_ini(args).await from_ini(args)
} }
} }
@ -60,18 +59,18 @@ 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))
} }
async fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?;
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 {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => Ok(futures::stream::iter(list).to_output_stream()), } => Ok(list.into_iter().to_output_stream()),
x => Ok(OutputStream::one(x)), x => Ok(OutputStream::one(x)),
}, },
Err(_) => Err(ShellError::labeled_error_with_secondary( Err(_) => Err(ShellError::labeled_error_with_secondary(

View file

@ -10,7 +10,6 @@ pub struct FromJsonArgs {
objects: bool, objects: bool,
} }
#[async_trait]
impl WholeStreamCommand for FromJson { impl WholeStreamCommand for FromJson {
fn name(&self) -> &str { fn name(&self) -> &str {
"from json" "from json"
@ -28,8 +27,8 @@ impl WholeStreamCommand for FromJson {
"Parse text as .json and create table." "Parse text as .json and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_json(args).await from_json(args)
} }
} }
@ -68,17 +67,18 @@ pub fn from_json_string_to_value(s: String, tag: impl Into<Tag>) -> nu_json::Res
Ok(convert_json_value_to_nu_value(&v, tag)) Ok(convert_json_value_to_nu_value(&v, tag))
} }
async fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name_tag = args.call_info.name_tag.clone(); let name_tag = args.call_info.name_tag.clone();
let (FromJsonArgs { objects }, input) = args.process().await?; let (FromJsonArgs { objects }, input) = args.process()?;
let concat_string = input.collect_string(name_tag.clone()).await?; let concat_string = input.collect_string(name_tag.clone())?;
let string_clone: Vec<_> = concat_string.item.lines().map(|x| x.to_string()).collect(); let string_clone: Vec<_> = concat_string.item.lines().map(|x| x.to_string()).collect();
if objects { if objects {
Ok( Ok(string_clone
futures::stream::iter(string_clone.into_iter().filter_map(move |json_str| { .into_iter()
.filter_map(move |json_str| {
if json_str.is_empty() { if json_str.is_empty() {
return None; return None;
} }
@ -99,19 +99,19 @@ async fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
))) )))
} }
} }
})) })
.to_output_stream(), .to_output_stream())
)
} else { } else {
match from_json_string_to_value(concat_string.item, name_tag.clone()) { match from_json_string_to_value(concat_string.item, name_tag.clone()) {
Ok(x) => match x { Ok(x) => match x {
Value { Value {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => Ok( } => Ok(list
futures::stream::iter(list.into_iter().map(ReturnSuccess::value)) .into_iter()
.to_output_stream(), .map(ReturnSuccess::value)
), .to_output_stream()),
x => Ok(OutputStream::one(ReturnSuccess::value(x))), x => Ok(OutputStream::one(ReturnSuccess::value(x))),
}, },
Err(e) => { Err(e) => {

View file

@ -13,7 +13,6 @@ pub struct FromOdsArgs {
noheaders: bool, noheaders: bool,
} }
#[async_trait]
impl WholeStreamCommand for FromOds { impl WholeStreamCommand for FromOds {
fn name(&self) -> &str { fn name(&self) -> &str {
"from ods" "from ods"
@ -31,12 +30,12 @@ impl WholeStreamCommand for FromOds {
"Parse OpenDocument Spreadsheet(.ods) data and create table." "Parse OpenDocument Spreadsheet(.ods) data and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_ods(args).await from_ods(args)
} }
} }
async fn from_ods(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_ods(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let span = tag.span; let span = tag.span;
@ -45,8 +44,8 @@ async fn from_ods(args: CommandArgs) -> Result<OutputStream, ShellError> {
noheaders: _noheaders, noheaders: _noheaders,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
let bytes = input.collect_binary(tag.clone()).await?; let bytes = input.collect_binary(tag.clone())?;
let buf: Cursor<Vec<u8>> = Cursor::new(bytes.item); let buf: Cursor<Vec<u8>> = Cursor::new(bytes.item);
let mut ods = Ods::<_>::new(buf).map_err(|_| { let mut ods = Ods::<_>::new(buf).map_err(|_| {
ShellError::labeled_error("Could not load ods file", "could not load ods file", &tag) ShellError::labeled_error("Could not load ods file", "could not load ods file", &tag)

View file

@ -20,7 +20,6 @@ pub struct FromSsvArgs {
const STRING_REPRESENTATION: &str = "from ssv"; const STRING_REPRESENTATION: &str = "from ssv";
const DEFAULT_MINIMUM_SPACES: usize = 2; const DEFAULT_MINIMUM_SPACES: usize = 2;
#[async_trait]
impl WholeStreamCommand for FromSsv { impl WholeStreamCommand for FromSsv {
fn name(&self) -> &str { fn name(&self) -> &str {
STRING_REPRESENTATION STRING_REPRESENTATION
@ -46,8 +45,8 @@ impl WholeStreamCommand for FromSsv {
"Parse text as space-separated values and create a table. The default minimum number of spaces counted as a separator is 2." "Parse text as space-separated values and create a table. The default minimum number of spaces counted as a separator is 2."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_ssv(args).await from_ssv(args)
} }
} }
@ -247,7 +246,7 @@ fn from_ssv_string_to_value(
UntaggedValue::Table(rows).into_value(&tag) UntaggedValue::Table(rows).into_value(&tag)
} }
async fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ( let (
FromSsvArgs { FromSsvArgs {
@ -256,8 +255,8 @@ async fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> {
minimum_spaces, minimum_spaces,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
let concat_string = input.collect_string(name.clone()).await?; let concat_string = input.collect_string(name.clone())?;
let split_at = match minimum_spaces { let split_at = match minimum_spaces {
Some(number) => number.item, Some(number) => number.item,
None => DEFAULT_MINIMUM_SPACES, None => DEFAULT_MINIMUM_SPACES,
@ -269,14 +268,15 @@ async fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> {
noheaders, noheaders,
aligned_columns, aligned_columns,
split_at, split_at,
name.clone(), name,
) { ) {
Value { Value {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => { } => list
futures::stream::iter(list.into_iter().map(ReturnSuccess::value)).to_output_stream() .into_iter()
} .map(ReturnSuccess::value)
.to_output_stream(),
x => OutputStream::one(ReturnSuccess::value(x)), x => OutputStream::one(ReturnSuccess::value(x)),
}, },
) )

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, Untagg
pub struct FromToml; pub struct FromToml;
#[async_trait]
impl WholeStreamCommand for FromToml { impl WholeStreamCommand for FromToml {
fn name(&self) -> &str { fn name(&self) -> &str {
"from toml" "from toml"
@ -19,8 +18,8 @@ impl WholeStreamCommand for FromToml {
"Parse text as .toml and create table." "Parse text as .toml and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_toml(args).await from_toml(args)
} }
} }
@ -61,19 +60,21 @@ pub fn from_toml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value
Ok(convert_toml_value_to_nu_value(&v, tag)) Ok(convert_toml_value_to_nu_value(&v, tag))
} }
pub async fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?;
Ok( Ok(
match from_toml_string_to_value(concat_string.item, tag.clone()) { match from_toml_string_to_value(concat_string.item, tag.clone()) {
Ok(x) => match x { Ok(x) => match x {
Value { Value {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => futures::stream::iter(list.into_iter().map(ReturnSuccess::value)) } => list
.into_iter()
.map(ReturnSuccess::value)
.to_output_stream(), .to_output_stream(),
x => OutputStream::one(ReturnSuccess::value(x)), x => OutputStream::one(ReturnSuccess::value(x)),
}, },

View file

@ -11,7 +11,6 @@ pub struct FromTsvArgs {
noheaders: bool, noheaders: bool,
} }
#[async_trait]
impl WholeStreamCommand for FromTsv { impl WholeStreamCommand for FromTsv {
fn name(&self) -> &str { fn name(&self) -> &str {
"from tsv" "from tsv"
@ -29,16 +28,16 @@ impl WholeStreamCommand for FromTsv {
"Parse text as .tsv and create table." "Parse text as .tsv and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_tsv(args).await from_tsv(args)
} }
} }
async fn from_tsv(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_tsv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (FromTsvArgs { noheaders }, input) = args.process().await?; let (FromTsvArgs { noheaders }, input) = args.process()?;
from_delimited_data(noheaders, '\t', "TSV", input, name).await from_delimited_data(noheaders, '\t', "TSV", input, name)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -5,7 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue};
pub struct FromUrl; pub struct FromUrl;
#[async_trait]
impl WholeStreamCommand for FromUrl { impl WholeStreamCommand for FromUrl {
fn name(&self) -> &str { fn name(&self) -> &str {
"from url" "from url"
@ -19,17 +18,17 @@ impl WholeStreamCommand for FromUrl {
"Parse url-encoded string as a table." "Parse url-encoded string as a table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_url(args).await from_url(args)
} }
} }
async fn from_url(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_url(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?;
let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item); let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item);

View file

@ -8,7 +8,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, Untagg
pub struct FromVcf; pub struct FromVcf;
#[async_trait]
impl WholeStreamCommand for FromVcf { impl WholeStreamCommand for FromVcf {
fn name(&self) -> &str { fn name(&self) -> &str {
"from vcf" "from vcf"
@ -22,17 +21,17 @@ impl WholeStreamCommand for FromVcf {
"Parse text as .vcf and create table." "Parse text as .vcf and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_vcf(args).await from_vcf(args)
} }
} }
async fn from_vcf(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_vcf(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?.item;
let input_bytes = input_string.into_bytes(); let input_bytes = input_string.into_bytes();
let cursor = std::io::Cursor::new(input_bytes); let cursor = std::io::Cursor::new(input_bytes);
let parser = ical::VcardParser::new(cursor); let parser = ical::VcardParser::new(cursor);
@ -46,7 +45,9 @@ async fn from_vcf(args: CommandArgs) -> Result<OutputStream, ShellError> {
)), )),
}); });
Ok(futures::stream::iter(iter).to_output_stream()) let collected: Vec<_> = iter.collect();
Ok(collected.into_iter().to_output_stream())
} }
fn contact_to_value(contact: VcardContact, tag: Tag) -> Value { fn contact_to_value(contact: VcardContact, tag: Tag) -> Value {

View file

@ -13,7 +13,6 @@ pub struct FromXlsxArgs {
noheaders: bool, noheaders: bool,
} }
#[async_trait]
impl WholeStreamCommand for FromXlsx { impl WholeStreamCommand for FromXlsx {
fn name(&self) -> &str { fn name(&self) -> &str {
"from xlsx" "from xlsx"
@ -31,12 +30,12 @@ impl WholeStreamCommand for FromXlsx {
"Parse binary Excel(.xlsx) data and create table." "Parse binary Excel(.xlsx) data and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_xlsx(args).await from_xlsx(args)
} }
} }
async fn from_xlsx(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_xlsx(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let span = tag.span; let span = tag.span;
let ( let (
@ -44,8 +43,8 @@ async fn from_xlsx(args: CommandArgs) -> Result<OutputStream, ShellError> {
noheaders: _noheaders, noheaders: _noheaders,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
let value = input.collect_binary(tag.clone()).await?; let value = input.collect_binary(tag.clone())?;
let buf: Cursor<Vec<u8>> = Cursor::new(value.item); let buf: Cursor<Vec<u8>> = Cursor::new(value.item);
let mut xls = Xlsx::<_>::new(buf).map_err(|_| { let mut xls = Xlsx::<_>::new(buf).map_err(|_| {

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, TaggedDictBuilder, Untagg
pub struct FromXml; pub struct FromXml;
#[async_trait]
impl WholeStreamCommand for FromXml { impl WholeStreamCommand for FromXml {
fn name(&self) -> &str { fn name(&self) -> &str {
"from xml" "from xml"
@ -19,8 +18,8 @@ impl WholeStreamCommand for FromXml {
"Parse text as .xml and create table." "Parse text as .xml and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_xml(args).await from_xml(args)
} }
} }
@ -95,12 +94,12 @@ pub fn from_xml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value,
Ok(from_document_to_value(&parsed, tag)) Ok(from_document_to_value(&parsed, tag))
} }
async fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?;
Ok( Ok(
match from_xml_string_to_value(concat_string.item, tag.clone()) { match from_xml_string_to_value(concat_string.item, tag.clone()) {
@ -108,7 +107,9 @@ async fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
Value { Value {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => futures::stream::iter(list.into_iter().map(ReturnSuccess::value)) } => list
.into_iter()
.map(ReturnSuccess::value)
.to_output_stream(), .to_output_stream(),
x => OutputStream::one(ReturnSuccess::value(x)), x => OutputStream::one(ReturnSuccess::value(x)),
}, },

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}
pub struct FromYaml; pub struct FromYaml;
#[async_trait]
impl WholeStreamCommand for FromYaml { impl WholeStreamCommand for FromYaml {
fn name(&self) -> &str { fn name(&self) -> &str {
"from yaml" "from yaml"
@ -19,14 +18,13 @@ impl WholeStreamCommand for FromYaml {
"Parse text as .yaml/.yml and create table." "Parse text as .yaml/.yml and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_yaml(args).await from_yaml(args)
} }
} }
pub struct FromYml; pub struct FromYml;
#[async_trait]
impl WholeStreamCommand for FromYml { impl WholeStreamCommand for FromYml {
fn name(&self) -> &str { fn name(&self) -> &str {
"from yml" "from yml"
@ -40,8 +38,8 @@ impl WholeStreamCommand for FromYml {
"Parse text as .yaml/.yml and create table." "Parse text as .yaml/.yml and create table."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
from_yaml(args).await from_yaml(args)
} }
} }
@ -133,19 +131,19 @@ pub fn from_yaml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value
convert_yaml_value_to_nu_value(&v, tag) convert_yaml_value_to_nu_value(&v, tag)
} }
async fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> { fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
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())?;
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 {
value: UntaggedValue::Table(list), value: UntaggedValue::Table(list),
.. ..
} => Ok(futures::stream::iter(list).to_output_stream()), } => Ok(list.into_iter().to_output_stream()),
x => Ok(OutputStream::one(x)), x => Ok(OutputStream::one(x)),
}, },
Err(_) => Err(ShellError::labeled_error_with_secondary( Err(_) => Err(ShellError::labeled_error_with_secondary(

View file

@ -18,7 +18,6 @@ pub struct Arguments {
rest: Vec<Value>, rest: Vec<Value>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"get" "get"
@ -35,8 +34,8 @@ impl WholeStreamCommand for Command {
"Open given cells as text." "Open given cells as text."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
get(args).await get(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -55,26 +54,28 @@ impl WholeStreamCommand for Command {
} }
} }
pub async fn get(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { mut rest }, mut input) = args.process().await?; let (Arguments { mut rest }, mut input) = args.process()?;
let (column_paths, _) = arguments(&mut rest)?; let (column_paths, _) = arguments(&mut rest)?;
if column_paths.is_empty() { if column_paths.is_empty() {
let vec = input.drain_vec().await; let vec = input.drain_vec();
let descs = nu_protocol::merge_descriptors(&vec); let descs = nu_protocol::merge_descriptors(&vec);
Ok(futures::stream::iter(descs.into_iter().map(ReturnSuccess::value)).to_output_stream()) Ok(descs
.into_iter()
.map(ReturnSuccess::value)
.to_output_stream())
} else { } else {
trace!("get {:?}", column_paths); trace!("get {:?}", column_paths);
let output_stream = input let output_stream = input
.map(move |item| { .map(move |item| {
let output = column_paths column_paths
.iter() .iter()
.map(move |path| get_output(&item, path)) .map(move |path| get_output(&item, path))
.flatten() .flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>()
futures::stream::iter(output)
}) })
.flatten() .flatten()
.to_output_stream(); .to_output_stream();

View file

@ -13,7 +13,6 @@ pub struct Arguments {
grouper: Option<Value>, grouper: Option<Value>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"group-by" "group-by"
@ -31,8 +30,8 @@ impl WholeStreamCommand for Command {
"Create a new table grouped." "Create a new table grouped."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
group_by(args).await group_by(args)
} }
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
@ -128,12 +127,12 @@ enum Grouper {
ByBlock, ByBlock,
} }
pub async fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let context = Arc::new(EvaluationContext::from_args(&args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (Arguments { grouper }, input) = args.process().await?; let (Arguments { grouper }, input) = args.process()?;
let values: Vec<Value> = input.collect().await; let values: Vec<Value> = input.collect();
let mut keys: Vec<Result<String, ShellError>> = vec![]; let mut keys: Vec<Result<String, ShellError>> = vec![];
let mut group_strategy = Grouper::ByColumn(None); let mut group_strategy = Grouper::ByColumn(None);
@ -149,10 +148,9 @@ pub async fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
let run = block.clone(); let run = block.clone();
let context = context.clone(); let context = context.clone();
match crate::commands::each::process_row(run, context, value.clone()).await { match crate::commands::each::process_row(run, context, value.clone()) {
Ok(mut s) => { Ok(mut s) => {
let collection: Vec<Result<ReturnSuccess, ShellError>> = let collection: Vec<Result<ReturnSuccess, ShellError>> = s.drain_vec();
s.drain_vec().await;
if collection.len() > 1 { if collection.len() > 1 {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -209,7 +207,7 @@ pub async fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
let group_value = match group_strategy { let group_value = match group_strategy {
Grouper::ByBlock => { Grouper::ByBlock => {
let map = keys.clone(); let map = keys;
let block = Box::new(move |idx: usize, row: &Value| match map.get(idx) { let block = Box::new(move |idx: usize, row: &Value| match map.get(idx) {
Some(Ok(key)) => Ok(key.clone()), Some(Ok(key)) => Ok(key.clone()),

View file

@ -13,7 +13,6 @@ pub struct GroupByDateArgs {
format: Option<Tagged<String>>, format: Option<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for GroupByDate { impl WholeStreamCommand for GroupByDate {
fn name(&self) -> &str { fn name(&self) -> &str {
"group-by date" "group-by date"
@ -38,8 +37,8 @@ impl WholeStreamCommand for GroupByDate {
"creates a table grouped by date." "creates a table grouped by date."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
group_by_date(args).await group_by_date(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -59,7 +58,7 @@ enum GroupByColumn {
Name(Option<Tagged<String>>), Name(Option<Tagged<String>>),
} }
pub async fn group_by_date(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn group_by_date(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ( let (
GroupByDateArgs { GroupByDateArgs {
@ -67,8 +66,8 @@ pub async fn group_by_date(args: CommandArgs) -> Result<OutputStream, ShellError
format, format,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
let values: Vec<Value> = input.collect().await; let values: Vec<Value> = input.collect();
if values.is_empty() { if values.is_empty() {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(

View file

@ -30,7 +30,6 @@ pub enum ActionType {
} }
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"hash base64" "hash base64"
@ -65,8 +64,8 @@ impl WholeStreamCommand for SubCommand {
"base64 encode or decode a value" "base64 encode or decode a value"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
operate(args).await operate(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -96,8 +95,8 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> { fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name_tag = &args.call_info.name_tag.clone(); let name_tag = args.call_info.name_tag.clone();
let ( let (
Arguments { Arguments {
@ -107,7 +106,7 @@ async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
rest, rest,
}, },
input, input,
) = args.process().await?; ) = args.process()?;
if encode.item && decode.item { if encode.item && decode.item {
return Ok(OutputStream::one(Err(ShellError::labeled_error( return Ok(OutputStream::one(Err(ShellError::labeled_error(

View file

@ -5,7 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
pub struct Command; pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"hash" "hash"
@ -22,7 +21,7 @@ impl WholeStreamCommand for Command {
"Apply hash function." "Apply hash function."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(ReturnSuccess::value( Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()), UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()),
))) )))

View file

@ -14,7 +14,6 @@ pub struct Arguments {
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"hash md5" "hash md5"
@ -31,8 +30,8 @@ impl WholeStreamCommand for SubCommand {
"md5 encode a value" "md5 encode a value"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
operate(args).await operate(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -57,8 +56,8 @@ impl WholeStreamCommand for SubCommand {
} }
} }
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> { fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rest }, input) = args.process().await?; let (Arguments { rest }, input) = args.process()?;
let column_paths: Vec<_> = rest; let column_paths: Vec<_> = rest;

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use futures::stream::StreamExt;
use indexmap::IndexMap; use indexmap::IndexMap;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
@ -8,7 +8,6 @@ use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
pub struct Headers; pub struct Headers;
#[async_trait]
impl WholeStreamCommand for Headers { impl WholeStreamCommand for Headers {
fn name(&self) -> &str { fn name(&self) -> &str {
"headers" "headers"
@ -22,8 +21,8 @@ impl WholeStreamCommand for Headers {
"Use the first row of the table as column names." "Use the first row of the table as column names."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
headers(args).await headers(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -42,9 +41,9 @@ impl WholeStreamCommand for Headers {
} }
} }
pub async fn headers(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn headers(args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
let rows: Vec<Value> = input.collect().await; let rows: Vec<Value> = input.collect();
if rows.is_empty() { if rows.is_empty() {
return Err(ShellError::untagged_runtime_error( return Err(ShellError::untagged_runtime_error(
@ -77,8 +76,10 @@ pub async fn headers(args: CommandArgs) -> Result<OutputStream, ShellError> {
)), )),
}?; }?;
Ok( Ok(rows
futures::stream::iter(rows.into_iter().skip(1).map(move |r| { .into_iter()
.skip(1)
.map(move |r| {
//Each row is a dictionary with the headers as keys //Each row is a dictionary with the headers as keys
match &r.value { match &r.value {
UntaggedValue::Row(d) => { UntaggedValue::Row(d) => {
@ -100,9 +101,8 @@ pub async fn headers(args: CommandArgs) -> Result<OutputStream, ShellError> {
r.tag.span, r.tag.span,
)), )),
} }
})) })
.to_output_stream(), .to_output_stream())
)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -18,7 +18,6 @@ pub struct HelpArgs {
rest: Vec<Tagged<String>>, rest: Vec<Tagged<String>>,
} }
#[async_trait]
impl WholeStreamCommand for Help { impl WholeStreamCommand for Help {
fn name(&self) -> &str { fn name(&self) -> &str {
"help" "help"
@ -32,15 +31,15 @@ impl WholeStreamCommand for Help {
"Display help information about commands." "Display help information about commands."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
help(args).await help(args)
} }
} }
async fn help(args: CommandArgs) -> Result<OutputStream, ShellError> { fn help(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let scope = args.scope.clone(); let scope = args.scope.clone();
let (HelpArgs { rest }, ..) = args.process().await?; let (HelpArgs { rest }, ..) = args.process()?;
if !rest.is_empty() { if !rest.is_empty() {
if rest[0].item == "commands" { if rest[0].item == "commands" {
@ -155,7 +154,7 @@ async fn help(args: CommandArgs) -> Result<OutputStream, ShellError> {
ReturnSuccess::value(short_desc.into_value()) ReturnSuccess::value(short_desc.into_value())
}); });
Ok(futures::stream::iter(iterator).to_output_stream()) Ok(iterator.to_output_stream())
} else if rest[0].item == "generate_docs" { } else if rest[0].item == "generate_docs" {
Ok(OutputStream::one(ReturnSuccess::value(generate_docs( Ok(OutputStream::one(ReturnSuccess::value(generate_docs(
&scope, &scope,

View file

@ -8,7 +8,6 @@ use nu_source::Tagged;
pub struct Histogram; pub struct Histogram;
#[async_trait]
impl WholeStreamCommand for Histogram { impl WholeStreamCommand for Histogram {
fn name(&self) -> &str { fn name(&self) -> &str {
"histogram" "histogram"
@ -32,8 +31,8 @@ impl WholeStreamCommand for Histogram {
"Creates a new table with a histogram based on the column name passed in." "Creates a new table with a histogram based on the column name passed in."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
histogram(args).await histogram(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -58,11 +57,11 @@ impl WholeStreamCommand for Histogram {
} }
} }
pub async fn histogram(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn histogram(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (input, args) = args.evaluate_once().await?.parts(); let (input, args) = args.evaluate_once()?.parts();
let values: Vec<Value> = input.collect().await; let values: Vec<Value> = input.collect();
let mut columns = args let mut columns = args
.positional_iter() .positional_iter()
@ -114,73 +113,71 @@ pub async fn histogram(args: CommandArgs) -> Result<OutputStream, ShellError> {
let labels = results.labels.y.clone(); let labels = results.labels.y.clone();
let mut idx = 0; let mut idx = 0;
Ok(futures::stream::iter( Ok(results
results .data
.data .table_entries()
.table_entries() .cloned()
.cloned() .collect::<Vec<_>>()
.collect::<Vec<_>>() .into_iter()
.into_iter() .zip(
.zip( results
results .percentages
.percentages .table_entries()
.table_entries() .cloned()
.cloned() .collect::<Vec<_>>()
.collect::<Vec<_>>() .into_iter(),
.into_iter(), )
) .map(move |(counts, percentages)| {
.map(move |(counts, percentages)| { let percentage = percentages
let percentage = percentages .table_entries()
.table_entries() .cloned()
.cloned() .last()
.last() .unwrap_or_else(|| {
.unwrap_or_else(|| { UntaggedValue::decimal_from_float(0.0, name.span).into_value(&name)
UntaggedValue::decimal_from_float(0.0, name.span).into_value(&name) });
}); let value = counts
let value = counts .table_entries()
.table_entries() .cloned()
.cloned() .last()
.last() .unwrap_or_else(|| UntaggedValue::int(0).into_value(&name));
.unwrap_or_else(|| UntaggedValue::int(0).into_value(&name));
let mut fact = TaggedDictBuilder::new(&name); let mut fact = TaggedDictBuilder::new(&name);
let column_value = labels let column_value = labels
.get(idx) .get(idx)
.ok_or_else(|| { .ok_or_else(|| {
ShellError::labeled_error( ShellError::labeled_error(
"Unable to load group labels", "Unable to load group labels",
"unable to load group labels", "unable to load group labels",
&name, &name,
) )
})? })?
.clone(); .clone();
fact.insert_value(&column.item, column_value); fact.insert_value(&column.item, column_value);
fact.insert_untagged("count", value); fact.insert_untagged("count", value);
let fmt_percentage = format!( let fmt_percentage = format!(
"{}%", "{}%",
// Some(2) < the number of digits // Some(2) < the number of digits
// true < group the digits // true < group the digits
crate::commands::str_::from::action(&percentage, &name, Some(2), true)? crate::commands::str_::from::action(&percentage, &name, Some(2), true)?
.as_string()? .as_string()?
); );
fact.insert_untagged("percentage", UntaggedValue::string(fmt_percentage)); fact.insert_untagged("percentage", UntaggedValue::string(fmt_percentage));
let string = std::iter::repeat("*") let string = std::iter::repeat("*")
.take(percentage.as_u64().map_err(|_| { .take(percentage.as_u64().map_err(|_| {
ShellError::labeled_error("expected a number", "expected a number", &name) ShellError::labeled_error("expected a number", "expected a number", &name)
})? as usize) })? as usize)
.collect::<String>(); .collect::<String>();
fact.insert_untagged(&frequency_column_name, UntaggedValue::string(string)); fact.insert_untagged(&frequency_column_name, UntaggedValue::string(string));
idx += 1; idx += 1;
ReturnSuccess::value(fact.into_value()) ReturnSuccess::value(fact.into_value())
}), })
) .to_output_stream())
.to_output_stream())
} }
fn evaluator(by: ColumnPath) -> Box<dyn Fn(usize, &Value) -> Result<Value, ShellError> + Send> { fn evaluator(by: ColumnPath) -> Box<dyn Fn(usize, &Value) -> Result<Value, ShellError> + Send> {

View file

@ -13,7 +13,6 @@ struct Arguments {
pub struct History; pub struct History;
#[async_trait]
impl WholeStreamCommand for History { impl WholeStreamCommand for History {
fn name(&self) -> &str { fn name(&self) -> &str {
"history" "history"
@ -27,15 +26,15 @@ impl WholeStreamCommand for History {
"Display command history." "Display command history."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
history(args).await history(args)
} }
} }
async fn history(args: CommandArgs) -> Result<OutputStream, ShellError> { fn history(args: CommandArgs) -> Result<OutputStream, ShellError> {
let config: Box<dyn Conf> = Box::new(NuConfig::new()); let config: Box<dyn Conf> = Box::new(NuConfig::new());
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { clear }, _) = args.process().await?; let (Arguments { clear }, _) = args.process()?;
let path = nu_data::config::path::history_path(&config); let path = nu_data::config::path::history_path(&config);
@ -55,7 +54,7 @@ async fn history(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(_) => None, Err(_) => None,
}); });
Ok(futures::stream::iter(output).to_output_stream()) Ok(output.to_output_stream())
} else { } else {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"Could not open history", "Could not open history",

View file

@ -16,7 +16,6 @@ pub struct IfArgs {
else_case: CapturedBlock, else_case: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for If { impl WholeStreamCommand for If {
fn name(&self) -> &str { fn name(&self) -> &str {
"if" "if"
@ -45,8 +44,8 @@ impl WholeStreamCommand for If {
"Run blocks if a condition is true or false." "Run blocks if a condition is true or false."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
if_command(args).await if_command(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -64,7 +63,7 @@ impl WholeStreamCommand for If {
] ]
} }
} }
async fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = raw_args.call_info.name_tag.clone(); let tag = raw_args.call_info.name_tag.clone();
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&raw_args));
@ -75,7 +74,7 @@ async fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
else_case, else_case,
}, },
input, input,
) = raw_args.process().await?; ) = raw_args.process()?;
let cond = { let cond = {
if condition.block.block.len() != 1 { if condition.block.block.len() != 1 {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -109,22 +108,22 @@ async fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
context.scope.add_vars(&condition.captured.entries); context.scope.add_vars(&condition.captured.entries);
//FIXME: should we use the scope that's brought in as well? //FIXME: should we use the scope that's brought in as well?
let condition = evaluate_baseline_expr(&cond, &*context).await; let condition = evaluate_baseline_expr(&cond, &*context);
match condition { match condition {
Ok(condition) => match condition.as_bool() { Ok(condition) => match condition.as_bool() {
Ok(b) => { Ok(b) => {
let result = if b { let result = if b {
run_block(&then_case.block, &*context, input).await run_block(&then_case.block, &*context, input)
} else { } else {
run_block(&else_case.block, &*context, input).await run_block(&else_case.block, &*context, input)
}; };
context.scope.exit_scope(); context.scope.exit_scope();
result.map(|x| x.to_output_stream()) result.map(|x| x.to_output_stream())
} }
Err(e) => Ok(futures::stream::iter(vec![Err(e)].into_iter()).to_output_stream()), Err(e) => Ok(vec![Err(e)].into_iter().to_output_stream()),
}, },
Err(e) => Ok(futures::stream::iter(vec![Err(e)].into_iter()).to_output_stream()), Err(e) => Ok(vec![Err(e)].into_iter().to_output_stream()),
} }
} }

View file

@ -7,8 +7,6 @@ use nu_protocol::{
}; };
use nu_value_ext::ValueExt; use nu_value_ext::ValueExt;
use futures::stream::once;
pub struct Command; pub struct Command;
#[derive(Deserialize)] #[derive(Deserialize)]
@ -17,7 +15,6 @@ pub struct Arguments {
value: Value, value: Value,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"insert" "insert"
@ -37,8 +34,8 @@ impl WholeStreamCommand for Command {
"Insert a new column with a given value." "Insert a new column with a given value."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
insert(args).await insert(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -64,7 +61,7 @@ impl WholeStreamCommand for Command {
} }
} }
async fn process_row( fn process_row(
context: Arc<EvaluationContext>, context: Arc<EvaluationContext>,
input: Value, input: Value,
mut value: Arc<Value>, mut value: Arc<Value>,
@ -78,19 +75,19 @@ async fn process_row(
tag: block_tag, tag: block_tag,
} => { } => {
let for_block = input.clone(); let for_block = input.clone();
let input_stream = once(async { Ok(for_block) }).to_input_stream(); let input_stream = vec![Ok(for_block)].into_iter().to_input_stream();
context.scope.enter_scope(); context.scope.enter_scope();
context.scope.add_vars(&block.captured.entries); context.scope.add_vars(&block.captured.entries);
context.scope.add_var("$it", input.clone()); context.scope.add_var("$it", input.clone());
let result = run_block(&block.block, &*context, input_stream).await; let result = run_block(&block.block, &*context, input_stream);
context.scope.exit_scope(); context.scope.exit_scope();
match result { match result {
Ok(mut stream) => { Ok(mut stream) => {
let values = stream.drain_vec().await; let values = stream.drain_vec();
let errors = context.get_errors(); let errors = context.get_errors();
if let Some(error) = errors.first() { if let Some(error) = errors.first() {
@ -153,23 +150,21 @@ async fn process_row(
}) })
} }
async fn insert(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn insert(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&raw_args));
let (Arguments { column, value }, input) = raw_args.process().await?; let (Arguments { column, value }, input) = raw_args.process()?;
let value = Arc::new(value); let value = Arc::new(value);
let column = Arc::new(column); let column = Arc::new(column);
Ok(input Ok(input
.then(move |input| { .map(move |input| {
let context = context.clone(); let context = context.clone();
let value = value.clone(); let value = value.clone();
let column = column.clone(); let column = column.clone();
async { match process_row(context, input, value, column) {
match process_row(context, input, value, column).await { Ok(s) => s,
Ok(s) => s, Err(e) => OutputStream::one(Err(e)),
Err(e) => OutputStream::one(Err(e)),
}
} }
}) })
.flatten() .flatten()

View file

@ -12,7 +12,6 @@ pub struct IntoIntArgs {
pub rest: Vec<Value>, pub rest: Vec<Value>,
} }
#[async_trait]
impl WholeStreamCommand for IntoInt { impl WholeStreamCommand for IntoInt {
fn name(&self) -> &str { fn name(&self) -> &str {
"into-int" "into-int"
@ -26,8 +25,8 @@ impl WholeStreamCommand for IntoInt {
"Convert value to integer." "Convert value to integer."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
into_int(args).await into_int(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -46,8 +45,8 @@ impl WholeStreamCommand for IntoInt {
} }
} }
async fn into_int(args: CommandArgs) -> Result<OutputStream, ShellError> { fn into_int(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (args, _): (IntoIntArgs, _) = args.process().await?; let (args, _): (IntoIntArgs, _) = args.process()?;
let stream = args.rest.into_iter().map(|i| match i { let stream = args.rest.into_iter().map(|i| match i {
Value { Value {
@ -71,7 +70,7 @@ async fn into_int(args: CommandArgs) -> Result<OutputStream, ShellError> {
_ => OutputStream::one(Ok(ReturnSuccess::Value(i))), _ => OutputStream::one(Ok(ReturnSuccess::Value(i))),
}); });
Ok(futures::stream::iter(stream).flatten().to_output_stream()) Ok(stream.flatten().to_output_stream())
} }
#[cfg(test)] #[cfg(test)]

View file

@ -11,7 +11,6 @@ pub struct Arguments {
rows: Option<Tagged<usize>>, rows: Option<Tagged<usize>>,
} }
#[async_trait]
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"keep" "keep"
@ -29,8 +28,8 @@ impl WholeStreamCommand for Command {
"Keep the number of rows only." "Keep the number of rows only."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
keep(args).await keep(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -54,8 +53,8 @@ impl WholeStreamCommand for Command {
} }
} }
async fn keep(args: CommandArgs) -> Result<OutputStream, ShellError> { fn keep(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { rows }, input) = args.process().await?; let (Arguments { rows }, input) = args.process()?;
let rows_desired = if let Some(quantity) = rows { let rows_desired = if let Some(quantity) = rows {
*quantity *quantity
} else { } else {

View file

@ -8,7 +8,6 @@ use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue,
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"keep until" "keep until"
@ -28,10 +27,10 @@ impl WholeStreamCommand for SubCommand {
"Keeps rows until the condition matches." "Keeps rows until the condition matches."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = Arc::new(EvaluationContext::from_args(&args)); let ctx = Arc::new(EvaluationContext::from_args(&args));
let call_info = args.evaluate_once().await?; let call_info = args.evaluate_once()?;
let block = call_info.args.expect_nth(0)?.clone(); let block = call_info.args.expect_nth(0)?.clone();
@ -88,13 +87,11 @@ impl WholeStreamCommand for SubCommand {
ctx.scope.add_var("$it", item.clone()); ctx.scope.add_var("$it", item.clone());
trace!("ITEM = {:?}", item); trace!("ITEM = {:?}", item);
async move { let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&*condition, &*ctx).await; ctx.scope.exit_scope();
ctx.scope.exit_scope(); trace!("RESULT = {:?}", result);
trace!("RESULT = {:?}", result);
!matches!(result, Ok(ref v) if v.is_true()) !matches!(result, Ok(ref v) if v.is_true())
}
}) })
.to_output_stream()) .to_output_stream())
} }

View file

@ -7,7 +7,6 @@ use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue,
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"keep while" "keep while"
@ -27,9 +26,9 @@ impl WholeStreamCommand for SubCommand {
"Keeps rows while the condition matches." "Keeps rows while the condition matches."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = Arc::new(EvaluationContext::from_args(&args)); let ctx = Arc::new(EvaluationContext::from_args(&args));
let call_info = args.evaluate_once().await?; let call_info = args.evaluate_once()?;
let block = call_info.args.expect_nth(0)?.clone(); let block = call_info.args.expect_nth(0)?.clone();
@ -87,13 +86,11 @@ impl WholeStreamCommand for SubCommand {
ctx.scope.add_vars(&captured.entries); ctx.scope.add_vars(&captured.entries);
trace!("ITEM = {:?}", item); trace!("ITEM = {:?}", item);
async move { let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&*condition, &*ctx).await; ctx.scope.exit_scope();
ctx.scope.exit_scope(); trace!("RESULT = {:?}", result);
trace!("RESULT = {:?}", result);
matches!(result, Ok(ref v) if v.is_true()) matches!(result, Ok(ref v) if v.is_true())
}
}) })
.to_output_stream()) .to_output_stream())
} }

View file

@ -16,7 +16,6 @@ pub struct KillArgs {
pub signal: Option<Tagged<u32>>, pub signal: Option<Tagged<u32>>,
} }
#[async_trait]
impl WholeStreamCommand for Kill { impl WholeStreamCommand for Kill {
fn name(&self) -> &str { fn name(&self) -> &str {
"kill" "kill"
@ -49,8 +48,8 @@ impl WholeStreamCommand for Kill {
"Kill a process using the process id." "Kill a process using the process id."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
kill(args).await kill(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -74,7 +73,7 @@ impl WholeStreamCommand for Kill {
} }
} }
async fn kill(args: CommandArgs) -> Result<OutputStream, ShellError> { fn kill(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ( let (
KillArgs { KillArgs {
pid, pid,
@ -84,7 +83,7 @@ async fn kill(args: CommandArgs) -> Result<OutputStream, ShellError> {
signal, signal,
}, },
.., ..,
) = args.process().await?; ) = args.process()?;
let mut cmd = if cfg!(windows) { let mut cmd = if cfg!(windows) {
let mut cmd = Command::new("taskkill"); let mut cmd = Command::new("taskkill");

View file

@ -11,7 +11,6 @@ pub struct LastArgs {
rows: Option<Tagged<u64>>, rows: Option<Tagged<u64>>,
} }
#[async_trait]
impl WholeStreamCommand for Last { impl WholeStreamCommand for Last {
fn name(&self) -> &str { fn name(&self) -> &str {
"last" "last"
@ -29,8 +28,8 @@ impl WholeStreamCommand for Last {
"Show only the last number of rows." "Show only the last number of rows."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
last(args).await last(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -53,9 +52,9 @@ impl WholeStreamCommand for Last {
} }
} }
async fn last(args: CommandArgs) -> Result<OutputStream, ShellError> { fn last(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (LastArgs { rows }, input) = args.process().await?; let (LastArgs { rows }, input) = args.process()?;
let v: Vec<_> = input.into_vec().await; let v: Vec<_> = input.into_vec();
let end_rows_desired = if let Some(quantity) = rows { let end_rows_desired = if let Some(quantity) = rows {
*quantity as usize *quantity as usize
@ -71,7 +70,7 @@ async fn last(args: CommandArgs) -> Result<OutputStream, ShellError> {
let iter = v.into_iter().skip(beginning_rows_to_skip); let iter = v.into_iter().skip(beginning_rows_to_skip);
Ok(futures::stream::iter(iter).to_output_stream()) Ok((iter).to_output_stream())
} }
#[cfg(test)] #[cfg(test)]

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use futures::stream::StreamExt;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, UntaggedValue, Value}; use nu_protocol::{Signature, UntaggedValue, Value};
@ -11,7 +11,6 @@ pub struct LengthArgs {
column: bool, column: bool,
} }
#[async_trait]
impl WholeStreamCommand for Length { impl WholeStreamCommand for Length {
fn name(&self) -> &str { fn name(&self) -> &str {
"length" "length"
@ -29,10 +28,10 @@ impl WholeStreamCommand for Length {
"Show the total number of rows or items." "Show the total number of rows or items."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (LengthArgs { column }, input) = args.process().await?; let (LengthArgs { column }, input) = args.process()?;
let rows: Vec<Value> = input.collect().await; let rows: Vec<Value> = input.collect();
let length = if column { let length = if column {
if rows.is_empty() { if rows.is_empty() {

View file

@ -14,7 +14,6 @@ pub struct LetArgs {
pub rhs: CapturedBlock, pub rhs: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for Let { impl WholeStreamCommand for Let {
fn name(&self) -> &str { fn name(&self) -> &str {
"let" "let"
@ -35,8 +34,8 @@ impl WholeStreamCommand for Let {
"Create a variable and give it a value." "Create a variable and give it a value."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
letcmd(args).await letcmd(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -44,11 +43,11 @@ impl WholeStreamCommand for Let {
} }
} }
pub async fn letcmd(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn letcmd(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let (LetArgs { name, rhs, .. }, _) = args.process().await?; let (LetArgs { name, rhs, .. }, _) = args.process()?;
let (expr, captured) = { let (expr, captured) = {
if rhs.block.block.len() != 1 { if rhs.block.block.len() != 1 {
@ -82,14 +81,14 @@ pub async fn letcmd(args: CommandArgs) -> Result<OutputStream, ShellError> {
ctx.scope.enter_scope(); ctx.scope.enter_scope();
ctx.scope.add_vars(&captured.entries); ctx.scope.add_vars(&captured.entries);
let value = evaluate_baseline_expr(&expr, &ctx).await; let value = evaluate_baseline_expr(&expr, &ctx);
ctx.scope.exit_scope(); ctx.scope.exit_scope();
let value = value?; let value = value?;
let name = if name.item.starts_with('$') { let name = if name.item.starts_with('$') {
name.item.clone() name.item
} else { } else {
format!("${}", name.item) format!("${}", name.item)
}; };

View file

@ -14,7 +14,6 @@ pub struct LetEnvArgs {
pub rhs: CapturedBlock, pub rhs: CapturedBlock,
} }
#[async_trait]
impl WholeStreamCommand for LetEnv { impl WholeStreamCommand for LetEnv {
fn name(&self) -> &str { fn name(&self) -> &str {
"let-env" "let-env"
@ -39,8 +38,8 @@ impl WholeStreamCommand for LetEnv {
"Create an environment variable and give it a value." "Create an environment variable and give it a value."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
set_env(args).await set_env(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -48,11 +47,11 @@ impl WholeStreamCommand for LetEnv {
} }
} }
pub async fn set_env(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn set_env(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let (LetEnvArgs { name, rhs, .. }, _) = args.process().await?; let (LetEnvArgs { name, rhs, .. }, _) = args.process()?;
let (expr, captured) = { let (expr, captured) = {
if rhs.block.block.len() != 1 { if rhs.block.block.len() != 1 {
@ -86,14 +85,14 @@ pub async fn set_env(args: CommandArgs) -> Result<OutputStream, ShellError> {
ctx.scope.enter_scope(); ctx.scope.enter_scope();
ctx.scope.add_vars(&captured.entries); ctx.scope.add_vars(&captured.entries);
let value = evaluate_baseline_expr(&expr, &ctx).await; let value = evaluate_baseline_expr(&expr, &ctx);
ctx.scope.exit_scope(); ctx.scope.exit_scope();
let value = value?; let value = value?;
let value = value.as_string()?; let value = value.as_string()?;
let name = name.item.clone(); let name = name.item;
// Note: this is a special case for setting the context from a command // Note: this is a special case for setting the context from a command
// In this case, if we don't set it now, we'll lose the scope that this // In this case, if we don't set it now, we'll lose the scope that this

View file

@ -6,7 +6,6 @@ use parking_lot::Mutex;
pub struct Lines; pub struct Lines;
#[async_trait]
impl WholeStreamCommand for Lines { impl WholeStreamCommand for Lines {
fn name(&self) -> &str { fn name(&self) -> &str {
"lines" "lines"
@ -20,8 +19,8 @@ impl WholeStreamCommand for Lines {
"Split single string into rows, one per line." "Split single string into rows, one per line."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
lines(args).await lines(args)
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
@ -43,83 +42,74 @@ fn ends_with_line_ending(st: &str) -> bool {
} }
} }
async fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> { fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
let leftover_string = Arc::new(Mutex::new(String::new())); let leftover_string = Arc::new(Mutex::new(String::new()));
let args = args.evaluate_once().await?; let args = args.evaluate_once()?;
let tag = args.name_tag(); let tag = args.name_tag();
let name_span = tag.span; let name_span = tag.span;
let eos = futures::stream::iter(vec![ let eos = vec![UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()];
UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()
]);
Ok(args Ok(args
.input .input
.chain(eos) .chain(eos)
.filter_map(move |item| { .filter_map(move |item| {
let leftover_string = leftover_string.clone(); let leftover_string = leftover_string.clone();
async move { match item {
match item { Value {
Value { value: UntaggedValue::Primitive(Primitive::String(st)),
value: UntaggedValue::Primitive(Primitive::String(st)), ..
.. } => {
} => { let mut leftover_string = leftover_string.lock();
let mut leftover_string = leftover_string.lock();
let mut buffer = leftover_string.clone(); let mut buffer = leftover_string.clone();
buffer.push_str(&st); buffer.push_str(&st);
let mut lines: Vec<String> = let mut lines: Vec<String> = buffer.lines().map(|x| x.to_string()).collect();
buffer.lines().map(|x| x.to_string()).collect();
leftover_string.clear(); leftover_string.clear();
if !ends_with_line_ending(&st) { if !ends_with_line_ending(&st) {
if let Some(last) = lines.pop() { if let Some(last) = lines.pop() {
leftover_string.push_str(&last); leftover_string.push_str(&last);
}
}
if !lines.is_empty() {
let success_lines: Vec<_> = lines
.iter()
.map(|x| {
ReturnSuccess::value(
UntaggedValue::string(x).into_untagged_value(),
)
})
.collect();
Some(futures::stream::iter(success_lines))
} else {
None
} }
} }
Value {
value: UntaggedValue::Primitive(Primitive::EndOfStream), if !lines.is_empty() {
.. let success_lines: Vec<_> = lines
} => { .iter()
let st = (&*leftover_string).lock().clone(); .map(|x| {
if !st.is_empty() { ReturnSuccess::value(UntaggedValue::string(x).into_untagged_value())
Some(futures::stream::iter(vec![ReturnSuccess::value( })
UntaggedValue::string(st).into_untagged_value(), .collect();
)]))
} else { Some(success_lines)
None } else {
} None
} }
Value {
tag: value_span, ..
} => Some(futures::stream::iter(vec![Err(
ShellError::labeled_error_with_secondary(
"Expected a string from pipeline",
"requires string input",
name_span,
"value originates from here",
value_span,
),
)])),
} }
Value {
value: UntaggedValue::Primitive(Primitive::EndOfStream),
..
} => {
let st = (&*leftover_string).lock().clone();
if !st.is_empty() {
Some(vec![ReturnSuccess::value(
UntaggedValue::string(st).into_untagged_value(),
)])
} else {
None
}
}
Value {
tag: value_span, ..
} => Some(vec![Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline",
"requires string input",
name_span,
"value originates from here",
value_span,
))]),
} }
}) })
.flatten() .flatten()

View file

@ -5,7 +5,6 @@ use nu_protocol::{Signature, SyntaxShape};
pub struct Ls; pub struct Ls;
#[async_trait]
impl WholeStreamCommand for Ls { impl WholeStreamCommand for Ls {
fn name(&self) -> &str { fn name(&self) -> &str {
"ls" "ls"
@ -40,11 +39,11 @@ impl WholeStreamCommand for Ls {
"View the contents of the current or given path." "View the contents of the current or given path."
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ctrl_c = args.ctrl_c.clone(); let ctrl_c = args.ctrl_c.clone();
let shell_manager = args.shell_manager.clone(); let shell_manager = args.shell_manager.clone();
let (args, _) = args.process().await?; let (args, _) = args.process()?;
shell_manager.ls(args, name, ctrl_c) shell_manager.ls(args, name, ctrl_c)
} }

View file

@ -33,7 +33,7 @@ macro_rules! command {
fn command($args: EvaluatedCommandArgs, ( $($param_name),*, ): ( $($param_type),*, )) -> Result<OutputStream, ShellError> { fn command($args: EvaluatedCommandArgs, ( $($param_name),*, ): ( $($param_type),*, )) -> Result<OutputStream, ShellError> {
let output = $body; let output = $body;
Ok(output.boxed().to_output_stream()) Ok(output.to_output_stream())
} }
let $args = $args.evaluate_once(registry)?; let $args = $args.evaluate_once(registry)?;

View file

@ -5,7 +5,6 @@ use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
pub struct SubCommand; pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"math abs" "math abs"
@ -19,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
"Returns absolute values of a list of numbers" "Returns absolute values of a list of numbers"
} }
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let mapped = args.input.map(move |val| match val.value { let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => { UntaggedValue::Primitive(Primitive::Int(val)) => {
UntaggedValue::int(val.magnitude().clone()).into() UntaggedValue::int(val.magnitude().clone()).into()

Some files were not shown because too many files have changed in this diff Show more