mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +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_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Arguments {
|
||||
value: Value,
|
||||
}
|
||||
|
||||
pub struct Command;
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
|
@ -28,11 +23,12 @@ impl WholeStreamCommand for Command {
|
|||
}
|
||||
|
||||
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![];
|
||||
|
||||
if let Some(first) = input.next() {
|
||||
if let Some(first) = args.input.next() {
|
||||
value.tag = first.tag();
|
||||
prepend.push(first);
|
||||
}
|
||||
|
@ -50,7 +46,7 @@ impl WholeStreamCommand for Command {
|
|||
|
||||
Ok(prepend
|
||||
.into_iter()
|
||||
.chain(input.into_iter().chain(vec![value]))
|
||||
.chain(args.input.into_iter().chain(vec![value]))
|
||||
.to_output_stream())
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,11 @@ use rand::{
|
|||
distributions::Alphanumeric,
|
||||
prelude::{thread_rng, Rng},
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::Instant;
|
||||
|
||||
pub struct Benchmark;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug)]
|
||||
struct BenchmarkArgs {
|
||||
block: CapturedBlock,
|
||||
passthrough: Option<CapturedBlock>,
|
||||
|
@ -113,7 +112,7 @@ fn benchmark(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||
{
|
||||
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);
|
||||
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>(
|
||||
indexmap: IndexMap<String, BigInt>,
|
||||
indexmap: IndexMap<String, i64>,
|
||||
block_output: Output,
|
||||
passthrough: Option<CapturedBlock>,
|
||||
tag: T,
|
||||
|
@ -206,13 +205,6 @@ fn add_implicit_autoview(mut block: Arc<Block>) -> Arc<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 {
|
||||
let mut thread_rng = thread_rng();
|
||||
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> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_engine::{shell::CopyArgs, WholeStreamCommand};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
|
||||
|
@ -28,7 +28,13 @@ impl WholeStreamCommand for Cpy {
|
|||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let shell_manager = args.shell_manager();
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
|||
|
||||
pub struct Debug;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DebugArgs {
|
||||
raw: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Debug {
|
||||
fn name(&self) -> &str {
|
||||
"debug"
|
||||
|
@ -29,7 +24,10 @@ impl WholeStreamCommand for Debug {
|
|||
}
|
||||
|
||||
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
|
||||
.map(move |v| {
|
||||
if raw {
|
||||
|
|
|
@ -5,12 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
|||
use nu_source::Tagged;
|
||||
use nu_value_ext::ValueExt;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultArgs {
|
||||
column: Tagged<String>,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
pub struct Default;
|
||||
|
||||
impl WholeStreamCommand for Default {
|
||||
|
@ -46,7 +40,11 @@ impl WholeStreamCommand for Default {
|
|||
}
|
||||
|
||||
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
|
||||
.map(move |item| {
|
||||
|
|
|
@ -88,7 +88,17 @@ fn du(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
let ctrl_c = args.ctrl_c();
|
||||
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| {
|
||||
Pattern::new(&x.item)
|
||||
.map(Option::Some)
|
||||
|
|
|
@ -10,11 +10,6 @@ use nu_protocol::{
|
|||
use crate::utils::arguments::arguments;
|
||||
use nu_value_ext::{as_string, ValueExt};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rest: Vec<Value>,
|
||||
}
|
||||
|
||||
pub struct 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 name_tag = Arc::new(args.call_info.name_tag.clone());
|
||||
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>>) =
|
||||
arguments(&mut rest)?;
|
||||
let input = args.input;
|
||||
let default_block = Arc::new(default_block);
|
||||
|
||||
if input.is_empty() {
|
||||
|
|
|
@ -2,16 +2,9 @@ use crate::prelude::*;
|
|||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Every;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct EveryArgs {
|
||||
stride: Tagged<u64>,
|
||||
skip: Tagged<bool>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Every {
|
||||
fn name(&self) -> &str {
|
||||
"every"
|
||||
|
@ -63,10 +56,11 @@ impl WholeStreamCommand for Every {
|
|||
}
|
||||
|
||||
fn every(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let (EveryArgs { stride, skip }, input) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
|
||||
let stride = stride.item;
|
||||
let skip = skip.item;
|
||||
let stride: u64 = args.req(0)?;
|
||||
let skip: bool = args.has_flag("skip");
|
||||
let input = args.input;
|
||||
|
||||
Ok(input
|
||||
.enumerate()
|
||||
|
|
|
@ -57,7 +57,12 @@ fn exec(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
use std::process::Command;
|
||||
|
||||
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);
|
||||
for tagged_arg in args.rest {
|
||||
|
|
|
@ -6,11 +6,6 @@ use nu_source::Tagged;
|
|||
|
||||
pub struct First;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct FirstArgs {
|
||||
rows: Option<Tagged<usize>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for First {
|
||||
fn name(&self) -> &str {
|
||||
"first"
|
||||
|
@ -52,7 +47,10 @@ impl WholeStreamCommand for First {
|
|||
}
|
||||
|
||||
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 {
|
||||
*quantity
|
||||
} else {
|
||||
|
|
|
@ -8,11 +8,6 @@ use nu_source::Tagged;
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"flatten"
|
||||
|
@ -53,7 +48,9 @@ impl WholeStreamCommand for Command {
|
|||
|
||||
fn flatten(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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
|
||||
.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;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rest: Vec<Value>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"get"
|
||||
|
@ -55,7 +50,10 @@ impl WholeStreamCommand for Command {
|
|||
}
|
||||
|
||||
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)?;
|
||||
|
||||
if column_paths.is_empty() {
|
||||
|
|
|
@ -7,12 +7,6 @@ use nu_source::Tagged;
|
|||
|
||||
pub struct GroupByDate;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GroupByDateArgs {
|
||||
column_name: Option<Tagged<String>>,
|
||||
format: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for GroupByDate {
|
||||
fn name(&self) -> &str {
|
||||
"group-by date"
|
||||
|
@ -60,14 +54,11 @@ enum GroupByColumn {
|
|||
|
||||
pub fn group_by_date(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
let (
|
||||
GroupByDateArgs {
|
||||
column_name,
|
||||
format,
|
||||
},
|
||||
input,
|
||||
) = args.process()?;
|
||||
let values: Vec<Value> = input.collect();
|
||||
let args = args.evaluate_once()?;
|
||||
let column_name: Option<Tagged<String>> = args.opt(0)?;
|
||||
let format: Option<Tagged<String>> = args.get_flag("format")?;
|
||||
|
||||
let values: Vec<Value> = args.input.collect();
|
||||
|
||||
if values.is_empty() {
|
||||
Err(ShellError::labeled_error(
|
||||
|
|
|
@ -13,11 +13,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct Help;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct HelpArgs {
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Help {
|
||||
fn name(&self) -> &str {
|
||||
"help"
|
||||
|
@ -39,7 +34,9 @@ impl WholeStreamCommand for Help {
|
|||
fn help(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.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[0].item == "commands" {
|
||||
|
|
|
@ -5,11 +5,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
|||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Arguments {
|
||||
clear: Option<bool>,
|
||||
}
|
||||
|
||||
pub struct History;
|
||||
|
||||
impl WholeStreamCommand for History {
|
||||
|
@ -33,7 +28,9 @@ impl WholeStreamCommand for History {
|
|||
fn history(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
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 {
|
||||
nu_data::config::path::history_path_or_default(global_cfg)
|
||||
|
@ -41,31 +38,26 @@ fn history(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
nu_data::config::path::default_history_path()
|
||||
};
|
||||
|
||||
match clear {
|
||||
Some(_) => {
|
||||
// This is a NOOP, the logic to clear is handled in cli.rs
|
||||
Ok(ActionStream::empty())
|
||||
}
|
||||
None => {
|
||||
if let Ok(file) = File::open(path) {
|
||||
let reader = BufReader::new(file);
|
||||
// Skips the first line, which is a Rustyline internal
|
||||
let output = reader.lines().skip(1).filter_map(move |line| match line {
|
||||
Ok(line) => Some(ReturnSuccess::value(
|
||||
UntaggedValue::string(line).into_value(tag.clone()),
|
||||
)),
|
||||
Err(_) => None,
|
||||
});
|
||||
if clear {
|
||||
// This is a NOOP, the logic to clear is handled in cli.rs
|
||||
Ok(ActionStream::empty())
|
||||
} else if let Ok(file) = File::open(path) {
|
||||
let reader = BufReader::new(file);
|
||||
// Skips the first line, which is a Rustyline internal
|
||||
let output = reader.lines().skip(1).filter_map(move |line| match line {
|
||||
Ok(line) => Some(ReturnSuccess::value(
|
||||
UntaggedValue::string(line).into_value(tag.clone()),
|
||||
)),
|
||||
Err(_) => None,
|
||||
});
|
||||
|
||||
Ok(output.to_action_stream())
|
||||
} else {
|
||||
Err(ShellError::labeled_error(
|
||||
"Could not open history",
|
||||
"history file could not be opened",
|
||||
tag,
|
||||
))
|
||||
}
|
||||
}
|
||||
Ok(output.to_action_stream())
|
||||
} else {
|
||||
Err(ShellError::labeled_error(
|
||||
"Could not open history",
|
||||
"history file could not be opened",
|
||||
tag,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
column: ColumnPath,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"insert"
|
||||
|
@ -158,9 +152,13 @@ fn process_row(
|
|||
})
|
||||
}
|
||||
|
||||
fn insert(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||
let (Arguments { column, value }, input) = raw_args.process()?;
|
||||
fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let context = Arc::new(EvaluationContext::from_args(&args));
|
||||
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 column = Arc::new(column);
|
||||
|
||||
|
|
|
@ -7,15 +7,6 @@ use std::process::{Command, Stdio};
|
|||
|
||||
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 {
|
||||
fn name(&self) -> &str {
|
||||
"kill"
|
||||
|
@ -74,20 +65,18 @@ impl WholeStreamCommand for Kill {
|
|||
}
|
||||
|
||||
fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let (
|
||||
KillArgs {
|
||||
pid,
|
||||
rest,
|
||||
force,
|
||||
quiet,
|
||||
signal,
|
||||
},
|
||||
..,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
|
||||
let pid: Tagged<u64> = args.req(0)?;
|
||||
let rest: Vec<Tagged<u64>> = args.rest(1)?;
|
||||
let force: Option<Tagged<bool>> = args.get_flag("force")?;
|
||||
let quiet: bool = args.has_flag("quiet");
|
||||
let signal: Option<Tagged<u32>> = args.get_flag("signal")?;
|
||||
|
||||
let mut cmd = if cfg!(windows) {
|
||||
let mut cmd = Command::new("taskkill");
|
||||
|
||||
if *force {
|
||||
if matches!(force, Some(Tagged { item: true, .. })) {
|
||||
cmd.arg("/F");
|
||||
}
|
||||
|
||||
|
@ -105,14 +94,14 @@ fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
} else {
|
||||
let mut cmd = Command::new("kill");
|
||||
|
||||
if *force {
|
||||
if matches!(force, Some(Tagged { item: true, .. })) {
|
||||
if let Some(signal_value) = signal {
|
||||
return Err(ShellError::labeled_error_with_secondary(
|
||||
"mixing force and signal options is not supported",
|
||||
"signal option",
|
||||
signal_value.tag(),
|
||||
"force option",
|
||||
force.tag(),
|
||||
force.expect("internal error: expected value").tag(),
|
||||
));
|
||||
}
|
||||
cmd.arg("-9");
|
||||
|
@ -128,7 +117,7 @@ fn kill(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
};
|
||||
|
||||
// pipe everything to null
|
||||
if *quiet {
|
||||
if quiet {
|
||||
cmd.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
|
|
|
@ -6,11 +6,6 @@ use nu_protocol::{Signature, UntaggedValue, Value};
|
|||
|
||||
pub struct Length;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LengthArgs {
|
||||
column: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Length {
|
||||
fn name(&self) -> &str {
|
||||
"length"
|
||||
|
@ -30,7 +25,9 @@ impl WholeStreamCommand for Length {
|
|||
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
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 {
|
||||
column,
|
||||
|
|
|
@ -51,7 +51,10 @@ pub fn set_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
let tag = args.call_info.name_tag.clone();
|
||||
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) = {
|
||||
if rhs.block.block.len() != 1 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_engine::{shell::LsArgs, WholeStreamCommand};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
|
||||
|
@ -43,7 +43,16 @@ impl WholeStreamCommand for Ls {
|
|||
let name = args.call_info.name_tag.clone();
|
||||
let ctrl_c = args.ctrl_c();
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ impl WholeStreamCommand for SubCommand {
|
|||
UntaggedValue::decimal(val.abs()).into()
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Duration(val)) => {
|
||||
UntaggedValue::duration(val.magnitude().clone()).into()
|
||||
UntaggedValue::duration(val).into()
|
||||
}
|
||||
other => abs_default(other),
|
||||
});
|
||||
|
|
|
@ -11,11 +11,6 @@ use nu_protocol::{
|
|||
};
|
||||
pub struct Merge;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MergeArgs {
|
||||
block: CapturedBlock,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Merge {
|
||||
fn name(&self) -> &str {
|
||||
"merge"
|
||||
|
@ -46,11 +41,13 @@ impl WholeStreamCommand for Merge {
|
|||
}
|
||||
}
|
||||
|
||||
fn merge(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let context = EvaluationContext::from_args(&raw_args);
|
||||
let name_tag = raw_args.call_info.name_tag.clone();
|
||||
let (merge_args, input): (MergeArgs, _) = raw_args.process()?;
|
||||
let block = merge_args.block;
|
||||
fn merge(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let context = EvaluationContext::from_args(&args);
|
||||
let name_tag = args.call_info.name_tag.clone();
|
||||
|
||||
let args = args.evaluate_once()?;
|
||||
let block: CapturedBlock = args.req(0)?;
|
||||
let input = args.input;
|
||||
|
||||
context.scope.enter_scope();
|
||||
context.scope.add_vars(&block.captured.entries);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_engine::{shell::MkdirArgs, WholeStreamCommand};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
pub struct Mkdir;
|
||||
|
@ -38,7 +38,12 @@ impl WholeStreamCommand for Mkdir {
|
|||
fn mkdir(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_engine::{shell::MvArgs, WholeStreamCommand};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
|
||||
|
@ -56,7 +56,12 @@ impl WholeStreamCommand for Mv {
|
|||
fn mv(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -4,13 +4,6 @@ use nu_errors::ShellError;
|
|||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NthArgs {
|
||||
row_number: Tagged<u64>,
|
||||
rest: Vec<Tagged<u64>>,
|
||||
skip: bool,
|
||||
}
|
||||
|
||||
pub struct Nth;
|
||||
|
||||
impl WholeStreamCommand for Nth {
|
||||
|
@ -59,14 +52,12 @@ impl WholeStreamCommand for Nth {
|
|||
}
|
||||
|
||||
fn nth(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let (
|
||||
NthArgs {
|
||||
row_number,
|
||||
rest: and_rows,
|
||||
skip,
|
||||
},
|
||||
input,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
|
||||
let row_number: Tagged<u64> = args.req(0)?;
|
||||
let and_rows: Vec<Tagged<u64>> = args.rest(1)?;
|
||||
let skip = args.has_flag("skip");
|
||||
let input = args.input;
|
||||
|
||||
let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect();
|
||||
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> {
|
||||
let scope = args.scope().clone();
|
||||
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 {
|
||||
item: load_path,
|
||||
|
|
|
@ -12,13 +12,6 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
pub struct Open;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct OpenArgs {
|
||||
path: Tagged<PathBuf>,
|
||||
raw: Tagged<bool>,
|
||||
encoding: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Open {
|
||||
fn name(&self) -> &str {
|
||||
"open"
|
||||
|
@ -106,14 +99,10 @@ fn open(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
let name = args.call_info.name_tag.clone();
|
||||
let ctrl_c = args.ctrl_c();
|
||||
|
||||
let (
|
||||
OpenArgs {
|
||||
path,
|
||||
raw,
|
||||
encoding,
|
||||
},
|
||||
_,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
let path: Tagged<PathBuf> = args.req(0)?;
|
||||
let raw = args.has_flag("raw");
|
||||
let encoding: Option<Tagged<String>> = args.get_flag("encoding")?;
|
||||
|
||||
if path.is_dir() {
|
||||
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
|
||||
// AND the user doesn't want the raw output
|
||||
// In these cases, we will collect the Stream
|
||||
let ext = if raw.item {
|
||||
let ext = if raw {
|
||||
None
|
||||
} else {
|
||||
path.extension()
|
||||
|
|
|
@ -52,8 +52,15 @@ impl WholeStreamCommand for Pivot {
|
|||
|
||||
pub fn pivot(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
let (args, input): (PivotArgs, _) = args.process()?;
|
||||
let input = input.into_vec();
|
||||
//let (args, input): (PivotArgs, _) = args.process()?;
|
||||
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);
|
||||
|
||||
|
|
|
@ -3,11 +3,6 @@ use nu_engine::WholeStreamCommand;
|
|||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct PrependArgs {
|
||||
row: Value,
|
||||
}
|
||||
|
||||
pub struct Prepend;
|
||||
|
||||
impl WholeStreamCommand for Prepend {
|
||||
|
@ -46,7 +41,9 @@ impl WholeStreamCommand for Prepend {
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ use nu_parser::ParserScope;
|
|||
use nu_protocol::{
|
||||
hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tagged;
|
||||
use nu_stream::ActionStream;
|
||||
|
||||
pub struct Reduce;
|
||||
|
@ -17,7 +16,7 @@ pub struct Reduce;
|
|||
pub struct ReduceArgs {
|
||||
block: CapturedBlock,
|
||||
fold: Option<Value>,
|
||||
numbered: Tagged<bool>,
|
||||
numbered: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Reduce {
|
||||
|
@ -107,10 +106,17 @@ fn process_row(
|
|||
result
|
||||
}
|
||||
|
||||
fn reduce(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let span = raw_args.call_info.name_tag.span;
|
||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||
let (reduce_args, mut input): (ReduceArgs, _) = raw_args.process()?;
|
||||
fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let span = args.call_info.name_tag.span;
|
||||
let context = Arc::new(EvaluationContext::from_args(&args));
|
||||
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 (ioffset, start) = if !input.is_empty() {
|
||||
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
|
||||
let initial = Ok(InputStream::one(each::make_indexed_item(
|
||||
ioffset - 1,
|
||||
|
|
|
@ -5,11 +5,6 @@ use nu_errors::ShellError;
|
|||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RejectArgs {
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
pub struct Reject;
|
||||
|
||||
impl WholeStreamCommand for Reject {
|
||||
|
@ -40,7 +35,9 @@ impl WholeStreamCommand for Reject {
|
|||
|
||||
fn reject(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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() {
|
||||
return Err(ShellError::labeled_error(
|
||||
"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();
|
||||
|
||||
Ok(input
|
||||
Ok(args
|
||||
.input
|
||||
.map(move |item| ReturnSuccess::value(reject_fields(&item, &fields, &item.tag)))
|
||||
.to_action_stream())
|
||||
}
|
||||
|
|
|
@ -7,12 +7,6 @@ use nu_source::Tagged;
|
|||
|
||||
pub struct Rename;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
column_name: Tagged<String>,
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Rename {
|
||||
fn name(&self) -> &str {
|
||||
"rename"
|
||||
|
@ -63,7 +57,11 @@ impl WholeStreamCommand for Rename {
|
|||
|
||||
pub fn rename(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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]];
|
||||
new_column_names.push(rest);
|
||||
|
||||
|
|
|
@ -65,9 +65,17 @@ impl WholeStreamCommand for Remove {
|
|||
fn rm(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
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(
|
||||
"only one of --permanent and --trash can be used",
|
||||
"conflicting flags",
|
||||
|
|
|
@ -10,11 +10,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"rotate"
|
||||
|
@ -38,9 +33,10 @@ impl WholeStreamCommand for Command {
|
|||
|
||||
pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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 descs = merge_descriptors(&input);
|
||||
let total_descriptors = descs.len();
|
||||
|
|
|
@ -10,11 +10,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct SubCommand;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rest: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"rotate counter-clockwise"
|
||||
|
@ -38,9 +33,10 @@ impl WholeStreamCommand for SubCommand {
|
|||
|
||||
pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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 total_rows = input.len();
|
||||
|
||||
|
|
|
@ -8,14 +8,6 @@ use std::cmp;
|
|||
|
||||
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 {
|
||||
fn name(&self) -> &str {
|
||||
"seq"
|
||||
|
@ -108,15 +100,11 @@ impl WholeStreamCommand for Seq {
|
|||
fn seq(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
|
||||
let (
|
||||
SeqArgs {
|
||||
rest: rest_nums,
|
||||
separator,
|
||||
terminator,
|
||||
widths,
|
||||
},
|
||||
_,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
let rest_nums: Vec<Tagged<f64>> = args.rest(0)?;
|
||||
let separator: Option<Tagged<String>> = args.get_flag("separator")?;
|
||||
let terminator: Option<Tagged<String>> = args.get_flag("terminator")?;
|
||||
let widths = args.has_flag("widths");
|
||||
|
||||
if rest_nums.is_empty() {
|
||||
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();
|
||||
|
||||
run_seq(sep, Some(term), widths.item, rest_nums)
|
||||
run_seq(sep, Some(term), widths, rest_nums)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -3,24 +3,12 @@ use chrono::naive::NaiveDate;
|
|||
use chrono::{Duration, Local};
|
||||
use nu_engine::WholeStreamCommand;
|
||||
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_source::Tagged;
|
||||
|
||||
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 {
|
||||
fn name(&self) -> &str {
|
||||
"seq date"
|
||||
|
@ -35,24 +23,24 @@ impl WholeStreamCommand for SeqDates {
|
|||
Some('s'),
|
||||
)
|
||||
.named(
|
||||
"output_format",
|
||||
"output-format",
|
||||
SyntaxShape::String,
|
||||
"prints dates in this format (defaults to %Y-%m-%d)",
|
||||
Some('o'),
|
||||
)
|
||||
.named(
|
||||
"input_format",
|
||||
"input-format",
|
||||
SyntaxShape::String,
|
||||
"give argument dates in this format (defaults to %Y-%m-%d)",
|
||||
Some('i'),
|
||||
)
|
||||
.named(
|
||||
"begin_date",
|
||||
"begin-date",
|
||||
SyntaxShape::String,
|
||||
"beginning date range",
|
||||
Some('b'),
|
||||
)
|
||||
.named("end_date", SyntaxShape::String, "ending date", Some('e'))
|
||||
.named("end-date", SyntaxShape::String, "ending date", Some('e'))
|
||||
.named(
|
||||
"increment",
|
||||
SyntaxShape::Int,
|
||||
|
@ -134,19 +122,16 @@ impl WholeStreamCommand for SeqDates {
|
|||
fn seq_dates(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let _name = args.call_info.name_tag.clone();
|
||||
|
||||
let (
|
||||
SeqDatesArgs {
|
||||
separator,
|
||||
output_format,
|
||||
input_format,
|
||||
begin_date,
|
||||
end_date,
|
||||
increment,
|
||||
days,
|
||||
reverse,
|
||||
},
|
||||
_,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
|
||||
let separator: Option<Tagged<String>> = args.get_flag("separator")?;
|
||||
let output_format: Option<Tagged<String>> = args.get_flag("output-format")?;
|
||||
let input_format: Option<Tagged<String>> = args.get_flag("input-format")?;
|
||||
let begin_date: Option<Tagged<String>> = args.get_flag("begin-date")?;
|
||||
let end_date: Option<Tagged<String>> = args.get_flag("end-date")?;
|
||||
let increment: Option<Tagged<i64>> = args.get_flag("increment")?;
|
||||
let days: Option<Tagged<i64>> = args.get_flag("days")?;
|
||||
let reverse = args.has_flag("reverse");
|
||||
|
||||
let sep: String = match separator {
|
||||
Some(s) => {
|
||||
|
@ -205,8 +190,8 @@ fn seq_dates(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
};
|
||||
|
||||
let mut rev = false;
|
||||
if *reverse {
|
||||
rev = *reverse;
|
||||
if reverse {
|
||||
rev = reverse;
|
||||
}
|
||||
|
||||
run_seq_dates(sep, outformat, informat, begin, end, inc, day_count, rev)
|
||||
|
|
|
@ -6,11 +6,6 @@ use nu_source::Tagged;
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
rows: Option<Tagged<usize>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"skip"
|
||||
|
@ -41,7 +36,10 @@ impl WholeStreamCommand for Command {
|
|||
}
|
||||
|
||||
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 {
|
||||
*quantity
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnValue, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::{
|
||||
sync::atomic::Ordering,
|
||||
|
@ -13,12 +13,6 @@ const CTRL_C_CHECK_INTERVAL: Duration = Duration::from_millis(100);
|
|||
|
||||
pub struct Sleep;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SleepArgs {
|
||||
pub duration: Tagged<u64>,
|
||||
pub rest: Vec<Tagged<u64>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Sleep {
|
||||
fn name(&self) -> &str {
|
||||
"sleep"
|
||||
|
@ -34,23 +28,28 @@ impl WholeStreamCommand for Sleep {
|
|||
"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 (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)
|
||||
+ rest
|
||||
.iter()
|
||||
.map(|val| Duration::from_nanos(val.item))
|
||||
.sum::<Duration>();
|
||||
let total_dur = Duration::from_nanos(if duration.item > 0 {
|
||||
duration.item as u64
|
||||
} else {
|
||||
0
|
||||
}) + rest
|
||||
.iter()
|
||||
.map(|val| Duration::from_nanos(if val.item > 0 { val.item as u64 } else { 0 }))
|
||||
.sum::<Duration>();
|
||||
|
||||
//SleepHandler::new(total_dur, ctrl_c);
|
||||
// this is necessary because the following 2 commands gave different results:
|
||||
// `echo | sleep 1sec` - nothing
|
||||
// `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() {
|
||||
// Ok(OutputStream::empty())
|
||||
|
@ -92,7 +91,7 @@ impl SleepIterator {
|
|||
}
|
||||
|
||||
impl Iterator for SleepIterator {
|
||||
type Item = ReturnValue;
|
||||
type Item = Value;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let start = Instant::now();
|
||||
|
|
|
@ -8,13 +8,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct SortBy;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SortByArgs {
|
||||
rest: Vec<Tagged<String>>,
|
||||
insensitive: bool,
|
||||
reverse: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for SortBy {
|
||||
fn name(&self) -> &str {
|
||||
"sort-by"
|
||||
|
@ -35,7 +28,7 @@ impl WholeStreamCommand for SortBy {
|
|||
"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)
|
||||
}
|
||||
|
||||
|
@ -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 mut args = args.evaluate_once()?;
|
||||
|
||||
let (
|
||||
SortByArgs {
|
||||
rest,
|
||||
insensitive,
|
||||
reverse,
|
||||
},
|
||||
mut input,
|
||||
) = args.process()?;
|
||||
let mut vec = input.drain_vec();
|
||||
let rest = args.rest(0)?;
|
||||
let insensitive = args.has_flag("insensitive");
|
||||
let reverse = args.has_flag("reverse");
|
||||
let mut vec = args.input.drain_vec();
|
||||
|
||||
sort(&mut vec, &rest, &tag, insensitive)?;
|
||||
|
||||
|
@ -130,7 +119,7 @@ fn sort_by(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||
vec.reverse()
|
||||
}
|
||||
|
||||
Ok((vec.into_iter()).to_action_stream())
|
||||
Ok((vec.into_iter()).to_output_stream())
|
||||
}
|
||||
|
||||
pub fn sort(
|
||||
|
|
|
@ -41,7 +41,8 @@ impl WholeStreamCommand for Source {
|
|||
|
||||
pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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
|
||||
// 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;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SplitColumnArgs {
|
||||
separator: Tagged<String>,
|
||||
rest: Vec<Tagged<String>>,
|
||||
#[serde(rename(deserialize = "collapse-empty"))]
|
||||
collapse_empty: bool,
|
||||
}
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
|
@ -26,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
|
|||
Signature::build("split column")
|
||||
.required(
|
||||
"separator",
|
||||
SyntaxShape::Any,
|
||||
SyntaxShape::String,
|
||||
"the character that denotes what separates columns",
|
||||
)
|
||||
.switch("collapse-empty", "remove empty columns", Some('c'))
|
||||
|
@ -44,14 +36,11 @@ impl WholeStreamCommand for SubCommand {
|
|||
|
||||
fn split_column(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name_span = args.call_info.name_tag.span;
|
||||
let (
|
||||
SplitColumnArgs {
|
||||
separator,
|
||||
rest,
|
||||
collapse_empty,
|
||||
},
|
||||
input,
|
||||
) = args.process()?;
|
||||
let args = args.evaluate_once()?;
|
||||
let separator: Tagged<String> = args.req(0)?;
|
||||
let rest: Vec<Tagged<String>> = args.rest(1)?;
|
||||
let collapse_empty = args.has_flag("collapse-empty");
|
||||
let input = args.input;
|
||||
|
||||
Ok(input
|
||||
.map(move |v| {
|
||||
|
|
|
@ -5,11 +5,6 @@ use nu_errors::ShellError;
|
|||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SplitRowArgs {
|
||||
separator: Tagged<String>,
|
||||
}
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
|
@ -20,7 +15,7 @@ impl WholeStreamCommand for SubCommand {
|
|||
fn signature(&self) -> Signature {
|
||||
Signature::build("split row").required(
|
||||
"separator",
|
||||
SyntaxShape::Any,
|
||||
SyntaxShape::String,
|
||||
"the character that denotes what separates rows",
|
||||
)
|
||||
}
|
||||
|
@ -36,7 +31,11 @@ impl WholeStreamCommand for SubCommand {
|
|||
|
||||
fn split_row(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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
|
||||
.flat_map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
|
|
|
@ -8,11 +8,6 @@ use nu_value_ext::as_string;
|
|||
|
||||
pub struct SplitBy;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SplitByArgs {
|
||||
column_name: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for SplitBy {
|
||||
fn name(&self) -> &str {
|
||||
"split-by"
|
||||
|
@ -37,8 +32,10 @@ impl WholeStreamCommand for SplitBy {
|
|||
|
||||
pub fn split_by(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name = args.call_info.name_tag.clone();
|
||||
let (SplitByArgs { column_name }, input) = args.process()?;
|
||||
let values: Vec<Value> = input.collect();
|
||||
let args = args.evaluate_once()?;
|
||||
let column_name: Option<Tagged<String>> = args.opt(0)?;
|
||||
|
||||
let values: Vec<Value> = args.input.collect();
|
||||
|
||||
if values.len() > 1 || values.is_empty() {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
|
|
@ -29,7 +29,10 @@ impl WholeStreamCommand for TermSize {
|
|||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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();
|
||||
match size {
|
||||
|
|
|
@ -8,12 +8,6 @@ use std::path::PathBuf;
|
|||
|
||||
pub struct Touch;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct TouchArgs {
|
||||
target: Tagged<PathBuf>,
|
||||
rest: Vec<Tagged<PathBuf>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Touch {
|
||||
fn name(&self) -> &str {
|
||||
"touch"
|
||||
|
@ -51,7 +45,9 @@ impl WholeStreamCommand for Touch {
|
|||
}
|
||||
|
||||
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()) {
|
||||
match OpenOptions::new().write(true).create(true).open(&item) {
|
||||
|
|
|
@ -11,12 +11,6 @@ use nu_value_ext::ValueExt;
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
field: ColumnPath,
|
||||
replacement: Value,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"update"
|
||||
|
@ -178,10 +172,15 @@ fn process_row(
|
|||
})
|
||||
}
|
||||
|
||||
fn update(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name_tag = Arc::new(raw_args.call_info.name_tag.clone());
|
||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||
let (Arguments { field, replacement }, input) = raw_args.process()?;
|
||||
fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let name_tag = Arc::new(args.call_info.name_tag.clone());
|
||||
let context = Arc::new(EvaluationContext::from_args(&args));
|
||||
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 field = Arc::new(field);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use url::Url;
|
||||
|
||||
use super::{operate, DefaultArguments};
|
||||
use super::operate;
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct UrlHost;
|
||||
|
||||
|
@ -23,7 +23,10 @@ impl WholeStreamCommand for UrlHost {
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,6 @@ pub use path::UrlPath;
|
|||
pub use query::UrlQuery;
|
||||
pub use scheme::UrlScheme;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
fn handle_value<F>(action: &F, v: &Value) -> Result<Value, ShellError>
|
||||
where
|
||||
F: Fn(&Url) -> &str + Send + 'static,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use url::Url;
|
||||
|
||||
use super::{operate, DefaultArguments};
|
||||
use super::operate;
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct UrlPath;
|
||||
|
||||
|
@ -23,7 +23,10 @@ impl WholeStreamCommand for UrlPath {
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use url::Url;
|
||||
|
||||
use super::{operate, DefaultArguments};
|
||||
use super::operate;
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct UrlQuery;
|
||||
|
||||
|
@ -23,7 +23,9 @@ impl WholeStreamCommand for UrlQuery {
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use url::Url;
|
||||
|
||||
use super::{operate, DefaultArguments};
|
||||
use super::operate;
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct UrlScheme;
|
||||
|
||||
|
@ -22,8 +22,9 @@ impl WholeStreamCommand for UrlScheme {
|
|||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let (DefaultArguments { rest }, input) = args.process()?;
|
||||
Ok(operate(input, rest, &Url::scheme))
|
||||
let args = args.evaluate_once()?;
|
||||
let rest: Vec<ColumnPath> = args.rest(0)?;
|
||||
Ok(operate(args.input, rest, &Url::scheme))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
|
|
|
@ -10,11 +10,6 @@ use nu_protocol::{
|
|||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
block: CapturedBlock,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"where"
|
||||
|
@ -61,10 +56,13 @@ impl WholeStreamCommand for Command {
|
|||
]
|
||||
}
|
||||
}
|
||||
fn where_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||
let tag = raw_args.call_info.name_tag.clone();
|
||||
let (Arguments { block }, input) = raw_args.process()?;
|
||||
fn where_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let context = Arc::new(EvaluationContext::from_args(&args));
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let args = args.evaluate_once()?;
|
||||
|
||||
let block: CapturedBlock = args.req(0)?;
|
||||
|
||||
let condition = {
|
||||
if block.block.block.len() != 1 {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
@ -97,7 +95,7 @@ fn where_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||
Ok(WhereIterator {
|
||||
condition,
|
||||
context,
|
||||
input,
|
||||
input: args.input,
|
||||
block,
|
||||
}
|
||||
.to_output_stream())
|
||||
|
|
|
@ -67,10 +67,12 @@ impl WholeStreamCommand for WithEnv {
|
|||
}
|
||||
}
|
||||
|
||||
fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||
let context = EvaluationContext::from_args(&raw_args);
|
||||
let (WithEnvArgs { variable, block }, input) = raw_args.process()?;
|
||||
fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let external_redirection = args.call_info.args.external_redirection;
|
||||
let context = EvaluationContext::from_args(&args);
|
||||
let args = args.evaluate_once()?;
|
||||
let variable: Value = args.req(0)?;
|
||||
let block: CapturedBlock = args.req(1)?;
|
||||
|
||||
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_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();
|
||||
|
||||
result.map(|x| x.to_action_stream())
|
||||
|
|
|
@ -9,11 +9,6 @@ const DEFAULT_COLUMN_NAME: &str = "Column";
|
|||
|
||||
pub struct Wrap;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct WrapArgs {
|
||||
column: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Wrap {
|
||||
fn name(&self) -> &str {
|
||||
"wrap"
|
||||
|
@ -78,11 +73,13 @@ impl WholeStreamCommand for Wrap {
|
|||
}
|
||||
|
||||
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 are_all_rows = true;
|
||||
|
||||
for value in input {
|
||||
for value in args.input {
|
||||
match value {
|
||||
Value {
|
||||
value: UntaggedValue::Row(_),
|
||||
|
|
|
@ -28,10 +28,11 @@ impl WholeStreamCommand for Command {
|
|||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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 input: Vec<Value> = input.collect();
|
||||
let input: Vec<Value> = args.input.collect();
|
||||
|
||||
if let Some(first) = input.get(0) {
|
||||
base_value = first.clone()
|
||||
|
|
|
@ -3,16 +3,8 @@ use nu_errors::ShellError;
|
|||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use nu_source::{AnchorLocation, Tag};
|
||||
use nu_stream::ActionStream;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
pub struct Command;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Arguments {
|
||||
path: Option<bool>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"stub open"
|
||||
|
@ -29,11 +21,11 @@ impl WholeStreamCommand for Command {
|
|||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
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");
|
||||
|
||||
if let Some(true) = mocked_path {
|
||||
if mocked_path {
|
||||
Ok(ActionStream::one(Ok(ReturnSuccess::Value(Value {
|
||||
value: out,
|
||||
tag: Tag {
|
||||
|
|
|
@ -77,7 +77,7 @@ pub enum CompareValues {
|
|||
Decimals(BigDecimal, BigDecimal),
|
||||
String(String, String),
|
||||
Date(DateTime<FixedOffset>, DateTime<FixedOffset>),
|
||||
DateDuration(DateTime<FixedOffset>, BigInt),
|
||||
DateDuration(DateTime<FixedOffset>, i64),
|
||||
Booleans(bool, bool),
|
||||
}
|
||||
|
||||
|
@ -92,11 +92,9 @@ impl CompareValues {
|
|||
CompareValues::Date(left, right) => left.cmp(right),
|
||||
CompareValues::DateDuration(left, right) => {
|
||||
// FIXME: Not sure if I could do something better with the Span.
|
||||
let duration = Primitive::into_chrono_duration(
|
||||
Primitive::Duration(right.clone()),
|
||||
Span::unknown(),
|
||||
)
|
||||
.expect("Could not convert nushell Duration into chrono Duration.");
|
||||
let duration =
|
||||
Primitive::into_chrono_duration(Primitive::Duration(*right), Span::unknown())
|
||||
.expect("Could not convert nushell Duration into chrono Duration.");
|
||||
let right: DateTime<FixedOffset> = Utc::now()
|
||||
.checked_sub_signed(duration)
|
||||
.expect("Data overflow")
|
||||
|
@ -160,7 +158,7 @@ pub fn coerce_compare_primitive(
|
|||
(Nothing, Nothing) => CompareValues::Booleans(true, true),
|
||||
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(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), Nothing) => CompareValues::Booleans(*left, false),
|
||||
(Nothing, Boolean(right)) => CompareValues::Booleans(false, *right),
|
||||
|
|
|
@ -33,7 +33,7 @@ pub enum InlineShape {
|
|||
GlobPattern(String),
|
||||
Boolean(bool),
|
||||
Date(DateTime<FixedOffset>),
|
||||
Duration(BigInt),
|
||||
Duration(i64),
|
||||
FilePath(PathBuf),
|
||||
Binary(usize),
|
||||
|
||||
|
@ -94,7 +94,7 @@ impl InlineShape {
|
|||
Primitive::GlobPattern(pattern) => InlineShape::GlobPattern(pattern.clone()),
|
||||
Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean),
|
||||
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::Binary(b) => InlineShape::Binary(b.len()),
|
||||
Primitive::BeginningOfStream => InlineShape::BeginningOfStream,
|
||||
|
@ -304,10 +304,9 @@ impl PrettyDebug for FormatInlineShape {
|
|||
.to_owned(),
|
||||
),
|
||||
InlineShape::Date(date) => DbgDocBldr::primitive(nu_protocol::format_date(date)),
|
||||
InlineShape::Duration(duration) => DbgDocBldr::description(format_primitive(
|
||||
&Primitive::Duration(duration.clone()),
|
||||
None,
|
||||
)),
|
||||
InlineShape::Duration(duration) => {
|
||||
DbgDocBldr::description(format_primitive(&Primitive::Duration(*duration), None))
|
||||
}
|
||||
InlineShape::FilePath(path) => DbgDocBldr::primitive(path.display()),
|
||||
InlineShape::Binary(length) => {
|
||||
DbgDocBldr::opaque(format!("<binary: {} bytes>", length))
|
||||
|
|
|
@ -475,8 +475,13 @@ pub fn compute_values(
|
|||
if y.is_zero() {
|
||||
return Ok(zero_division_error());
|
||||
}
|
||||
|
||||
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())),
|
||||
}?;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::deserializer::ConfigDeserializer;
|
||||
use crate::env::host::Host;
|
||||
use crate::evaluate::scope::Scope;
|
||||
use crate::evaluation_context::EvaluationContext;
|
||||
|
@ -13,7 +12,6 @@ use nu_protocol::{CallInfo, Value};
|
|||
use nu_source::Tag;
|
||||
use nu_stream::InputStream;
|
||||
use parking_lot::Mutex;
|
||||
use serde::Deserialize;
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
@ -79,14 +77,14 @@ impl CommandArgs {
|
|||
Ok((f(&evaluated_args.args)?, evaluated_args.input))
|
||||
}
|
||||
|
||||
pub fn process<'de, T: Deserialize<'de>>(self) -> Result<(T, InputStream), ShellError> {
|
||||
let args = self.evaluate_once()?;
|
||||
let call_info = args.call_info.clone();
|
||||
// pub fn process<'de, T: Deserialize<'de>>(self) -> Result<(T, InputStream), ShellError> {
|
||||
// let args = self.evaluate_once()?;
|
||||
// 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 {
|
||||
|
|
|
@ -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()));
|
||||
|
||||
if any_source_is_dir && !recursive.item {
|
||||
if any_source_is_dir && !recursive {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Directories must be copied using \"--recursive\"",
|
||||
"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 \
|
||||
built with feature `trash_support`.",
|
||||
));
|
||||
} else if _trash.item {
|
||||
} else if _trash {
|
||||
return Err(ShellError::labeled_error(
|
||||
"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",
|
||||
_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(
|
||||
"No valid paths",
|
||||
"no valid paths",
|
||||
|
@ -715,7 +715,7 @@ impl Shell for FilesystemShell {
|
|||
|
||||
if metadata.is_file()
|
||||
|| metadata.file_type().is_symlink()
|
||||
|| recursive.item
|
||||
|| recursive
|
||||
|| is_socket
|
||||
|| is_fifo
|
||||
|| is_empty()
|
||||
|
@ -724,7 +724,7 @@ impl Shell for FilesystemShell {
|
|||
#[cfg(feature = "trash-support")]
|
||||
{
|
||||
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| {
|
||||
Error::new(ErrorKind::Other, format!("{:?}", e))
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use bigdecimal::ToPrimitive;
|
||||
use bigdecimal::{BigDecimal, ToPrimitive};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use nu_errors::ShellError;
|
||||
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 {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
match v {
|
||||
|
@ -33,7 +59,7 @@ impl FromValue for num_bigint::BigInt {
|
|||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Duration(i)),
|
||||
..
|
||||
} => Ok(i.clone()),
|
||||
} => Ok(BigInt::from(*i)),
|
||||
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||
"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> {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
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 {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
v.as_i32()
|
||||
|
@ -109,6 +141,10 @@ impl FromValue for bigdecimal::BigDecimal {
|
|||
value: UntaggedValue::Primitive(Primitive::Decimal(d)),
|
||||
..
|
||||
} => Ok(d.clone()),
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(i)),
|
||||
..
|
||||
} => Ok(BigDecimal::from(*i)),
|
||||
Value { tag, .. } => Err(ShellError::labeled_error(
|
||||
"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();
|
||||
match &v.value {
|
||||
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(
|
||||
"Can't convert to decimal",
|
||||
"can't convert to decimal",
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
mod call_info;
|
||||
mod command_args;
|
||||
mod config_holder;
|
||||
pub mod deserializer;
|
||||
pub mod documentation;
|
||||
mod env;
|
||||
mod evaluate;
|
||||
|
|
|
@ -11,7 +11,7 @@ pub struct CdArgs {
|
|||
pub struct CopyArgs {
|
||||
pub src: Tagged<PathBuf>,
|
||||
pub dst: Tagged<PathBuf>,
|
||||
pub recursive: Tagged<bool>,
|
||||
pub recursive: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -41,10 +41,10 @@ pub struct MkdirArgs {
|
|||
#[derive(Deserialize)]
|
||||
pub struct RemoveArgs {
|
||||
pub rest: Vec<Tagged<PathBuf>>,
|
||||
pub recursive: Tagged<bool>,
|
||||
pub recursive: bool,
|
||||
#[allow(unused)]
|
||||
pub trash: Tagged<bool>,
|
||||
pub trash: bool,
|
||||
#[allow(unused)]
|
||||
pub permanent: Tagged<bool>,
|
||||
pub force: Tagged<bool>,
|
||||
pub permanent: 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 {
|
||||
|
@ -573,21 +587,21 @@ impl Unit {
|
|||
Unit::Tebibyte => filesize(size * 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 => {
|
||||
duration(size.to_bigint().expect("Conversion should never fail.") * 1000)
|
||||
duration(size.to_i64().expect("Conversion should never fail.") * 1000)
|
||||
}
|
||||
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(
|
||||
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(
|
||||
size.to_bigint().expect("Conversion should never fail.")
|
||||
size.to_i64().expect("Conversion should never fail.")
|
||||
* 60
|
||||
* 60
|
||||
* 1000
|
||||
|
@ -595,7 +609,7 @@ impl Unit {
|
|||
* 1000,
|
||||
),
|
||||
Unit::Day => duration(
|
||||
size.to_bigint().expect("Conversion should never fail.")
|
||||
size.to_i64().expect("Conversion should never fail.")
|
||||
* 24
|
||||
* 60
|
||||
* 60
|
||||
|
@ -604,7 +618,7 @@ impl Unit {
|
|||
* 1000,
|
||||
),
|
||||
Unit::Week => duration(
|
||||
size.to_bigint().expect("Conversion should never fail.")
|
||||
size.to_i64().expect("Conversion should never fail.")
|
||||
* 7
|
||||
* 24
|
||||
* 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))
|
||||
}
|
||||
|
||||
|
|
|
@ -250,8 +250,8 @@ impl UntaggedValue {
|
|||
}
|
||||
|
||||
/// Helper for creating date duration values
|
||||
pub fn duration(nanos: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Duration(nanos.into()))
|
||||
pub fn duration(nanos: i64) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Duration(nanos))
|
||||
}
|
||||
|
||||
/// Helper for creating datatime values
|
||||
|
@ -369,10 +369,10 @@ impl Value {
|
|||
}
|
||||
}
|
||||
|
||||
/// View the Value as a Duration (BigInt), if possible
|
||||
pub fn as_duration(&self) -> Result<BigInt, ShellError> {
|
||||
/// View the Value as a Duration (i64), if possible
|
||||
pub fn as_duration(&self) -> Result<i64, ShellError> {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
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_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 {
|
||||
let end = self.to_string().len();
|
||||
Value {
|
||||
|
|
|
@ -45,8 +45,7 @@ pub enum Primitive {
|
|||
/// A date value
|
||||
Date(DateTime<FixedOffset>),
|
||||
/// A count in the number of nanoseconds
|
||||
#[serde(with = "serde_bigint")]
|
||||
Duration(BigInt),
|
||||
Duration(i64),
|
||||
/// A range of values
|
||||
Range(Box<Range>),
|
||||
/// A file path
|
||||
|
@ -172,6 +171,7 @@ impl Primitive {
|
|||
"converting a decimal into a signed 64-bit integer",
|
||||
)
|
||||
}),
|
||||
Primitive::Duration(duration) => Ok(*duration),
|
||||
other => Err(ShellError::type_error(
|
||||
"number",
|
||||
other.type_name().spanned(span),
|
||||
|
@ -277,7 +277,7 @@ impl Primitive {
|
|||
match self {
|
||||
Primitive::Duration(duration) => {
|
||||
// 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() {
|
||||
Some(secs) => secs,
|
||||
None => {
|
||||
|
@ -396,7 +396,7 @@ impl From<chrono::Duration> for Primitive {
|
|||
.expect("Unexpected overflow")
|
||||
.num_nanoseconds()
|
||||
.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
|
||||
pub fn format_duration(duration: &BigInt) -> String {
|
||||
pub fn format_duration(duration: &i64) -> String {
|
||||
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.
|
||||
let (sign, duration) = if duration.is_zero() || duration.is_positive() {
|
||||
(1, duration.clone())
|
||||
(1, *duration)
|
||||
} else {
|
||||
(-1, -duration)
|
||||
};
|
||||
let (micros, nanos): (BigInt, BigInt) = duration.div_rem(&big_int_1000);
|
||||
let (millis, micros): (BigInt, BigInt) = micros.div_rem(&big_int_1000);
|
||||
let (secs, millis): (BigInt, BigInt) = millis.div_rem(&big_int_1000);
|
||||
let (mins, secs): (BigInt, BigInt) = secs.div_rem(&big_int_60);
|
||||
let (hours, mins): (BigInt, BigInt) = mins.div_rem(&big_int_60);
|
||||
let (days, hours): (BigInt, BigInt) = hours.div_rem(&big_int_24);
|
||||
let (micros, nanos): (i64, i64) = duration.div_rem(&1000);
|
||||
let (millis, micros): (i64, i64) = micros.div_rem(&1000);
|
||||
let (secs, millis): (i64, i64) = millis.div_rem(&1000);
|
||||
let (mins, secs): (i64, i64) = secs.div_rem(&60);
|
||||
let (hours, mins): (i64, i64) = mins.div_rem(&60);
|
||||
let (days, hours): (i64, i64) = hours.div_rem(&24);
|
||||
|
||||
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")),
|
||||
),
|
||||
UntaggedValue::Primitive(Primitive::Duration(i)) => {
|
||||
serde_json::Value::Number(serde_json::Number::from(CoerceInto::<i64>::coerce_into(
|
||||
i.tagged(&v.tag),
|
||||
"converting to JSON number",
|
||||
)?))
|
||||
serde_json::Value::Number(serde_json::Number::from(*i))
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()),
|
||||
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(
|
||||
"uptime",
|
||||
UntaggedValue::duration(1000000000 * sys.get_uptime()),
|
||||
UntaggedValue::duration(1000000000 * sys.get_uptime() as i64),
|
||||
);
|
||||
|
||||
let mut users = vec![];
|
||||
|
|
|
@ -898,31 +898,6 @@ fn table_with_commas() {
|
|||
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 {
|
||||
use nu_test_support::nu;
|
||||
|
||||
|
|
Loading…
Reference in a new issue