mirror of
https://github.com/nushell/nushell.git
synced 2025-01-18 12:22:21 +01:00
Evaluation of command arguments (#1801)
* WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * Finish adding the baseline refactors for argument invocation * Finish cleanup and add test * Add missing plugin references
This commit is contained in:
parent
822440d5ff
commit
076fde16dd
553
Cargo.lock
generated
553
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,7 @@ nu_plugin_binaryview = { version = "0.14.1", path = "./crates/nu_plugin_binaryvi
|
|||||||
nu_plugin_fetch = { version = "0.14.1", path = "./crates/nu_plugin_fetch", optional=true }
|
nu_plugin_fetch = { version = "0.14.1", path = "./crates/nu_plugin_fetch", optional=true }
|
||||||
nu_plugin_inc = { version = "0.14.1", path = "./crates/nu_plugin_inc", optional=true }
|
nu_plugin_inc = { version = "0.14.1", path = "./crates/nu_plugin_inc", optional=true }
|
||||||
nu_plugin_match = { version = "0.14.1", path = "./crates/nu_plugin_match", optional=true }
|
nu_plugin_match = { version = "0.14.1", path = "./crates/nu_plugin_match", optional=true }
|
||||||
|
nu_plugin_parse = { version = "0.14.1", path = "./crates/nu_plugin_parse", optional=true }
|
||||||
nu_plugin_post = { version = "0.14.1", path = "./crates/nu_plugin_post", optional=true }
|
nu_plugin_post = { version = "0.14.1", path = "./crates/nu_plugin_post", optional=true }
|
||||||
nu_plugin_ps = { version = "0.14.1", path = "./crates/nu_plugin_ps", optional=true }
|
nu_plugin_ps = { version = "0.14.1", path = "./crates/nu_plugin_ps", optional=true }
|
||||||
nu_plugin_start = { version = "0.1.0", path = "./crates/nu_plugin_start", optional=true }
|
nu_plugin_start = { version = "0.1.0", path = "./crates/nu_plugin_start", optional=true }
|
||||||
@ -63,7 +64,7 @@ nu-build = { version = "0.14.1", path = "./crates/nu-build" }
|
|||||||
test-bins = []
|
test-bins = []
|
||||||
|
|
||||||
default = ["sys", "ps", "textview", "inc", "str"]
|
default = ["sys", "ps", "textview", "inc", "str"]
|
||||||
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "post", "fetch", "clipboard-cli", "trash-support", "start"]
|
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "parse", "post", "fetch", "clipboard-cli", "trash-support", "start"]
|
||||||
|
|
||||||
# Default
|
# Default
|
||||||
textview = ["crossterm", "syntect", "url", "nu_plugin_textview"]
|
textview = ["crossterm", "syntect", "url", "nu_plugin_textview"]
|
||||||
@ -77,6 +78,7 @@ average = ["nu_plugin_average"]
|
|||||||
binaryview = ["nu_plugin_binaryview"]
|
binaryview = ["nu_plugin_binaryview"]
|
||||||
fetch = ["nu_plugin_fetch"]
|
fetch = ["nu_plugin_fetch"]
|
||||||
match = ["nu_plugin_match"]
|
match = ["nu_plugin_match"]
|
||||||
|
parse = ["nu_plugin_parse"]
|
||||||
post = ["nu_plugin_post"]
|
post = ["nu_plugin_post"]
|
||||||
trace = ["nu-parser/trace"]
|
trace = ["nu-parser/trace"]
|
||||||
tree = ["nu_plugin_tree"]
|
tree = ["nu_plugin_tree"]
|
||||||
@ -160,6 +162,11 @@ name = "nu_plugin_stable_match"
|
|||||||
path = "src/plugins/nu_plugin_stable_match.rs"
|
path = "src/plugins/nu_plugin_stable_match.rs"
|
||||||
required-features = ["match"]
|
required-features = ["match"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "nu_plugin_stable_parse"
|
||||||
|
path = "src/plugins/nu_plugin_stable_parse.rs"
|
||||||
|
required-features = ["parse"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nu_plugin_stable_post"
|
name = "nu_plugin_stable_post"
|
||||||
path = "src/plugins/nu_plugin_stable_post.rs"
|
path = "src/plugins/nu_plugin_stable_post.rs"
|
||||||
|
@ -20,6 +20,8 @@ nu-test-support = { version = "0.14.1", path = "../nu-test-support" }
|
|||||||
|
|
||||||
|
|
||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
|
app_dirs = "1.2.1"
|
||||||
|
async-recursion = "0.3.1"
|
||||||
directories = "2.0.2"
|
directories = "2.0.2"
|
||||||
async-stream = "0.2"
|
async-stream = "0.2"
|
||||||
base64 = "0.12.0"
|
base64 = "0.12.0"
|
||||||
|
@ -284,7 +284,6 @@ pub fn create_default_context(
|
|||||||
whole_stream_command(Lines),
|
whole_stream_command(Lines),
|
||||||
whole_stream_command(Trim),
|
whole_stream_command(Trim),
|
||||||
whole_stream_command(Echo),
|
whole_stream_command(Echo),
|
||||||
whole_stream_command(Parse),
|
|
||||||
// Column manipulation
|
// Column manipulation
|
||||||
whole_stream_command(Reject),
|
whole_stream_command(Reject),
|
||||||
whole_stream_command(Select),
|
whole_stream_command(Select),
|
||||||
|
@ -71,7 +71,6 @@ pub(crate) mod mv;
|
|||||||
pub(crate) mod next;
|
pub(crate) mod next;
|
||||||
pub(crate) mod nth;
|
pub(crate) mod nth;
|
||||||
pub(crate) mod open;
|
pub(crate) mod open;
|
||||||
pub(crate) mod parse;
|
|
||||||
pub(crate) mod pivot;
|
pub(crate) mod pivot;
|
||||||
pub(crate) mod plugin;
|
pub(crate) mod plugin;
|
||||||
pub(crate) mod prepend;
|
pub(crate) mod prepend;
|
||||||
@ -199,7 +198,6 @@ pub(crate) use mv::Move;
|
|||||||
pub(crate) use next::Next;
|
pub(crate) use next::Next;
|
||||||
pub(crate) use nth::Nth;
|
pub(crate) use nth::Nth;
|
||||||
pub(crate) use open::Open;
|
pub(crate) use open::Open;
|
||||||
pub(crate) use parse::Parse;
|
|
||||||
pub(crate) use pivot::Pivot;
|
pub(crate) use pivot::Pivot;
|
||||||
pub(crate) use prepend::Prepend;
|
pub(crate) use prepend::Prepend;
|
||||||
pub(crate) use prev::Previous;
|
pub(crate) use prev::Previous;
|
||||||
|
@ -39,7 +39,8 @@ impl WholeStreamCommand for Alias {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, alias)?.run()
|
//args.process(registry, alias)?.run()
|
||||||
|
alias(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -56,15 +57,10 @@ impl WholeStreamCommand for Alias {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alias(
|
pub fn alias(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
AliasArgs {
|
let registry = registry.clone();
|
||||||
name,
|
|
||||||
args: list,
|
|
||||||
block,
|
|
||||||
}: AliasArgs,
|
|
||||||
_: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (AliasArgs { name, args: list, block }, _) = args.process(®istry).await?;
|
||||||
let mut args: Vec<String> = vec![];
|
let mut args: Vec<String> = vec![];
|
||||||
for item in list.iter() {
|
for item in list.iter() {
|
||||||
if let Ok(string) = item.as_string() {
|
if let Ok(string) = item.as_string() {
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct AppendArgs {
|
struct AppendArgs {
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for Append {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, append)?.run()
|
append(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -44,13 +44,17 @@ impl WholeStreamCommand for Append {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append(
|
fn append(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
AppendArgs { row }: AppendArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let mut after: VecDeque<Value> = VecDeque::new();
|
|
||||||
after.push_back(row);
|
|
||||||
let after = futures::stream::iter(after);
|
|
||||||
|
|
||||||
Ok(OutputStream::from_input(input.chain(after)))
|
let stream = async_stream! {
|
||||||
|
let (AppendArgs { row }, mut input) = args.process(®istry).await?;
|
||||||
|
|
||||||
|
while let Some(item) = input.next().await {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
|
yield ReturnSuccess::value(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use nu_protocol::Dictionary;
|
|||||||
|
|
||||||
use crate::commands::{command::EvaluatedWholeStreamCommandArgs, WholeStreamCommand};
|
use crate::commands::{command::EvaluatedWholeStreamCommandArgs, WholeStreamCommand};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct Cal;
|
pub struct Cal;
|
||||||
|
|
||||||
@ -59,52 +59,59 @@ impl WholeStreamCommand for Cal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cal(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn cal(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let mut calendar_vec_deque = VecDeque::new();
|
let stream = async_stream! {
|
||||||
let tag = args.call_info.name_tag.clone();
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let mut calendar_vec_deque = VecDeque::new();
|
||||||
|
let tag = args.call_info.name_tag.clone();
|
||||||
|
|
||||||
let (current_year, current_month, current_day) = get_current_date();
|
let (current_year, current_month, current_day) = get_current_date();
|
||||||
|
|
||||||
if args.has("full-year") {
|
if args.has("full-year") {
|
||||||
let mut day_value: Option<u32> = Some(current_day);
|
let mut day_value: Option<u32> = Some(current_day);
|
||||||
let mut year_value = current_year as u64;
|
let mut year_value = current_year as u64;
|
||||||
|
|
||||||
if let Some(year) = args.get("full-year") {
|
if let Some(year) = args.get("full-year") {
|
||||||
if let Ok(year_u64) = year.as_u64() {
|
if let Ok(year_u64) = year.as_u64() {
|
||||||
year_value = year_u64;
|
year_value = year_u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if year_value != current_year as u64 {
|
||||||
|
day_value = None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if year_value != current_year as u64 {
|
add_year_to_table(
|
||||||
day_value = None
|
&mut calendar_vec_deque,
|
||||||
}
|
&tag,
|
||||||
|
year_value as i32,
|
||||||
|
current_year,
|
||||||
|
current_month,
|
||||||
|
day_value,
|
||||||
|
&args,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let (day_start_offset, number_of_days_in_month, _) =
|
||||||
|
get_month_information(current_year, current_month, current_year);
|
||||||
|
|
||||||
|
add_month_to_table(
|
||||||
|
&mut calendar_vec_deque,
|
||||||
|
&tag,
|
||||||
|
current_year,
|
||||||
|
current_month,
|
||||||
|
Some(current_day),
|
||||||
|
day_start_offset,
|
||||||
|
number_of_days_in_month as usize,
|
||||||
|
&args,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_year_to_table(
|
for item in calendar_vec_deque {
|
||||||
&mut calendar_vec_deque,
|
yield ReturnSuccess::value(item);
|
||||||
&tag,
|
}
|
||||||
year_value as i32,
|
};
|
||||||
current_year,
|
|
||||||
current_month,
|
|
||||||
day_value,
|
|
||||||
&args,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let (day_start_offset, number_of_days_in_month, _) =
|
|
||||||
get_month_information(current_year, current_month, current_year);
|
|
||||||
|
|
||||||
add_month_to_table(
|
Ok(stream.to_output_stream())
|
||||||
&mut calendar_vec_deque,
|
|
||||||
&tag,
|
|
||||||
current_year,
|
|
||||||
current_month,
|
|
||||||
Some(current_day),
|
|
||||||
day_start_offset,
|
|
||||||
number_of_days_in_month as usize,
|
|
||||||
&args,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(futures::stream::iter(calendar_vec_deque).to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_date() -> (i32, u32, u32) {
|
fn get_current_date() -> (i32, u32, u32) {
|
||||||
|
@ -5,9 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
|||||||
|
|
||||||
pub struct Calc;
|
pub struct Calc;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct CalcArgs {}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Calc {
|
impl WholeStreamCommand for Calc {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"calc"
|
"calc"
|
||||||
@ -22,7 +19,7 @@ impl WholeStreamCommand for Calc {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, calc)?.run()
|
calc(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -33,30 +30,31 @@ impl WholeStreamCommand for Calc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calc(
|
pub fn calc(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
_: CalcArgs,
|
let stream = async_stream! {
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let mut input = args.input;
|
||||||
) -> Result<OutputStream, ShellError> {
|
let name = args.call_info.name_tag.clone();
|
||||||
Ok(input
|
while let Some(input) = input.next().await {
|
||||||
.map(move |input| {
|
|
||||||
if let Ok(string) = input.as_string() {
|
if let Ok(string) = input.as_string() {
|
||||||
match parse(&string, &input.tag) {
|
match parse(&string, &input.tag) {
|
||||||
Ok(value) => ReturnSuccess::value(value),
|
Ok(value) => yield ReturnSuccess::value(value),
|
||||||
Err(err) => Err(ShellError::labeled_error(
|
Err(err) => yield Err(ShellError::labeled_error(
|
||||||
"Calculation error",
|
"Calculation error",
|
||||||
err,
|
err,
|
||||||
&input.tag.span,
|
&input.tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name.clone(),
|
name.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.to_output_stream())
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(math_expression: &str, tag: impl Into<Tag>) -> Result<Value, String> {
|
pub fn parse(math_expression: &str, tag: impl Into<Tag>) -> Result<Value, String> {
|
||||||
|
@ -36,7 +36,7 @@ impl WholeStreamCommand for Cd {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, cd)?.run()
|
cd(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -61,6 +61,18 @@ impl WholeStreamCommand for Cd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(args: CdArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
context.shell_manager.cd(args, &context)
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
|
||||||
|
let (args, _): (CdArgs, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.cd(args, name)?;
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ async fn run_pipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
(Some(ClassifiedCommand::Expr(expr)), _) => {
|
(Some(ClassifiedCommand::Expr(expr)), _) => {
|
||||||
run_expression_block(*expr, ctx, input, scope)?
|
run_expression_block(*expr, ctx, input, scope).await?
|
||||||
}
|
}
|
||||||
(Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()),
|
(Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()),
|
||||||
(_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()),
|
(_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()),
|
||||||
|
@ -8,7 +8,7 @@ use nu_errors::ShellError;
|
|||||||
use nu_protocol::hir::SpannedExpression;
|
use nu_protocol::hir::SpannedExpression;
|
||||||
use nu_protocol::Scope;
|
use nu_protocol::Scope;
|
||||||
|
|
||||||
pub(crate) fn run_expression_block(
|
pub(crate) async fn run_expression_block(
|
||||||
expr: SpannedExpression,
|
expr: SpannedExpression,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_input: InputStream,
|
_input: InputStream,
|
||||||
@ -21,7 +21,7 @@ pub(crate) fn run_expression_block(
|
|||||||
|
|
||||||
let scope = scope.clone();
|
let scope = scope.clone();
|
||||||
let registry = context.registry().clone();
|
let registry = context.registry().clone();
|
||||||
let output = evaluate_baseline_expr(&expr, ®istry, &scope)?;
|
let output = evaluate_baseline_expr(&expr, ®istry, &scope).await?;
|
||||||
|
|
||||||
Ok(once(async { Ok(output) }).to_input_stream())
|
Ok(once(async { Ok(output) }).to_input_stream())
|
||||||
}
|
}
|
||||||
|
@ -99,10 +99,10 @@ pub(crate) async fn run_external_command(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
run_with_stdin(command, context, input, scope, is_last)
|
run_with_stdin(command, context, input, scope, is_last).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_with_stdin(
|
async fn run_with_stdin(
|
||||||
command: ExternalCommand,
|
command: ExternalCommand,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
@ -115,7 +115,7 @@ fn run_with_stdin(
|
|||||||
|
|
||||||
let mut command_args = vec![];
|
let mut command_args = vec![];
|
||||||
for arg in command.args.iter() {
|
for arg in command.args.iter() {
|
||||||
let value = evaluate_baseline_expr(arg, &context.registry, scope)?;
|
let value = evaluate_baseline_expr(arg, &context.registry, scope).await?;
|
||||||
// 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
|
||||||
// what value we would put in its place.
|
// what value we would put in its place.
|
||||||
|
@ -11,9 +11,6 @@ pub mod clipboard {
|
|||||||
|
|
||||||
pub struct Clip;
|
pub struct Clip;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct ClipArgs {}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Clip {
|
impl WholeStreamCommand for Clip {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"clip"
|
"clip"
|
||||||
@ -32,7 +29,7 @@ pub mod clipboard {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, clip)?.run()
|
clip(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -44,10 +41,12 @@ pub mod clipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clip(
|
pub fn clip(
|
||||||
ClipArgs {}: ClipArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
_registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let mut input = args.input;
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
let mut clip_stream = inner_clip(values, name).await;
|
let mut clip_stream = inner_clip(values, name).await;
|
||||||
|
@ -7,7 +7,7 @@ use derive_new::new;
|
|||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir;
|
use nu_protocol::hir;
|
||||||
use nu_protocol::{CallInfo, EvaluatedArgs, ReturnValue, Scope, Signature, Value};
|
use nu_protocol::{CallInfo, EvaluatedArgs, ReturnSuccess, Scope, Signature, UntaggedValue, Value};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
@ -20,8 +20,8 @@ pub struct UnevaluatedCallInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UnevaluatedCallInfo {
|
impl UnevaluatedCallInfo {
|
||||||
pub fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
|
pub async fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
|
||||||
let args = evaluate_args(&self.args, registry, &self.scope)?;
|
let args = evaluate_args(&self.args, registry, &self.scope).await?;
|
||||||
|
|
||||||
Ok(CallInfo {
|
Ok(CallInfo {
|
||||||
args,
|
args,
|
||||||
@ -29,14 +29,14 @@ impl UnevaluatedCallInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate_with_new_it(
|
pub async fn evaluate_with_new_it(
|
||||||
self,
|
self,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
it: &Value,
|
it: &Value,
|
||||||
) -> Result<CallInfo, ShellError> {
|
) -> Result<CallInfo, ShellError> {
|
||||||
let mut scope = self.scope.clone();
|
let mut scope = self.scope.clone();
|
||||||
scope = scope.set_it(it.clone());
|
scope = scope.set_it(it.clone());
|
||||||
let args = evaluate_args(&self.args, registry, &scope)?;
|
let args = evaluate_args(&self.args, registry, &scope).await?;
|
||||||
|
|
||||||
Ok(CallInfo {
|
Ok(CallInfo {
|
||||||
args,
|
args,
|
||||||
@ -87,7 +87,7 @@ impl std::fmt::Debug for CommandArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CommandArgs {
|
impl CommandArgs {
|
||||||
pub fn evaluate_once(
|
pub async fn evaluate_once(
|
||||||
self,
|
self,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
||||||
@ -95,7 +95,7 @@ impl CommandArgs {
|
|||||||
let ctrl_c = self.ctrl_c.clone();
|
let ctrl_c = self.ctrl_c.clone();
|
||||||
let shell_manager = self.shell_manager.clone();
|
let shell_manager = self.shell_manager.clone();
|
||||||
let input = self.input;
|
let input = self.input;
|
||||||
let call_info = self.call_info.evaluate(registry)?;
|
let call_info = self.call_info.evaluate(registry).await?;
|
||||||
|
|
||||||
Ok(EvaluatedWholeStreamCommandArgs::new(
|
Ok(EvaluatedWholeStreamCommandArgs::new(
|
||||||
host,
|
host,
|
||||||
@ -106,7 +106,7 @@ impl CommandArgs {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate_once_with_scope(
|
pub async fn evaluate_once_with_scope(
|
||||||
self,
|
self,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
@ -120,7 +120,7 @@ impl CommandArgs {
|
|||||||
args: self.call_info.args,
|
args: self.call_info.args,
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
};
|
};
|
||||||
let call_info = call_info.evaluate(registry)?;
|
let call_info = call_info.evaluate(registry).await?;
|
||||||
|
|
||||||
Ok(EvaluatedWholeStreamCommandArgs::new(
|
Ok(EvaluatedWholeStreamCommandArgs::new(
|
||||||
host,
|
host,
|
||||||
@ -131,69 +131,16 @@ impl CommandArgs {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process<'de, T: Deserialize<'de>, O: ToOutputStream>(
|
pub async fn process<'de, T: Deserialize<'de>>(
|
||||||
self,
|
self,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
callback: fn(T, RunnableContext) -> Result<O, ShellError>,
|
) -> Result<(T, InputStream), ShellError> {
|
||||||
) -> Result<RunnableArgs<T, O>, ShellError> {
|
let args = self.evaluate_once(registry).await?;
|
||||||
let shell_manager = self.shell_manager.clone();
|
|
||||||
let host = self.host.clone();
|
|
||||||
let ctrl_c = self.ctrl_c.clone();
|
|
||||||
let args = self.evaluate_once(registry)?;
|
|
||||||
let call_info = args.call_info.clone();
|
|
||||||
let (input, args) = args.split();
|
|
||||||
let name_tag = args.call_info.name_tag;
|
|
||||||
let mut deserializer = ConfigDeserializer::from_call_info(call_info);
|
|
||||||
|
|
||||||
Ok(RunnableArgs {
|
|
||||||
args: T::deserialize(&mut deserializer)?,
|
|
||||||
context: RunnableContext {
|
|
||||||
input,
|
|
||||||
registry: registry.clone(),
|
|
||||||
shell_manager,
|
|
||||||
name: name_tag,
|
|
||||||
host,
|
|
||||||
ctrl_c,
|
|
||||||
},
|
|
||||||
callback,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn process_raw<'de, T: Deserialize<'de>>(
|
|
||||||
self,
|
|
||||||
registry: &CommandRegistry,
|
|
||||||
callback: fn(T, RunnableContext, RawCommandArgs) -> Result<OutputStream, ShellError>,
|
|
||||||
) -> Result<RunnableRawArgs<T>, ShellError> {
|
|
||||||
let raw_args = RawCommandArgs {
|
|
||||||
host: self.host.clone(),
|
|
||||||
ctrl_c: self.ctrl_c.clone(),
|
|
||||||
shell_manager: self.shell_manager.clone(),
|
|
||||||
call_info: self.call_info.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let shell_manager = self.shell_manager.clone();
|
|
||||||
let host = self.host.clone();
|
|
||||||
let ctrl_c = self.ctrl_c.clone();
|
|
||||||
let args = self.evaluate_once(registry)?;
|
|
||||||
let call_info = args.call_info.clone();
|
let call_info = args.call_info.clone();
|
||||||
|
|
||||||
let (input, args) = args.split();
|
|
||||||
let name_tag = args.call_info.name_tag;
|
|
||||||
let mut deserializer = ConfigDeserializer::from_call_info(call_info);
|
let mut deserializer = ConfigDeserializer::from_call_info(call_info);
|
||||||
|
|
||||||
Ok(RunnableRawArgs {
|
Ok((T::deserialize(&mut deserializer)?, args.input))
|
||||||
args: T::deserialize(&mut deserializer)?,
|
|
||||||
context: RunnableContext {
|
|
||||||
input,
|
|
||||||
registry: registry.clone(),
|
|
||||||
shell_manager,
|
|
||||||
name: name_tag,
|
|
||||||
host,
|
|
||||||
ctrl_c,
|
|
||||||
},
|
|
||||||
raw_args,
|
|
||||||
callback,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,34 +159,6 @@ impl RunnableContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunnableArgs<T, O: ToOutputStream> {
|
|
||||||
args: T,
|
|
||||||
context: RunnableContext,
|
|
||||||
callback: fn(T, RunnableContext) -> Result<O, ShellError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, O: ToOutputStream> RunnableArgs<T, O> {
|
|
||||||
pub fn run(self) -> Result<OutputStream, ShellError> {
|
|
||||||
(self.callback)(self.args, self.context).map(|v| v.to_output_stream())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RunnableRawArgs<T> {
|
|
||||||
args: T,
|
|
||||||
raw_args: RawCommandArgs,
|
|
||||||
context: RunnableContext,
|
|
||||||
callback: fn(T, RunnableContext, RawCommandArgs) -> Result<OutputStream, ShellError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> RunnableRawArgs<T> {
|
|
||||||
pub fn run(self) -> OutputStream {
|
|
||||||
match (self.callback)(self.args, self.context, self.raw_args) {
|
|
||||||
Ok(stream) => stream,
|
|
||||||
Err(err) => OutputStream::one(Err(err)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EvaluatedWholeStreamCommandArgs {
|
pub struct EvaluatedWholeStreamCommandArgs {
|
||||||
pub args: EvaluatedCommandArgs,
|
pub args: EvaluatedCommandArgs,
|
||||||
pub input: InputStream,
|
pub input: InputStream,
|
||||||
@ -416,7 +335,12 @@ impl Command {
|
|||||||
|
|
||||||
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
|
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
|
||||||
if args.call_info.switch_present("help") {
|
if args.call_info.switch_present("help") {
|
||||||
get_help(&*self.0, registry).into()
|
let cl = self.0.clone();
|
||||||
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(&*cl, ®istry)).into_value(Tag::unknown())));
|
||||||
|
};
|
||||||
|
stream.to_output_stream()
|
||||||
} else {
|
} else {
|
||||||
match self.0.run(args, registry) {
|
match self.0.run(args, registry) {
|
||||||
Ok(stream) => stream,
|
Ok(stream) => stream,
|
||||||
@ -458,37 +382,40 @@ impl WholeStreamCommand for FnFilterCommand {
|
|||||||
ctrl_c,
|
ctrl_c,
|
||||||
shell_manager,
|
shell_manager,
|
||||||
call_info,
|
call_info,
|
||||||
input,
|
mut input,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
let host: Arc<parking_lot::Mutex<dyn Host>> = host.clone();
|
let host: Arc<parking_lot::Mutex<dyn Host>> = host.clone();
|
||||||
let registry: CommandRegistry = registry.clone();
|
let registry: CommandRegistry = registry.clone();
|
||||||
let func = self.func;
|
let func = self.func;
|
||||||
|
|
||||||
let result = input.map(move |it| {
|
let stream = async_stream! {
|
||||||
let registry = registry.clone();
|
while let Some(it) = input.next().await {
|
||||||
let call_info = match call_info.clone().evaluate_with_new_it(®istry, &it) {
|
let registry = registry.clone();
|
||||||
Err(err) => return OutputStream::from(vec![Err(err)]).values,
|
let call_info = match call_info.clone().evaluate_with_new_it(®istry, &it).await {
|
||||||
Ok(args) => args,
|
Err(err) => { yield Err(err); return; },
|
||||||
};
|
Ok(args) => args,
|
||||||
|
};
|
||||||
|
|
||||||
let args = EvaluatedFilterCommandArgs::new(
|
let args = EvaluatedFilterCommandArgs::new(
|
||||||
host.clone(),
|
host.clone(),
|
||||||
ctrl_c.clone(),
|
ctrl_c.clone(),
|
||||||
shell_manager.clone(),
|
shell_manager.clone(),
|
||||||
call_info,
|
call_info,
|
||||||
);
|
);
|
||||||
|
|
||||||
match func(args) {
|
match func(args) {
|
||||||
Err(err) => OutputStream::from(vec![Err(err)]).values,
|
Err(err) => yield Err(err),
|
||||||
Ok(stream) => stream.values,
|
Ok(mut stream) => {
|
||||||
|
while let Some(value) = stream.values.next().await {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
let result = result.flatten();
|
Ok(stream.to_output_stream())
|
||||||
let result: BoxStream<ReturnValue> = result.boxed();
|
|
||||||
|
|
||||||
Ok(result.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::context::CommandRegistry;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Compact;
|
pub struct Compact;
|
||||||
@ -31,7 +31,7 @@ impl WholeStreamCommand for Compact {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, compact)?.run()
|
compact(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -42,27 +42,29 @@ impl WholeStreamCommand for Compact {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compact(
|
pub fn compact(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
CompactArgs { rest: columns }: CompactArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (CompactArgs { rest: columns }, mut input) = args.process(®istry).await?;
|
||||||
let objects = input.filter(move |item| {
|
while let Some(item) = input.next().await {
|
||||||
let keep = if columns.is_empty() {
|
if columns.is_empty() {
|
||||||
item.is_some()
|
if !item.is_empty() {
|
||||||
} else {
|
yield ReturnSuccess::value(item);
|
||||||
match item {
|
}
|
||||||
Value {
|
} else {
|
||||||
value: UntaggedValue::Row(ref r),
|
match item {
|
||||||
..
|
Value {
|
||||||
} => columns
|
value: UntaggedValue::Row(ref r),
|
||||||
.iter()
|
..
|
||||||
.all(|field| r.get_data(field).borrow().is_some()),
|
} => if columns
|
||||||
_ => false,
|
.iter()
|
||||||
}
|
.all(|field| r.get_data(field).borrow().is_some()) {
|
||||||
};
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
futures::future::ready(keep)
|
_ => {},
|
||||||
});
|
}
|
||||||
|
};
|
||||||
Ok(objects.from_input_stream())
|
}
|
||||||
|
};
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ impl WholeStreamCommand for Config {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, config)?.run()
|
config(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -107,21 +107,22 @@ impl WholeStreamCommand for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(
|
pub fn config(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
ConfigArgs {
|
let name_span = args.call_info.name_tag.clone();
|
||||||
load,
|
let name = args.call_info.name_tag.clone();
|
||||||
set,
|
let registry = registry.clone();
|
||||||
set_into,
|
|
||||||
get,
|
|
||||||
clear,
|
|
||||||
remove,
|
|
||||||
path,
|
|
||||||
}: ConfigArgs,
|
|
||||||
RunnableContext { name, input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let name_span = name.clone();
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (ConfigArgs {
|
||||||
|
load,
|
||||||
|
set,
|
||||||
|
set_into,
|
||||||
|
get,
|
||||||
|
clear,
|
||||||
|
remove,
|
||||||
|
path,
|
||||||
|
}, mut input) = args.process(®istry).await?;
|
||||||
|
|
||||||
let configuration = if let Some(supplied) = load {
|
let configuration = if let Some(supplied) = load {
|
||||||
Some(supplied.item().clone())
|
Some(supplied.item().clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,9 +7,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
|||||||
|
|
||||||
pub struct Count;
|
pub struct Count;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct CountArgs {}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Count {
|
impl WholeStreamCommand for Count {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"count"
|
"count"
|
||||||
@ -28,7 +25,7 @@ impl WholeStreamCommand for Count {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, count)?.run()
|
count(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -39,12 +36,10 @@ impl WholeStreamCommand for Count {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count(
|
pub fn count(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
CountArgs {}: CountArgs,
|
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let rows: Vec<Value> = input.collect().await;
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let rows: Vec<Value> = args.input.collect().await;
|
||||||
|
|
||||||
yield ReturnSuccess::value(UntaggedValue::int(rows.len()).into_value(name))
|
yield ReturnSuccess::value(UntaggedValue::int(rows.len()).into_value(name))
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ impl WholeStreamCommand for Cpy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, cp)?.run()
|
cp(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -57,7 +57,18 @@ impl WholeStreamCommand for Cpy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp(args: CopyArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = context.shell_manager.clone();
|
let registry = registry.clone();
|
||||||
shell_manager.cp(args, &context)
|
let stream = async_stream! {
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let (args, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.cp(args, name)?;
|
||||||
|
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use chrono::{Datelike, TimeZone, Timelike};
|
use chrono::{Datelike, TimeZone, Timelike};
|
||||||
use core::fmt::Display;
|
use core::fmt::Display;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_protocol::{Signature, UntaggedValue};
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
|
||||||
pub struct Date;
|
pub struct Date;
|
||||||
|
|
||||||
@ -89,20 +89,22 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let mut date_out = VecDeque::new();
|
let tag = args.call_info.name_tag.clone();
|
||||||
let tag = args.call_info.name_tag.clone();
|
|
||||||
|
|
||||||
let value = if args.has("utc") {
|
let value = if args.has("utc") {
|
||||||
let utc: DateTime<Utc> = Utc::now();
|
let utc: DateTime<Utc> = Utc::now();
|
||||||
date_to_value(utc, tag)
|
date_to_value(utc, tag)
|
||||||
} else {
|
} else {
|
||||||
let local: DateTime<Local> = Local::now();
|
let local: DateTime<Local> = Local::now();
|
||||||
date_to_value(local, tag)
|
date_to_value(local, tag)
|
||||||
|
};
|
||||||
|
|
||||||
|
yield ReturnSuccess::value(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
date_out.push_back(value);
|
Ok(stream.to_output_stream())
|
||||||
|
|
||||||
Ok(futures::stream::iter(date_out).to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
@ -28,23 +28,24 @@ impl WholeStreamCommand for Debug {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, debug_value)?.run()
|
debug_value(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_value(
|
fn debug_value(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
DebugArgs { raw }: DebugArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<impl ToOutputStream, ShellError> {
|
let (DebugArgs { raw }, mut input) = args.process(®istry).await?;
|
||||||
Ok(input
|
while let Some(v) = input.next().await {
|
||||||
.map(move |v| {
|
|
||||||
if raw {
|
if raw {
|
||||||
ReturnSuccess::value(
|
yield ReturnSuccess::value(
|
||||||
UntaggedValue::string(format!("{:#?}", v)).into_untagged_value(),
|
UntaggedValue::string(format!("{:#?}", v)).into_untagged_value(),
|
||||||
)
|
);
|
||||||
} else {
|
} else {
|
||||||
ReturnSuccess::debug_value(v)
|
yield ReturnSuccess::debug_value(v);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.to_output_stream())
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ impl WholeStreamCommand for Default {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, default)?.run()
|
default(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -49,14 +49,11 @@ impl WholeStreamCommand for Default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default(
|
fn default(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
DefaultArgs { column, value }: DefaultArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (DefaultArgs { column, value }, mut input) = args.process(®istry).await?;
|
||||||
let stream = input
|
while let Some(item) = input.next().await {
|
||||||
.map(move |item| {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
|
|
||||||
let should_add = match item {
|
let should_add = match item {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Row(ref r),
|
value: UntaggedValue::Row(ref r),
|
||||||
@ -67,16 +64,15 @@ fn default(
|
|||||||
|
|
||||||
if should_add {
|
if should_add {
|
||||||
match item.insert_data_at_path(&column.item, value.clone()) {
|
match item.insert_data_at_path(&column.item, value.clone()) {
|
||||||
Some(new_value) => result.push_back(ReturnSuccess::value(new_value)),
|
Some(new_value) => yield ReturnSuccess::value(new_value),
|
||||||
None => result.push_back(ReturnSuccess::value(item)),
|
None => yield ReturnSuccess::value(item),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.push_back(ReturnSuccess::value(item));
|
yield ReturnSuccess::value(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
futures::stream::iter(result)
|
}
|
||||||
})
|
};
|
||||||
.flatten();
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl WholeStreamCommand for Drop {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, drop)?.run()
|
drop(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -51,9 +51,11 @@ impl WholeStreamCommand for Drop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop(DropArgs { rows }: DropArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn drop(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let v: Vec<_> = context.input.into_vec().await;
|
let (DropArgs { rows }, mut input) = args.process(®istry).await?;
|
||||||
|
let v: Vec<_> = input.into_vec().await;
|
||||||
|
|
||||||
let rows_to_drop = if let Some(quantity) = rows {
|
let rows_to_drop = if let Some(quantity) = rows {
|
||||||
*quantity as usize
|
*quantity as usize
|
||||||
|
@ -76,7 +76,7 @@ impl WholeStreamCommand for Du {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, du)?.run()
|
du(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -87,65 +87,72 @@ impl WholeStreamCommand for Du {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn du(args: DuArgs, ctx: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn du(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let tag = ctx.name.clone();
|
let registry = registry.clone();
|
||||||
|
let tag = args.call_info.name_tag.clone();
|
||||||
|
let ctrl_c = args.ctrl_c.clone();
|
||||||
|
|
||||||
let exclude = args.exclude.map_or(Ok(None), move |x| {
|
let stream = async_stream! {
|
||||||
Pattern::new(&x.item)
|
let (args, mut input): (DuArgs, _) = args.process(®istry).await?;
|
||||||
.map(Option::Some)
|
let exclude = args.exclude.map_or(Ok(None), move |x| {
|
||||||
.map_err(|e| ShellError::labeled_error(e.msg, "glob error", x.tag.clone()))
|
Pattern::new(&x.item)
|
||||||
})?;
|
.map(Option::Some)
|
||||||
|
.map_err(|e| ShellError::labeled_error(e.msg, "glob error", x.tag.clone()))
|
||||||
|
})?;
|
||||||
|
|
||||||
let include_files = args.all;
|
let include_files = args.all;
|
||||||
let paths = match args.path {
|
let paths = match args.path {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
let p = p.item.to_str().expect("Why isn't this encoded properly?");
|
let p = p.item.to_str().expect("Why isn't this encoded properly?");
|
||||||
glob::glob_with(p, GLOB_PARAMS)
|
glob::glob_with(p, GLOB_PARAMS)
|
||||||
}
|
|
||||||
None => glob::glob_with("*", GLOB_PARAMS),
|
|
||||||
}
|
|
||||||
.map_err(|e| ShellError::labeled_error(e.msg, "glob error", tag.clone()))?
|
|
||||||
.filter(move |p| {
|
|
||||||
if include_files {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
match p {
|
|
||||||
Ok(f) if f.is_dir() => true,
|
|
||||||
Err(e) if e.path().is_dir() => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
|
None => glob::glob_with("*", GLOB_PARAMS),
|
||||||
}
|
}
|
||||||
})
|
.map_err(|e| ShellError::labeled_error(e.msg, "glob error", tag.clone()))?
|
||||||
.map(|v| v.map_err(glob_err_into));
|
.filter(move |p| {
|
||||||
|
if include_files {
|
||||||
let ctrl_c = ctx.ctrl_c;
|
true
|
||||||
let all = args.all;
|
} else {
|
||||||
let deref = args.deref;
|
match p {
|
||||||
let max_depth = args.max_depth.map(|f| f.item);
|
Ok(f) if f.is_dir() => true,
|
||||||
let min_size = args.min_size.map(|f| f.item);
|
Err(e) if e.path().is_dir() => true,
|
||||||
|
_ => false,
|
||||||
let params = DirBuilder {
|
|
||||||
tag: tag.clone(),
|
|
||||||
min: min_size,
|
|
||||||
deref,
|
|
||||||
exclude,
|
|
||||||
all,
|
|
||||||
};
|
|
||||||
|
|
||||||
let stream = futures::stream::iter(paths)
|
|
||||||
.interruptible(ctrl_c)
|
|
||||||
.map(move |path| match path {
|
|
||||||
Ok(p) => {
|
|
||||||
if p.is_dir() {
|
|
||||||
Ok(ReturnSuccess::Value(
|
|
||||||
DirInfo::new(p, ¶ms, max_depth).into(),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
FileInfo::new(p, deref, tag.clone()).map(|v| ReturnSuccess::Value(v.into()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
})
|
||||||
});
|
.map(|v| v.map_err(glob_err_into));
|
||||||
|
|
||||||
|
let all = args.all;
|
||||||
|
let deref = args.deref;
|
||||||
|
let max_depth = args.max_depth.map(|f| f.item);
|
||||||
|
let min_size = args.min_size.map(|f| f.item);
|
||||||
|
|
||||||
|
let params = DirBuilder {
|
||||||
|
tag: tag.clone(),
|
||||||
|
min: min_size,
|
||||||
|
deref,
|
||||||
|
exclude,
|
||||||
|
all,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut inp = futures::stream::iter(paths).interruptible(ctrl_c);
|
||||||
|
while let Some(path) = inp.next().await {
|
||||||
|
match path {
|
||||||
|
Ok(p) => {
|
||||||
|
if p.is_dir() {
|
||||||
|
yield Ok(ReturnSuccess::Value(
|
||||||
|
DirInfo::new(p, ¶ms, max_depth).into(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
for v in FileInfo::new(p, deref, tag.clone()).into_iter() {
|
||||||
|
yield Ok(ReturnSuccess::Value(v.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => yield Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ impl WholeStreamCommand for Each {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(args.process_raw(registry, each)?.run())
|
each(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -60,21 +60,18 @@ fn is_expanded_it_usage(head: &SpannedExpression) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each(
|
fn each(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
each_args: EachArgs,
|
let registry = registry.clone();
|
||||||
context: RunnableContext,
|
|
||||||
raw_args: RawCommandArgs,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let block = each_args.block;
|
|
||||||
let scope = raw_args.call_info.scope.clone();
|
|
||||||
let registry = context.registry.clone();
|
|
||||||
let mut input_stream = context.input;
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
while let Some(input) = input_stream.next().await {
|
let head = raw_args.call_info.args.head.clone();
|
||||||
let mut context = Context::from_raw(&raw_args, ®istry);
|
let scope = raw_args.call_info.scope.clone();
|
||||||
|
let mut context = Context::from_raw(&raw_args, ®istry);
|
||||||
|
let (each_args, mut input): (EachArgs, _) = raw_args.process(®istry).await?;
|
||||||
|
let block = each_args.block;
|
||||||
|
while let Some(input) = input.next().await {
|
||||||
|
|
||||||
let input_clone = input.clone();
|
let input_clone = input.clone();
|
||||||
let input_stream = if is_expanded_it_usage(&raw_args.call_info.args.head) {
|
let input_stream = if is_expanded_it_usage(&head) {
|
||||||
InputStream::empty()
|
InputStream::empty()
|
||||||
} else {
|
} else {
|
||||||
once(async { Ok(input) }).to_input_stream()
|
once(async { Ok(input) }).to_input_stream()
|
||||||
|
@ -28,7 +28,7 @@ impl WholeStreamCommand for Echo {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, echo)?.run()
|
echo(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -45,34 +45,34 @@ impl WholeStreamCommand for Echo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn echo(args: EchoArgs, _: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn echo(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let mut output = vec![];
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
let (args, _): (EchoArgs, _) = args.process(®istry).await?;
|
||||||
|
|
||||||
for i in args.rest {
|
for i in args.rest {
|
||||||
match i.as_string() {
|
match i.as_string() {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
output.push(Ok(ReturnSuccess::Value(
|
yield Ok(ReturnSuccess::Value(
|
||||||
UntaggedValue::string(s).into_value(i.tag.clone()),
|
UntaggedValue::string(s).into_value(i.tag.clone()),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
_ => match i {
|
_ => match i {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Table(table),
|
value: UntaggedValue::Table(table),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for value in table {
|
for value in table {
|
||||||
output.push(Ok(ReturnSuccess::Value(value.clone())));
|
yield Ok(ReturnSuccess::Value(value.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
_ => {
|
yield Ok(ReturnSuccess::Value(i.clone()));
|
||||||
output.push(Ok(ReturnSuccess::Value(i.clone())));
|
}
|
||||||
}
|
},
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// TODO: This whole block can probably be replaced with `.map()`
|
|
||||||
let stream = futures::stream::iter(output);
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ impl WholeStreamCommand for Enter {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(args.process_raw(registry, enter)?.run())
|
enter(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -55,44 +55,42 @@ impl WholeStreamCommand for Enter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter(
|
fn enter(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
EnterArgs { location }: EnterArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext {
|
let stream = async_stream! {
|
||||||
registry,
|
let scope = raw_args.call_info.scope.clone();
|
||||||
name: tag,
|
let shell_manager = raw_args.shell_manager.clone();
|
||||||
..
|
let head = raw_args.call_info.args.head.clone();
|
||||||
}: RunnableContext,
|
let ctrl_c = raw_args.ctrl_c.clone();
|
||||||
raw_args: RawCommandArgs,
|
let host = raw_args.host.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
let location_string = location.display().to_string();
|
let (EnterArgs { location }, _) = raw_args.process(®istry).await?;
|
||||||
let location_clone = location_string.clone();
|
let location_string = location.display().to_string();
|
||||||
|
let location_clone = location_string.clone();
|
||||||
|
|
||||||
if location_string.starts_with("help") {
|
if location_string.starts_with("help") {
|
||||||
let spec = location_string.split(':').collect::<Vec<&str>>();
|
let spec = location_string.split(':').collect::<Vec<&str>>();
|
||||||
|
|
||||||
if spec.len() == 2 {
|
if spec.len() == 2 {
|
||||||
let (_, command) = (spec[0], spec[1]);
|
let (_, command) = (spec[0], spec[1]);
|
||||||
|
|
||||||
if registry.has(command) {
|
if registry.has(command) {
|
||||||
return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
||||||
UntaggedValue::string(command).into_value(Tag::unknown()),
|
UntaggedValue::string(command).into_value(Tag::unknown()),
|
||||||
)))]
|
)));
|
||||||
.into());
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
||||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
UntaggedValue::nothing().into_value(Tag::unknown()),
|
||||||
UntaggedValue::nothing().into_value(Tag::unknown()),
|
)));
|
||||||
)))]
|
} else if location.is_dir() {
|
||||||
.into())
|
yield Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
||||||
} else if location.is_dir() {
|
location_clone,
|
||||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
)));
|
||||||
location_clone,
|
} else {
|
||||||
)))]
|
|
||||||
.into())
|
|
||||||
} else {
|
|
||||||
let stream = async_stream! {
|
|
||||||
// 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
|
||||||
let cwd = raw_args.shell_manager.path();
|
let cwd = shell_manager.path();
|
||||||
|
|
||||||
let full_path = std::path::PathBuf::from(cwd);
|
let full_path = std::path::PathBuf::from(cwd);
|
||||||
|
|
||||||
@ -113,19 +111,19 @@ fn enter(
|
|||||||
registry.get_command(&command_name)
|
registry.get_command(&command_name)
|
||||||
{
|
{
|
||||||
let new_args = RawCommandArgs {
|
let new_args = RawCommandArgs {
|
||||||
host: raw_args.host,
|
host,
|
||||||
ctrl_c: raw_args.ctrl_c,
|
ctrl_c,
|
||||||
shell_manager: raw_args.shell_manager,
|
shell_manager,
|
||||||
call_info: UnevaluatedCallInfo {
|
call_info: UnevaluatedCallInfo {
|
||||||
args: nu_protocol::hir::Call {
|
args: nu_protocol::hir::Call {
|
||||||
head: raw_args.call_info.args.head,
|
head,
|
||||||
positional: None,
|
positional: None,
|
||||||
named: None,
|
named: None,
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
is_last: false,
|
is_last: false,
|
||||||
},
|
},
|
||||||
name_tag: raw_args.call_info.name_tag,
|
name_tag: tag.clone(),
|
||||||
scope: raw_args.call_info.scope.clone()
|
scope: scope.clone()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut result = converter.run(
|
let mut result = converter.run(
|
||||||
@ -162,7 +160,8 @@ fn enter(
|
|||||||
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
|
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Ok(stream.to_output_stream())
|
};
|
||||||
}
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -36,15 +36,18 @@ impl WholeStreamCommand for EvaluateBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, evaluate_by)?.run()
|
evaluate_by(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate_by(
|
pub fn evaluate_by(
|
||||||
EvaluateByArgs { evaluate_with }: EvaluateByArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let (EvaluateByArgs { evaluate_with }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
|
@ -42,11 +42,16 @@ impl WholeStreamCommand for Exit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn exit(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
if args.call_info.args.has("now") {
|
if args.call_info.args.has("now") {
|
||||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::Exit))].into())
|
yield Ok(ReturnSuccess::Action(CommandAction::Exit));
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::LeaveShell))].into())
|
yield Ok(ReturnSuccess::Action(CommandAction::LeaveShell));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct First;
|
pub struct First;
|
||||||
@ -34,7 +34,7 @@ impl WholeStreamCommand for First {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, first)?.run()
|
first(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -51,15 +51,25 @@ impl WholeStreamCommand for First {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first(
|
fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FirstArgs { rows }: FirstArgs,
|
let registry = registry.clone();
|
||||||
context: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (FirstArgs { rows }, mut input) = args.process(®istry).await?;
|
||||||
let rows_desired = if let Some(quantity) = rows {
|
let mut rows_desired = if let Some(quantity) = rows {
|
||||||
*quantity
|
*quantity
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(input) = input.next().await {
|
||||||
|
if rows_desired > 0 {
|
||||||
|
yield ReturnSuccess::value(input);
|
||||||
|
rows_desired -= 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(OutputStream::from_input(context.input.take(rows_desired)))
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl WholeStreamCommand for Format {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, format_command)?.run()
|
format_command(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -48,16 +48,17 @@ impl WholeStreamCommand for Format {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn format_command(
|
fn format_command(
|
||||||
FormatArgs { pattern }: FormatArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let pattern_tag = pattern.tag.clone();
|
let registry = registry.clone();
|
||||||
|
|
||||||
let format_pattern = format(&pattern);
|
|
||||||
let commands = format_pattern;
|
|
||||||
let mut input = input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (FormatArgs { pattern }, mut input) = args.process(®istry).await?;
|
||||||
|
let pattern_tag = pattern.tag.clone();
|
||||||
|
|
||||||
|
let format_pattern = format(&pattern);
|
||||||
|
let commands = format_pattern;
|
||||||
|
|
||||||
while let Some(value) = input.next().await {
|
while let Some(value) = input.next().await {
|
||||||
match value {
|
match value {
|
||||||
value
|
value
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::Signature;
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
|
||||||
pub struct From;
|
pub struct From;
|
||||||
|
|
||||||
@ -23,6 +23,14 @@ impl WholeStreamCommand for From {
|
|||||||
_args: CommandArgs,
|
_args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(crate::commands::help::get_help(&*self, registry).into())
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
yield Ok(ReturnSuccess::Value(
|
||||||
|
UntaggedValue::string(crate::commands::help::get_help(&From, ®istry))
|
||||||
|
.into_value(Tag::unknown()),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +207,12 @@ pub fn from_bson_bytes_to_value(bytes: Vec<u8>, tag: impl Into<Tag>) -> Result<V
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let bytes = input.collect_binary(tag.clone()).await?;
|
let bytes = input.collect_binary(tag.clone()).await?;
|
||||||
|
|
||||||
match from_bson_bytes_to_value(bytes.item, tag.clone()) {
|
match from_bson_bytes_to_value(bytes.item, tag.clone()) {
|
||||||
|
@ -41,7 +41,7 @@ impl WholeStreamCommand for FromCSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_csv)?.run()
|
from_csv(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -62,35 +62,41 @@ impl WholeStreamCommand for FromCSV {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_csv(
|
fn from_csv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromCSVArgs {
|
let registry = registry.clone();
|
||||||
headerless,
|
let name = args.call_info.name_tag.clone();
|
||||||
separator,
|
let stream = async_stream! {
|
||||||
}: FromCSVArgs,
|
let (FromCSVArgs { headerless, separator }, mut input) = args.process(®istry).await?;
|
||||||
runnable_context: RunnableContext,
|
let sep = match separator {
|
||||||
) -> Result<OutputStream, ShellError> {
|
Some(Value {
|
||||||
let sep = match separator {
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
Some(Value {
|
tag,
|
||||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
..
|
||||||
tag,
|
}) => {
|
||||||
..
|
if s == r"\t" {
|
||||||
}) => {
|
'\t'
|
||||||
if s == r"\t" {
|
} else {
|
||||||
'\t'
|
let vec_s: Vec<char> = s.chars().collect();
|
||||||
} else {
|
if vec_s.len() != 1 {
|
||||||
let vec_s: Vec<char> = s.chars().collect();
|
yield Err(ShellError::labeled_error(
|
||||||
if vec_s.len() != 1 {
|
"Expected a single separator char from --separator",
|
||||||
return Err(ShellError::labeled_error(
|
"requires a single character string input",
|
||||||
"Expected a single separator char from --separator",
|
tag,
|
||||||
"requires a single character string input",
|
));
|
||||||
tag,
|
return;
|
||||||
));
|
};
|
||||||
};
|
vec_s[0]
|
||||||
vec_s[0]
|
}
|
||||||
}
|
}
|
||||||
|
_ => ',',
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = from_delimited_data(headerless, sep, "CSV", input, name)?;
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
}
|
}
|
||||||
_ => ',',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
from_delimited_data(headerless, sep, "CSV", runnable_context)
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@ pub fn from_delimited_data(
|
|||||||
headerless: bool,
|
headerless: bool,
|
||||||
sep: char,
|
sep: char,
|
||||||
format_name: &'static str,
|
format_name: &'static str,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
input: InputStream,
|
||||||
|
name: Tag,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_tag = name;
|
let name_tag = name;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl WholeStreamCommand for FromEML {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_eml)?.run()
|
from_eml(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,14 +76,11 @@ fn headerfieldvalue_to_value(tag: &Tag, value: &HeaderFieldValue) -> UntaggedVal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_eml(
|
fn from_eml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
eml_args: FromEMLArgs,
|
let tag = args.call_info.name_tag.clone();
|
||||||
runnable_context: RunnableContext,
|
let registry = registry.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let input = runnable_context.input;
|
|
||||||
let tag = runnable_context.name;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (eml_args, mut input): (FromEMLArgs, _) = args.process(®istry).await?;
|
||||||
let value = input.collect_string(tag.clone()).await?;
|
let value = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
let body_preview = eml_args.preview_body.map(|b| b.item).unwrap_or(DEFAULT_BODY_PREVIEW);
|
let body_preview = eml_args.preview_body.map(|b| b.item).unwrap_or(DEFAULT_BODY_PREVIEW);
|
||||||
|
@ -32,11 +32,12 @@ impl WholeStreamCommand for FromIcs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_ics(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_ics(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let input_string = input.collect_string(tag.clone()).await?.item;
|
let input_string = input.collect_string(tag.clone()).await?.item;
|
||||||
let input_bytes = input_string.as_bytes();
|
let input_bytes = input_string.as_bytes();
|
||||||
let buf_reader = BufReader::new(input_bytes);
|
let buf_reader = BufReader::new(input_bytes);
|
||||||
|
@ -64,11 +64,11 @@ pub fn from_ini_string_to_value(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
match from_ini_string_to_value(concat_string.item, tag.clone()) {
|
match from_ini_string_to_value(concat_string.item, tag.clone()) {
|
||||||
|
@ -32,7 +32,7 @@ impl WholeStreamCommand for FromJSON {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_json)?.run()
|
from_json(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +70,12 @@ pub fn from_json_string_to_value(s: String, tag: impl Into<Tag>) -> serde_hjson:
|
|||||||
Ok(convert_json_value_to_nu_value(&v, tag))
|
Ok(convert_json_value_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_json(
|
fn from_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromJSONArgs { objects }: FromJSONArgs,
|
let name_tag = args.call_info.name_tag.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let registry = registry.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let name_tag = name;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (FromJSONArgs { objects }, mut input) = args.process(®istry).await?;
|
||||||
let concat_string = input.collect_string(name_tag.clone()).await?;
|
let concat_string = input.collect_string(name_tag.clone()).await?;
|
||||||
|
|
||||||
if objects {
|
if objects {
|
||||||
|
@ -35,20 +35,16 @@ impl WholeStreamCommand for FromODS {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_ods)?.run()
|
from_ods(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ods(
|
fn from_ods(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromODSArgs {
|
let tag = args.call_info.name_tag.clone();
|
||||||
headerless: _headerless,
|
let registry = registry.clone();
|
||||||
}: FromODSArgs,
|
|
||||||
runnable_context: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let input = runnable_context.input;
|
|
||||||
let tag = runnable_context.name;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (FromODSArgs { headerless: _headerless }, mut input) = args.process(®istry).await?;
|
||||||
let bytes = input.collect_binary(tag.clone()).await?;
|
let bytes = input.collect_binary(tag.clone()).await?;
|
||||||
let mut buf: Cursor<Vec<u8>> = Cursor::new(bytes.item);
|
let mut buf: Cursor<Vec<u8>> = Cursor::new(bytes.item);
|
||||||
let mut ods = Ods::<_>::new(buf).map_err(|_| ShellError::labeled_error(
|
let mut ods = Ods::<_>::new(buf).map_err(|_| ShellError::labeled_error(
|
||||||
|
@ -133,11 +133,12 @@ pub fn from_sqlite_bytes_to_value(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let bytes = input.collect_binary(tag.clone()).await?;
|
let bytes = input.collect_binary(tag.clone()).await?;
|
||||||
match from_sqlite_bytes_to_value(bytes.item, tag.clone()) {
|
match from_sqlite_bytes_to_value(bytes.item, tag.clone()) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
|
@ -50,7 +50,7 @@ impl WholeStreamCommand for FromSSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_ssv)?.run()
|
from_ssv(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,15 +250,11 @@ fn from_ssv_string_to_value(
|
|||||||
Some(UntaggedValue::Table(rows).into_value(&tag))
|
Some(UntaggedValue::Table(rows).into_value(&tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ssv(
|
fn from_ssv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromSSVArgs {
|
let name = args.call_info.name_tag.clone();
|
||||||
headerless,
|
let registry = registry.clone();
|
||||||
aligned_columns,
|
|
||||||
minimum_spaces,
|
|
||||||
}: FromSSVArgs,
|
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (FromSSVArgs { headerless, aligned_columns, minimum_spaces }, mut input) = args.process(®istry).await?;
|
||||||
let concat_string = input.collect_string(name.clone()).await?;
|
let concat_string = input.collect_string(name.clone()).await?;
|
||||||
let split_at = match minimum_spaces {
|
let split_at = match minimum_spaces {
|
||||||
Some(number) => number.item,
|
Some(number) => number.item,
|
||||||
|
@ -67,11 +67,12 @@ pub fn from_toml(
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
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 {
|
||||||
|
@ -33,13 +33,21 @@ impl WholeStreamCommand for FromTSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_tsv)?.run()
|
from_tsv(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_tsv(
|
fn from_tsv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromTSVArgs { headerless }: FromTSVArgs,
|
let registry = registry.clone();
|
||||||
runnable_context: RunnableContext,
|
let name = args.call_info.name_tag.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
let stream = async_stream! {
|
||||||
from_delimited_data(headerless, '\t', "TSV", runnable_context)
|
let (FromTSVArgs { headerless }, mut input) = args.process(®istry).await?;
|
||||||
|
let mut result = from_delimited_data(headerless, '\t', "TSV", input, name)?;
|
||||||
|
|
||||||
|
while let Some(output) = result.next().await {
|
||||||
|
yield output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,12 @@ impl WholeStreamCommand for FromURL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item);
|
let result = serde_urlencoded::from_str::<Vec<(String, String)>>(&concat_string.item);
|
||||||
|
@ -32,11 +32,12 @@ impl WholeStreamCommand for FromVcf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_vcf(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_vcf(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let input_string = input.collect_string(tag.clone()).await?.item;
|
let input_string = input.collect_string(tag.clone()).await?.item;
|
||||||
let input_bytes = input_string.as_bytes();
|
let input_bytes = input_string.as_bytes();
|
||||||
let buf_reader = BufReader::new(input_bytes);
|
let buf_reader = BufReader::new(input_bytes);
|
||||||
|
@ -35,20 +35,15 @@ impl WholeStreamCommand for FromXLSX {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, from_xlsx)?.run()
|
from_xlsx(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_xlsx(
|
fn from_xlsx(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
FromXLSXArgs {
|
let tag = args.call_info.name_tag.clone();
|
||||||
headerless: _headerless,
|
let registry = registry.clone();
|
||||||
}: FromXLSXArgs,
|
|
||||||
runnable_context: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let input = runnable_context.input;
|
|
||||||
let tag = runnable_context.name;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (FromXLSXArgs { headerless: _headerless }, mut input) = args.process(®istry).await?;
|
||||||
let value = input.collect_binary(tag.clone()).await?;
|
let value = input.collect_binary(tag.clone()).await?;
|
||||||
|
|
||||||
let mut buf: Cursor<Vec<u8>> = Cursor::new(value.item);
|
let mut buf: Cursor<Vec<u8>> = Cursor::new(value.item);
|
||||||
|
@ -99,11 +99,12 @@ pub fn from_xml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
match from_xml_string_to_value(concat_string.item, tag.clone()) {
|
match from_xml_string_to_value(concat_string.item, tag.clone()) {
|
||||||
|
@ -119,11 +119,12 @@ pub fn from_yaml_string_to_value(s: String, tag: impl Into<Tag>) -> Result<Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let tag = args.name_tag();
|
|
||||||
let input = args.input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
let concat_string = input.collect_string(tag.clone()).await?;
|
let concat_string = input.collect_string(tag.clone()).await?;
|
||||||
|
|
||||||
match from_yaml_string_to_value(concat_string.item, tag.clone()) {
|
match from_yaml_string_to_value(concat_string.item, tag.clone()) {
|
||||||
|
@ -4,8 +4,8 @@ use indexmap::set::IndexSet;
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
did_you_mean, ColumnPath, PathMember, Primitive, ReturnSuccess, ReturnValue, Signature,
|
did_you_mean, ColumnPath, PathMember, Primitive, ReturnSuccess, Signature, SyntaxShape,
|
||||||
SyntaxShape, UnspannedPathMember, UntaggedValue, Value,
|
UnspannedPathMember, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
use nu_source::span_for_spanned_list;
|
use nu_source::span_for_spanned_list;
|
||||||
use nu_value_ext::get_data_by_column_path;
|
use nu_value_ext::get_data_by_column_path;
|
||||||
@ -38,7 +38,7 @@ impl WholeStreamCommand for Get {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, get)?.run()
|
get(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -189,30 +189,21 @@ pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result<Value, ShellErr
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(
|
pub fn get(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
GetArgs { rest: mut fields }: GetArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { mut input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (GetArgs { rest: mut fields }, mut input) = args.process(®istry).await?;
|
||||||
if fields.is_empty() {
|
if fields.is_empty() {
|
||||||
let stream = async_stream! {
|
|
||||||
let mut vec = input.drain_vec().await;
|
let mut vec = input.drain_vec().await;
|
||||||
|
|
||||||
let descs = nu_protocol::merge_descriptors(&vec);
|
let descs = nu_protocol::merge_descriptors(&vec);
|
||||||
for desc in descs {
|
for desc in descs {
|
||||||
yield ReturnSuccess::value(desc);
|
yield ReturnSuccess::value(desc);
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
let member = fields.remove(0);
|
||||||
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
|
trace!("get {:?} {:?}", member, fields);
|
||||||
|
while let Some(item) = input.next().await {
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
} else {
|
|
||||||
let member = fields.remove(0);
|
|
||||||
trace!("get {:?} {:?}", member, fields);
|
|
||||||
let stream = input
|
|
||||||
.map(move |item| {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
|
|
||||||
let member = vec![member.clone()];
|
let member = vec![member.clone()];
|
||||||
|
|
||||||
let column_paths = vec![&member, &fields]
|
let column_paths = vec![&member, &fields]
|
||||||
@ -230,25 +221,22 @@ pub fn get(
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for item in rows {
|
for item in rows {
|
||||||
result.push_back(ReturnSuccess::value(item.clone()));
|
yield ReturnSuccess::value(item.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Primitive(Primitive::Nothing),
|
value: UntaggedValue::Primitive(Primitive::Nothing),
|
||||||
..
|
..
|
||||||
} => {}
|
} => {}
|
||||||
other => result.push_back(ReturnSuccess::value(other.clone())),
|
other => yield ReturnSuccess::value(other.clone()),
|
||||||
},
|
},
|
||||||
Err(reason) => result.push_back(ReturnSuccess::value(
|
Err(reason) => yield ReturnSuccess::value(
|
||||||
UntaggedValue::Error(reason).into_untagged_value(),
|
UntaggedValue::Error(reason).into_untagged_value(),
|
||||||
)),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
futures::stream::iter(result)
|
}
|
||||||
})
|
};
|
||||||
.flatten();
|
Ok(stream.to_output_stream())
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ impl WholeStreamCommand for GroupBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, group_by)?.run()
|
group_by(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -44,11 +44,11 @@ impl WholeStreamCommand for GroupBy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn group_by(
|
pub fn group_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
GroupByArgs { column_name }: GroupByArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let name = args.call_info.name_tag.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (GroupByArgs { column_name }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
|
@ -41,7 +41,7 @@ impl WholeStreamCommand for GroupByDate {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, group_by_date)?.run()
|
group_by_date(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -57,13 +57,13 @@ enum Grouper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn group_by_date(
|
pub fn group_by_date(
|
||||||
GroupByDateArgs {
|
args: CommandArgs,
|
||||||
column_name,
|
registry: &CommandRegistry,
|
||||||
format,
|
|
||||||
}: GroupByDateArgs,
|
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (GroupByDateArgs { column_name, format }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
|
@ -8,8 +8,6 @@ use nu_protocol::Dictionary;
|
|||||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct Headers;
|
pub struct Headers;
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct HeadersArgs {}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Headers {
|
impl WholeStreamCommand for Headers {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@ -29,7 +27,7 @@ impl WholeStreamCommand for Headers {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, headers)?.run()
|
headers(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -40,11 +38,9 @@ impl WholeStreamCommand for Headers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn headers(
|
pub fn headers(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
HeadersArgs {}: HeadersArgs,
|
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let mut input = args.input;
|
||||||
let rows: Vec<Value> = input.collect().await;
|
let rows: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if rows.len() < 1 {
|
if rows.len() < 1 {
|
||||||
|
@ -35,72 +35,70 @@ impl WholeStreamCommand for Help {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, help)?.run()
|
help(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help(
|
fn help(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
HelpArgs { rest }: HelpArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { registry, name, .. }: RunnableContext,
|
let name = args.call_info.name_tag.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
let stream = async_stream! {
|
||||||
if let Some(document) = rest.get(0) {
|
let (HelpArgs { rest }, mut input) = args.process(®istry).await?;
|
||||||
let mut help = VecDeque::new();
|
if let Some(document) = rest.get(0) {
|
||||||
if document.item == "commands" {
|
if document.item == "commands" {
|
||||||
let mut sorted_names = registry.names();
|
let mut sorted_names = registry.names();
|
||||||
sorted_names.sort();
|
sorted_names.sort();
|
||||||
for cmd in sorted_names {
|
for cmd in sorted_names {
|
||||||
// If it's a subcommand, don't list it during the commands list
|
// If it's a subcommand, don't list it during the commands list
|
||||||
if cmd.contains(' ') {
|
if cmd.contains(' ') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut short_desc = TaggedDictBuilder::new(name.clone());
|
let mut short_desc = TaggedDictBuilder::new(name.clone());
|
||||||
let document_tag = document.tag.clone();
|
let document_tag = document.tag.clone();
|
||||||
let value = command_dict(
|
let value = command_dict(
|
||||||
registry.get_command(&cmd).ok_or_else(|| {
|
registry.get_command(&cmd).ok_or_else(|| {
|
||||||
ShellError::labeled_error(
|
|
||||||
format!("Could not load {}", cmd),
|
|
||||||
"could not load command",
|
|
||||||
document_tag,
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
name.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
short_desc.insert_untagged("name", cmd);
|
|
||||||
short_desc.insert_untagged(
|
|
||||||
"description",
|
|
||||||
get_data_by_key(&value, "usage".spanned_unknown())
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Expected a usage key",
|
format!("Could not load {}", cmd),
|
||||||
"expected a 'usage' key",
|
"could not load command",
|
||||||
&value.tag,
|
document_tag,
|
||||||
)
|
)
|
||||||
})?
|
})?,
|
||||||
.as_string()?,
|
name.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
help.push_back(ReturnSuccess::value(short_desc.into_value()));
|
short_desc.insert_untagged("name", cmd);
|
||||||
|
short_desc.insert_untagged(
|
||||||
|
"description",
|
||||||
|
get_data_by_key(&value, "usage".spanned_unknown())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ShellError::labeled_error(
|
||||||
|
"Expected a usage key",
|
||||||
|
"expected a 'usage' key",
|
||||||
|
&value.tag,
|
||||||
|
)
|
||||||
|
})?
|
||||||
|
.as_string()?,
|
||||||
|
);
|
||||||
|
|
||||||
|
yield ReturnSuccess::value(short_desc.into_value());
|
||||||
|
}
|
||||||
|
} else if rest.len() == 2 {
|
||||||
|
// Check for a subcommand
|
||||||
|
let command_name = format!("{} {}", rest[0].item, rest[1].item);
|
||||||
|
if let Some(command) = registry.get_command(&command_name) {
|
||||||
|
yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(command.stream_command(), ®istry)).into_value(Tag::unknown())));
|
||||||
|
}
|
||||||
|
} else if let Some(command) = registry.get_command(&document.item) {
|
||||||
|
yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(command.stream_command(), ®istry)).into_value(Tag::unknown())));
|
||||||
|
} else {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Can't find command (use 'help commands' for full list)",
|
||||||
|
"can't find command",
|
||||||
|
document.tag.span,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else if rest.len() == 2 {
|
|
||||||
// Check for a subcommand
|
|
||||||
let command_name = format!("{} {}", rest[0].item, rest[1].item);
|
|
||||||
if let Some(command) = registry.get_command(&command_name) {
|
|
||||||
return Ok(get_help(command.stream_command(), ®istry).into());
|
|
||||||
}
|
|
||||||
} else if let Some(command) = registry.get_command(&document.item) {
|
|
||||||
return Ok(get_help(command.stream_command(), ®istry).into());
|
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::labeled_error(
|
let msg = r#"Welcome to Nushell.
|
||||||
"Can't find command (use 'help commands' for full list)",
|
|
||||||
"can't find command",
|
|
||||||
document.tag.span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let help = futures::stream::iter(help);
|
|
||||||
Ok(help.to_output_stream())
|
|
||||||
} else {
|
|
||||||
let msg = r#"Welcome to Nushell.
|
|
||||||
|
|
||||||
Here are some tips to help you get started.
|
Here are some tips to help you get started.
|
||||||
* help commands - list all available commands
|
* help commands - list all available commands
|
||||||
@ -122,22 +120,17 @@ Get the processes on your system actively using CPU:
|
|||||||
|
|
||||||
You can also learn more at https://www.nushell.sh/book/"#;
|
You can also learn more at https://www.nushell.sh/book/"#;
|
||||||
|
|
||||||
let output_stream = futures::stream::iter(vec![ReturnSuccess::value(
|
yield Ok(ReturnSuccess::Value(UntaggedValue::string(msg).into_value(Tag::unknown())));
|
||||||
UntaggedValue::string(msg).into_value(name),
|
}
|
||||||
)]);
|
};
|
||||||
|
|
||||||
Ok(output_stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn get_help(
|
pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> String {
|
||||||
cmd: &dyn WholeStreamCommand,
|
|
||||||
registry: &CommandRegistry,
|
|
||||||
) -> impl Into<OutputStream> {
|
|
||||||
let cmd_name = cmd.name();
|
let cmd_name = cmd.name();
|
||||||
let signature = cmd.signature();
|
let signature = cmd.signature();
|
||||||
let mut help = VecDeque::new();
|
|
||||||
let mut long_desc = String::new();
|
let mut long_desc = String::new();
|
||||||
|
|
||||||
long_desc.push_str(&cmd.usage());
|
long_desc.push_str(&cmd.usage());
|
||||||
@ -285,8 +278,5 @@ pub fn get_help(
|
|||||||
|
|
||||||
long_desc.push_str("\n");
|
long_desc.push_str("\n");
|
||||||
|
|
||||||
help.push_back(ReturnSuccess::value(
|
long_desc
|
||||||
UntaggedValue::string(long_desc).into_value(Tag::from((0, cmd_name.len(), None))),
|
|
||||||
));
|
|
||||||
help
|
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ impl WholeStreamCommand for Histogram {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, histogram)?.run()
|
histogram(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -67,10 +67,13 @@ impl WholeStreamCommand for Histogram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn histogram(
|
pub fn histogram(
|
||||||
HistogramArgs { column_name, rest }: HistogramArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (HistogramArgs { column_name, rest}, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
let Tagged { item: group_by, .. } = column_name.clone();
|
let Tagged { item: group_by, .. } = column_name.clone();
|
||||||
|
@ -8,9 +8,6 @@ use std::io::{BufRead, BufReader};
|
|||||||
|
|
||||||
pub struct History;
|
pub struct History;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct HistoryArgs {}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for History {
|
impl WholeStreamCommand for History {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"history"
|
"history"
|
||||||
@ -29,14 +26,12 @@ impl WholeStreamCommand for History {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, history)?.run()
|
history(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn history(
|
fn history(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
_: HistoryArgs,
|
let tag = args.call_info.name_tag;
|
||||||
RunnableContext { name: tag, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let history_path = HistoryFile::path();
|
let history_path = HistoryFile::path();
|
||||||
let file = File::open(history_path);
|
let file = File::open(history_path);
|
||||||
|
@ -41,17 +41,15 @@ impl WholeStreamCommand for Insert {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, insert)?.run()
|
insert(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(
|
fn insert(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
InsertArgs { column, value }: InsertArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let mut input = input;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (InsertArgs { column, value }, mut input) = args.process(®istry).await?;
|
||||||
match input.next().await {
|
match input.next().await {
|
||||||
Some(obj @ Value {
|
Some(obj @ Value {
|
||||||
value: UntaggedValue::Row(_),
|
value: UntaggedValue::Row(_),
|
||||||
|
@ -41,16 +41,15 @@ impl WholeStreamCommand for IsEmpty {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, is_empty)?.run()
|
is_empty(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty(
|
fn is_empty(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
IsEmptyArgs { rest }: IsEmptyArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (IsEmptyArgs { rest }, mut input) = args.process(®istry).await?;
|
||||||
Ok(input
|
while let Some(value) = input.next().await {
|
||||||
.map(move |value| {
|
|
||||||
let value_tag = value.tag();
|
let value_tag = value.tag();
|
||||||
|
|
||||||
let action = if rest.len() <= 2 {
|
let action = if rest.len() <= 2 {
|
||||||
@ -85,7 +84,7 @@ fn is_empty(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
IsEmptyFor::Value => Ok(ReturnSuccess::Value(
|
IsEmptyFor::Value => yield Ok(ReturnSuccess::Value(
|
||||||
UntaggedValue::boolean(value.is_empty()).into_value(value_tag),
|
UntaggedValue::boolean(value.is_empty()).into_value(value_tag),
|
||||||
)),
|
)),
|
||||||
IsEmptyFor::RowWithFieldsAndFallback(fields, default) => {
|
IsEmptyFor::RowWithFieldsAndFallback(fields, default) => {
|
||||||
@ -93,7 +92,7 @@ fn is_empty(
|
|||||||
|
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
let val =
|
let val =
|
||||||
out.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?;
|
crate::commands::get::get_column_path(&field, &out)?;
|
||||||
|
|
||||||
let emptiness_value = match out {
|
let emptiness_value = match out {
|
||||||
obj
|
obj
|
||||||
@ -125,11 +124,11 @@ fn is_empty(
|
|||||||
out = emptiness_value?;
|
out = emptiness_value?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ReturnSuccess::Value(out))
|
yield Ok(ReturnSuccess::Value(out))
|
||||||
}
|
}
|
||||||
IsEmptyFor::RowWithField(field) => {
|
IsEmptyFor::RowWithField(field) => {
|
||||||
let val =
|
let val =
|
||||||
value.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?;
|
crate::commands::get::get_column_path(&field, &value)?;
|
||||||
|
|
||||||
match &value {
|
match &value {
|
||||||
obj
|
obj
|
||||||
@ -143,18 +142,18 @@ fn is_empty(
|
|||||||
&field,
|
&field,
|
||||||
UntaggedValue::boolean(true).into_value(&value_tag),
|
UntaggedValue::boolean(true).into_value(&value_tag),
|
||||||
) {
|
) {
|
||||||
Some(v) => Ok(ReturnSuccess::Value(v)),
|
Some(v) => yield Ok(ReturnSuccess::Value(v)),
|
||||||
None => Err(ShellError::labeled_error(
|
None => yield Err(ShellError::labeled_error(
|
||||||
"empty? could not find place to check emptiness",
|
"empty? could not find place to check emptiness",
|
||||||
"column name",
|
"column name",
|
||||||
&field.tag,
|
&field.tag,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(ReturnSuccess::Value(value))
|
yield Ok(ReturnSuccess::Value(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Unrecognized type in stream",
|
"Unrecognized type in stream",
|
||||||
"original value",
|
"original value",
|
||||||
&value_tag,
|
&value_tag,
|
||||||
@ -163,7 +162,7 @@ fn is_empty(
|
|||||||
}
|
}
|
||||||
IsEmptyFor::RowWithFieldAndFallback(field, default) => {
|
IsEmptyFor::RowWithFieldAndFallback(field, default) => {
|
||||||
let val =
|
let val =
|
||||||
value.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?;
|
crate::commands::get::get_column_path(&field, &value)?;
|
||||||
|
|
||||||
match &value {
|
match &value {
|
||||||
obj
|
obj
|
||||||
@ -174,18 +173,18 @@ fn is_empty(
|
|||||||
} => {
|
} => {
|
||||||
if val.is_empty() {
|
if val.is_empty() {
|
||||||
match obj.replace_data_at_column_path(&field, default) {
|
match obj.replace_data_at_column_path(&field, default) {
|
||||||
Some(v) => Ok(ReturnSuccess::Value(v)),
|
Some(v) => yield Ok(ReturnSuccess::Value(v)),
|
||||||
None => Err(ShellError::labeled_error(
|
None => yield Err(ShellError::labeled_error(
|
||||||
"empty? could not find place to check emptiness",
|
"empty? could not find place to check emptiness",
|
||||||
"column name",
|
"column name",
|
||||||
&field.tag,
|
&field.tag,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(ReturnSuccess::Value(value))
|
yield Ok(ReturnSuccess::Value(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Unrecognized type in stream",
|
"Unrecognized type in stream",
|
||||||
"original value",
|
"original value",
|
||||||
&value_tag,
|
&value_tag,
|
||||||
@ -193,6 +192,7 @@ fn is_empty(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.to_output_stream())
|
};
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Keep;
|
pub struct Keep;
|
||||||
@ -34,7 +34,7 @@ impl WholeStreamCommand for Keep {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, keep)?.run()
|
keep(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -51,12 +51,25 @@ impl WholeStreamCommand for Keep {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keep(KeepArgs { rows }: KeepArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn keep(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let rows_desired = if let Some(quantity) = rows {
|
let registry = registry.clone();
|
||||||
*quantity
|
let stream = async_stream! {
|
||||||
} else {
|
let (KeepArgs { rows }, mut input) = args.process(®istry).await?;
|
||||||
1
|
let mut rows_desired = if let Some(quantity) = rows {
|
||||||
|
*quantity
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(input) = input.next().await {
|
||||||
|
if rows_desired > 0 {
|
||||||
|
yield ReturnSuccess::value(input);
|
||||||
|
rows_desired -= 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(OutputStream::from_input(context.input.take(rows_desired)))
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct KeepUntil;
|
pub struct KeepUntil;
|
||||||
|
|
||||||
@ -33,66 +35,77 @@ impl WholeStreamCommand for KeepUntil {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = args.call_info.scope.clone();
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry)?;
|
let stream = async_stream! {
|
||||||
|
let mut call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
|
|
||||||
let condition = match block {
|
let condition = match block {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Block(block),
|
value: UntaggedValue::Block(block),
|
||||||
tag,
|
tag,
|
||||||
} => {
|
} => {
|
||||||
if block.block.len() != 1 {
|
if block.block.len() != 1 {
|
||||||
return Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
match block.block[0].list.get(0) {
|
|
||||||
Some(item) => match item {
|
|
||||||
ClassifiedCommand::Expr(expr) => expr.clone(),
|
|
||||||
_ => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
"Expected a condition",
|
||||||
"expected a condition",
|
"expected a condition",
|
||||||
tag,
|
tag,
|
||||||
));
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match block.block[0].list.get(0) {
|
||||||
|
Some(item) => match item {
|
||||||
|
ClassifiedCommand::Expr(expr) => expr.clone(),
|
||||||
|
_ => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Value { tag, .. } => {
|
||||||
Value { tag, .. } => {
|
yield Err(ShellError::labeled_error(
|
||||||
return Err(ShellError::labeled_error(
|
"Expected a condition",
|
||||||
"Expected a condition",
|
"expected a condition",
|
||||||
"expected a condition",
|
tag,
|
||||||
tag,
|
));
|
||||||
));
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(item) = call_info.input.next().await {
|
||||||
|
let condition = condition.clone();
|
||||||
|
trace!("ITEM = {:?}", item);
|
||||||
|
let result =
|
||||||
|
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
||||||
|
.await;
|
||||||
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
let return_value = match result {
|
||||||
|
Ok(ref v) if v.is_true() => false,
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if return_value {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let objects = call_info.input.take_while(move |item| {
|
Ok(stream.to_output_stream())
|
||||||
let condition = condition.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
|
||||||
let result =
|
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()));
|
|
||||||
trace!("RESULT = {:?}", result);
|
|
||||||
|
|
||||||
let return_value = match result {
|
|
||||||
Ok(ref v) if v.is_true() => false,
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
futures::future::ready(return_value)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct KeepWhile;
|
pub struct KeepWhile;
|
||||||
|
|
||||||
@ -33,66 +35,77 @@ impl WholeStreamCommand for KeepWhile {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = args.call_info.scope.clone();
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry)?;
|
let stream = async_stream! {
|
||||||
|
let mut call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
|
|
||||||
let condition = match block {
|
let condition = match block {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Block(block),
|
value: UntaggedValue::Block(block),
|
||||||
tag,
|
tag,
|
||||||
} => {
|
} => {
|
||||||
if block.block.len() != 1 {
|
if block.block.len() != 1 {
|
||||||
return Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
match block.block[0].list.get(0) {
|
|
||||||
Some(item) => match item {
|
|
||||||
ClassifiedCommand::Expr(expr) => expr.clone(),
|
|
||||||
_ => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
"Expected a condition",
|
||||||
"expected a condition",
|
"expected a condition",
|
||||||
tag,
|
tag,
|
||||||
));
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match block.block[0].list.get(0) {
|
||||||
|
Some(item) => match item {
|
||||||
|
ClassifiedCommand::Expr(expr) => expr.clone(),
|
||||||
|
_ => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Value { tag, .. } => {
|
||||||
Value { tag, .. } => {
|
yield Err(ShellError::labeled_error(
|
||||||
return Err(ShellError::labeled_error(
|
"Expected a condition",
|
||||||
"Expected a condition",
|
"expected a condition",
|
||||||
"expected a condition",
|
tag,
|
||||||
tag,
|
));
|
||||||
));
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(item) = call_info.input.next().await {
|
||||||
|
let condition = condition.clone();
|
||||||
|
trace!("ITEM = {:?}", item);
|
||||||
|
let result =
|
||||||
|
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
||||||
|
.await;
|
||||||
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
let return_value = match result {
|
||||||
|
Ok(ref v) if v.is_true() => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if return_value {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let objects = call_info.input.take_while(move |item| {
|
Ok(stream.to_output_stream())
|
||||||
let condition = condition.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
|
||||||
let result =
|
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()));
|
|
||||||
trace!("RESULT = {:?}", result);
|
|
||||||
|
|
||||||
let return_value = match result {
|
|
||||||
Ok(ref v) if v.is_true() => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
futures::future::ready(return_value)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ impl WholeStreamCommand for Kill {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, kill)?.run()
|
kill(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -59,55 +59,61 @@ impl WholeStreamCommand for Kill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill(
|
fn kill(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
KillArgs {
|
let registry = registry.clone();
|
||||||
pid,
|
|
||||||
rest,
|
|
||||||
force,
|
|
||||||
quiet,
|
|
||||||
}: KillArgs,
|
|
||||||
_context: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let mut cmd = if cfg!(windows) {
|
|
||||||
let mut cmd = Command::new("taskkill");
|
|
||||||
|
|
||||||
if *force {
|
let stream = async_stream! {
|
||||||
cmd.arg("/F");
|
let (KillArgs {
|
||||||
}
|
pid,
|
||||||
|
rest,
|
||||||
|
force,
|
||||||
|
quiet,
|
||||||
|
}, mut input) = args.process(®istry).await?;
|
||||||
|
let mut cmd = if cfg!(windows) {
|
||||||
|
let mut cmd = Command::new("taskkill");
|
||||||
|
|
||||||
cmd.arg("/PID");
|
if *force {
|
||||||
cmd.arg(pid.item().to_string());
|
cmd.arg("/F");
|
||||||
|
}
|
||||||
|
|
||||||
// each pid must written as `/PID 0` otherwise
|
|
||||||
// taskkill will act as `killall` unix command
|
|
||||||
for id in &rest {
|
|
||||||
cmd.arg("/PID");
|
cmd.arg("/PID");
|
||||||
cmd.arg(id.item().to_string());
|
cmd.arg(pid.item().to_string());
|
||||||
|
|
||||||
|
// each pid must written as `/PID 0` otherwise
|
||||||
|
// taskkill will act as `killall` unix command
|
||||||
|
for id in &rest {
|
||||||
|
cmd.arg("/PID");
|
||||||
|
cmd.arg(id.item().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd
|
||||||
|
} else {
|
||||||
|
let mut cmd = Command::new("kill");
|
||||||
|
|
||||||
|
if *force {
|
||||||
|
cmd.arg("-9");
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.arg(pid.item().to_string());
|
||||||
|
|
||||||
|
cmd.args(rest.iter().map(move |id| id.item().to_string()));
|
||||||
|
|
||||||
|
cmd
|
||||||
|
};
|
||||||
|
|
||||||
|
// pipe everything to null
|
||||||
|
if *quiet {
|
||||||
|
cmd.stdin(Stdio::null())
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null());
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd
|
cmd.status().expect("failed to execute shell command");
|
||||||
} else {
|
|
||||||
let mut cmd = Command::new("kill");
|
|
||||||
|
|
||||||
if *force {
|
if false {
|
||||||
cmd.arg("-9");
|
yield ReturnSuccess::value(UntaggedValue::nothing().into_value(Tag::unknown()));
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.arg(pid.item().to_string());
|
|
||||||
|
|
||||||
cmd.args(rest.iter().map(move |id| id.item().to_string()));
|
|
||||||
|
|
||||||
cmd
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// pipe everything to null
|
Ok(stream.to_output_stream())
|
||||||
if *quiet {
|
|
||||||
cmd.stdin(Stdio::null())
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.stderr(Stdio::null());
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.status().expect("failed to execute shell command");
|
|
||||||
|
|
||||||
Ok(OutputStream::empty())
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl WholeStreamCommand for Last {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, last)?.run()
|
last(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -51,9 +51,11 @@ impl WholeStreamCommand for Last {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last(LastArgs { rows }: LastArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let v: Vec<_> = context.input.into_vec().await;
|
let (LastArgs { rows }, mut input) = args.process(®istry).await?;
|
||||||
|
let v: Vec<_> = input.into_vec().await;
|
||||||
|
|
||||||
let rows_desired = if let Some(quantity) = rows {
|
let rows_desired = if let Some(quantity) = rows {
|
||||||
*quantity
|
*quantity
|
||||||
|
@ -45,14 +45,14 @@ fn ends_with_line_ending(st: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
|
||||||
let tag = args.name_tag();
|
|
||||||
let name_span = tag.span;
|
|
||||||
let mut input = args.input;
|
|
||||||
|
|
||||||
let mut leftover = vec![];
|
let mut leftover = vec![];
|
||||||
let mut leftover_string = String::new();
|
let mut leftover_string = String::new();
|
||||||
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await.unwrap();
|
||||||
|
let tag = args.name_tag();
|
||||||
|
let name_span = tag.span;
|
||||||
|
let mut input = args.input;
|
||||||
loop {
|
loop {
|
||||||
match input.next().await {
|
match input.next().await {
|
||||||
Some(Value { value: UntaggedValue::Primitive(Primitive::String(st)), ..}) => {
|
Some(Value { value: UntaggedValue::Primitive(Primitive::String(st)), ..}) => {
|
||||||
|
@ -64,7 +64,7 @@ impl WholeStreamCommand for Ls {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, ls)?.run()
|
ls(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -85,6 +85,19 @@ impl WholeStreamCommand for Ls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls(args: LsArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
context.shell_manager.ls(args, &context)
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let ctrl_c = args.ctrl_c.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let (args, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.ls(args, name, ctrl_c)?;
|
||||||
|
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -37,18 +37,20 @@ impl WholeStreamCommand for MapMaxBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, map_max_by)?.run()
|
map_max_by(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_max_by(
|
pub fn map_max_by(
|
||||||
MapMaxByArgs { column_name }: MapMaxByArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (MapMaxByArgs { column_name }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
yield Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected table from pipeline",
|
"Expected table from pipeline",
|
||||||
|
@ -36,7 +36,7 @@ impl WholeStreamCommand for Merge {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(args.process_raw(registry, merge)?.run())
|
merge(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -47,19 +47,15 @@ impl WholeStreamCommand for Merge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge(
|
fn merge(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
merge_args: MergeArgs,
|
let registry = registry.clone();
|
||||||
context: RunnableContext,
|
|
||||||
raw_args: RawCommandArgs,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let block = merge_args.block;
|
|
||||||
let registry = context.registry.clone();
|
|
||||||
let mut input = context.input;
|
|
||||||
let scope = raw_args.call_info.scope.clone();
|
|
||||||
|
|
||||||
let mut context = Context::from_raw(&raw_args, ®istry);
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let mut context = Context::from_raw(&raw_args, ®istry);
|
||||||
|
let name_tag = raw_args.call_info.name_tag.clone();
|
||||||
|
let scope = raw_args.call_info.scope.clone();
|
||||||
|
let (merge_args, mut input): (MergeArgs, _) = raw_args.process(®istry).await?;
|
||||||
|
let block = merge_args.block;
|
||||||
|
|
||||||
let table: Option<Vec<Value>> = match run_block(&block,
|
let table: Option<Vec<Value>> = match run_block(&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
InputStream::empty(),
|
InputStream::empty(),
|
||||||
@ -74,7 +70,7 @@ fn merge(
|
|||||||
|
|
||||||
let table = table.unwrap_or_else(|| vec![Value {
|
let table = table.unwrap_or_else(|| vec![Value {
|
||||||
value: UntaggedValue::row(IndexMap::default()),
|
value: UntaggedValue::row(IndexMap::default()),
|
||||||
tag: raw_args.call_info.name_tag,
|
tag: name_tag,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
|
@ -31,7 +31,7 @@ impl WholeStreamCommand for Mkdir {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, mkdir)?.run()
|
mkdir(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -42,7 +42,18 @@ impl WholeStreamCommand for Mkdir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkdir(args: MkdirArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn mkdir(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = context.shell_manager.clone();
|
let registry = registry.clone();
|
||||||
shell_manager.mkdir(args, &context)
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let (args, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.mkdir(args, name)?;
|
||||||
|
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ impl WholeStreamCommand for Move {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, mv)?.run()
|
mv(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -63,7 +63,18 @@ impl WholeStreamCommand for Move {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mv(args: MoveArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = context.shell_manager.clone();
|
let registry = registry.clone();
|
||||||
shell_manager.mv(args, &context)
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let (args, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.mv(args, name)?;
|
||||||
|
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ impl WholeStreamCommand for Nth {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, nth)?.run()
|
nth(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -54,16 +54,13 @@ impl WholeStreamCommand for Nth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nth(
|
fn nth(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
NthArgs {
|
let registry = registry.clone();
|
||||||
row_number,
|
let stream = async_stream! {
|
||||||
rest: and_rows,
|
let (NthArgs { row_number, rest: and_rows}, input) = args.process(®istry).await?;
|
||||||
}: NthArgs,
|
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let mut inp = input.enumerate();
|
||||||
) -> Result<OutputStream, ShellError> {
|
while let Some((idx, item)) = inp.next().await {
|
||||||
let stream = input
|
|
||||||
.enumerate()
|
|
||||||
.map(move |(idx, item)| {
|
|
||||||
let row_number = vec![row_number.clone()];
|
let row_number = vec![row_number.clone()];
|
||||||
|
|
||||||
let row_numbers = vec![&row_number, &and_rows]
|
let row_numbers = vec![&row_number, &and_rows]
|
||||||
@ -71,18 +68,14 @@ fn nth(
|
|||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<&Tagged<u64>>>();
|
.collect::<Vec<&Tagged<u64>>>();
|
||||||
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
|
|
||||||
if row_numbers
|
if row_numbers
|
||||||
.iter()
|
.iter()
|
||||||
.any(|requested| requested.item == idx as u64)
|
.any(|requested| requested.item == idx as u64)
|
||||||
{
|
{
|
||||||
result.push_back(ReturnSuccess::value(item));
|
yield ReturnSuccess::value(item);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
futures::stream::iter(result)
|
};
|
||||||
})
|
|
||||||
.flatten();
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -41,19 +41,17 @@ impl WholeStreamCommand for Open {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, open)?.run()
|
open(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(
|
fn open(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
OpenArgs { path, raw }: OpenArgs,
|
let cwd = PathBuf::from(args.shell_manager.path());
|
||||||
RunnableContext { shell_manager, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let cwd = PathBuf::from(shell_manager.path());
|
|
||||||
let full_path = cwd;
|
let full_path = cwd;
|
||||||
|
let registry = registry.clone();
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (OpenArgs { path, raw }, _) = args.process(®istry).await?;
|
||||||
let result = fetch(&full_path, &path.item, path.tag.span).await;
|
let result = fetch(&full_path, &path.item, path.tag.span).await;
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
|
@ -1,167 +0,0 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
|
||||||
use crate::context::CommandRegistry;
|
|
||||||
use crate::prelude::*;
|
|
||||||
use nu_errors::ShellError;
|
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue};
|
|
||||||
use nu_source::Tagged;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum ParseCommand {
|
|
||||||
Text(String),
|
|
||||||
Column(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse(input: &str) -> Vec<ParseCommand> {
|
|
||||||
let mut output = vec![];
|
|
||||||
|
|
||||||
//let mut loop_input = input;
|
|
||||||
let mut loop_input = input.chars();
|
|
||||||
loop {
|
|
||||||
let mut before = String::new();
|
|
||||||
|
|
||||||
while let Some(c) = loop_input.next() {
|
|
||||||
if c == '{' {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
before.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !before.is_empty() {
|
|
||||||
output.push(ParseCommand::Text(before.to_string()));
|
|
||||||
}
|
|
||||||
// Look for column as we're now at one
|
|
||||||
let mut column = String::new();
|
|
||||||
|
|
||||||
while let Some(c) = loop_input.next() {
|
|
||||||
if c == '}' {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
column.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !column.is_empty() {
|
|
||||||
output.push(ParseCommand::Column(column.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if before.is_empty() && column.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
}
|
|
||||||
|
|
||||||
fn column_names(commands: &[ParseCommand]) -> Vec<String> {
|
|
||||||
let mut output = vec![];
|
|
||||||
|
|
||||||
for command in commands {
|
|
||||||
if let ParseCommand::Column(c) = command {
|
|
||||||
output.push(c.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_regex(commands: &[ParseCommand]) -> String {
|
|
||||||
let mut output = String::new();
|
|
||||||
|
|
||||||
for command in commands {
|
|
||||||
match command {
|
|
||||||
ParseCommand::Text(s) => {
|
|
||||||
output.push_str(&s.replace("(", "\\("));
|
|
||||||
}
|
|
||||||
ParseCommand::Column(_) => {
|
|
||||||
output.push_str("(.*)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
}
|
|
||||||
pub struct Parse;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct ParseArgs {
|
|
||||||
pattern: Tagged<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WholeStreamCommand for Parse {
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"parse"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
|
||||||
Signature::build("parse").required(
|
|
||||||
"pattern",
|
|
||||||
SyntaxShape::String,
|
|
||||||
"the pattern to match. Eg) \"{foo}: {bar}\"",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
|
||||||
"Parse columns from string data using a simple pattern."
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(
|
|
||||||
&self,
|
|
||||||
args: CommandArgs,
|
|
||||||
registry: &CommandRegistry,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
args.process(registry, parse_command)?.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
|
||||||
&[Example {
|
|
||||||
description: "Parse values from a string into a table",
|
|
||||||
example: r#"echo "data: 123" | parse "{key}: {value}""#,
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_command(
|
|
||||||
ParseArgs { pattern }: ParseArgs,
|
|
||||||
RunnableContext { name, input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let parse_pattern = parse(&pattern.item);
|
|
||||||
let parse_regex = build_regex(&parse_pattern);
|
|
||||||
let column_names = column_names(&parse_pattern);
|
|
||||||
let name = name.span;
|
|
||||||
let regex = Regex::new(&parse_regex).map_err(|_| {
|
|
||||||
ShellError::labeled_error(
|
|
||||||
"Could not parse regex",
|
|
||||||
"could not parse regex",
|
|
||||||
&pattern.tag,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(input
|
|
||||||
.map(move |value| {
|
|
||||||
if let Ok(s) = value.as_string() {
|
|
||||||
let mut output = vec![];
|
|
||||||
for cap in regex.captures_iter(&s) {
|
|
||||||
let mut dict = TaggedDictBuilder::new(value.tag());
|
|
||||||
for (idx, column_name) in column_names.iter().enumerate() {
|
|
||||||
dict.insert_untagged(
|
|
||||||
column_name,
|
|
||||||
UntaggedValue::string(cap[idx + 1].to_string()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
output.push(Ok(ReturnSuccess::Value(dict.into_value())));
|
|
||||||
}
|
|
||||||
output
|
|
||||||
} else {
|
|
||||||
vec![Err(ShellError::labeled_error_with_secondary(
|
|
||||||
"Expected string input",
|
|
||||||
"expected string input",
|
|
||||||
name,
|
|
||||||
"value originated here",
|
|
||||||
value.tag,
|
|
||||||
))]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(futures::stream::iter)
|
|
||||||
.flatten()
|
|
||||||
.to_output_stream())
|
|
||||||
}
|
|
@ -50,20 +50,23 @@ impl WholeStreamCommand for Pivot {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, pivot)?.run()
|
pivot(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
pub fn pivot(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let input = context.input.into_vec().await;
|
let (args, mut input): (PivotArgs, _) = args.process(®istry).await?;
|
||||||
|
let input = input.into_vec().await;
|
||||||
|
|
||||||
let descs = merge_descriptors(&input);
|
let descs = merge_descriptors(&input);
|
||||||
|
|
||||||
let mut headers: Vec<String> = vec![];
|
let mut headers: Vec<String> = vec![];
|
||||||
|
|
||||||
if args.rest.len() > 0 && args.header_row {
|
if args.rest.len() > 0 && args.header_row {
|
||||||
yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", context.name));
|
yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,17 +78,17 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream,
|
|||||||
if let Ok(s) = x.as_string() {
|
if let Ok(s) = x.as_string() {
|
||||||
headers.push(s.to_string());
|
headers.push(s.to_string());
|
||||||
} else {
|
} else {
|
||||||
yield Err(ShellError::labeled_error("Header row needs string headers", "used non-string headers", context.name));
|
yield Err(ShellError::labeled_error("Header row needs string headers", "used non-string headers", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", context.name));
|
yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", context.name));
|
yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +110,7 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream,
|
|||||||
|
|
||||||
for desc in descs {
|
for desc in descs {
|
||||||
let mut column_num: usize = 0;
|
let mut column_num: usize = 0;
|
||||||
let mut dict = TaggedDictBuilder::new(&context.name);
|
let mut dict = TaggedDictBuilder::new(&name);
|
||||||
|
|
||||||
if !args.ignore_titles && !args.header_row {
|
if !args.ignore_titles && !args.header_row {
|
||||||
dict.insert_untagged(headers[column_num].clone(), UntaggedValue::string(desc.clone()));
|
dict.insert_untagged(headers[column_num].clone(), UntaggedValue::string(desc.clone()));
|
||||||
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value};
|
||||||
use serde::{self, Deserialize, Serialize};
|
use serde::{self, Deserialize, Serialize};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
@ -70,180 +70,84 @@ pub fn filter_plugin(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
trace!("filter_plugin :: {}", path);
|
trace!("filter_plugin :: {}", path);
|
||||||
|
let registry = registry.clone();
|
||||||
|
|
||||||
let scope = &args
|
let scope = args
|
||||||
.call_info
|
.call_info
|
||||||
.scope
|
.scope
|
||||||
.clone()
|
.clone()
|
||||||
.set_it(UntaggedValue::string("$it").into_untagged_value());
|
.set_it(UntaggedValue::string("$it").into_untagged_value());
|
||||||
|
|
||||||
let args = args.evaluate_once_with_scope(registry, &scope)?;
|
let stream = async_stream! {
|
||||||
|
let mut args = args.evaluate_once_with_scope(®istry, &scope).await?;
|
||||||
|
|
||||||
let mut child = std::process::Command::new(path)
|
let mut child = std::process::Command::new(path)
|
||||||
.stdin(std::process::Stdio::piped())
|
.stdin(std::process::Stdio::piped())
|
||||||
.stdout(std::process::Stdio::piped())
|
.stdout(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("Failed to spawn child process");
|
.expect("Failed to spawn child process");
|
||||||
|
|
||||||
let mut bos: VecDeque<Value> = VecDeque::new();
|
let call_info = args.call_info.clone();
|
||||||
bos.push_back(UntaggedValue::Primitive(Primitive::BeginningOfStream).into_untagged_value());
|
|
||||||
let bos = futures::stream::iter(bos);
|
|
||||||
|
|
||||||
let mut eos: VecDeque<Value> = VecDeque::new();
|
trace!("filtering :: {:?}", call_info);
|
||||||
eos.push_back(UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value());
|
|
||||||
let eos = futures::stream::iter(eos);
|
|
||||||
|
|
||||||
let call_info = args.call_info.clone();
|
// Beginning of the stream
|
||||||
|
{
|
||||||
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||||
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
||||||
|
|
||||||
trace!("filtering :: {:?}", call_info);
|
let mut reader = BufReader::new(stdout);
|
||||||
|
|
||||||
let stream = bos
|
let request = JsonRpc::new("begin_filter", call_info.clone());
|
||||||
.chain(args.input)
|
let request_raw = serde_json::to_string(&request);
|
||||||
.chain(eos)
|
|
||||||
.map(move |v| match v {
|
|
||||||
Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::BeginningOfStream),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
||||||
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
|
||||||
|
|
||||||
let mut reader = BufReader::new(stdout);
|
match request_raw {
|
||||||
|
Err(_) => {
|
||||||
let request = JsonRpc::new("begin_filter", call_info.clone());
|
yield Err(ShellError::labeled_error(
|
||||||
let request_raw = serde_json::to_string(&request);
|
"Could not load json from plugin",
|
||||||
|
"could not load json from plugin",
|
||||||
match request_raw {
|
&call_info.name_tag,
|
||||||
Err(_) => {
|
));
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(Err(ShellError::labeled_error(
|
|
||||||
"Could not load json from plugin",
|
|
||||||
"could not load json from plugin",
|
|
||||||
&call_info.name_tag,
|
|
||||||
)));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
Ok(request_raw) => match stdin.write(format!("{}\n", request_raw).as_bytes()) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(Err(ShellError::unexpected(format!("{}", err))));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
Ok(request_raw) => match stdin.write(format!("{}\n", request_raw).as_bytes()) {
|
||||||
let mut input = String::new();
|
Ok(_) => {}
|
||||||
match reader.read_line(&mut input) {
|
|
||||||
Ok(_) => {
|
|
||||||
let response = serde_json::from_str::<NuResult>(&input);
|
|
||||||
match response {
|
|
||||||
Ok(NuResult::response { params }) => match params {
|
|
||||||
Ok(params) => params,
|
|
||||||
Err(e) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(ReturnValue::Err(e));
|
|
||||||
result
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while processing begin_filter response: {:?} {}",
|
|
||||||
e, input
|
|
||||||
))));
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while reading begin_filter response: {:?}",
|
|
||||||
e
|
|
||||||
))));
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::EndOfStream),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
||||||
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
|
||||||
|
|
||||||
let mut reader = BufReader::new(stdout);
|
|
||||||
|
|
||||||
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("end_filter", vec![]);
|
|
||||||
let request_raw = match serde_json::to_string(&request) {
|
|
||||||
Ok(req) => req,
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let mut result = VecDeque::new();
|
yield Err(ShellError::unexpected(format!("{}", err)));
|
||||||
result.push_back(Err(ShellError::unexpected(format!("{}", err))));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
}
|
||||||
|
|
||||||
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
let mut input = String::new();
|
||||||
|
match reader.read_line(&mut input) {
|
||||||
let mut input = String::new();
|
Ok(_) => {
|
||||||
let result = match reader.read_line(&mut input) {
|
let response = serde_json::from_str::<NuResult>(&input);
|
||||||
Ok(_) => {
|
match response {
|
||||||
let response = serde_json::from_str::<NuResult>(&input);
|
Ok(NuResult::response { params }) => match params {
|
||||||
match response {
|
Ok(params) => for param in params { yield param },
|
||||||
Ok(NuResult::response { params }) => match params {
|
|
||||||
Ok(params) => {
|
|
||||||
let request: JsonRpc<std::vec::Vec<Value>> =
|
|
||||||
JsonRpc::new("quit", vec![]);
|
|
||||||
let request_raw = serde_json::to_string(&request);
|
|
||||||
match request_raw {
|
|
||||||
Ok(request_raw) => {
|
|
||||||
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while processing begin_filter response: {:?} {}",
|
|
||||||
e, input
|
|
||||||
))));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
params
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
result.push_back(ReturnValue::Err(e));
|
|
||||||
result
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut result = VecDeque::new();
|
yield ReturnValue::Err(e);
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while processing end_filter response: {:?} {}",
|
|
||||||
e, input
|
|
||||||
))));
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
|
"Error while processing begin_filter response: {:?} {}",
|
||||||
|
e, input
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
}
|
||||||
let mut result = VecDeque::new();
|
Err(e) => {
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
"Error while reading end_filter: {:?}",
|
"Error while reading begin_filter response: {:?}",
|
||||||
e
|
e
|
||||||
))));
|
)));
|
||||||
result
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = child.wait();
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
_ => {
|
}
|
||||||
|
|
||||||
|
// Stream contents
|
||||||
|
{
|
||||||
|
while let Some(v) = args.input.next().await {
|
||||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||||
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
||||||
|
|
||||||
@ -256,12 +160,10 @@ pub fn filter_plugin(
|
|||||||
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut result = VecDeque::new();
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while processing filter response: {:?}",
|
"Error while processing filter response: {:?}",
|
||||||
e
|
e
|
||||||
))));
|
)));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,36 +173,97 @@ pub fn filter_plugin(
|
|||||||
let response = serde_json::from_str::<NuResult>(&input);
|
let response = serde_json::from_str::<NuResult>(&input);
|
||||||
match response {
|
match response {
|
||||||
Ok(NuResult::response { params }) => match params {
|
Ok(NuResult::response { params }) => match params {
|
||||||
Ok(params) => params,
|
Ok(params) => for param in params { yield param },
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut result = VecDeque::new();
|
yield ReturnValue::Err(e);
|
||||||
result.push_back(ReturnValue::Err(e));
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut result = VecDeque::new();
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while processing filter response: {:?}\n== input ==\n{}",
|
"Error while processing filter response: {:?}\n== input ==\n{}",
|
||||||
e, input
|
e, input
|
||||||
))));
|
)));
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut result = VecDeque::new();
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
result.push_back(Err(ShellError::untagged_runtime_error(format!(
|
|
||||||
"Error while reading filter response: {:?}",
|
"Error while reading filter response: {:?}",
|
||||||
e
|
e
|
||||||
))));
|
)));
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.map(futures::stream::iter) // convert to a stream
|
|
||||||
.flatten();
|
// End of the stream
|
||||||
|
{
|
||||||
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||||
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
||||||
|
|
||||||
|
let mut reader = BufReader::new(stdout);
|
||||||
|
|
||||||
|
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("end_filter", vec![]);
|
||||||
|
let request_raw = match serde_json::to_string(&request) {
|
||||||
|
Ok(req) => req,
|
||||||
|
Err(err) => {
|
||||||
|
yield Err(ShellError::unexpected(format!("{}", err)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
||||||
|
|
||||||
|
let mut input = String::new();
|
||||||
|
match reader.read_line(&mut input) {
|
||||||
|
Ok(_) => {
|
||||||
|
let response = serde_json::from_str::<NuResult>(&input);
|
||||||
|
match response {
|
||||||
|
Ok(NuResult::response { params }) => match params {
|
||||||
|
Ok(params) => {
|
||||||
|
let request: JsonRpc<std::vec::Vec<Value>> =
|
||||||
|
JsonRpc::new("quit", vec![]);
|
||||||
|
let request_raw = serde_json::to_string(&request);
|
||||||
|
match request_raw {
|
||||||
|
Ok(request_raw) => {
|
||||||
|
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
|
"Error while processing begin_filter response: {:?} {}",
|
||||||
|
e, input
|
||||||
|
)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//yield ReturnValue::Ok(params)
|
||||||
|
//yield ReturnSuccess::value(Value)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
yield ReturnValue::Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
|
"Error while processing end_filter response: {:?} {}",
|
||||||
|
e, input
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
yield Err(ShellError::untagged_runtime_error(format!(
|
||||||
|
"Error while reading end_filter: {:?}",
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = child.wait();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
@ -339,10 +302,11 @@ pub fn sink_plugin(
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let call_info = args.call_info.clone();
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let call_info = args.call_info.clone();
|
||||||
|
|
||||||
let input: Vec<Value> = args.input.collect().await;
|
let input: Vec<Value> = args.input.collect().await;
|
||||||
|
|
||||||
let request = JsonRpc::new("sink", (call_info.clone(), input));
|
let request = JsonRpc::new("sink", (call_info.clone(), input));
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct PrependArgs {
|
struct PrependArgs {
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for Prepend {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, prepend)?.run()
|
prepend(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -44,11 +44,17 @@ impl WholeStreamCommand for Prepend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepend(
|
fn prepend(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
PrependArgs { row }: PrependArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let prepend = futures::stream::iter(vec![row]);
|
|
||||||
|
|
||||||
Ok(prepend.chain(input).to_output_stream())
|
let stream = async_stream! {
|
||||||
|
let (PrependArgs { row }, mut input) = args.process(®istry).await?;
|
||||||
|
|
||||||
|
yield ReturnSuccess::value(row);
|
||||||
|
while let Some(item) = input.next().await {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,17 @@ impl WholeStreamCommand for Pwd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn pwd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = args.shell_manager.clone();
|
let registry = registry.clone();
|
||||||
let args = args.evaluate_once(registry)?;
|
|
||||||
shell_manager.pwd(args)
|
let stream = async_stream! {
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let mut out = shell_manager.pwd(args)?;
|
||||||
|
|
||||||
|
while let Some(l) = out.next().await {
|
||||||
|
yield l;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::context::CommandRegistry;
|
|||||||
use crate::deserializer::NumericRange;
|
use crate::deserializer::NumericRange;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -35,20 +35,26 @@ impl WholeStreamCommand for Range {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, range)?.run()
|
range(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range(
|
fn range(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
RangeArgs { area }: RangeArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (RangeArgs { area }, mut input) = args.process(®istry).await?;
|
||||||
let range = area.item;
|
let range = area.item;
|
||||||
let (from, _) = range.from;
|
let (from, _) = range.from;
|
||||||
let (to, _) = range.to;
|
let (to, _) = range.to;
|
||||||
|
|
||||||
let from = *from as usize;
|
let from = *from as usize;
|
||||||
let to = *to as usize;
|
let to = *to as usize;
|
||||||
|
|
||||||
Ok(input.skip(from).take(to - from + 1).to_output_stream())
|
let mut inp = input.skip(from).take(to - from + 1);
|
||||||
|
while let Some(item) = inp.next().await {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -36,15 +36,18 @@ impl WholeStreamCommand for ReduceBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, reduce_by)?.run()
|
reduce_by(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce_by(
|
pub fn reduce_by(
|
||||||
ReduceByArgs { reduce_with }: ReduceByArgs,
|
args: CommandArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let registry = registry.clone();
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (ReduceByArgs { reduce_with }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::data::base::reject_fields;
|
use crate::data::base::reject_fields;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -30,25 +30,30 @@ impl WholeStreamCommand for Reject {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, reject)?.run()
|
reject(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reject(
|
fn reject(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
RejectArgs { rest: fields }: RejectArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let name = args.call_info.name_tag.clone();
|
||||||
if fields.is_empty() {
|
let (RejectArgs { rest: fields }, mut input) = args.process(®istry).await?;
|
||||||
return Err(ShellError::labeled_error(
|
if fields.is_empty() {
|
||||||
"Reject requires fields",
|
yield Err(ShellError::labeled_error(
|
||||||
"needs parameter",
|
"Reject requires fields",
|
||||||
name,
|
"needs parameter",
|
||||||
));
|
name,
|
||||||
}
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect();
|
let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect();
|
||||||
|
|
||||||
let stream = input.map(move |item| reject_fields(&item, &fields, &item.tag));
|
while let Some(item) = input.next().await {
|
||||||
|
yield ReturnSuccess::value(reject_fields(&item, &fields, &item.tag));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(stream.from_input_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ impl WholeStreamCommand for Rename {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, rename)?.run()
|
rename(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -54,19 +54,17 @@ impl WholeStreamCommand for Rename {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(
|
pub fn rename(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
Arguments { column_name, rest }: Arguments,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let name = args.call_info.name_tag.clone();
|
||||||
) -> Result<OutputStream, ShellError> {
|
let stream = async_stream! {
|
||||||
let mut new_column_names = vec![vec![column_name]];
|
let (Arguments { column_name, rest }, mut input) = args.process(®istry).await?;
|
||||||
new_column_names.push(rest);
|
let mut new_column_names = vec![vec![column_name]];
|
||||||
|
new_column_names.push(rest);
|
||||||
|
|
||||||
let new_column_names = new_column_names.into_iter().flatten().collect::<Vec<_>>();
|
let new_column_names = new_column_names.into_iter().flatten().collect::<Vec<_>>();
|
||||||
|
|
||||||
let stream = input
|
|
||||||
.map(move |item| {
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
|
|
||||||
|
while let Some(item) = input.next().await {
|
||||||
if let Value {
|
if let Value {
|
||||||
value: UntaggedValue::Row(row),
|
value: UntaggedValue::Row(row),
|
||||||
tag,
|
tag,
|
||||||
@ -86,21 +84,19 @@ pub fn rename(
|
|||||||
|
|
||||||
let out = UntaggedValue::Row(renamed_row.into()).into_value(tag);
|
let out = UntaggedValue::Row(renamed_row.into()).into_value(tag);
|
||||||
|
|
||||||
result.push_back(ReturnSuccess::value(out));
|
yield ReturnSuccess::value(out);
|
||||||
} else {
|
} else {
|
||||||
result.push_back(ReturnSuccess::value(
|
yield ReturnSuccess::value(
|
||||||
UntaggedValue::Error(ShellError::labeled_error(
|
UntaggedValue::Error(ShellError::labeled_error(
|
||||||
"no column names available",
|
"no column names available",
|
||||||
"can't rename",
|
"can't rename",
|
||||||
&name,
|
&name,
|
||||||
))
|
))
|
||||||
.into_untagged_value(),
|
.into_untagged_value(),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
futures::stream::iter(result)
|
};
|
||||||
})
|
|
||||||
.flatten();
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::Signature;
|
use nu_protocol::{ReturnSuccess, Signature};
|
||||||
|
|
||||||
pub struct Reverse;
|
pub struct Reverse;
|
||||||
|
|
||||||
@ -36,15 +36,16 @@ impl WholeStreamCommand for Reverse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reverse(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn reverse(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let (input, _args) = args.parts();
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let (input, _args) = args.parts();
|
||||||
|
|
||||||
let input = input.collect::<Vec<_>>();
|
let input = input.collect::<Vec<_>>().await;
|
||||||
|
for output in input.into_iter().rev() {
|
||||||
|
yield ReturnSuccess::value(output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let output = input.map(move |mut vec| {
|
Ok(stream.to_output_stream())
|
||||||
vec.reverse();
|
|
||||||
futures::stream::iter(vec)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(output.flatten_stream().from_input_stream())
|
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl WholeStreamCommand for Remove {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, rm)?.run()
|
rm(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -58,7 +58,17 @@ impl WholeStreamCommand for Remove {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rm(args: RemoveArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn rm(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = context.shell_manager.clone();
|
let registry = registry.clone();
|
||||||
shell_manager.rm(args, &context)
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
let (args, _): (RemoveArgs, _) = args.process(®istry).await?;
|
||||||
|
let mut result = shell_manager.rm(args, name)?;
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ impl WholeStreamCommand for AliasCommand {
|
|||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let mut scope = call_info.scope.clone();
|
let mut scope = call_info.scope.clone();
|
||||||
let evaluated = call_info.evaluate(®istry)?;
|
let evaluated = call_info.evaluate(®istry).await?;
|
||||||
if let Some(positional) = &evaluated.args.positional {
|
if let Some(positional) = &evaluated.args.positional {
|
||||||
for (pos, arg) in positional.iter().enumerate() {
|
for (pos, arg) in positional.iter().enumerate() {
|
||||||
scope = scope.set_var(alias_command.args[pos].to_string(), arg.clone());
|
scope = scope.set_var(alias_command.args[pos].to_string(), arg.clone());
|
||||||
|
@ -117,16 +117,7 @@ impl WholeStreamCommand for RunExternalCommand {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let context = RunnableContext {
|
let result = external_context.shell_manager.cd(cd_args, args.call_info.name_tag.clone());
|
||||||
input: InputStream::empty(),
|
|
||||||
shell_manager: external_context.shell_manager.clone(),
|
|
||||||
host: external_context.host.clone(),
|
|
||||||
ctrl_c: external_context.ctrl_c.clone(),
|
|
||||||
registry: external_context.registry.clone(),
|
|
||||||
name: args.call_info.name_tag.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = external_context.shell_manager.cd(cd_args, &context);
|
|
||||||
match result {
|
match result {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
while let Some(value) = stream.next().await {
|
while let Some(value) = stream.next().await {
|
||||||
|
@ -153,31 +153,23 @@ impl WholeStreamCommand for Save {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(args.process_raw(registry, save)?.run())
|
save(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save(
|
fn save(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SaveArgs {
|
let mut full_path = PathBuf::from(raw_args.shell_manager.path());
|
||||||
path,
|
let name_tag = raw_args.call_info.name_tag.clone();
|
||||||
raw: save_raw,
|
let name = raw_args.call_info.name_tag.clone();
|
||||||
}: SaveArgs,
|
|
||||||
RunnableContext {
|
|
||||||
input,
|
|
||||||
name,
|
|
||||||
shell_manager,
|
|
||||||
host,
|
|
||||||
ctrl_c,
|
|
||||||
registry,
|
|
||||||
..
|
|
||||||
}: RunnableContext,
|
|
||||||
raw_args: RawCommandArgs,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let mut full_path = PathBuf::from(shell_manager.path());
|
|
||||||
let name_tag = name.clone();
|
|
||||||
let scope = raw_args.call_info.scope.clone();
|
let scope = raw_args.call_info.scope.clone();
|
||||||
|
let registry = registry.clone();
|
||||||
|
let host = raw_args.host.clone();
|
||||||
|
let ctrl_c = raw_args.ctrl_c.clone();
|
||||||
|
let shell_manager = raw_args.shell_manager.clone();
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let head = raw_args.call_info.args.head.clone();
|
||||||
|
let (SaveArgs { path, raw: save_raw }, mut input) = raw_args.process(®istry).await?;
|
||||||
let input: Vec<Value> = input.collect().await;
|
let input: Vec<Value> = input.collect().await;
|
||||||
if path.is_none() {
|
if path.is_none() {
|
||||||
// If there is no filename, check the metadata for the anchor filename
|
// If there is no filename, check the metadata for the anchor filename
|
||||||
@ -230,13 +222,13 @@ fn save(
|
|||||||
shell_manager,
|
shell_manager,
|
||||||
call_info: UnevaluatedCallInfo {
|
call_info: UnevaluatedCallInfo {
|
||||||
args: nu_protocol::hir::Call {
|
args: nu_protocol::hir::Call {
|
||||||
head: raw_args.call_info.args.head,
|
head,
|
||||||
positional: None,
|
positional: None,
|
||||||
named: None,
|
named: None,
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
is_last: false,
|
is_last: false,
|
||||||
},
|
},
|
||||||
name_tag: raw_args.call_info.name_tag,
|
name_tag: name_tag.clone(),
|
||||||
scope,
|
scope,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,8 +3,8 @@ use crate::context::CommandRegistry;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ColumnPath, PathMember, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape,
|
ColumnPath, PathMember, Primitive, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder,
|
||||||
TaggedDictBuilder, UnspannedPathMember, UntaggedValue, Value,
|
UnspannedPathMember, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
use nu_source::span_for_spanned_list;
|
use nu_source::span_for_spanned_list;
|
||||||
use nu_value_ext::{as_string, get_data_by_column_path};
|
use nu_value_ext::{as_string, get_data_by_column_path};
|
||||||
@ -37,7 +37,7 @@ impl WholeStreamCommand for Select {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, select)?.run()
|
select(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -54,30 +54,28 @@ impl WholeStreamCommand for Select {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select(
|
fn select(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SelectArgs { rest: mut fields }: SelectArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext {
|
let name = args.call_info.name_tag.clone();
|
||||||
mut input, name, ..
|
|
||||||
}: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
if fields.is_empty() {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Select requires columns to select",
|
|
||||||
"needs parameter",
|
|
||||||
name,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let member = fields.remove(0);
|
|
||||||
let member = vec![member];
|
|
||||||
|
|
||||||
let column_paths = vec![&member, &fields]
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.cloned()
|
|
||||||
.collect::<Vec<ColumnPath>>();
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (SelectArgs { rest: mut fields }, mut input) = args.process(®istry).await?;
|
||||||
|
if fields.is_empty() {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Select requires columns to select",
|
||||||
|
"needs parameter",
|
||||||
|
name,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let member = fields.remove(0);
|
||||||
|
let member = vec![member];
|
||||||
|
|
||||||
|
let column_paths = vec![&member, &fields]
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<ColumnPath>>();
|
||||||
let mut empty = true;
|
let mut empty = true;
|
||||||
let mut bring_back: indexmap::IndexMap<String, Vec<Value>> = indexmap::IndexMap::new();
|
let mut bring_back: indexmap::IndexMap<String, Vec<Value>> = indexmap::IndexMap::new();
|
||||||
|
|
||||||
@ -172,7 +170,5 @@ fn select(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -39,15 +39,14 @@ impl WholeStreamCommand for Shuffle {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, shuffle)?.run()
|
shuffle(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shuffle(
|
fn shuffle(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
Arguments { limit }: Arguments,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let (Arguments { limit }, mut input) = args.process(®istry).await?;
|
||||||
let mut values: Vec<Value> = input.collect().await;
|
let mut values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
let out = if let Some(n) = limit {
|
let out = if let Some(n) = limit {
|
||||||
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Skip;
|
pub struct Skip;
|
||||||
@ -30,7 +30,7 @@ impl WholeStreamCommand for Skip {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, skip)?.run()
|
skip(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -41,12 +41,25 @@ impl WholeStreamCommand for Skip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(SkipArgs { rows }: SkipArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
fn skip(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let rows_desired = if let Some(quantity) = rows {
|
let registry = registry.clone();
|
||||||
*quantity
|
let stream = async_stream! {
|
||||||
} else {
|
let (SkipArgs { rows }, mut input) = args.process(®istry).await?;
|
||||||
1
|
let mut rows_desired = if let Some(quantity) = rows {
|
||||||
|
*quantity
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(input) = input.next().await {
|
||||||
|
if rows_desired == 0 {
|
||||||
|
yield ReturnSuccess::value(input);
|
||||||
|
}
|
||||||
|
if rows_desired > 0{
|
||||||
|
rows_desired -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(OutputStream::from_input(context.input.skip(rows_desired)))
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct SkipUntil;
|
pub struct SkipUntil;
|
||||||
|
|
||||||
@ -33,66 +35,80 @@ impl WholeStreamCommand for SkipUntil {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = args.call_info.scope.clone();
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry)?;
|
let stream = async_stream! {
|
||||||
|
let mut call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
|
|
||||||
let condition = match block {
|
let condition = match block {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Block(block),
|
value: UntaggedValue::Block(block),
|
||||||
tag,
|
tag,
|
||||||
} => {
|
} => {
|
||||||
if block.block.len() != 1 {
|
if block.block.len() != 1 {
|
||||||
return Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
match block.block[0].list.get(0) {
|
|
||||||
Some(item) => match item {
|
|
||||||
ClassifiedCommand::Expr(expr) => expr.clone(),
|
|
||||||
_ => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
"Expected a condition",
|
||||||
"expected a condition",
|
"expected a condition",
|
||||||
tag,
|
tag,
|
||||||
));
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match block.block[0].list.get(0) {
|
||||||
|
Some(item) => match item {
|
||||||
|
ClassifiedCommand::Expr(expr) => expr.clone(),
|
||||||
|
_ => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Value { tag, .. } => {
|
||||||
Value { tag, .. } => {
|
yield Err(ShellError::labeled_error(
|
||||||
return Err(ShellError::labeled_error(
|
"Expected a condition",
|
||||||
"Expected a condition",
|
"expected a condition",
|
||||||
"expected a condition",
|
tag,
|
||||||
tag,
|
));
|
||||||
));
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut skipping = true;
|
||||||
|
while let Some(item) = call_info.input.next().await {
|
||||||
|
let condition = condition.clone();
|
||||||
|
trace!("ITEM = {:?}", item);
|
||||||
|
let result =
|
||||||
|
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
||||||
|
.await;
|
||||||
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
let return_value = match result {
|
||||||
|
Ok(ref v) if v.is_true() => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if return_value {
|
||||||
|
skipping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !skipping {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let objects = call_info.input.skip_while(move |item| {
|
Ok(stream.to_output_stream())
|
||||||
let condition = condition.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
|
||||||
let result =
|
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()));
|
|
||||||
trace!("RESULT = {:?}", result);
|
|
||||||
|
|
||||||
let return_value = match result {
|
|
||||||
Ok(ref v) if v.is_true() => false,
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
futures::future::ready(return_value)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct SkipWhile;
|
pub struct SkipWhile;
|
||||||
|
|
||||||
@ -33,66 +35,80 @@ impl WholeStreamCommand for SkipWhile {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = args.call_info.scope.clone();
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry)?;
|
let stream = async_stream! {
|
||||||
|
let mut call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
|
|
||||||
let condition = match block {
|
let condition = match block {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Block(block),
|
value: UntaggedValue::Block(block),
|
||||||
tag,
|
tag,
|
||||||
} => {
|
} => {
|
||||||
if block.block.len() != 1 {
|
if block.block.len() != 1 {
|
||||||
return Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
match block.block[0].list.get(0) {
|
|
||||||
Some(item) => match item {
|
|
||||||
ClassifiedCommand::Expr(expr) => expr.clone(),
|
|
||||||
_ => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
|
||||||
"expected a condition",
|
|
||||||
tag,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Expected a condition",
|
"Expected a condition",
|
||||||
"expected a condition",
|
"expected a condition",
|
||||||
tag,
|
tag,
|
||||||
));
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match block.block[0].list.get(0) {
|
||||||
|
Some(item) => match item {
|
||||||
|
ClassifiedCommand::Expr(expr) => expr.clone(),
|
||||||
|
_ => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
yield Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"expected a condition",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Value { tag, .. } => {
|
||||||
Value { tag, .. } => {
|
yield Err(ShellError::labeled_error(
|
||||||
return Err(ShellError::labeled_error(
|
"Expected a condition",
|
||||||
"Expected a condition",
|
"expected a condition",
|
||||||
"expected a condition",
|
tag,
|
||||||
tag,
|
));
|
||||||
));
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut skipping = true;
|
||||||
|
while let Some(item) = call_info.input.next().await {
|
||||||
|
let condition = condition.clone();
|
||||||
|
trace!("ITEM = {:?}", item);
|
||||||
|
let result =
|
||||||
|
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
||||||
|
.await;
|
||||||
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
let return_value = match result {
|
||||||
|
Ok(ref v) if v.is_true() => false,
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if return_value {
|
||||||
|
skipping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !skipping {
|
||||||
|
yield ReturnSuccess::value(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let objects = call_info.input.skip_while(move |item| {
|
Ok(stream.to_output_stream())
|
||||||
let condition = condition.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
|
||||||
let result =
|
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()));
|
|
||||||
trace!("RESULT = {:?}", result);
|
|
||||||
|
|
||||||
let return_value = match result {
|
|
||||||
Ok(ref v) if v.is_true() => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
futures::future::ready(return_value)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ impl WholeStreamCommand for SortBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, sort_by)?.run()
|
sort_by(args, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> &[Example] {
|
fn examples(&self) -> &[Example] {
|
||||||
@ -47,12 +47,11 @@ impl WholeStreamCommand for SortBy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_by(
|
fn sort_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SortByArgs { rest }: SortByArgs,
|
let registry = registry.clone();
|
||||||
mut context: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let (SortByArgs { rest }, mut input) = args.process(®istry).await?;
|
||||||
Ok(OutputStream::new(async_stream! {
|
let mut vec = input.drain_vec().await;
|
||||||
let mut vec = context.input.drain_vec().await;
|
|
||||||
|
|
||||||
if vec.is_empty() {
|
if vec.is_empty() {
|
||||||
return;
|
return;
|
||||||
@ -78,5 +77,7 @@ fn sort_by(
|
|||||||
for item in vec {
|
for item in vec {
|
||||||
yield item.into();
|
yield item.into();
|
||||||
}
|
}
|
||||||
}))
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -35,15 +35,15 @@ impl WholeStreamCommand for SplitBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, split_by)?.run()
|
split_by(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_by(
|
pub fn split_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SplitByArgs { column_name }: SplitByArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let (SplitByArgs { column_name }, mut input) = args.process(®istry).await?;
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
if values.len() > 1 || values.is_empty() {
|
if values.len() > 1 || values.is_empty() {
|
||||||
|
@ -42,22 +42,16 @@ impl WholeStreamCommand for SplitColumn {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, split_column)?.run()
|
split_column(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_column(
|
fn split_column(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SplitColumnArgs {
|
let name_span = args.call_info.name_tag.span;
|
||||||
separator,
|
let registry = registry.clone();
|
||||||
rest,
|
let stream = async_stream! {
|
||||||
collapse_empty,
|
let (SplitColumnArgs { separator, rest, collapse_empty }, mut input) = args.process(®istry).await?;
|
||||||
}: SplitColumnArgs,
|
while let Some(v) = input.next().await {
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let name_span = name.span;
|
|
||||||
|
|
||||||
Ok(input
|
|
||||||
.map(move |v| {
|
|
||||||
if let Ok(s) = v.as_string() {
|
if let Ok(s) = v.as_string() {
|
||||||
let splitter = separator.replace("\\n", "\n");
|
let splitter = separator.replace("\\n", "\n");
|
||||||
trace!("splitting with {:?}", splitter);
|
trace!("splitting with {:?}", splitter);
|
||||||
@ -84,7 +78,7 @@ fn split_column(
|
|||||||
dict.insert_untagged(v.clone(), Primitive::String(k.into()));
|
dict.insert_untagged(v.clone(), Primitive::String(k.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnSuccess::value(dict.into_value())
|
yield ReturnSuccess::value(dict.into_value());
|
||||||
} else {
|
} else {
|
||||||
let mut dict = TaggedDictBuilder::new(&v.tag);
|
let mut dict = TaggedDictBuilder::new(&v.tag);
|
||||||
for (&k, v) in split_result.iter().zip(positional.iter()) {
|
for (&k, v) in split_result.iter().zip(positional.iter()) {
|
||||||
@ -93,17 +87,19 @@ fn split_column(
|
|||||||
UntaggedValue::Primitive(Primitive::String(k.into())),
|
UntaggedValue::Primitive(Primitive::String(k.into())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(dict.into_value())
|
yield ReturnSuccess::value(dict.into_value());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name_span,
|
name_span,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.tag.span,
|
v.tag.span,
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.to_output_stream())
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -34,16 +34,16 @@ impl WholeStreamCommand for SplitRow {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, split_row)?.run()
|
split_row(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_row(
|
fn split_row(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
SplitRowArgs { separator }: SplitRowArgs,
|
let registry = registry.clone();
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
let stream = async_stream! {
|
||||||
) -> Result<OutputStream, ShellError> {
|
let name = args.call_info.name_tag.clone();
|
||||||
let stream = input
|
let (SplitRowArgs { separator }, mut input) = args.process(®istry).await?;
|
||||||
.map(move |v| {
|
while let Some(v) = input.next().await {
|
||||||
if let Ok(s) = v.as_string() {
|
if let Ok(s) = v.as_string() {
|
||||||
let splitter = separator.item.replace("\\n", "\n");
|
let splitter = separator.item.replace("\\n", "\n");
|
||||||
trace!("splitting with {:?}", splitter);
|
trace!("splitting with {:?}", splitter);
|
||||||
@ -51,26 +51,22 @@ fn split_row(
|
|||||||
|
|
||||||
trace!("split result = {:?}", split_result);
|
trace!("split result = {:?}", split_result);
|
||||||
|
|
||||||
let mut result = VecDeque::new();
|
|
||||||
for s in split_result {
|
for s in split_result {
|
||||||
result.push_back(ReturnSuccess::value(
|
yield ReturnSuccess::value(
|
||||||
UntaggedValue::Primitive(Primitive::String(s.into())).into_value(&v.tag),
|
UntaggedValue::Primitive(Primitive::String(s.into())).into_value(&v.tag),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
futures::stream::iter(result)
|
|
||||||
} else {
|
} else {
|
||||||
let mut result = VecDeque::new();
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name.span,
|
name.span,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.tag.span,
|
v.tag.span,
|
||||||
)));
|
));
|
||||||
futures::stream::iter(result)
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.flatten();
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -56,19 +56,15 @@ impl WholeStreamCommand for TSortBy {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, t_sort_by)?.run()
|
t_sort_by(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn t_sort_by(
|
fn t_sort_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
TSortByArgs {
|
let registry = registry.clone();
|
||||||
show_columns,
|
let stream = async_stream! {
|
||||||
group_by,
|
let name = args.call_info.name_tag.clone();
|
||||||
..
|
let (TSortByArgs { show_columns, group_by, ..}, mut input) = args.process(®istry).await?;
|
||||||
}: TSortByArgs,
|
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
Ok(OutputStream::new(async_stream! {
|
|
||||||
let values: Vec<Value> = input.collect().await;
|
let values: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
let column_grouped_by_name = if let Some(grouped_by) = group_by {
|
let column_grouped_by_name = if let Some(grouped_by) = group_by {
|
||||||
@ -87,5 +83,7 @@ fn t_sort_by(
|
|||||||
Err(err) => yield Err(err)
|
Err(err) => yield Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,11 @@ impl WholeStreamCommand for Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let mut args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let mut finished = false;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let mut args = args.evaluate_once(®istry).await?;
|
||||||
|
let mut finished = false;
|
||||||
|
|
||||||
let host = args.host.clone();
|
let host = args.host.clone();
|
||||||
let mut start_number = match args.get("start_number") {
|
let mut start_number = match args.get("start_number") {
|
||||||
Some(Value { value: UntaggedValue::Primitive(Primitive::Int(i)), .. }) => {
|
Some(Value { value: UntaggedValue::Primitive(Primitive::Int(i)), .. }) => {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::Signature;
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct To;
|
pub struct To;
|
||||||
|
|
||||||
impl WholeStreamCommand for To {
|
impl WholeStreamCommand for To {
|
||||||
@ -23,6 +24,14 @@ impl WholeStreamCommand for To {
|
|||||||
_args: CommandArgs,
|
_args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(crate::commands::help::get_help(self, registry).into())
|
let registry = registry.clone();
|
||||||
|
let stream = async_stream! {
|
||||||
|
yield Ok(ReturnSuccess::Value(
|
||||||
|
UntaggedValue::string(crate::commands::help::get_help(&To, ®istry))
|
||||||
|
.into_value(Tag::unknown()),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,11 +261,12 @@ fn bson_value_to_bytes(bson: Bson, tag: Tag) -> Result<Vec<u8>, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let registry = registry.clone();
|
||||||
let name_tag = args.name_tag();
|
|
||||||
let name_span = name_tag.span;
|
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
|
let args = args.evaluate_once(®istry).await?;
|
||||||
|
let name_tag = args.name_tag();
|
||||||
|
let name_span = name_tag.span;
|
||||||
|
|
||||||
let input: Vec<Value> = args.input.collect().await;
|
let input: Vec<Value> = args.input.collect().await;
|
||||||
|
|
||||||
let to_process_input = if input.len() > 1 {
|
let to_process_input = if input.len() > 1 {
|
||||||
|
@ -41,39 +41,45 @@ impl WholeStreamCommand for ToCSV {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
args.process(registry, to_csv)?.run()
|
to_csv(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_csv(
|
fn to_csv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
ToCSVArgs {
|
let registry = registry.clone();
|
||||||
separator,
|
let stream = async_stream! {
|
||||||
headerless,
|
let name = args.call_info.name_tag.clone();
|
||||||
}: ToCSVArgs,
|
let (ToCSVArgs { separator, headerless }, mut input) = args.process(®istry).await?;
|
||||||
runnable_context: RunnableContext,
|
let sep = match separator {
|
||||||
) -> Result<OutputStream, ShellError> {
|
Some(Value {
|
||||||
let sep = match separator {
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||||
Some(Value {
|
tag,
|
||||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
..
|
||||||
tag,
|
}) => {
|
||||||
..
|
if s == r"\t" {
|
||||||
}) => {
|
'\t'
|
||||||
if s == r"\t" {
|
} else {
|
||||||
'\t'
|
let vec_s: Vec<char> = s.chars().collect();
|
||||||
} else {
|
if vec_s.len() != 1 {
|
||||||
let vec_s: Vec<char> = s.chars().collect();
|
yield Err(ShellError::labeled_error(
|
||||||
if vec_s.len() != 1 {
|
"Expected a single separator char from --separator",
|
||||||
return Err(ShellError::labeled_error(
|
"requires a single character string input",
|
||||||
"Expected a single separator char from --separator",
|
tag,
|
||||||
"requires a single character string input",
|
));
|
||||||
tag,
|
return;
|
||||||
));
|
};
|
||||||
};
|
vec_s[0]
|
||||||
vec_s[0]
|
}
|
||||||
}
|
}
|
||||||
|
_ => ',',
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = to_delimited_data(headerless, sep, "CSV", input, name)?;
|
||||||
|
|
||||||
|
while let Some(item) = result.next().await {
|
||||||
|
yield item;
|
||||||
}
|
}
|
||||||
_ => ',',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
to_delimited_data(headerless, sep, "CSV", runnable_context)
|
Ok(stream.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,8 @@ pub fn to_delimited_data(
|
|||||||
headerless: bool,
|
headerless: bool,
|
||||||
sep: char,
|
sep: char,
|
||||||
format_name: &'static str,
|
format_name: &'static str,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
input: InputStream,
|
||||||
|
name: Tag,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_tag = name;
|
let name_tag = name;
|
||||||
let name_span = name_tag.span;
|
let name_span = name_tag.span;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user