mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Finish removing arg deserialization (#3552)
* WIP remove process * WIP * WIP * Finish removing arg deserialization
This commit is contained in:
parent
fcd94efbd6
commit
131b5b56d7
73 changed files with 483 additions and 1216 deletions
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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(_),
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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())),
|
||||||
}?;
|
}?;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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))
|
||||||
})
|
})
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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![];
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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![];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue