Finish removing arg deserialization (#3552)

* WIP remove process

* WIP

* WIP

* Finish removing arg deserialization
This commit is contained in:
JT 2021-06-04 18:23:57 +12:00 committed by GitHub
parent fcd94efbd6
commit 131b5b56d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 483 additions and 1216 deletions

View file

@ -3,11 +3,6 @@ use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
#[derive(Deserialize)]
struct Arguments {
value: Value,
}
pub struct Command; pub struct Command;
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
@ -28,11 +23,12 @@ impl WholeStreamCommand for Command {
} }
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { mut value }, mut input) = args.process()?; let mut args = args.evaluate_once()?;
let mut value: Value = args.req(0)?;
let mut prepend = vec![]; let mut prepend = vec![];
if let Some(first) = input.next() { if let Some(first) = args.input.next() {
value.tag = first.tag(); value.tag = first.tag();
prepend.push(first); prepend.push(first);
} }
@ -50,7 +46,7 @@ impl WholeStreamCommand for Command {
Ok(prepend Ok(prepend
.into_iter() .into_iter()
.chain(input.into_iter().chain(vec![value])) .chain(args.input.into_iter().chain(vec![value]))
.to_output_stream()) .to_output_stream())
} }

View file

@ -15,12 +15,11 @@ use rand::{
distributions::Alphanumeric, distributions::Alphanumeric,
prelude::{thread_rng, Rng}, prelude::{thread_rng, Rng},
}; };
use std::convert::TryInto; use std::time::Instant;
use std::time::{Duration, Instant};
pub struct Benchmark; pub struct Benchmark;
#[derive(Deserialize, Debug)] #[derive(Debug)]
struct BenchmarkArgs { struct BenchmarkArgs {
block: CapturedBlock, block: CapturedBlock,
passthrough: Option<CapturedBlock>, passthrough: Option<CapturedBlock>,
@ -113,7 +112,7 @@ fn benchmark(args: CommandArgs) -> Result<OutputStream, ShellError> {
{ {
let mut indexmap = IndexMap::with_capacity(1); let mut indexmap = IndexMap::with_capacity(1);
let real_time = into_big_int(end_time - start_time); let real_time = (end_time - start_time).as_nanos() as i64;
indexmap.insert("real time".to_string(), real_time); indexmap.insert("real time".to_string(), real_time);
benchmark_output(indexmap, output, cmd_args.passthrough, &tag, &mut context) benchmark_output(indexmap, output, cmd_args.passthrough, &tag, &mut context)
} }
@ -143,7 +142,7 @@ fn benchmark(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
fn benchmark_output<T, Output>( fn benchmark_output<T, Output>(
indexmap: IndexMap<String, BigInt>, indexmap: IndexMap<String, i64>,
block_output: Output, block_output: Output,
passthrough: Option<CapturedBlock>, passthrough: Option<CapturedBlock>,
tag: T, tag: T,
@ -206,13 +205,6 @@ fn add_implicit_autoview(mut block: Arc<Block>) -> Arc<Block> {
block block
} }
fn into_big_int<T: TryInto<Duration>>(time: T) -> BigInt {
time.try_into()
.unwrap_or_else(|_| Duration::new(0, 0))
.as_nanos()
.into()
}
fn generate_random_env_value() -> String { fn generate_random_env_value() -> String {
let mut thread_rng = thread_rng(); let mut thread_rng = thread_rng();
let len = thread_rng.gen_range(1, 16 * 1024); let len = thread_rng.gen_range(1, 16 * 1024);

View file

@ -27,7 +27,9 @@ impl WholeStreamCommand for Cd {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (args, _): (CdArgs, _) = args.process()?; let args = args.evaluate_once()?;
let args = CdArgs { path: args.opt(0)? };
shell_manager.cd(args, name) shell_manager.cd(args, name)
} }

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::{shell::CopyArgs, WholeStreamCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape}; use nu_protocol::{Signature, SyntaxShape};
@ -28,7 +28,13 @@ impl WholeStreamCommand for Cpy {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (args, _) = args.process()?; let args = args.evaluate_once()?;
let args = CopyArgs {
src: args.req(0)?,
dst: args.req(1)?,
recursive: args.has_flag("recursive"),
};
shell_manager.cp(args, name) shell_manager.cp(args, name)
} }

View file

@ -5,11 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
pub struct Debug; pub struct Debug;
#[derive(Deserialize)]
pub struct DebugArgs {
raw: bool,
}
impl WholeStreamCommand for Debug { impl WholeStreamCommand for Debug {
fn name(&self) -> &str { fn name(&self) -> &str {
"debug" "debug"
@ -29,7 +24,10 @@ impl WholeStreamCommand for Debug {
} }
fn debug_value(args: CommandArgs) -> Result<ActionStream, ShellError> { fn debug_value(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DebugArgs { raw }, input) = args.process()?; let args = args.evaluate_once()?;
let raw = args.has_flag("raw");
let input = args.input;
Ok(input Ok(input
.map(move |v| { .map(move |v| {
if raw { if raw {

View file

@ -5,12 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged; use nu_source::Tagged;
use nu_value_ext::ValueExt; use nu_value_ext::ValueExt;
#[derive(Deserialize)]
struct DefaultArgs {
column: Tagged<String>,
value: Value,
}
pub struct Default; pub struct Default;
impl WholeStreamCommand for Default { impl WholeStreamCommand for Default {
@ -46,7 +40,11 @@ impl WholeStreamCommand for Default {
} }
fn default(args: CommandArgs) -> Result<ActionStream, ShellError> { fn default(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DefaultArgs { column, value }, input) = args.process()?; let args = args.evaluate_once()?;
let column: Tagged<String> = args.req(0)?;
let value: Value = args.req(1)?;
let input = args.input;
Ok(input Ok(input
.map(move |item| { .map(move |item| {

View file

@ -88,7 +88,17 @@ fn du(args: CommandArgs) -> Result<ActionStream, ShellError> {
let ctrl_c = args.ctrl_c(); let ctrl_c = args.ctrl_c();
let ctrl_c_copy = ctrl_c.clone(); let ctrl_c_copy = ctrl_c.clone();
let (args, _): (DuArgs, _) = args.process()?; let args = args.evaluate_once()?;
let args = DuArgs {
path: args.opt(0)?,
all: args.has_flag("all"),
deref: args.has_flag("deref"),
exclude: args.get_flag("exclude")?,
max_depth: args.get_flag("max-depth")?,
min_size: args.get_flag("min_size")?,
};
let exclude = args.exclude.map_or(Ok(None), move |x| { let exclude = args.exclude.map_or(Ok(None), move |x| {
Pattern::new(&x.item) Pattern::new(&x.item)
.map(Option::Some) .map(Option::Some)

View file

@ -10,11 +10,6 @@ use nu_protocol::{
use crate::utils::arguments::arguments; use crate::utils::arguments::arguments;
use nu_value_ext::{as_string, ValueExt}; use nu_value_ext::{as_string, ValueExt};
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Value>,
}
pub struct Command; pub struct Command;
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
@ -83,9 +78,11 @@ fn is_empty(args: CommandArgs) -> Result<ActionStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let name_tag = Arc::new(args.call_info.name_tag.clone()); let name_tag = Arc::new(args.call_info.name_tag.clone());
let context = Arc::new(EvaluationContext::from_args(&args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (Arguments { mut rest }, input) = args.process()?; let args = args.evaluate_once()?;
let mut rest = args.rest(0)?;
let (columns, default_block): (Vec<ColumnPath>, Option<Box<CapturedBlock>>) = let (columns, default_block): (Vec<ColumnPath>, Option<Box<CapturedBlock>>) =
arguments(&mut rest)?; arguments(&mut rest)?;
let input = args.input;
let default_block = Arc::new(default_block); let default_block = Arc::new(default_block);
if input.is_empty() { if input.is_empty() {

View file

@ -2,16 +2,9 @@ use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
pub struct Every; pub struct Every;
#[derive(Deserialize)]
pub struct EveryArgs {
stride: Tagged<u64>,
skip: Tagged<bool>,
}
impl WholeStreamCommand for Every { impl WholeStreamCommand for Every {
fn name(&self) -> &str { fn name(&self) -> &str {
"every" "every"
@ -63,10 +56,11 @@ impl WholeStreamCommand for Every {
} }
fn every(args: CommandArgs) -> Result<ActionStream, ShellError> { fn every(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (EveryArgs { stride, skip }, input) = args.process()?; let args = args.evaluate_once()?;
let stride = stride.item; let stride: u64 = args.req(0)?;
let skip = skip.item; let skip: bool = args.has_flag("skip");
let input = args.input;
Ok(input Ok(input
.enumerate() .enumerate()

View file

@ -57,7 +57,12 @@ fn exec(args: CommandArgs) -> Result<ActionStream, ShellError> {
use std::process::Command; use std::process::Command;
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (args, _): (ExecArgs, _) = args.process()?; let args = args.evaluate_once()?;
let args = ExecArgs {
command: args.req(0)?,
rest: args.rest(1)?,
};
let mut command = Command::new(args.command.item); let mut command = Command::new(args.command.item);
for tagged_arg in args.rest { for tagged_arg in args.rest {

View file

@ -6,11 +6,6 @@ use nu_source::Tagged;
pub struct First; pub struct First;
#[derive(Deserialize)]
pub struct FirstArgs {
rows: Option<Tagged<usize>>,
}
impl WholeStreamCommand for First { impl WholeStreamCommand for First {
fn name(&self) -> &str { fn name(&self) -> &str {
"first" "first"
@ -52,7 +47,10 @@ impl WholeStreamCommand for First {
} }
fn first(args: CommandArgs) -> Result<ActionStream, ShellError> { fn first(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (FirstArgs { rows }, input) = args.process()?; let args = args.evaluate_once()?;
let rows: Option<Tagged<usize>> = args.opt(0)?;
let input = args.input;
let rows_desired = if let Some(quantity) = rows { let rows_desired = if let Some(quantity) = rows {
*quantity *quantity
} else { } else {

View file

@ -8,11 +8,6 @@ use nu_source::Tagged;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"flatten" "flatten"
@ -53,7 +48,9 @@ impl WholeStreamCommand for Command {
fn flatten(args: CommandArgs) -> Result<ActionStream, ShellError> { fn flatten(args: CommandArgs) -> Result<ActionStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { rest: columns }, input) = args.process()?; let args = args.evaluate_once()?;
let columns: Vec<Tagged<String>> = args.rest(0)?;
let input = args.input;
Ok(input Ok(input
.map(move |item| flat_value(&columns, &item, &tag).into_iter()) .map(move |item| flat_value(&columns, &item, &tag).into_iter())

View file

@ -13,11 +13,6 @@ use nu_value_ext::get_data_by_column_path;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Value>,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"get" "get"
@ -55,7 +50,10 @@ impl WholeStreamCommand for Command {
} }
pub fn get(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn get(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (Arguments { mut rest }, mut input) = args.process()?; let args = args.evaluate_once()?;
let mut rest: Vec<Value> = args.rest(0)?;
let mut input = args.input;
let (column_paths, _) = arguments(&mut rest)?; let (column_paths, _) = arguments(&mut rest)?;
if column_paths.is_empty() { if column_paths.is_empty() {

View file

@ -7,12 +7,6 @@ use nu_source::Tagged;
pub struct GroupByDate; pub struct GroupByDate;
#[derive(Deserialize)]
pub struct GroupByDateArgs {
column_name: Option<Tagged<String>>,
format: Option<Tagged<String>>,
}
impl WholeStreamCommand for GroupByDate { impl WholeStreamCommand for GroupByDate {
fn name(&self) -> &str { fn name(&self) -> &str {
"group-by date" "group-by date"
@ -60,14 +54,11 @@ enum GroupByColumn {
pub fn group_by_date(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn group_by_date(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ( let args = args.evaluate_once()?;
GroupByDateArgs { let column_name: Option<Tagged<String>> = args.opt(0)?;
column_name, let format: Option<Tagged<String>> = args.get_flag("format")?;
format,
}, let values: Vec<Value> = args.input.collect();
input,
) = args.process()?;
let values: Vec<Value> = input.collect();
if values.is_empty() { if values.is_empty() {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(

View file

@ -13,11 +13,6 @@ use nu_value_ext::ValueExt;
pub struct Help; pub struct Help;
#[derive(Deserialize)]
pub struct HelpArgs {
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for Help { impl WholeStreamCommand for Help {
fn name(&self) -> &str { fn name(&self) -> &str {
"help" "help"
@ -39,7 +34,9 @@ impl WholeStreamCommand for Help {
fn help(args: CommandArgs) -> Result<ActionStream, ShellError> { fn help(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let scope = args.scope().clone(); let scope = args.scope().clone();
let (HelpArgs { rest }, ..) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<Tagged<String>> = args.rest(0)?;
if !rest.is_empty() { if !rest.is_empty() {
if rest[0].item == "commands" { if rest[0].item == "commands" {

View file

@ -5,11 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
#[derive(Deserialize)]
struct Arguments {
clear: Option<bool>,
}
pub struct History; pub struct History;
impl WholeStreamCommand for History { impl WholeStreamCommand for History {
@ -33,7 +28,9 @@ impl WholeStreamCommand for History {
fn history(args: CommandArgs) -> Result<ActionStream, ShellError> { fn history(args: CommandArgs) -> Result<ActionStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let (Arguments { clear }, _) = args.process()?; let args = args.evaluate_once()?;
let clear = args.has_flag("clear");
let path = if let Some(global_cfg) = &ctx.configs.lock().global_config { let path = if let Some(global_cfg) = &ctx.configs.lock().global_config {
nu_data::config::path::history_path_or_default(global_cfg) nu_data::config::path::history_path_or_default(global_cfg)
@ -41,13 +38,10 @@ fn history(args: CommandArgs) -> Result<ActionStream, ShellError> {
nu_data::config::path::default_history_path() nu_data::config::path::default_history_path()
}; };
match clear { if clear {
Some(_) => {
// This is a NOOP, the logic to clear is handled in cli.rs // This is a NOOP, the logic to clear is handled in cli.rs
Ok(ActionStream::empty()) Ok(ActionStream::empty())
} } else if let Ok(file) = File::open(path) {
None => {
if let Ok(file) = File::open(path) {
let reader = BufReader::new(file); let reader = BufReader::new(file);
// Skips the first line, which is a Rustyline internal // Skips the first line, which is a Rustyline internal
let output = reader.lines().skip(1).filter_map(move |line| match line { let output = reader.lines().skip(1).filter_map(move |line| match line {
@ -65,8 +59,6 @@ fn history(args: CommandArgs) -> Result<ActionStream, ShellError> {
tag, tag,
)) ))
} }
}
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -10,12 +10,6 @@ use nu_value_ext::ValueExt;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
column: ColumnPath,
value: Value,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"insert" "insert"
@ -158,9 +152,13 @@ fn process_row(
}) })
} }
fn insert(raw_args: CommandArgs) -> Result<ActionStream, ShellError> { fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (Arguments { column, value }, input) = raw_args.process()?; let args = args.evaluate_once()?;
let column: ColumnPath = args.req(0)?;
let value: Value = args.req(1)?;
let input = args.input;
let value = Arc::new(value); let value = Arc::new(value);
let column = Arc::new(column); let column = Arc::new(column);

View file

@ -7,15 +7,6 @@ use std::process::{Command, Stdio};
pub struct Kill; pub struct Kill;
#[derive(Deserialize)]
pub struct KillArgs {
pub pid: Tagged<u64>,
pub rest: Vec<Tagged<u64>>,
pub force: Tagged<bool>,
pub quiet: Tagged<bool>,
pub signal: Option<Tagged<u32>>,
}
impl WholeStreamCommand for Kill { impl WholeStreamCommand for Kill {
fn name(&self) -> &str { fn name(&self) -> &str {
"kill" "kill"
@ -74,20 +65,18 @@ impl WholeStreamCommand for Kill {
} }
fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> { fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
let ( let args = args.evaluate_once()?;
KillArgs {
pid, let pid: Tagged<u64> = args.req(0)?;
rest, let rest: Vec<Tagged<u64>> = args.rest(1)?;
force, let force: Option<Tagged<bool>> = args.get_flag("force")?;
quiet, let quiet: bool = args.has_flag("quiet");
signal, let signal: Option<Tagged<u32>> = args.get_flag("signal")?;
},
..,
) = args.process()?;
let mut cmd = if cfg!(windows) { let mut cmd = if cfg!(windows) {
let mut cmd = Command::new("taskkill"); let mut cmd = Command::new("taskkill");
if *force { if matches!(force, Some(Tagged { item: true, .. })) {
cmd.arg("/F"); cmd.arg("/F");
} }
@ -105,14 +94,14 @@ fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
} else { } else {
let mut cmd = Command::new("kill"); let mut cmd = Command::new("kill");
if *force { if matches!(force, Some(Tagged { item: true, .. })) {
if let Some(signal_value) = signal { if let Some(signal_value) = signal {
return Err(ShellError::labeled_error_with_secondary( return Err(ShellError::labeled_error_with_secondary(
"mixing force and signal options is not supported", "mixing force and signal options is not supported",
"signal option", "signal option",
signal_value.tag(), signal_value.tag(),
"force option", "force option",
force.tag(), force.expect("internal error: expected value").tag(),
)); ));
} }
cmd.arg("-9"); cmd.arg("-9");
@ -128,7 +117,7 @@ fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
}; };
// pipe everything to null // pipe everything to null
if *quiet { if quiet {
cmd.stdin(Stdio::null()) cmd.stdin(Stdio::null())
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()); .stderr(Stdio::null());

View file

@ -6,11 +6,6 @@ use nu_protocol::{Signature, UntaggedValue, Value};
pub struct Length; pub struct Length;
#[derive(Deserialize)]
pub struct LengthArgs {
column: bool,
}
impl WholeStreamCommand for Length { impl WholeStreamCommand for Length {
fn name(&self) -> &str { fn name(&self) -> &str {
"length" "length"
@ -30,7 +25,9 @@ impl WholeStreamCommand for Length {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (LengthArgs { column }, input) = args.process()?; let args = args.evaluate_once()?;
let column = args.has_flag("column");
let input = args.input;
Ok(CountIterator { Ok(CountIterator {
column, column,

View file

@ -51,7 +51,10 @@ pub fn set_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let (LetEnvArgs { name, rhs, .. }, _) = args.process()?; let args = args.evaluate_once()?;
let name: Tagged<String> = args.req(0)?;
let rhs: CapturedBlock = args.req(2)?;
let (expr, captured) = { let (expr, captured) = {
if rhs.block.block.len() != 1 { if rhs.block.block.len() != 1 {

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::{shell::LsArgs, WholeStreamCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape}; use nu_protocol::{Signature, SyntaxShape};
@ -43,7 +43,16 @@ impl WholeStreamCommand for Ls {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ctrl_c = args.ctrl_c(); let ctrl_c = args.ctrl_c();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (args, _) = args.process()?; let args = args.evaluate_once()?;
let args = LsArgs {
path: args.opt(0)?,
all: args.has_flag("all"),
long: args.has_flag("long"),
short_names: args.has_flag("short-names"),
du: args.has_flag("du"),
};
shell_manager.ls(args, name, ctrl_c) shell_manager.ls(args, name, ctrl_c)
} }

View file

@ -28,7 +28,7 @@ impl WholeStreamCommand for SubCommand {
UntaggedValue::decimal(val.abs()).into() UntaggedValue::decimal(val.abs()).into()
} }
UntaggedValue::Primitive(Primitive::Duration(val)) => { UntaggedValue::Primitive(Primitive::Duration(val)) => {
UntaggedValue::duration(val.magnitude().clone()).into() UntaggedValue::duration(val).into()
} }
other => abs_default(other), other => abs_default(other),
}); });

View file

@ -11,11 +11,6 @@ use nu_protocol::{
}; };
pub struct Merge; pub struct Merge;
#[derive(Deserialize)]
pub struct MergeArgs {
block: CapturedBlock,
}
impl WholeStreamCommand for Merge { impl WholeStreamCommand for Merge {
fn name(&self) -> &str { fn name(&self) -> &str {
"merge" "merge"
@ -46,11 +41,13 @@ impl WholeStreamCommand for Merge {
} }
} }
fn merge(raw_args: CommandArgs) -> Result<ActionStream, ShellError> { fn merge(args: CommandArgs) -> Result<ActionStream, ShellError> {
let context = EvaluationContext::from_args(&raw_args); let context = EvaluationContext::from_args(&args);
let name_tag = raw_args.call_info.name_tag.clone(); let name_tag = args.call_info.name_tag.clone();
let (merge_args, input): (MergeArgs, _) = raw_args.process()?;
let block = merge_args.block; let args = args.evaluate_once()?;
let block: CapturedBlock = args.req(0)?;
let input = args.input;
context.scope.enter_scope(); context.scope.enter_scope();
context.scope.add_vars(&block.captured.entries); context.scope.add_vars(&block.captured.entries);

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::{shell::MkdirArgs, WholeStreamCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape}; use nu_protocol::{Signature, SyntaxShape};
pub struct Mkdir; pub struct Mkdir;
@ -38,7 +38,12 @@ impl WholeStreamCommand for Mkdir {
fn mkdir(args: CommandArgs) -> Result<ActionStream, ShellError> { fn mkdir(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (args, _) = args.process()?;
let args = args.evaluate_once()?;
let args = MkdirArgs {
rest: args.rest(0)?,
show_created_paths: args.has_flag("show-created-paths"),
};
shell_manager.mkdir(args, name) shell_manager.mkdir(args, name)
} }

View file

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::{shell::MvArgs, WholeStreamCommand};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape}; use nu_protocol::{Signature, SyntaxShape};
@ -56,7 +56,12 @@ impl WholeStreamCommand for Mv {
fn mv(args: CommandArgs) -> Result<ActionStream, ShellError> { fn mv(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (args, _) = args.process()?;
let args = args.evaluate_once()?;
let args = MvArgs {
src: args.req(0)?,
dst: args.req(1)?,
};
shell_manager.mv(args, name) shell_manager.mv(args, name)
} }

View file

@ -4,13 +4,6 @@ use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{Signature, SyntaxShape, Value};
use nu_source::Tagged; use nu_source::Tagged;
#[derive(Deserialize)]
struct NthArgs {
row_number: Tagged<u64>,
rest: Vec<Tagged<u64>>,
skip: bool,
}
pub struct Nth; pub struct Nth;
impl WholeStreamCommand for Nth { impl WholeStreamCommand for Nth {
@ -59,14 +52,12 @@ impl WholeStreamCommand for Nth {
} }
fn nth(args: CommandArgs) -> Result<OutputStream, ShellError> { fn nth(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ( let args = args.evaluate_once()?;
NthArgs {
row_number, let row_number: Tagged<u64> = args.req(0)?;
rest: and_rows, let and_rows: Vec<Tagged<u64>> = args.rest(1)?;
skip, let skip = args.has_flag("skip");
}, let input = args.input;
input,
) = args.process()?;
let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect(); let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect();
rows.push(row_number.item as usize); rows.push(row_number.item as usize);

View file

@ -48,7 +48,10 @@ impl WholeStreamCommand for SubCommand {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let scope = args.scope().clone(); let scope = args.scope().clone();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (Arguments { load_path }, _) = args.process()?;
let args = args.evaluate_once()?;
let load_path: Option<Tagged<PathBuf>> = args.get_flag("load")?;
if let Some(Tagged { if let Some(Tagged {
item: load_path, item: load_path,

View file

@ -12,13 +12,6 @@ use std::path::{Path, PathBuf};
pub struct Open; pub struct Open;
#[derive(Deserialize)]
pub struct OpenArgs {
path: Tagged<PathBuf>,
raw: Tagged<bool>,
encoding: Option<Tagged<String>>,
}
impl WholeStreamCommand for Open { impl WholeStreamCommand for Open {
fn name(&self) -> &str { fn name(&self) -> &str {
"open" "open"
@ -106,14 +99,10 @@ fn open(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ctrl_c = args.ctrl_c(); let ctrl_c = args.ctrl_c();
let ( let args = args.evaluate_once()?;
OpenArgs { let path: Tagged<PathBuf> = args.req(0)?;
path, let raw = args.has_flag("raw");
raw, let encoding: Option<Tagged<String>> = args.get_flag("encoding")?;
encoding,
},
_,
) = args.process()?;
if path.is_dir() { if path.is_dir() {
let args = nu_engine::shell::LsArgs { let args = nu_engine::shell::LsArgs {
@ -132,7 +121,7 @@ fn open(args: CommandArgs) -> Result<ActionStream, ShellError> {
// Check if the extension has a "from *" command OR "bat" supports syntax highlighting // Check if the extension has a "from *" command OR "bat" supports syntax highlighting
// AND the user doesn't want the raw output // AND the user doesn't want the raw output
// In these cases, we will collect the Stream // In these cases, we will collect the Stream
let ext = if raw.item { let ext = if raw {
None None
} else { } else {
path.extension() path.extension()

View file

@ -52,8 +52,15 @@ impl WholeStreamCommand for Pivot {
pub fn pivot(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn pivot(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (args, input): (PivotArgs, _) = args.process()?; //let (args, input): (PivotArgs, _) = args.process()?;
let input = input.into_vec(); let args = args.evaluate_once()?;
let pivot_args = PivotArgs {
header_row: args.has_flag("header-row"),
ignore_titles: args.has_flag("ignore-titles"),
rest: args.rest(0)?,
};
let input = args.input.into_vec();
let args = pivot_args;
let descs = merge_descriptors(&input); let descs = merge_descriptors(&input);

View file

@ -3,11 +3,6 @@ use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
#[derive(Deserialize)]
struct PrependArgs {
row: Value,
}
pub struct Prepend; pub struct Prepend;
impl WholeStreamCommand for Prepend { impl WholeStreamCommand for Prepend {
@ -46,7 +41,9 @@ impl WholeStreamCommand for Prepend {
} }
fn prepend(args: CommandArgs) -> Result<OutputStream, ShellError> { fn prepend(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (PrependArgs { row }, input) = args.process()?; let args = args.evaluate_once()?;
let row: Value = args.req(0)?;
let input = args.input;
let bos = vec![row].into_iter(); let bos = vec![row].into_iter();

View file

@ -8,7 +8,6 @@ use nu_parser::ParserScope;
use nu_protocol::{ use nu_protocol::{
hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value, hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value,
}; };
use nu_source::Tagged;
use nu_stream::ActionStream; use nu_stream::ActionStream;
pub struct Reduce; pub struct Reduce;
@ -17,7 +16,7 @@ pub struct Reduce;
pub struct ReduceArgs { pub struct ReduceArgs {
block: CapturedBlock, block: CapturedBlock,
fold: Option<Value>, fold: Option<Value>,
numbered: Tagged<bool>, numbered: bool,
} }
impl WholeStreamCommand for Reduce { impl WholeStreamCommand for Reduce {
@ -107,10 +106,17 @@ fn process_row(
result result
} }
fn reduce(raw_args: CommandArgs) -> Result<ActionStream, ShellError> { fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
let span = raw_args.call_info.name_tag.span; let span = args.call_info.name_tag.span;
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (reduce_args, mut input): (ReduceArgs, _) = raw_args.process()?; let args = args.evaluate_once()?;
let reduce_args = ReduceArgs {
block: args.req(0)?,
fold: args.get_flag("fold")?,
numbered: args.has_flag("numbered"),
};
let mut input = args.input;
let block = Arc::new(reduce_args.block); let block = Arc::new(reduce_args.block);
let (ioffset, start) = if !input.is_empty() { let (ioffset, start) = if !input.is_empty() {
match reduce_args.fold { match reduce_args.fold {
@ -129,7 +135,7 @@ fn reduce(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
)); ));
}; };
if reduce_args.numbered.item { if reduce_args.numbered {
// process_row returns Result<InputStream, ShellError>, so we must fold with one // process_row returns Result<InputStream, ShellError>, so we must fold with one
let initial = Ok(InputStream::one(each::make_indexed_item( let initial = Ok(InputStream::one(each::make_indexed_item(
ioffset - 1, ioffset - 1,

View file

@ -5,11 +5,6 @@ use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
use nu_source::Tagged; use nu_source::Tagged;
#[derive(Deserialize)]
pub struct RejectArgs {
rest: Vec<Tagged<String>>,
}
pub struct Reject; pub struct Reject;
impl WholeStreamCommand for Reject { impl WholeStreamCommand for Reject {
@ -40,7 +35,9 @@ impl WholeStreamCommand for Reject {
fn reject(args: CommandArgs) -> Result<ActionStream, ShellError> { fn reject(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (RejectArgs { rest: fields }, input) = args.process()?; let args = args.evaluate_once()?;
let fields: Vec<Tagged<String>> = args.rest(0)?;
if fields.is_empty() { if fields.is_empty() {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Reject requires fields", "Reject requires fields",
@ -51,7 +48,8 @@ fn reject(args: CommandArgs) -> Result<ActionStream, ShellError> {
let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect(); let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect();
Ok(input Ok(args
.input
.map(move |item| ReturnSuccess::value(reject_fields(&item, &fields, &item.tag))) .map(move |item| ReturnSuccess::value(reject_fields(&item, &fields, &item.tag)))
.to_action_stream()) .to_action_stream())
} }

View file

@ -7,12 +7,6 @@ use nu_source::Tagged;
pub struct Rename; pub struct Rename;
#[derive(Deserialize)]
pub struct Arguments {
column_name: Tagged<String>,
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for Rename { impl WholeStreamCommand for Rename {
fn name(&self) -> &str { fn name(&self) -> &str {
"rename" "rename"
@ -63,7 +57,11 @@ impl WholeStreamCommand for Rename {
pub fn rename(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn rename(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (Arguments { column_name, rest }, input) = args.process()?; let args = args.evaluate_once()?;
let column_name: Tagged<String> = args.req(0)?;
let rest: Vec<Tagged<String>> = args.rest(1)?;
let input = args.input;
let mut new_column_names = vec![vec![column_name]]; let mut new_column_names = vec![vec![column_name]];
new_column_names.push(rest); new_column_names.push(rest);

View file

@ -65,9 +65,17 @@ impl WholeStreamCommand for Remove {
fn rm(args: CommandArgs) -> Result<ActionStream, ShellError> { fn rm(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let shell_manager = args.shell_manager(); let shell_manager = args.shell_manager();
let (args, _): (RemoveArgs, _) = args.process()?; let args = args.evaluate_once()?;
if args.trash.item && args.permanent.item { let args = RemoveArgs {
rest: args.rest(0)?,
recursive: args.has_flag("recursive"),
trash: args.has_flag("trash"),
permanent: args.has_flag("permanent"),
force: args.has_flag("force"),
};
if args.trash && args.permanent {
return Ok(ActionStream::one(Err(ShellError::labeled_error( return Ok(ActionStream::one(Err(ShellError::labeled_error(
"only one of --permanent and --trash can be used", "only one of --permanent and --trash can be used",
"conflicting flags", "conflicting flags",

View file

@ -10,11 +10,6 @@ use nu_value_ext::ValueExt;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"rotate" "rotate"
@ -38,9 +33,10 @@ impl WholeStreamCommand for Command {
pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (Arguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<Tagged<String>> = args.rest(0)?;
let input = args.input.into_vec();
let input = input.into_vec();
let total_rows = input.len(); let total_rows = input.len();
let descs = merge_descriptors(&input); let descs = merge_descriptors(&input);
let total_descriptors = descs.len(); let total_descriptors = descs.len();

View file

@ -10,11 +10,6 @@ use nu_value_ext::ValueExt;
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"rotate counter-clockwise" "rotate counter-clockwise"
@ -38,9 +33,10 @@ impl WholeStreamCommand for SubCommand {
pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (Arguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<Tagged<String>> = args.rest(0)?;
let input = input.into_vec(); let input = args.input.into_vec();
let descs = merge_descriptors(&input); let descs = merge_descriptors(&input);
let total_rows = input.len(); let total_rows = input.len();

View file

@ -8,14 +8,6 @@ use std::cmp;
pub struct Seq; pub struct Seq;
#[derive(Deserialize)]
pub struct SeqArgs {
rest: Vec<Tagged<f64>>,
separator: Option<Tagged<String>>,
terminator: Option<Tagged<String>>,
widths: Tagged<bool>,
}
impl WholeStreamCommand for Seq { impl WholeStreamCommand for Seq {
fn name(&self) -> &str { fn name(&self) -> &str {
"seq" "seq"
@ -108,15 +100,11 @@ impl WholeStreamCommand for Seq {
fn seq(args: CommandArgs) -> Result<OutputStream, ShellError> { fn seq(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let ( let args = args.evaluate_once()?;
SeqArgs { let rest_nums: Vec<Tagged<f64>> = args.rest(0)?;
rest: rest_nums, let separator: Option<Tagged<String>> = args.get_flag("separator")?;
separator, let terminator: Option<Tagged<String>> = args.get_flag("terminator")?;
terminator, let widths = args.has_flag("widths");
widths,
},
_,
) = args.process()?;
if rest_nums.is_empty() { if rest_nums.is_empty() {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -174,7 +162,7 @@ fn seq(args: CommandArgs) -> Result<OutputStream, ShellError> {
let rest_nums: Vec<String> = rest_nums.iter().map(|n| n.item.to_string()).collect(); let rest_nums: Vec<String> = rest_nums.iter().map(|n| n.item.to_string()).collect();
run_seq(sep, Some(term), widths.item, rest_nums) run_seq(sep, Some(term), widths, rest_nums)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -3,24 +3,12 @@ use chrono::naive::NaiveDate;
use chrono::{Duration, Local}; use chrono::{Duration, Local};
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{value::I64Ext, value::StrExt, value::StringExt, value::U64Ext}; use nu_protocol::{value::I64Ext, value::StrExt, value::StringExt};
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged; use nu_source::Tagged;
pub struct SeqDates; pub struct SeqDates;
#[derive(Deserialize)]
pub struct SeqDatesArgs {
separator: Option<Tagged<String>>,
output_format: Option<Tagged<String>>,
input_format: Option<Tagged<String>>,
begin_date: Option<Tagged<String>>,
end_date: Option<Tagged<String>>,
increment: Option<Tagged<i64>>,
days: Option<Tagged<u64>>,
reverse: Tagged<bool>,
}
impl WholeStreamCommand for SeqDates { impl WholeStreamCommand for SeqDates {
fn name(&self) -> &str { fn name(&self) -> &str {
"seq date" "seq date"
@ -35,24 +23,24 @@ impl WholeStreamCommand for SeqDates {
Some('s'), Some('s'),
) )
.named( .named(
"output_format", "output-format",
SyntaxShape::String, SyntaxShape::String,
"prints dates in this format (defaults to %Y-%m-%d)", "prints dates in this format (defaults to %Y-%m-%d)",
Some('o'), Some('o'),
) )
.named( .named(
"input_format", "input-format",
SyntaxShape::String, SyntaxShape::String,
"give argument dates in this format (defaults to %Y-%m-%d)", "give argument dates in this format (defaults to %Y-%m-%d)",
Some('i'), Some('i'),
) )
.named( .named(
"begin_date", "begin-date",
SyntaxShape::String, SyntaxShape::String,
"beginning date range", "beginning date range",
Some('b'), Some('b'),
) )
.named("end_date", SyntaxShape::String, "ending date", Some('e')) .named("end-date", SyntaxShape::String, "ending date", Some('e'))
.named( .named(
"increment", "increment",
SyntaxShape::Int, SyntaxShape::Int,
@ -134,19 +122,16 @@ impl WholeStreamCommand for SeqDates {
fn seq_dates(args: CommandArgs) -> Result<ActionStream, ShellError> { fn seq_dates(args: CommandArgs) -> Result<ActionStream, ShellError> {
let _name = args.call_info.name_tag.clone(); let _name = args.call_info.name_tag.clone();
let ( let args = args.evaluate_once()?;
SeqDatesArgs {
separator, let separator: Option<Tagged<String>> = args.get_flag("separator")?;
output_format, let output_format: Option<Tagged<String>> = args.get_flag("output-format")?;
input_format, let input_format: Option<Tagged<String>> = args.get_flag("input-format")?;
begin_date, let begin_date: Option<Tagged<String>> = args.get_flag("begin-date")?;
end_date, let end_date: Option<Tagged<String>> = args.get_flag("end-date")?;
increment, let increment: Option<Tagged<i64>> = args.get_flag("increment")?;
days, let days: Option<Tagged<i64>> = args.get_flag("days")?;
reverse, let reverse = args.has_flag("reverse");
},
_,
) = args.process()?;
let sep: String = match separator { let sep: String = match separator {
Some(s) => { Some(s) => {
@ -205,8 +190,8 @@ fn seq_dates(args: CommandArgs) -> Result<ActionStream, ShellError> {
}; };
let mut rev = false; let mut rev = false;
if *reverse { if reverse {
rev = *reverse; rev = reverse;
} }
run_seq_dates(sep, outformat, informat, begin, end, inc, day_count, rev) run_seq_dates(sep, outformat, informat, begin, end, inc, day_count, rev)

View file

@ -6,11 +6,6 @@ use nu_source::Tagged;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
rows: Option<Tagged<usize>>,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"skip" "skip"
@ -41,7 +36,10 @@ impl WholeStreamCommand for Command {
} }
fn skip(args: CommandArgs) -> Result<ActionStream, ShellError> { fn skip(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (Arguments { rows }, input) = args.process()?; let args = args.evaluate_once()?;
let rows: Option<Tagged<usize>> = args.opt(0)?;
let input = args.input;
let rows_desired = if let Some(quantity) = rows { let rows_desired = if let Some(quantity) = rows {
*quantity *quantity
} else { } else {

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnValue, Signature, SyntaxShape, UntaggedValue}; use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged; use nu_source::Tagged;
use std::{ use std::{
sync::atomic::Ordering, sync::atomic::Ordering,
@ -13,12 +13,6 @@ const CTRL_C_CHECK_INTERVAL: Duration = Duration::from_millis(100);
pub struct Sleep; pub struct Sleep;
#[derive(Deserialize)]
pub struct SleepArgs {
pub duration: Tagged<u64>,
pub rest: Vec<Tagged<u64>>,
}
impl WholeStreamCommand for Sleep { impl WholeStreamCommand for Sleep {
fn name(&self) -> &str { fn name(&self) -> &str {
"sleep" "sleep"
@ -34,15 +28,20 @@ impl WholeStreamCommand for Sleep {
"Delay for a specified amount of time." "Delay for a specified amount of time."
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctrl_c = args.ctrl_c(); let ctrl_c = args.ctrl_c();
let (SleepArgs { duration, rest }, _) = args.process()?; let args = args.evaluate_once()?;
let duration: Tagged<i64> = args.req(0)?;
let rest: Vec<Tagged<i64>> = args.rest(1)?;
let total_dur = Duration::from_nanos(duration.item) let total_dur = Duration::from_nanos(if duration.item > 0 {
+ rest duration.item as u64
} else {
0
}) + rest
.iter() .iter()
.map(|val| Duration::from_nanos(val.item)) .map(|val| Duration::from_nanos(if val.item > 0 { val.item as u64 } else { 0 }))
.sum::<Duration>(); .sum::<Duration>();
//SleepHandler::new(total_dur, ctrl_c); //SleepHandler::new(total_dur, ctrl_c);
@ -50,7 +49,7 @@ impl WholeStreamCommand for Sleep {
// `echo | sleep 1sec` - nothing // `echo | sleep 1sec` - nothing
// `sleep 1sec` - table with 0 elements // `sleep 1sec` - table with 0 elements
Ok(SleepIterator::new(total_dur, ctrl_c).to_action_stream()) Ok(SleepIterator::new(total_dur, ctrl_c).to_output_stream())
// if input.is_empty() { // if input.is_empty() {
// Ok(OutputStream::empty()) // Ok(OutputStream::empty())
@ -92,7 +91,7 @@ impl SleepIterator {
} }
impl Iterator for SleepIterator { impl Iterator for SleepIterator {
type Item = ReturnValue; type Item = Value;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let start = Instant::now(); let start = Instant::now();

View file

@ -8,13 +8,6 @@ use nu_value_ext::ValueExt;
pub struct SortBy; pub struct SortBy;
#[derive(Deserialize)]
pub struct SortByArgs {
rest: Vec<Tagged<String>>,
insensitive: bool,
reverse: bool,
}
impl WholeStreamCommand for SortBy { impl WholeStreamCommand for SortBy {
fn name(&self) -> &str { fn name(&self) -> &str {
"sort-by" "sort-by"
@ -35,7 +28,7 @@ impl WholeStreamCommand for SortBy {
"Sort by the given columns, in increasing order." "Sort by the given columns, in increasing order."
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
sort_by(args) sort_by(args)
} }
@ -111,18 +104,14 @@ impl WholeStreamCommand for SortBy {
} }
} }
fn sort_by(args: CommandArgs) -> Result<ActionStream, ShellError> { fn sort_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let mut args = args.evaluate_once()?;
let ( let rest = args.rest(0)?;
SortByArgs { let insensitive = args.has_flag("insensitive");
rest, let reverse = args.has_flag("reverse");
insensitive, let mut vec = args.input.drain_vec();
reverse,
},
mut input,
) = args.process()?;
let mut vec = input.drain_vec();
sort(&mut vec, &rest, &tag, insensitive)?; sort(&mut vec, &rest, &tag, insensitive)?;
@ -130,7 +119,7 @@ fn sort_by(args: CommandArgs) -> Result<ActionStream, ShellError> {
vec.reverse() vec.reverse()
} }
Ok((vec.into_iter()).to_action_stream()) Ok((vec.into_iter()).to_output_stream())
} }
pub fn sort( pub fn sort(

View file

@ -41,7 +41,8 @@ impl WholeStreamCommand for Source {
pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
let ctx = EvaluationContext::from_args(&args); let ctx = EvaluationContext::from_args(&args);
let (SourceArgs { filename }, _) = args.process()?; let args = args.evaluate_once()?;
let filename: Tagged<String> = args.req(0)?;
// Note: this is a special case for setting the context from a command // Note: this is a special case for setting the context from a command
// In this case, if we don't set it now, we'll lose the scope that this // In this case, if we don't set it now, we'll lose the scope that this

View file

@ -7,14 +7,6 @@ use nu_protocol::{
}; };
use nu_source::Tagged; use nu_source::Tagged;
#[derive(Deserialize)]
struct SplitColumnArgs {
separator: Tagged<String>,
rest: Vec<Tagged<String>>,
#[serde(rename(deserialize = "collapse-empty"))]
collapse_empty: bool,
}
pub struct SubCommand; pub struct SubCommand;
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
@ -26,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
Signature::build("split column") Signature::build("split column")
.required( .required(
"separator", "separator",
SyntaxShape::Any, SyntaxShape::String,
"the character that denotes what separates columns", "the character that denotes what separates columns",
) )
.switch("collapse-empty", "remove empty columns", Some('c')) .switch("collapse-empty", "remove empty columns", Some('c'))
@ -44,14 +36,11 @@ impl WholeStreamCommand for SubCommand {
fn split_column(args: CommandArgs) -> Result<ActionStream, ShellError> { fn split_column(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name_span = args.call_info.name_tag.span; let name_span = args.call_info.name_tag.span;
let ( let args = args.evaluate_once()?;
SplitColumnArgs { let separator: Tagged<String> = args.req(0)?;
separator, let rest: Vec<Tagged<String>> = args.rest(1)?;
rest, let collapse_empty = args.has_flag("collapse-empty");
collapse_empty, let input = args.input;
},
input,
) = args.process()?;
Ok(input Ok(input
.map(move |v| { .map(move |v| {

View file

@ -5,11 +5,6 @@ use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged; use nu_source::Tagged;
#[derive(Deserialize)]
struct SplitRowArgs {
separator: Tagged<String>,
}
pub struct SubCommand; pub struct SubCommand;
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
@ -20,7 +15,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("split row").required( Signature::build("split row").required(
"separator", "separator",
SyntaxShape::Any, SyntaxShape::String,
"the character that denotes what separates rows", "the character that denotes what separates rows",
) )
} }
@ -36,7 +31,11 @@ impl WholeStreamCommand for SubCommand {
fn split_row(args: CommandArgs) -> Result<ActionStream, ShellError> { fn split_row(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (SplitRowArgs { separator }, input) = args.process()?; let args = args.evaluate_once()?;
let separator: Tagged<String> = args.req(0)?;
let input = args.input;
Ok(input Ok(input
.flat_map(move |v| { .flat_map(move |v| {
if let Ok(s) = v.as_string() { if let Ok(s) = v.as_string() {

View file

@ -8,11 +8,6 @@ use nu_value_ext::as_string;
pub struct SplitBy; pub struct SplitBy;
#[derive(Deserialize)]
pub struct SplitByArgs {
column_name: Option<Tagged<String>>,
}
impl WholeStreamCommand for SplitBy { impl WholeStreamCommand for SplitBy {
fn name(&self) -> &str { fn name(&self) -> &str {
"split-by" "split-by"
@ -37,8 +32,10 @@ impl WholeStreamCommand for SplitBy {
pub fn split_by(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn split_by(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (SplitByArgs { column_name }, input) = args.process()?; let args = args.evaluate_once()?;
let values: Vec<Value> = input.collect(); let column_name: Option<Tagged<String>> = args.opt(0)?;
let values: Vec<Value> = args.input.collect();
if values.len() > 1 || values.is_empty() { if values.len() > 1 || values.is_empty() {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(

View file

@ -29,7 +29,10 @@ impl WholeStreamCommand for TermSize {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let tag = args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (TermSizeArgs { wide, tall }, _) = args.process()?; let args = args.evaluate_once()?;
let wide = args.has_flag("wide");
let tall = args.has_flag("tall");
let size = term_size::dimensions(); let size = term_size::dimensions();
match size { match size {

View file

@ -8,12 +8,6 @@ use std::path::PathBuf;
pub struct Touch; pub struct Touch;
#[derive(Deserialize)]
pub struct TouchArgs {
target: Tagged<PathBuf>,
rest: Vec<Tagged<PathBuf>>,
}
impl WholeStreamCommand for Touch { impl WholeStreamCommand for Touch {
fn name(&self) -> &str { fn name(&self) -> &str {
"touch" "touch"
@ -51,7 +45,9 @@ impl WholeStreamCommand for Touch {
} }
fn touch(args: CommandArgs) -> Result<ActionStream, ShellError> { fn touch(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (TouchArgs { target, rest }, _) = args.process()?; let args = args.evaluate_once()?;
let target: Tagged<PathBuf> = args.req(0)?;
let rest: Vec<Tagged<PathBuf>> = args.rest(1)?;
for item in vec![target].into_iter().chain(rest.into_iter()) { for item in vec![target].into_iter().chain(rest.into_iter()) {
match OpenOptions::new().write(true).create(true).open(&item) { match OpenOptions::new().write(true).create(true).open(&item) {

View file

@ -11,12 +11,6 @@ use nu_value_ext::ValueExt;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
field: ColumnPath,
replacement: Value,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"update" "update"
@ -178,10 +172,15 @@ fn process_row(
}) })
} }
fn update(raw_args: CommandArgs) -> Result<ActionStream, ShellError> { fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name_tag = Arc::new(raw_args.call_info.name_tag.clone()); let name_tag = Arc::new(args.call_info.name_tag.clone());
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&args));
let (Arguments { field, replacement }, input) = raw_args.process()?; let args = args.evaluate_once()?;
let field: ColumnPath = args.req(0)?;
let replacement: Value = args.req(1)?;
let input = args.input;
let replacement = Arc::new(replacement); let replacement = Arc::new(replacement);
let field = Arc::new(field); let field = Arc::new(field);

View file

@ -1,10 +1,10 @@
use url::Url; use url::Url;
use super::{operate, DefaultArguments}; use super::operate;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
pub struct UrlHost; pub struct UrlHost;
@ -23,7 +23,10 @@ impl WholeStreamCommand for UrlHost {
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DefaultArguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<ColumnPath> = args.rest(0)?;
let input = args.input;
Ok(operate(input, rest, &host)) Ok(operate(input, rest, &host))
} }

View file

@ -15,11 +15,6 @@ pub use path::UrlPath;
pub use query::UrlQuery; pub use query::UrlQuery;
pub use scheme::UrlScheme; pub use scheme::UrlScheme;
#[derive(Deserialize)]
struct DefaultArguments {
rest: Vec<ColumnPath>,
}
fn handle_value<F>(action: &F, v: &Value) -> Result<Value, ShellError> fn handle_value<F>(action: &F, v: &Value) -> Result<Value, ShellError>
where where
F: Fn(&Url) -> &str + Send + 'static, F: Fn(&Url) -> &str + Send + 'static,

View file

@ -1,10 +1,10 @@
use url::Url; use url::Url;
use super::{operate, DefaultArguments}; use super::operate;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
pub struct UrlPath; pub struct UrlPath;
@ -23,7 +23,10 @@ impl WholeStreamCommand for UrlPath {
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DefaultArguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<ColumnPath> = args.rest(0)?;
let input = args.input;
Ok(operate(input, rest, &Url::path)) Ok(operate(input, rest, &Url::path))
} }

View file

@ -1,10 +1,10 @@
use url::Url; use url::Url;
use super::{operate, DefaultArguments}; use super::operate;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
pub struct UrlQuery; pub struct UrlQuery;
@ -23,7 +23,9 @@ impl WholeStreamCommand for UrlQuery {
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DefaultArguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<ColumnPath> = args.rest(0)?;
let input = args.input;
Ok(operate(input, rest, &query)) Ok(operate(input, rest, &query))
} }

View file

@ -1,10 +1,10 @@
use url::Url; use url::Url;
use super::{operate, DefaultArguments}; use super::operate;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
pub struct UrlScheme; pub struct UrlScheme;
@ -22,8 +22,9 @@ impl WholeStreamCommand for UrlScheme {
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let (DefaultArguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
Ok(operate(input, rest, &Url::scheme)) let rest: Vec<ColumnPath> = args.rest(0)?;
Ok(operate(args.input, rest, &Url::scheme))
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View file

@ -10,11 +10,6 @@ use nu_protocol::{
pub struct Command; pub struct Command;
#[derive(Deserialize)]
pub struct Arguments {
block: CapturedBlock,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"where" "where"
@ -61,10 +56,13 @@ impl WholeStreamCommand for Command {
] ]
} }
} }
fn where_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> { fn where_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(EvaluationContext::from_args(&raw_args)); let context = Arc::new(EvaluationContext::from_args(&args));
let tag = raw_args.call_info.name_tag.clone(); let tag = args.call_info.name_tag.clone();
let (Arguments { block }, input) = raw_args.process()?; let args = args.evaluate_once()?;
let block: CapturedBlock = args.req(0)?;
let condition = { let condition = {
if block.block.block.len() != 1 { if block.block.block.len() != 1 {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -97,7 +95,7 @@ fn where_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(WhereIterator { Ok(WhereIterator {
condition, condition,
context, context,
input, input: args.input,
block, block,
} }
.to_output_stream()) .to_output_stream())

View file

@ -67,10 +67,12 @@ impl WholeStreamCommand for WithEnv {
} }
} }
fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> { fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
let external_redirection = raw_args.call_info.args.external_redirection; let external_redirection = args.call_info.args.external_redirection;
let context = EvaluationContext::from_args(&raw_args); let context = EvaluationContext::from_args(&args);
let (WithEnvArgs { variable, block }, input) = raw_args.process()?; let args = args.evaluate_once()?;
let variable: Value = args.req(0)?;
let block: CapturedBlock = args.req(1)?;
let mut env = IndexMap::new(); let mut env = IndexMap::new();
@ -108,7 +110,7 @@ fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
context.scope.add_env(env); context.scope.add_env(env);
context.scope.add_vars(&block.captured.entries); context.scope.add_vars(&block.captured.entries);
let result = run_block(&block.block, &context, input, external_redirection); let result = run_block(&block.block, &context, args.input, external_redirection);
context.scope.exit_scope(); context.scope.exit_scope();
result.map(|x| x.to_action_stream()) result.map(|x| x.to_action_stream())

View file

@ -9,11 +9,6 @@ const DEFAULT_COLUMN_NAME: &str = "Column";
pub struct Wrap; pub struct Wrap;
#[derive(Deserialize)]
struct WrapArgs {
column: Option<Tagged<String>>,
}
impl WholeStreamCommand for Wrap { impl WholeStreamCommand for Wrap {
fn name(&self) -> &str { fn name(&self) -> &str {
"wrap" "wrap"
@ -78,11 +73,13 @@ impl WholeStreamCommand for Wrap {
} }
fn wrap(args: CommandArgs) -> Result<ActionStream, ShellError> { fn wrap(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (WrapArgs { column }, input) = args.process()?; let args = args.evaluate_once()?;
let column: Option<Tagged<String>> = args.opt(0)?;
let mut result_table = vec![]; let mut result_table = vec![];
let mut are_all_rows = true; let mut are_all_rows = true;
for value in input { for value in args.input {
match value { match value {
Value { Value {
value: UntaggedValue::Row(_), value: UntaggedValue::Row(_),

View file

@ -28,10 +28,11 @@ impl WholeStreamCommand for Command {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let name_tag = args.call_info.name_tag.clone(); let name_tag = args.call_info.name_tag.clone();
let (Arguments { rest }, input) = args.process()?; let args = args.evaluate_once()?;
let rest: Vec<Value> = args.rest(0)?;
let mut base_value = UntaggedValue::string("Yehuda Katz in Ecuador").into_value(name_tag); let mut base_value = UntaggedValue::string("Yehuda Katz in Ecuador").into_value(name_tag);
let input: Vec<Value> = input.collect(); let input: Vec<Value> = args.input.collect();
if let Some(first) = input.get(0) { if let Some(first) = input.get(0) {
base_value = first.clone() base_value = first.clone()

View file

@ -3,16 +3,8 @@ use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
use nu_source::{AnchorLocation, Tag}; use nu_source::{AnchorLocation, Tag};
use nu_stream::ActionStream; use nu_stream::ActionStream;
use serde::Deserialize;
pub struct Command; pub struct Command;
#[derive(Deserialize)]
struct Arguments {
path: Option<bool>,
}
impl WholeStreamCommand for Command { impl WholeStreamCommand for Command {
fn name(&self) -> &str { fn name(&self) -> &str {
"stub open" "stub open"
@ -29,11 +21,11 @@ impl WholeStreamCommand for Command {
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
let name_tag = args.call_info.name_tag.clone(); let name_tag = args.call_info.name_tag.clone();
let (Arguments { path: mocked_path }, _input) = args.process()?; let mocked_path = args.call_info.switch_present("path");
let out = UntaggedValue::string("Yehuda Katz in Ecuador"); let out = UntaggedValue::string("Yehuda Katz in Ecuador");
if let Some(true) = mocked_path { if mocked_path {
Ok(ActionStream::one(Ok(ReturnSuccess::Value(Value { Ok(ActionStream::one(Ok(ReturnSuccess::Value(Value {
value: out, value: out,
tag: Tag { tag: Tag {

View file

@ -77,7 +77,7 @@ pub enum CompareValues {
Decimals(BigDecimal, BigDecimal), Decimals(BigDecimal, BigDecimal),
String(String, String), String(String, String),
Date(DateTime<FixedOffset>, DateTime<FixedOffset>), Date(DateTime<FixedOffset>, DateTime<FixedOffset>),
DateDuration(DateTime<FixedOffset>, BigInt), DateDuration(DateTime<FixedOffset>, i64),
Booleans(bool, bool), Booleans(bool, bool),
} }
@ -92,10 +92,8 @@ impl CompareValues {
CompareValues::Date(left, right) => left.cmp(right), CompareValues::Date(left, right) => left.cmp(right),
CompareValues::DateDuration(left, right) => { CompareValues::DateDuration(left, right) => {
// FIXME: Not sure if I could do something better with the Span. // FIXME: Not sure if I could do something better with the Span.
let duration = Primitive::into_chrono_duration( let duration =
Primitive::Duration(right.clone()), Primitive::into_chrono_duration(Primitive::Duration(*right), Span::unknown())
Span::unknown(),
)
.expect("Could not convert nushell Duration into chrono Duration."); .expect("Could not convert nushell Duration into chrono Duration.");
let right: DateTime<FixedOffset> = Utc::now() let right: DateTime<FixedOffset> = Utc::now()
.checked_sub_signed(duration) .checked_sub_signed(duration)
@ -160,7 +158,7 @@ pub fn coerce_compare_primitive(
(Nothing, Nothing) => CompareValues::Booleans(true, true), (Nothing, Nothing) => CompareValues::Booleans(true, true),
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()), (String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
(Date(left), Date(right)) => CompareValues::Date(*left, *right), (Date(left), Date(right)) => CompareValues::Date(*left, *right),
(Date(left), Duration(right)) => CompareValues::DateDuration(*left, right.clone()), (Date(left), Duration(right)) => CompareValues::DateDuration(*left, *right),
(Boolean(left), Boolean(right)) => CompareValues::Booleans(*left, *right), (Boolean(left), Boolean(right)) => CompareValues::Booleans(*left, *right),
(Boolean(left), Nothing) => CompareValues::Booleans(*left, false), (Boolean(left), Nothing) => CompareValues::Booleans(*left, false),
(Nothing, Boolean(right)) => CompareValues::Booleans(false, *right), (Nothing, Boolean(right)) => CompareValues::Booleans(false, *right),

View file

@ -33,7 +33,7 @@ pub enum InlineShape {
GlobPattern(String), GlobPattern(String),
Boolean(bool), Boolean(bool),
Date(DateTime<FixedOffset>), Date(DateTime<FixedOffset>),
Duration(BigInt), Duration(i64),
FilePath(PathBuf), FilePath(PathBuf),
Binary(usize), Binary(usize),
@ -94,7 +94,7 @@ impl InlineShape {
Primitive::GlobPattern(pattern) => InlineShape::GlobPattern(pattern.clone()), Primitive::GlobPattern(pattern) => InlineShape::GlobPattern(pattern.clone()),
Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean), Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean),
Primitive::Date(date) => InlineShape::Date(*date), Primitive::Date(date) => InlineShape::Date(*date),
Primitive::Duration(duration) => InlineShape::Duration(duration.clone()), Primitive::Duration(duration) => InlineShape::Duration(*duration),
Primitive::FilePath(path) => InlineShape::FilePath(path.clone()), Primitive::FilePath(path) => InlineShape::FilePath(path.clone()),
Primitive::Binary(b) => InlineShape::Binary(b.len()), Primitive::Binary(b) => InlineShape::Binary(b.len()),
Primitive::BeginningOfStream => InlineShape::BeginningOfStream, Primitive::BeginningOfStream => InlineShape::BeginningOfStream,
@ -304,10 +304,9 @@ impl PrettyDebug for FormatInlineShape {
.to_owned(), .to_owned(),
), ),
InlineShape::Date(date) => DbgDocBldr::primitive(nu_protocol::format_date(date)), InlineShape::Date(date) => DbgDocBldr::primitive(nu_protocol::format_date(date)),
InlineShape::Duration(duration) => DbgDocBldr::description(format_primitive( InlineShape::Duration(duration) => {
&Primitive::Duration(duration.clone()), DbgDocBldr::description(format_primitive(&Primitive::Duration(*duration), None))
None, }
)),
InlineShape::FilePath(path) => DbgDocBldr::primitive(path.display()), InlineShape::FilePath(path) => DbgDocBldr::primitive(path.display()),
InlineShape::Binary(length) => { InlineShape::Binary(length) => {
DbgDocBldr::opaque(format!("<binary: {} bytes>", length)) DbgDocBldr::opaque(format!("<binary: {} bytes>", length))

View file

@ -475,8 +475,13 @@ pub fn compute_values(
if y.is_zero() { if y.is_zero() {
return Ok(zero_division_error()); return Ok(zero_division_error());
} }
let y = y.as_bigint_and_exponent(); let y = y.as_bigint_and_exponent();
Ok(x / y.0) let z = y.0.to_i64();
match z {
Some(z) => Ok(x / z),
None => Err((left.type_name(), right.type_name())),
}
} }
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}?; }?;

View file

@ -1,4 +1,3 @@
use crate::deserializer::ConfigDeserializer;
use crate::env::host::Host; use crate::env::host::Host;
use crate::evaluate::scope::Scope; use crate::evaluate::scope::Scope;
use crate::evaluation_context::EvaluationContext; use crate::evaluation_context::EvaluationContext;
@ -13,7 +12,6 @@ use nu_protocol::{CallInfo, Value};
use nu_source::Tag; use nu_source::Tag;
use nu_stream::InputStream; use nu_stream::InputStream;
use parking_lot::Mutex; use parking_lot::Mutex;
use serde::Deserialize;
use std::ops::Deref; use std::ops::Deref;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
@ -79,14 +77,14 @@ impl CommandArgs {
Ok((f(&evaluated_args.args)?, evaluated_args.input)) Ok((f(&evaluated_args.args)?, evaluated_args.input))
} }
pub fn process<'de, T: Deserialize<'de>>(self) -> Result<(T, InputStream), ShellError> { // pub fn process<'de, T: Deserialize<'de>>(self) -> Result<(T, InputStream), ShellError> {
let args = self.evaluate_once()?; // let args = self.evaluate_once()?;
let call_info = args.call_info.clone(); // let call_info = args.call_info.clone();
let mut deserializer = ConfigDeserializer::from_call_info(call_info); // let mut deserializer = ConfigDeserializer::from_call_info(call_info);
Ok((T::deserialize(&mut deserializer)?, args.input)) // Ok((T::deserialize(&mut deserializer)?, args.input))
} // }
} }
pub struct EvaluatedCommandArgs { pub struct EvaluatedCommandArgs {

View file

@ -1,621 +0,0 @@
use log::trace;
use nu_errors::{CoerceInto, ShellError};
use nu_protocol::{
hir::CapturedBlock, CallInfo, ColumnPath, Primitive, RangeInclusion, ShellTypeName,
UntaggedValue, Value,
};
use nu_source::Span;
use nu_source::{HasSpan, Spanned, SpannedItem, Tagged, TaggedItem};
use nu_value_ext::ValueExt;
use serde::de;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Copy, Clone, Deserialize, Serialize)]
pub struct NumericRange {
pub from: (Option<Spanned<u64>>, RangeInclusion),
pub to: (Option<Spanned<u64>>, RangeInclusion),
}
impl NumericRange {
pub fn min(self) -> u64 {
match self.from.1 {
RangeInclusion::Inclusive => self.from.0.map(|from| *from).unwrap_or(0),
RangeInclusion::Exclusive => {
self.from.0.map(|from| *from).unwrap_or(0).saturating_add(1)
}
}
}
pub fn max(self) -> u64 {
match self.to.1 {
RangeInclusion::Inclusive => self.to.0.map(|to| *to).unwrap_or(u64::MAX),
RangeInclusion::Exclusive => self
.to
.0
.map(|to| *to)
.unwrap_or(u64::MAX)
.saturating_sub(1),
}
}
}
#[derive(Debug)]
pub struct DeserializerItem<'de> {
key_struct_field: Option<(String, &'de str)>,
val: Value,
}
pub struct ConfigDeserializer<'de> {
call: CallInfo,
stack: Vec<DeserializerItem<'de>>,
saw_root: bool,
position: usize,
}
impl<'de> ConfigDeserializer<'de> {
pub fn from_call_info(call: CallInfo) -> ConfigDeserializer<'de> {
ConfigDeserializer {
call,
stack: vec![],
saw_root: false,
position: 0,
}
}
pub fn push_val(&mut self, val: Value) {
self.stack.push(DeserializerItem {
key_struct_field: None,
val,
});
}
pub fn push(&mut self, name: &'static str) -> Result<(), ShellError> {
let value: Option<Value> = if name == "rest" {
let positional = self.call.args.slice_from(self.position);
self.position += positional.len();
Some(UntaggedValue::Table(positional).into_untagged_value()) // TODO: correct tag
} else if self.call.args.has(name) {
self.call.args.get(name).cloned()
} else {
let position = self.position;
self.position += 1;
self.call.args.nth(position).cloned()
};
trace!("pushing {:?}", value);
self.stack.push(DeserializerItem {
key_struct_field: Some((name.to_string(), name)),
val: value.unwrap_or_else(|| UntaggedValue::nothing().into_value(&self.call.name_tag)),
});
Ok(())
}
pub fn top(&mut self) -> &DeserializerItem {
let value = self.stack.last();
trace!("inspecting top value :: {:?}", value);
value.expect("Can't get top element of an empty stack")
}
pub fn pop(&mut self) -> DeserializerItem {
let value = self.stack.pop();
trace!("popping value :: {:?}", value);
value.expect("Can't pop an empty stack")
}
}
use de::Visitor;
impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> {
type Error = ShellError;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_any")
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.pop();
trace!("Extracting {:?} for bool", value.val);
match &value.val {
Value {
value: UntaggedValue::Primitive(Primitive::Boolean(b)),
..
} => visitor.visit_bool(*b),
Value {
value: UntaggedValue::Primitive(Primitive::Nothing),
..
} => visitor.visit_bool(false),
other => Err(ShellError::type_error(
"Boolean",
other.type_name().spanned(other.span()),
)),
}
}
fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i8")
}
fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i16")
}
fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i32")
}
fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i64")
}
fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u8")
}
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u16")
}
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u32")
}
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u64")
}
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_f32")
}
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_f64")
}
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_char")
}
fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_str")
}
fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_string")
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_bytes")
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_byte_buf")
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.top();
let name = std::any::type_name::<V::Value>();
trace!("<Option> Extracting {:?} for Option<{}>", value, name);
match &value.val.value {
UntaggedValue::Primitive(Primitive::Nothing) => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_unit")
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_unit_struct")
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_newtype_struct")
}
fn deserialize_seq<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.pop();
trace!("<Vec> Extracting {:?} for vec", value.val);
match value.val.into_parts() {
(UntaggedValue::Table(items), _) => {
let de = SeqDeserializer::new(&mut self, items.into_iter());
visitor.visit_seq(de)
}
(other, tag) => Err(ShellError::type_error(
"Vec",
other.type_name().spanned(tag),
)),
}
}
fn deserialize_tuple<V>(mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.pop();
trace!(
"<Tuple> Extracting {:?} for tuple with {} elements",
value.val,
len
);
match value.val.into_parts() {
(UntaggedValue::Table(items), _) => {
let de = SeqDeserializer::new(&mut self, items.into_iter());
visitor.visit_seq(de)
}
(other, tag) => Err(ShellError::type_error(
"Tuple",
other.type_name().spanned(tag),
)),
}
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_tuple_struct")
}
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_map")
}
fn deserialize_struct<V>(
mut self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
fn visit<'de, T, V>(
val: T,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, ShellError>
where
T: serde::Serialize,
V: Visitor<'de>,
{
let json = serde_json::to_string(&val)?;
let json_cursor = std::io::Cursor::new(json.into_bytes());
let mut json_de = serde_json::Deserializer::from_reader(json_cursor);
let r = json_de.deserialize_struct(name, fields, visitor)?;
Ok(r)
}
trace!(
"deserializing struct {:?} {:?} (saw_root={} stack={:?})",
name,
fields,
self.saw_root,
self.stack
);
if !self.saw_root {
self.saw_root = true;
return visitor.visit_seq(StructDeserializer::new(&mut self, fields));
}
let value = self.pop();
let type_name = std::any::type_name::<V::Value>();
let tagged_val_name = std::any::type_name::<Value>();
trace!(
"name={} type_name={} tagged_val_name={}",
name,
type_name,
tagged_val_name
);
if type_name == tagged_val_name {
return visit::<Value, _>(value.val, name, fields, visitor);
}
if name == "CapturedBlock" {
let block = match value.val {
Value {
value: UntaggedValue::Block(block),
..
} => block,
other => {
return Err(ShellError::type_error(
"Block",
other.type_name().spanned(other.span()),
))
}
};
return visit::<CapturedBlock, _>(*block, name, fields, visitor);
}
if name == "ColumnPath" {
let path = match value.val {
Value {
value: UntaggedValue::Primitive(Primitive::ColumnPath(path)),
..
} => path,
Value {
value: UntaggedValue::Primitive(Primitive::String(path)),
..
} => {
let s = path.spanned(Span::unknown());
ColumnPath::build(&s)
}
other => {
return Err(ShellError::type_error(
"column path",
other.type_name().spanned(other.span()),
))
}
};
return visit::<ColumnPath, _>(path, name, fields, visitor);
}
trace!("Extracting {:?} for {:?}", value.val, type_name);
let tag = value.val.tag();
match value.val {
Value {
value: UntaggedValue::Primitive(Primitive::Boolean(b)),
..
} => visit::<Tagged<bool>, _>(b.tagged(tag), name, fields, visitor),
Value {
value: UntaggedValue::Primitive(Primitive::Nothing),
..
} => visit::<Tagged<bool>, _>(false.tagged(tag), name, fields, visitor),
Value {
value: UntaggedValue::Primitive(Primitive::FilePath(p)),
..
} => visit::<Tagged<PathBuf>, _>(p.tagged(tag), name, fields, visitor),
Value {
value: UntaggedValue::Primitive(Primitive::Int(int)),
..
} => visit::<Tagged<i64>, _>(int.tagged(tag), name, fields, visitor),
Value {
value: UntaggedValue::Primitive(Primitive::BigInt(int)),
..
} => {
let i: i64 = int.tagged(value.val.tag).coerce_into("converting to i64")?;
visit::<Tagged<i64>, _>(i.tagged(tag), name, fields, visitor)
}
Value {
value: UntaggedValue::Primitive(Primitive::Duration(big_int)),
..
} => {
let u_int: u64 = big_int
.tagged(value.val.tag)
.coerce_into("converting to u64")?;
visit::<Tagged<u64>, _>(u_int.tagged(tag), name, fields, visitor)
}
Value {
value: UntaggedValue::Primitive(Primitive::Decimal(decimal)),
..
} => {
let i: f64 = decimal
.tagged(value.val.tag)
.coerce_into("converting to f64")?;
visit::<Tagged<f64>, _>(i.tagged(tag), name, fields, visitor)
}
Value {
value: UntaggedValue::Primitive(Primitive::String(string)),
..
} => visit::<Tagged<String>, _>(string.tagged(tag), name, fields, visitor),
Value {
value: UntaggedValue::Primitive(Primitive::Range(range)),
..
} => {
let (left, left_inclusion) = range.from;
let (right, right_inclusion) = range.to;
let left_span = left.span;
let right_span = right.span;
let left = match left.item {
Primitive::Nothing => None,
_ => Some(left.as_u64(left_span)?),
};
let right = match right.item {
Primitive::Nothing => None,
_ => Some(right.as_u64(right_span)?),
};
let numeric_range = NumericRange {
from: (left.map(|left| left.spanned(left_span)), left_inclusion),
to: (
right.map(|right| right.spanned(right_span)),
right_inclusion,
),
};
visit::<Tagged<NumericRange>, _>(numeric_range.tagged(tag), name, fields, visitor)
}
other => Err(ShellError::type_error(
name,
other.type_name().spanned(other.span()),
)),
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_enum")
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_identifier")
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_ignored_any")
}
}
struct SeqDeserializer<'a, 'de: 'a, I: Iterator<Item = Value>> {
de: &'a mut ConfigDeserializer<'de>,
vals: I,
}
impl<'a, 'de: 'a, I: Iterator<Item = Value>> SeqDeserializer<'a, 'de, I> {
fn new(de: &'a mut ConfigDeserializer<'de>, vals: I) -> Self {
SeqDeserializer { de, vals }
}
}
impl<'a, 'de: 'a, I: Iterator<Item = Value>> de::SeqAccess<'de> for SeqDeserializer<'a, 'de, I> {
type Error = ShellError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
let next = if let Some(next) = self.vals.next() {
next
} else {
return Ok(None);
};
self.de.push_val(next);
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
self.vals.size_hint().1
}
}
struct StructDeserializer<'a, 'de: 'a> {
de: &'a mut ConfigDeserializer<'de>,
fields: &'static [&'static str],
}
impl<'a, 'de: 'a> StructDeserializer<'a, 'de> {
fn new(de: &'a mut ConfigDeserializer<'de>, fields: &'static [&'static str]) -> Self {
StructDeserializer { de, fields }
}
}
impl<'a, 'de: 'a> de::SeqAccess<'de> for StructDeserializer<'a, 'de> {
type Error = ShellError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
if self.fields.is_empty() {
return Ok(None);
}
trace!("Processing {}", self.fields[0]);
self.de.push(self.fields[0])?;
self.fields = &self.fields[1..];
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
Some(self.fields.len())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::any::type_name;
#[test]
fn check_type_name_properties() {
// This ensures that certain properties for the
// std::any::type_name function hold, that
// this code relies on. The type_name docs explicitly
// mention that the actual format of the output
// is unspecified and change is likely.
// This test makes sure that such change is detected
// by this test failing, and not things silently breaking.
// Specifically, we rely on this behavior further above
// in the file for the Value special case parsing.
let tuple = type_name::<()>();
let tagged_tuple = type_name::<Tagged<()>>();
let tagged_value = type_name::<Value>();
assert_ne!(tuple, tagged_tuple);
assert_ne!(tuple, tagged_value);
assert_ne!(tagged_tuple, tagged_value);
}
}

View file

@ -378,7 +378,7 @@ impl Shell for FilesystemShell {
let any_source_is_dir = sources.iter().any(|f| matches!(f, Ok(f) if f.is_dir())); let any_source_is_dir = sources.iter().any(|f| matches!(f, Ok(f) if f.is_dir()));
if any_source_is_dir && !recursive.item { if any_source_is_dir && !recursive {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Directories must be copied using \"--recursive\"", "Directories must be copied using \"--recursive\"",
"resolves to a directory (not copied)", "resolves to a directory (not copied)",
@ -607,11 +607,11 @@ impl Shell for FilesystemShell {
`rm_always_trash = true`, but the current nu executable was not \ `rm_always_trash = true`, but the current nu executable was not \
built with feature `trash_support`.", built with feature `trash_support`.",
)); ));
} else if _trash.item { } else if _trash {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Cannot execute `rm` with option `--trash`; feature `trash-support` not enabled", "Cannot execute `rm` with option `--trash`; feature `trash-support` not enabled",
"this option is only available if nu is built with the `trash-support` feature", "this option is only available if nu is built with the `trash-support` feature",
_trash.tag name
)); ));
} }
} }
@ -686,7 +686,7 @@ impl Shell for FilesystemShell {
}; };
} }
if all_targets.is_empty() && !_force.item { if all_targets.is_empty() && !_force {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"No valid paths", "No valid paths",
"no valid paths", "no valid paths",
@ -715,7 +715,7 @@ impl Shell for FilesystemShell {
if metadata.is_file() if metadata.is_file()
|| metadata.file_type().is_symlink() || metadata.file_type().is_symlink()
|| recursive.item || recursive
|| is_socket || is_socket
|| is_fifo || is_fifo
|| is_empty() || is_empty()
@ -724,7 +724,7 @@ impl Shell for FilesystemShell {
#[cfg(feature = "trash-support")] #[cfg(feature = "trash-support")]
{ {
use std::io::Error; use std::io::Error;
result = if _trash.item || (rm_always_trash && !_permanent.item) { result = if _trash || (rm_always_trash && !_permanent) {
trash::delete(&f).map_err(|e: trash::Error| { trash::delete(&f).map_err(|e: trash::Error| {
Error::new(ErrorKind::Other, format!("{:?}", e)) Error::new(ErrorKind::Other, format!("{:?}", e))
}) })

View file

@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use bigdecimal::ToPrimitive; use bigdecimal::{BigDecimal, ToPrimitive};
use chrono::{DateTime, FixedOffset}; use chrono::{DateTime, FixedOffset};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ use nu_protocol::{
@ -19,6 +19,32 @@ impl FromValue for Value {
} }
} }
impl FromValue for Tagged<num_bigint::BigInt> {
fn from_value(v: &Value) -> Result<Self, ShellError> {
let tag = v.tag.clone();
match v {
Value {
value: UntaggedValue::Primitive(Primitive::Int(i)),
..
} => Ok(BigInt::from(*i).tagged(tag)),
Value {
value: UntaggedValue::Primitive(Primitive::Filesize(i)),
..
} => Ok(BigInt::from(*i).tagged(tag)),
Value {
value: UntaggedValue::Primitive(Primitive::Duration(i)),
..
} => Ok(BigInt::from(*i).tagged(tag)),
Value { tag, .. } => Err(ShellError::labeled_error(
"Can't convert to integer",
"can't convert to integer",
tag.span,
)),
}
}
}
impl FromValue for num_bigint::BigInt { impl FromValue for num_bigint::BigInt {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
match v { match v {
@ -33,7 +59,7 @@ impl FromValue for num_bigint::BigInt {
Value { Value {
value: UntaggedValue::Primitive(Primitive::Duration(i)), value: UntaggedValue::Primitive(Primitive::Duration(i)),
.. ..
} => Ok(i.clone()), } => Ok(BigInt::from(*i)),
Value { tag, .. } => Err(ShellError::labeled_error( Value { tag, .. } => Err(ShellError::labeled_error(
"Can't convert to integer", "Can't convert to integer",
"can't convert to integer", "can't convert to integer",
@ -56,6 +82,18 @@ impl FromValue for u64 {
} }
} }
impl FromValue for i64 {
fn from_value(v: &Value) -> Result<Self, ShellError> {
v.as_i64()
}
}
impl FromValue for Tagged<i64> {
fn from_value(v: &Value) -> Result<Self, ShellError> {
let tag = v.tag.clone();
v.as_i64().map(|s| s.tagged(tag))
}
}
impl FromValue for Tagged<u32> { impl FromValue for Tagged<u32> {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
let tag = v.tag.clone(); let tag = v.tag.clone();
@ -90,12 +128,6 @@ impl FromValue for usize {
} }
} }
impl FromValue for i64 {
fn from_value(v: &Value) -> Result<Self, ShellError> {
v.as_i64()
}
}
impl FromValue for i32 { impl FromValue for i32 {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
v.as_i32() v.as_i32()
@ -109,6 +141,10 @@ impl FromValue for bigdecimal::BigDecimal {
value: UntaggedValue::Primitive(Primitive::Decimal(d)), value: UntaggedValue::Primitive(Primitive::Decimal(d)),
.. ..
} => Ok(d.clone()), } => Ok(d.clone()),
Value {
value: UntaggedValue::Primitive(Primitive::Int(i)),
..
} => Ok(BigDecimal::from(*i)),
Value { tag, .. } => Err(ShellError::labeled_error( Value { tag, .. } => Err(ShellError::labeled_error(
"Can't convert to decimal", "Can't convert to decimal",
"can't convert to decimal", "can't convert to decimal",
@ -123,6 +159,7 @@ impl FromValue for Tagged<bigdecimal::BigDecimal> {
let tag = v.tag.clone(); let tag = v.tag.clone();
match &v.value { match &v.value {
UntaggedValue::Primitive(Primitive::Decimal(d)) => Ok(d.clone().tagged(tag)), UntaggedValue::Primitive(Primitive::Decimal(d)) => Ok(d.clone().tagged(tag)),
UntaggedValue::Primitive(Primitive::Int(i)) => Ok(BigDecimal::from(*i).tagged(tag)),
_ => Err(ShellError::labeled_error( _ => Err(ShellError::labeled_error(
"Can't convert to decimal", "Can't convert to decimal",
"can't convert to decimal", "can't convert to decimal",

View file

@ -1,7 +1,6 @@
mod call_info; mod call_info;
mod command_args; mod command_args;
mod config_holder; mod config_holder;
pub mod deserializer;
pub mod documentation; pub mod documentation;
mod env; mod env;
mod evaluate; mod evaluate;

View file

@ -11,7 +11,7 @@ pub struct CdArgs {
pub struct CopyArgs { pub struct CopyArgs {
pub src: Tagged<PathBuf>, pub src: Tagged<PathBuf>,
pub dst: Tagged<PathBuf>, pub dst: Tagged<PathBuf>,
pub recursive: Tagged<bool>, pub recursive: bool,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -41,10 +41,10 @@ pub struct MkdirArgs {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct RemoveArgs { pub struct RemoveArgs {
pub rest: Vec<Tagged<PathBuf>>, pub rest: Vec<Tagged<PathBuf>>,
pub recursive: Tagged<bool>, pub recursive: bool,
#[allow(unused)] #[allow(unused)]
pub trash: Tagged<bool>, pub trash: bool,
#[allow(unused)] #[allow(unused)]
pub permanent: Tagged<bool>, pub permanent: bool,
pub force: Tagged<bool>, pub force: bool,
} }

View file

@ -422,6 +422,20 @@ impl Number {
)), )),
} }
} }
pub fn to_u64(&self) -> Result<u64, ShellError> {
match self {
Number::BigInt(bi) => match bi.to_u64() {
Some(i) => Ok(i),
None => Err(ShellError::untagged_runtime_error(
"Cannot convert bigint to u64, too large",
)),
},
Number::Int(i) => Ok(*i as u64),
Number::Decimal(_) => Err(ShellError::untagged_runtime_error(
"Cannont convert decimal to u64",
)),
}
}
} }
impl PrettyDebug for Number { impl PrettyDebug for Number {
@ -573,21 +587,21 @@ impl Unit {
Unit::Tebibyte => filesize(size * 1024 * 1024 * 1024 * 1024), Unit::Tebibyte => filesize(size * 1024 * 1024 * 1024 * 1024),
Unit::Pebibyte => filesize(size * 1024 * 1024 * 1024 * 1024 * 1024), Unit::Pebibyte => filesize(size * 1024 * 1024 * 1024 * 1024 * 1024),
Unit::Nanosecond => duration(size.to_bigint().expect("Conversion should never fail.")), Unit::Nanosecond => duration(size.to_i64().expect("Conversion should never fail.")),
Unit::Microsecond => { Unit::Microsecond => {
duration(size.to_bigint().expect("Conversion should never fail.") * 1000) duration(size.to_i64().expect("Conversion should never fail.") * 1000)
} }
Unit::Millisecond => { Unit::Millisecond => {
duration(size.to_bigint().expect("Conversion should never fail.") * 1000 * 1000) duration(size.to_i64().expect("Conversion should never fail.") * 1000 * 1000)
}
Unit::Second => {
duration(size.to_i64().expect("Conversion should never fail.") * 1000 * 1000 * 1000)
} }
Unit::Second => duration(
size.to_bigint().expect("Conversion should never fail.") * 1000 * 1000 * 1000,
),
Unit::Minute => duration( Unit::Minute => duration(
size.to_bigint().expect("Conversion should never fail.") * 60 * 1000 * 1000 * 1000, size.to_i64().expect("Conversion should never fail.") * 60 * 1000 * 1000 * 1000,
), ),
Unit::Hour => duration( Unit::Hour => duration(
size.to_bigint().expect("Conversion should never fail.") size.to_i64().expect("Conversion should never fail.")
* 60 * 60
* 60 * 60
* 1000 * 1000
@ -595,7 +609,7 @@ impl Unit {
* 1000, * 1000,
), ),
Unit::Day => duration( Unit::Day => duration(
size.to_bigint().expect("Conversion should never fail.") size.to_i64().expect("Conversion should never fail.")
* 24 * 24
* 60 * 60
* 60 * 60
@ -604,7 +618,7 @@ impl Unit {
* 1000, * 1000,
), ),
Unit::Week => duration( Unit::Week => duration(
size.to_bigint().expect("Conversion should never fail.") size.to_i64().expect("Conversion should never fail.")
* 7 * 7
* 24 * 24
* 60 * 60
@ -632,7 +646,7 @@ pub fn filesize(size_in_bytes: Number) -> UntaggedValue {
} }
} }
pub fn duration(nanos: BigInt) -> UntaggedValue { pub fn duration(nanos: i64) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Duration(nanos)) UntaggedValue::Primitive(Primitive::Duration(nanos))
} }

View file

@ -250,8 +250,8 @@ impl UntaggedValue {
} }
/// Helper for creating date duration values /// Helper for creating date duration values
pub fn duration(nanos: impl Into<BigInt>) -> UntaggedValue { pub fn duration(nanos: i64) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Duration(nanos.into())) UntaggedValue::Primitive(Primitive::Duration(nanos))
} }
/// Helper for creating datatime values /// Helper for creating datatime values
@ -369,10 +369,10 @@ impl Value {
} }
} }
/// View the Value as a Duration (BigInt), if possible /// View the Value as a Duration (i64), if possible
pub fn as_duration(&self) -> Result<BigInt, ShellError> { pub fn as_duration(&self) -> Result<i64, ShellError> {
match &self.value { match &self.value {
UntaggedValue::Primitive(Primitive::Duration(dur)) => Ok(dur.clone()), UntaggedValue::Primitive(Primitive::Duration(dur)) => Ok(*dur),
_ => Err(ShellError::type_error("bigint", self.spanned_type_name())), _ => Err(ShellError::type_error("bigint", self.spanned_type_name())),
} }
} }
@ -818,51 +818,10 @@ impl StrExt for &str {
} }
} }
pub trait U64Ext {
fn to_untagged_value(&self) -> UntaggedValue;
fn to_value(&self, tag: Tag) -> Value;
fn to_value_create_tag(&self) -> Value;
fn to_duration_untagged_value(&self) -> UntaggedValue;
fn to_duration_value(&self, tag: Tag) -> Value;
}
impl U64Ext for u64 {
fn to_value(&self, the_tag: Tag) -> Value {
Value {
value: UntaggedValue::Primitive(Primitive::Int(*self as i64)),
tag: the_tag,
}
}
fn to_duration_value(&self, the_tag: Tag) -> Value {
Value {
value: UntaggedValue::Primitive(Primitive::Duration(BigInt::from(*self))),
tag: the_tag,
}
}
fn to_value_create_tag(&self) -> Value {
let end = self.to_string().len();
Value {
value: UntaggedValue::Primitive(Primitive::Int(*self as i64)),
tag: Tag {
anchor: None,
span: Span::new(0, end),
},
}
}
fn to_untagged_value(&self) -> UntaggedValue {
UntaggedValue::int(*self as i64)
}
fn to_duration_untagged_value(&self) -> UntaggedValue {
UntaggedValue::duration(BigInt::from(*self))
}
}
pub trait I64Ext { pub trait I64Ext {
fn to_untagged_value(&self) -> UntaggedValue; fn to_untagged_value(&self) -> UntaggedValue;
fn to_duration_value(&self, tag: Tag) -> Value;
fn to_duration_untagged_value(&self) -> UntaggedValue;
fn to_value(&self, tag: Tag) -> Value; fn to_value(&self, tag: Tag) -> Value;
fn to_value_create_tag(&self) -> Value; fn to_value_create_tag(&self) -> Value;
} }
@ -875,6 +834,17 @@ impl I64Ext for i64 {
} }
} }
fn to_duration_value(&self, the_tag: Tag) -> Value {
Value {
value: UntaggedValue::Primitive(Primitive::Duration(*self)),
tag: the_tag,
}
}
fn to_duration_untagged_value(&self) -> UntaggedValue {
UntaggedValue::duration(*self)
}
fn to_value_create_tag(&self) -> Value { fn to_value_create_tag(&self) -> Value {
let end = self.to_string().len(); let end = self.to_string().len();
Value { Value {

View file

@ -45,8 +45,7 @@ pub enum Primitive {
/// A date value /// A date value
Date(DateTime<FixedOffset>), Date(DateTime<FixedOffset>),
/// A count in the number of nanoseconds /// A count in the number of nanoseconds
#[serde(with = "serde_bigint")] Duration(i64),
Duration(BigInt),
/// A range of values /// A range of values
Range(Box<Range>), Range(Box<Range>),
/// A file path /// A file path
@ -172,6 +171,7 @@ impl Primitive {
"converting a decimal into a signed 64-bit integer", "converting a decimal into a signed 64-bit integer",
) )
}), }),
Primitive::Duration(duration) => Ok(*duration),
other => Err(ShellError::type_error( other => Err(ShellError::type_error(
"number", "number",
other.type_name().spanned(span), other.type_name().spanned(span),
@ -277,7 +277,7 @@ impl Primitive {
match self { match self {
Primitive::Duration(duration) => { Primitive::Duration(duration) => {
// Divide into seconds because BigInt can be larger than i64 // Divide into seconds because BigInt can be larger than i64
let (secs, nanos) = duration.div_rem(&BigInt::from(NANOS_PER_SEC)); let (secs, nanos) = duration.div_rem(&(NANOS_PER_SEC as i64));
let secs = match secs.to_i64() { let secs = match secs.to_i64() {
Some(secs) => secs, Some(secs) => secs,
None => { None => {
@ -396,7 +396,7 @@ impl From<chrono::Duration> for Primitive {
.expect("Unexpected overflow") .expect("Unexpected overflow")
.num_nanoseconds() .num_nanoseconds()
.expect("Unexpected overflow") as u32; .expect("Unexpected overflow") as u32;
Primitive::Duration(BigInt::from(secs) * NANOS_PER_SEC + nanos) Primitive::Duration(secs * NANOS_PER_SEC as i64 + nanos as i64)
} }
} }
@ -513,24 +513,20 @@ pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> S
} }
/// Format a duration in nanoseconds into a string /// Format a duration in nanoseconds into a string
pub fn format_duration(duration: &BigInt) -> String { pub fn format_duration(duration: &i64) -> String {
let is_zero = duration.is_zero(); let is_zero = duration.is_zero();
// FIXME: This involves a lot of allocation, but it seems inevitable with BigInt.
let big_int_1000 = BigInt::from(1000);
let big_int_60 = BigInt::from(60);
let big_int_24 = BigInt::from(24);
// We only want the biggest subdivision to have the negative sign. // We only want the biggest subdivision to have the negative sign.
let (sign, duration) = if duration.is_zero() || duration.is_positive() { let (sign, duration) = if duration.is_zero() || duration.is_positive() {
(1, duration.clone()) (1, *duration)
} else { } else {
(-1, -duration) (-1, -duration)
}; };
let (micros, nanos): (BigInt, BigInt) = duration.div_rem(&big_int_1000); let (micros, nanos): (i64, i64) = duration.div_rem(&1000);
let (millis, micros): (BigInt, BigInt) = micros.div_rem(&big_int_1000); let (millis, micros): (i64, i64) = micros.div_rem(&1000);
let (secs, millis): (BigInt, BigInt) = millis.div_rem(&big_int_1000); let (secs, millis): (i64, i64) = millis.div_rem(&1000);
let (mins, secs): (BigInt, BigInt) = secs.div_rem(&big_int_60); let (mins, secs): (i64, i64) = secs.div_rem(&60);
let (hours, mins): (BigInt, BigInt) = mins.div_rem(&big_int_60); let (hours, mins): (i64, i64) = mins.div_rem(&60);
let (days, hours): (BigInt, BigInt) = hours.div_rem(&big_int_24); let (days, hours): (i64, i64) = hours.div_rem(&24);
let mut output_prep = vec![]; let mut output_prep = vec![];

View file

@ -350,10 +350,7 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
serde_json::Number::from(b.to_u64().expect("What about really big numbers")), serde_json::Number::from(b.to_u64().expect("What about really big numbers")),
), ),
UntaggedValue::Primitive(Primitive::Duration(i)) => { UntaggedValue::Primitive(Primitive::Duration(i)) => {
serde_json::Value::Number(serde_json::Number::from(CoerceInto::<i64>::coerce_into( serde_json::Value::Number(serde_json::Number::from(*i))
i.tagged(&v.tag),
"converting to JSON number",
)?))
} }
UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()), UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()),
UntaggedValue::Primitive(Primitive::EndOfStream) => serde_json::Value::Null, UntaggedValue::Primitive(Primitive::EndOfStream) => serde_json::Value::Null,

View file

@ -135,7 +135,7 @@ pub fn host(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
} }
dict.insert_untagged( dict.insert_untagged(
"uptime", "uptime",
UntaggedValue::duration(1000000000 * sys.get_uptime()), UntaggedValue::duration(1000000000 * sys.get_uptime() as i64),
); );
let mut users = vec![]; let mut users = vec![];

View file

@ -898,31 +898,6 @@ fn table_with_commas() {
assert_eq!(actual.out, "141"); assert_eq!(actual.out, "141");
} }
#[test]
fn duration_overflow() {
let actual = nu!(
cwd: ".", pipeline(
r#"
ls | get modified | each { $it + 10000000000000000day }
"#)
);
assert!(actual.err.contains("Duration overflow"));
}
#[test]
fn date_and_duration_overflow() {
let actual = nu!(
cwd: ".", pipeline(
r#"
ls | get modified | each { $it + 1000000000day }
"#)
);
// assert_eq!(actual.err, "overflow");
assert!(actual.err.contains("Duration and date addition overflow"));
}
mod parse { mod parse {
use nu_test_support::nu; use nu_test_support::nu;