mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 10:45:41 +02:00
Merge remote-tracking branch 'upstream/master' into range
This commit is contained in:
74
src/cli.rs
74
src/cli.rs
@ -1,27 +1,19 @@
|
||||
use crate::commands::classified::{
|
||||
ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalArg, ExternalArgs,
|
||||
ExternalCommand, InternalCommand,
|
||||
};
|
||||
use crate::commands::classified::pipeline::run_pipeline;
|
||||
use crate::commands::classified::ClassifiedInputStream;
|
||||
use crate::commands::plugin::JsonRpc;
|
||||
use crate::commands::plugin::{PluginCommand, PluginSink};
|
||||
use crate::commands::whole_stream_command;
|
||||
use crate::context::Context;
|
||||
use crate::data::{
|
||||
base::{UntaggedValue, Value},
|
||||
config,
|
||||
};
|
||||
pub(crate) use crate::errors::ShellError;
|
||||
use crate::data::config;
|
||||
#[cfg(not(feature = "starship-prompt"))]
|
||||
use crate::git::current_branch;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::parser::{
|
||||
hir,
|
||||
hir::syntax_shape::{expand_syntax, ExpandContext, PipelineShape},
|
||||
hir::{expand_external_tokens::ExternalTokensShape, tokens_iterator::TokensIterator},
|
||||
TokenNode,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use nu_source::{Spanned, Tagged};
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::{
|
||||
expand_syntax, hir, ClassifiedCommand, ClassifiedPipeline, InternalCommand, PipelineShape,
|
||||
TokenNode, TokensIterator,
|
||||
};
|
||||
use nu_protocol::{Signature, UntaggedValue, Value};
|
||||
|
||||
use log::{debug, log_enabled, trace};
|
||||
use rustyline::error::ReadlineError;
|
||||
@ -32,21 +24,6 @@ use std::iter::Iterator;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MaybeOwned<'a, T> {
|
||||
Owned(T),
|
||||
Borrowed(&'a T),
|
||||
}
|
||||
|
||||
impl<T> MaybeOwned<'_, T> {
|
||||
pub fn borrow(&self) -> &T {
|
||||
match self {
|
||||
MaybeOwned::Owned(v) => v,
|
||||
MaybeOwned::Borrowed(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), ShellError> {
|
||||
let mut child = std::process::Command::new(path)
|
||||
.stdin(std::process::Stdio::piped())
|
||||
@ -572,7 +549,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||
Ok(line) => {
|
||||
let line = chomp_newline(line);
|
||||
|
||||
let result = match crate::parser::parse(&line) {
|
||||
let result = match nu_parser::parse(&line) {
|
||||
Err(err) => {
|
||||
return LineResult::Error(line.to_string(), err);
|
||||
}
|
||||
@ -610,7 +587,8 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||
set_env_from_config();
|
||||
|
||||
let input = ClassifiedInputStream::new();
|
||||
match pipeline.run(ctx, input, line).await {
|
||||
|
||||
match run_pipeline(pipeline, ctx, input, line).await {
|
||||
Ok(_) => LineResult::Success(line.to_string()),
|
||||
Err(err) => LineResult::Error(line.to_string(), err),
|
||||
}
|
||||
@ -648,39 +626,13 @@ fn classify_pipeline(
|
||||
result
|
||||
}
|
||||
|
||||
// Classify this command as an external command, which doesn't give special meaning
|
||||
// to nu syntactic constructs, and passes all arguments to the external command as
|
||||
// strings.
|
||||
pub(crate) fn external_command(
|
||||
tokens: &mut TokensIterator,
|
||||
context: &ExpandContext,
|
||||
name: Tagged<&str>,
|
||||
) -> Result<ClassifiedCommand, ParseError> {
|
||||
let Spanned { item, span } = expand_syntax(&ExternalTokensShape, tokens, context)?.tokens;
|
||||
|
||||
Ok(ClassifiedCommand::External(ExternalCommand {
|
||||
name: name.to_string(),
|
||||
name_tag: name.tag(),
|
||||
args: ExternalArgs {
|
||||
list: item
|
||||
.iter()
|
||||
.map(|x| ExternalArg {
|
||||
tag: x.span.into(),
|
||||
arg: x.item.clone(),
|
||||
})
|
||||
.collect(),
|
||||
span,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn print_err(err: ShellError, host: &dyn Host, source: &Text) {
|
||||
let diag = err.to_diagnostic();
|
||||
|
||||
let writer = host.err_termcolor();
|
||||
let mut source = source.to_string();
|
||||
source.push_str(" ");
|
||||
let files = crate::parser::Files::new(source);
|
||||
let files = nu_parser::Files::new(source);
|
||||
let _ = std::panic::catch_unwind(move || {
|
||||
let _ = language_reporting::emit(
|
||||
&mut writer.lock(),
|
||||
|
@ -100,7 +100,6 @@ pub(crate) use command::{
|
||||
};
|
||||
|
||||
pub(crate) use append::Append;
|
||||
pub(crate) use classified::ClassifiedCommand;
|
||||
pub(crate) use compact::Compact;
|
||||
pub(crate) use config::Config;
|
||||
pub(crate) use count::Count;
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AppendArgs {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::data::Value;
|
||||
use nu_protocol::Value;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogLevel {}
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::commands::{RawCommandArgs, WholeStreamCommand};
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::{Expression, NamedArguments};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use futures::stream::TryStreamExt;
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::hir::{Expression, NamedArguments};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub struct Autoview;
|
||||
@ -137,7 +139,7 @@ pub fn autoview(
|
||||
} if anchor.is_some() => {
|
||||
if let Some(text) = text {
|
||||
let mut stream = VecDeque::new();
|
||||
stream.push_back(UntaggedValue::string(s).into_value(Tag { anchor, span }));
|
||||
stream.push_back(value::string(s).into_value(Tag { anchor, span }));
|
||||
let result = text.run(raw.with_input(stream.into()), &context.commands);
|
||||
result.collect::<Vec<_>>().await;
|
||||
} else {
|
||||
@ -150,6 +152,43 @@ pub fn autoview(
|
||||
} => {
|
||||
outln!("{}", s);
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Line(ref s)),
|
||||
tag: Tag { anchor, span },
|
||||
} if anchor.is_some() => {
|
||||
if let Some(text) = text {
|
||||
let mut stream = VecDeque::new();
|
||||
stream.push_back(value::string(s).into_value(Tag { anchor, span }));
|
||||
let result = text.run(raw.with_input(stream.into()), &context.commands);
|
||||
result.collect::<Vec<_>>().await;
|
||||
} else {
|
||||
outln!("{}\n", s);
|
||||
}
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Line(s)),
|
||||
..
|
||||
} => {
|
||||
outln!("{}\n", s);
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Path(s)),
|
||||
..
|
||||
} => {
|
||||
outln!("{}", s.display());
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(n)),
|
||||
..
|
||||
} => {
|
||||
outln!("{}", n);
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Decimal(n)),
|
||||
..
|
||||
} => {
|
||||
outln!("{}", n);
|
||||
}
|
||||
|
||||
Value { value: UntaggedValue::Primitive(Primitive::Binary(ref b)), .. } => {
|
||||
if let Some(binary) = binary {
|
||||
@ -188,7 +227,7 @@ pub fn autoview(
|
||||
|
||||
// Needed for async_stream to type check
|
||||
if false {
|
||||
yield ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value());
|
||||
yield ReturnSuccess::value(value::nothing().into_untagged_value());
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
|
||||
pub struct CD;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::parser::hir;
|
||||
use derive_new::new;
|
||||
use nu_parser::hir;
|
||||
|
||||
#[derive(new, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct Command {
|
||||
|
@ -1,12 +1,16 @@
|
||||
use super::ClassifiedInputStream;
|
||||
use crate::prelude::*;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::stream::StreamExt;
|
||||
use futures_codec::{Decoder, Encoder, Framed};
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::ExternalCommand;
|
||||
use nu_protocol::Value;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use subprocess::Exec;
|
||||
|
||||
use super::ClassifiedInputStream;
|
||||
|
||||
/// A simple `Codec` implementation that splits up data into lines.
|
||||
pub struct LinesCodec {}
|
||||
|
||||
@ -21,7 +25,7 @@ impl Encoder for LinesCodec {
|
||||
}
|
||||
|
||||
impl Decoder for LinesCodec {
|
||||
type Item = String;
|
||||
type Item = nu_protocol::UntaggedValue;
|
||||
type Error = Error;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
@ -29,12 +33,14 @@ impl Decoder for LinesCodec {
|
||||
Some(pos) if !src.is_empty() => {
|
||||
let buf = src.split_to(pos + 1);
|
||||
String::from_utf8(buf.to_vec())
|
||||
.map(value::line)
|
||||
.map(Some)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
||||
}
|
||||
_ if !src.is_empty() => {
|
||||
let drained = src.take();
|
||||
String::from_utf8(drained.to_vec())
|
||||
.map(value::string)
|
||||
.map(Some)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
||||
}
|
||||
@ -43,36 +49,6 @@ impl Decoder for LinesCodec {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Command {
|
||||
pub(crate) name: String,
|
||||
|
||||
pub(crate) name_tag: Tag,
|
||||
pub(crate) args: ExternalArgs,
|
||||
}
|
||||
|
||||
impl HasSpan for Command {
|
||||
fn span(&self) -> Span {
|
||||
self.name_tag.span.until(self.args.span)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for Command {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
b::typed(
|
||||
"external command",
|
||||
b::description(&self.name)
|
||||
+ b::preceded(
|
||||
b::space(),
|
||||
b::intersperse(
|
||||
self.args.iter().map(|a| b::primitive(format!("{}", a.arg))),
|
||||
b::space(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum StreamNext {
|
||||
Last,
|
||||
@ -80,196 +56,155 @@ pub(crate) enum StreamNext {
|
||||
Internal,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub(crate) async fn run(
|
||||
self,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
stream_next: StreamNext,
|
||||
) -> Result<ClassifiedInputStream, ShellError> {
|
||||
let stdin = input.stdin;
|
||||
let inputs: Vec<Value> = input.objects.into_vec().await;
|
||||
pub(crate) async fn run_external_command(
|
||||
command: ExternalCommand,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
stream_next: StreamNext,
|
||||
) -> Result<ClassifiedInputStream, ShellError> {
|
||||
let stdin = input.stdin;
|
||||
let inputs: Vec<Value> = input.objects.into_vec().await;
|
||||
|
||||
trace!(target: "nu::run::external", "-> {}", self.name);
|
||||
trace!(target: "nu::run::external", "inputs = {:?}", inputs);
|
||||
trace!(target: "nu::run::external", "-> {}", command.name);
|
||||
trace!(target: "nu::run::external", "inputs = {:?}", inputs);
|
||||
|
||||
let mut arg_string = format!("{}", self.name);
|
||||
for arg in &self.args.list {
|
||||
arg_string.push_str(&arg);
|
||||
}
|
||||
let mut arg_string = format!("{}", command.name);
|
||||
for arg in command.args.iter() {
|
||||
arg_string.push_str(&arg);
|
||||
}
|
||||
|
||||
let home_dir = dirs::home_dir();
|
||||
let home_dir = dirs::home_dir();
|
||||
|
||||
trace!(target: "nu::run::external", "command = {:?}", self.name);
|
||||
trace!(target: "nu::run::external", "command = {:?}", command.name);
|
||||
|
||||
let mut process;
|
||||
if arg_string.contains("$it") {
|
||||
let input_strings = inputs
|
||||
.iter()
|
||||
.map(|i| {
|
||||
i.as_string().map_err(|_| {
|
||||
let arg = self.args.iter().find(|arg| arg.arg.contains("$it"));
|
||||
if let Some(arg) = arg {
|
||||
ShellError::labeled_error(
|
||||
"External $it needs string data",
|
||||
"given row instead of string data",
|
||||
&arg.tag,
|
||||
)
|
||||
} else {
|
||||
ShellError::labeled_error(
|
||||
"$it needs string data",
|
||||
"given something else",
|
||||
self.name_tag.clone(),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<String>, ShellError>>()?;
|
||||
|
||||
let commands = input_strings.iter().map(|i| {
|
||||
let args = self.args.iter().filter_map(|arg| {
|
||||
if arg.chars().all(|c| c.is_whitespace()) {
|
||||
None
|
||||
let mut process;
|
||||
if arg_string.contains("$it") {
|
||||
let input_strings = inputs
|
||||
.iter()
|
||||
.map(|i| {
|
||||
i.as_string().map(|s| s.to_string()).map_err(|_| {
|
||||
let arg = command.args.iter().find(|arg| arg.contains("$it"));
|
||||
if let Some(arg) = arg {
|
||||
ShellError::labeled_error(
|
||||
"External $it needs string data",
|
||||
"given row instead of string data",
|
||||
&arg.tag,
|
||||
)
|
||||
} else {
|
||||
// Let's also replace ~ as we shell out
|
||||
let arg = if let Some(ref home_dir) = home_dir {
|
||||
arg.replace("~", home_dir.to_str().unwrap())
|
||||
} else {
|
||||
arg.replace("~", "~")
|
||||
};
|
||||
|
||||
Some(arg.replace("$it", &i))
|
||||
ShellError::labeled_error(
|
||||
"$it needs string data",
|
||||
"given something else",
|
||||
command.name_tag.clone(),
|
||||
)
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<String>, ShellError>>()?;
|
||||
|
||||
format!("{} {}", self.name, itertools::join(args, " "))
|
||||
let commands = input_strings.iter().map(|i| {
|
||||
let args = command.args.iter().filter_map(|arg| {
|
||||
if arg.chars().all(|c| c.is_whitespace()) {
|
||||
None
|
||||
} else {
|
||||
// Let's also replace ~ as we shell out
|
||||
let arg = if let Some(ref home_dir) = home_dir {
|
||||
arg.replace("~", home_dir.to_str().unwrap())
|
||||
} else {
|
||||
arg.replace("~", "~")
|
||||
};
|
||||
|
||||
Some(arg.replace("$it", &i))
|
||||
}
|
||||
});
|
||||
|
||||
process = Exec::shell(itertools::join(commands, " && "))
|
||||
} else {
|
||||
process = Exec::cmd(&self.name);
|
||||
for arg in &self.args.list {
|
||||
// Let's also replace ~ as we shell out
|
||||
let arg = if let Some(ref home_dir) = home_dir {
|
||||
arg.replace("~", home_dir.to_str().unwrap())
|
||||
} else {
|
||||
arg.replace("~", "~")
|
||||
};
|
||||
format!("{} {}", command.name, itertools::join(args, " "))
|
||||
});
|
||||
|
||||
let arg_chars: Vec<_> = arg.chars().collect();
|
||||
if arg_chars.len() > 1
|
||||
&& arg_chars[0] == '"'
|
||||
&& arg_chars[arg_chars.len() - 1] == '"'
|
||||
{
|
||||
// quoted string
|
||||
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
|
||||
process = process.arg(new_arg);
|
||||
} else {
|
||||
process = process.arg(arg.clone());
|
||||
}
|
||||
process = Exec::shell(itertools::join(commands, " && "))
|
||||
} else {
|
||||
process = Exec::cmd(&command.name);
|
||||
for arg in command.args.iter() {
|
||||
// Let's also replace ~ as we shell out
|
||||
let arg = if let Some(ref home_dir) = home_dir {
|
||||
arg.replace("~", home_dir.to_str().unwrap())
|
||||
} else {
|
||||
arg.replace("~", "~")
|
||||
};
|
||||
|
||||
let arg_chars: Vec<_> = arg.chars().collect();
|
||||
if arg_chars.len() > 1 && arg_chars[0] == '"' && arg_chars[arg_chars.len() - 1] == '"' {
|
||||
// quoted string
|
||||
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
|
||||
process = process.arg(new_arg);
|
||||
} else {
|
||||
process = process.arg(arg.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process = process.cwd(context.shell_manager.path());
|
||||
process = process.cwd(context.shell_manager.path());
|
||||
|
||||
trace!(target: "nu::run::external", "cwd = {:?}", context.shell_manager.path());
|
||||
trace!(target: "nu::run::external", "cwd = {:?}", context.shell_manager.path());
|
||||
|
||||
let mut process = match stream_next {
|
||||
StreamNext::Last => process,
|
||||
StreamNext::External | StreamNext::Internal => {
|
||||
process.stdout(subprocess::Redirection::Pipe)
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "nu::run::external", "set up stdout pipe");
|
||||
|
||||
if let Some(stdin) = stdin {
|
||||
process = process.stdin(stdin);
|
||||
let mut process = match stream_next {
|
||||
StreamNext::Last => process,
|
||||
StreamNext::External | StreamNext::Internal => {
|
||||
process.stdout(subprocess::Redirection::Pipe)
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "nu::run::external", "set up stdin pipe");
|
||||
trace!(target: "nu::run::external", "built process {:?}", process);
|
||||
trace!(target: "nu::run::external", "set up stdout pipe");
|
||||
|
||||
let popen = process.popen();
|
||||
if let Some(stdin) = stdin {
|
||||
process = process.stdin(stdin);
|
||||
}
|
||||
|
||||
trace!(target: "nu::run::external", "next = {:?}", stream_next);
|
||||
trace!(target: "nu::run::external", "set up stdin pipe");
|
||||
trace!(target: "nu::run::external", "built process {:?}", process);
|
||||
|
||||
let name_tag = self.name_tag.clone();
|
||||
if let Ok(mut popen) = popen {
|
||||
match stream_next {
|
||||
StreamNext::Last => {
|
||||
let _ = popen.detach();
|
||||
loop {
|
||||
match popen.poll() {
|
||||
None => {
|
||||
let _ = std::thread::sleep(std::time::Duration::new(0, 100000000));
|
||||
}
|
||||
_ => {
|
||||
let _ = popen.terminate();
|
||||
break;
|
||||
}
|
||||
let popen = process.popen();
|
||||
|
||||
trace!(target: "nu::run::external", "next = {:?}", stream_next);
|
||||
|
||||
let name_tag = command.name_tag.clone();
|
||||
if let Ok(mut popen) = popen {
|
||||
match stream_next {
|
||||
StreamNext::Last => {
|
||||
let _ = popen.detach();
|
||||
loop {
|
||||
match popen.poll() {
|
||||
None => {
|
||||
let _ = std::thread::sleep(std::time::Duration::new(0, 100000000));
|
||||
}
|
||||
_ => {
|
||||
let _ = popen.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(ClassifiedInputStream::new())
|
||||
}
|
||||
StreamNext::External => {
|
||||
let _ = popen.detach();
|
||||
let stdout = popen.stdout.take().unwrap();
|
||||
Ok(ClassifiedInputStream::from_stdout(stdout))
|
||||
}
|
||||
StreamNext::Internal => {
|
||||
let _ = popen.detach();
|
||||
let stdout = popen.stdout.take().unwrap();
|
||||
let file = futures::io::AllowStdIo::new(stdout);
|
||||
let stream = Framed::new(file, LinesCodec {});
|
||||
let stream = stream.map(move |line| {
|
||||
UntaggedValue::string(line.unwrap()).into_value(&name_tag)
|
||||
});
|
||||
Ok(ClassifiedInputStream::from_input_stream(
|
||||
stream.boxed() as BoxStream<'static, Value>
|
||||
))
|
||||
}
|
||||
Ok(ClassifiedInputStream::new())
|
||||
}
|
||||
StreamNext::External => {
|
||||
let _ = popen.detach();
|
||||
let stdout = popen.stdout.take().unwrap();
|
||||
Ok(ClassifiedInputStream::from_stdout(stdout))
|
||||
}
|
||||
StreamNext::Internal => {
|
||||
let _ = popen.detach();
|
||||
let stdout = popen.stdout.take().unwrap();
|
||||
let file = futures::io::AllowStdIo::new(stdout);
|
||||
let stream = Framed::new(file, LinesCodec {});
|
||||
let stream = stream.map(move |line| line.unwrap().into_value(&name_tag));
|
||||
Ok(ClassifiedInputStream::from_input_stream(
|
||||
stream.boxed() as BoxStream<'static, Value>
|
||||
))
|
||||
}
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Command not found",
|
||||
"command not found",
|
||||
name_tag,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ExternalArg {
|
||||
pub arg: String,
|
||||
pub tag: Tag,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ExternalArg {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
&self.arg
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ExternalArgs {
|
||||
pub list: Vec<ExternalArg>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl ExternalArgs {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &ExternalArg> {
|
||||
self.list.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ExternalArgs {
|
||||
type Target = [ExternalArg];
|
||||
|
||||
fn deref(&self) -> &[ExternalArg] {
|
||||
&self.list
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Command not found",
|
||||
"command not found",
|
||||
name_tag,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1,147 +1,129 @@
|
||||
use crate::parser::hir;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use log::{log_enabled, trace};
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::InternalCommand;
|
||||
use nu_protocol::{CommandAction, Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||
|
||||
use super::ClassifiedInputStream;
|
||||
|
||||
#[derive(new, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Command {
|
||||
pub(crate) name: String,
|
||||
pub(crate) name_tag: Tag,
|
||||
pub(crate) args: hir::Call,
|
||||
}
|
||||
|
||||
impl HasSpan for Command {
|
||||
fn span(&self) -> Span {
|
||||
let start = self.name_tag.span;
|
||||
|
||||
start.until(self.args.span)
|
||||
pub(crate) async fn run_internal_command(
|
||||
command: InternalCommand,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
source: Text,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
if log_enabled!(log::Level::Trace) {
|
||||
trace!(target: "nu::run::internal", "->");
|
||||
trace!(target: "nu::run::internal", "{}", command.name);
|
||||
trace!(target: "nu::run::internal", "{}", command.args.debug(&source));
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebugWithSource for Command {
|
||||
fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
|
||||
b::typed(
|
||||
"internal command",
|
||||
b::description(&self.name) + b::space() + self.args.pretty_debug(source),
|
||||
let objects: InputStream =
|
||||
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
|
||||
|
||||
let internal_command = context.expect_command(&command.name);
|
||||
|
||||
let result = {
|
||||
context.run_command(
|
||||
internal_command,
|
||||
command.name_tag.clone(),
|
||||
command.args,
|
||||
&source,
|
||||
objects,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
impl Command {
|
||||
pub(crate) fn run(
|
||||
self,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
source: Text,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
if log_enabled!(log::Level::Trace) {
|
||||
trace!(target: "nu::run::internal", "->");
|
||||
trace!(target: "nu::run::internal", "{}", self.name);
|
||||
trace!(target: "nu::run::internal", "{}", self.args.debug(&source));
|
||||
}
|
||||
let result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
|
||||
let mut result = result.values;
|
||||
let mut context = context.clone();
|
||||
|
||||
let objects: InputStream =
|
||||
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
|
||||
let stream = async_stream! {
|
||||
let mut soft_errs: Vec<ShellError> = vec![];
|
||||
let mut yielded = false;
|
||||
|
||||
let command = context.expect_command(&self.name);
|
||||
|
||||
let result =
|
||||
{ context.run_command(command, self.name_tag.clone(), self.args, &source, objects) };
|
||||
|
||||
let result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
|
||||
let mut result = result.values;
|
||||
let mut context = context.clone();
|
||||
|
||||
let stream = async_stream! {
|
||||
let mut soft_errs: Vec<ShellError> = vec![];
|
||||
let mut yielded = false;
|
||||
|
||||
while let Some(item) = result.next().await {
|
||||
match item {
|
||||
Ok(ReturnSuccess::Action(action)) => match action {
|
||||
CommandAction::ChangePath(path) => {
|
||||
context.shell_manager.set_path(path);
|
||||
}
|
||||
CommandAction::Exit => std::process::exit(0), // TODO: save history.txt
|
||||
CommandAction::Error(err) => {
|
||||
context.error(err);
|
||||
break;
|
||||
}
|
||||
CommandAction::EnterHelpShell(value) => {
|
||||
match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::String(cmd)),
|
||||
tag,
|
||||
} => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
HelpShell::for_command(
|
||||
UntaggedValue::string(cmd).into_value(tag),
|
||||
&context.registry(),
|
||||
).unwrap(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
HelpShell::index(&context.registry()).unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
CommandAction::EnterValueShell(value) => {
|
||||
context
|
||||
.shell_manager
|
||||
.insert_at_current(Box::new(ValueShell::new(value)));
|
||||
}
|
||||
CommandAction::EnterShell(location) => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
FilesystemShell::with_location(location, context.registry().clone()).unwrap(),
|
||||
));
|
||||
}
|
||||
CommandAction::PreviousShell => {
|
||||
context.shell_manager.prev();
|
||||
}
|
||||
CommandAction::NextShell => {
|
||||
context.shell_manager.next();
|
||||
}
|
||||
CommandAction::LeaveShell => {
|
||||
context.shell_manager.remove_at_current();
|
||||
if context.shell_manager.is_empty() {
|
||||
std::process::exit(0); // TODO: save history.txt
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Ok(ReturnSuccess::Value(v)) => {
|
||||
yielded = true;
|
||||
yield Ok(v);
|
||||
while let Some(item) = result.next().await {
|
||||
match item {
|
||||
Ok(ReturnSuccess::Action(action)) => match action {
|
||||
CommandAction::ChangePath(path) => {
|
||||
context.shell_manager.set_path(path);
|
||||
}
|
||||
|
||||
Ok(ReturnSuccess::DebugValue(v)) => {
|
||||
yielded = true;
|
||||
|
||||
let doc = PrettyDebug::pretty_doc(&v);
|
||||
let mut buffer = termcolor::Buffer::ansi();
|
||||
|
||||
doc.render_raw(
|
||||
context.with_host(|host| host.width() - 5),
|
||||
&mut crate::parser::debug::TermColored::new(&mut buffer),
|
||||
).unwrap();
|
||||
|
||||
let value = String::from_utf8_lossy(buffer.as_slice());
|
||||
|
||||
yield Ok(UntaggedValue::string(value).into_untagged_value())
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
CommandAction::Exit => std::process::exit(0), // TODO: save history.txt
|
||||
CommandAction::Error(err) => {
|
||||
context.error(err);
|
||||
break;
|
||||
}
|
||||
CommandAction::EnterHelpShell(value) => {
|
||||
match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::String(cmd)),
|
||||
tag,
|
||||
} => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
HelpShell::for_command(
|
||||
value::string(cmd).into_value(tag),
|
||||
&context.registry(),
|
||||
).unwrap(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
HelpShell::index(&context.registry()).unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
CommandAction::EnterValueShell(value) => {
|
||||
context
|
||||
.shell_manager
|
||||
.insert_at_current(Box::new(ValueShell::new(value)));
|
||||
}
|
||||
CommandAction::EnterShell(location) => {
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
FilesystemShell::with_location(location, context.registry().clone()).unwrap(),
|
||||
));
|
||||
}
|
||||
CommandAction::PreviousShell => {
|
||||
context.shell_manager.prev();
|
||||
}
|
||||
CommandAction::NextShell => {
|
||||
context.shell_manager.next();
|
||||
}
|
||||
CommandAction::LeaveShell => {
|
||||
context.shell_manager.remove_at_current();
|
||||
if context.shell_manager.is_empty() {
|
||||
std::process::exit(0); // TODO: save history.txt
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Ok(ReturnSuccess::Value(v)) => {
|
||||
yielded = true;
|
||||
yield Ok(v);
|
||||
}
|
||||
|
||||
Ok(ReturnSuccess::DebugValue(v)) => {
|
||||
yielded = true;
|
||||
|
||||
let doc = PrettyDebug::pretty_doc(&v);
|
||||
let mut buffer = termcolor::Buffer::ansi();
|
||||
|
||||
doc.render_raw(
|
||||
context.with_host(|host| host.width() - 5),
|
||||
&mut nu_source::TermColored::new(&mut buffer),
|
||||
).unwrap();
|
||||
|
||||
let value = String::from_utf8_lossy(buffer.as_slice());
|
||||
|
||||
yield Ok(value::string(value).into_untagged_value())
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
context.error(err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Ok(stream.to_input_stream())
|
||||
}
|
||||
Ok(stream.to_input_stream())
|
||||
}
|
||||
|
@ -1,17 +1,13 @@
|
||||
use crate::parser::{hir, TokenNode};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
|
||||
mod dynamic;
|
||||
mod external;
|
||||
mod internal;
|
||||
mod pipeline;
|
||||
pub(crate) mod external;
|
||||
pub(crate) mod internal;
|
||||
pub(crate) mod pipeline;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use dynamic::Command as DynamicCommand;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use external::{Command as ExternalCommand, ExternalArg, ExternalArgs, StreamNext};
|
||||
pub(crate) use internal::Command as InternalCommand;
|
||||
pub(crate) use pipeline::Pipeline as ClassifiedPipeline;
|
||||
|
||||
pub(crate) struct ClassifiedInputStream {
|
||||
pub(crate) objects: InputStream,
|
||||
@ -21,7 +17,7 @@ pub(crate) struct ClassifiedInputStream {
|
||||
impl ClassifiedInputStream {
|
||||
pub(crate) fn new() -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: vec![UntaggedValue::nothing().into_untagged_value()].into(),
|
||||
objects: vec![value::nothing().into_value(Tag::unknown())].into(),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
@ -40,35 +36,3 @@ impl ClassifiedInputStream {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum ClassifiedCommand {
|
||||
#[allow(unused)]
|
||||
Expr(TokenNode),
|
||||
#[allow(unused)]
|
||||
Dynamic(hir::Call),
|
||||
Internal(InternalCommand),
|
||||
External(ExternalCommand),
|
||||
}
|
||||
|
||||
impl PrettyDebugWithSource for ClassifiedCommand {
|
||||
fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
|
||||
match self {
|
||||
ClassifiedCommand::Expr(token) => b::typed("command", token.pretty_debug(source)),
|
||||
ClassifiedCommand::Dynamic(call) => b::typed("command", call.pretty_debug(source)),
|
||||
ClassifiedCommand::Internal(internal) => internal.pretty_debug(source),
|
||||
ClassifiedCommand::External(external) => external.pretty_debug(source),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSpan for ClassifiedCommand {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
ClassifiedCommand::Expr(node) => node.span(),
|
||||
ClassifiedCommand::Internal(command) => command.span(),
|
||||
ClassifiedCommand::Dynamic(call) => call.span,
|
||||
ClassifiedCommand::External(command) => command.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,107 +1,74 @@
|
||||
use super::{ClassifiedCommand, ClassifiedInputStream, StreamNext};
|
||||
use crate::data::base::Value;
|
||||
use crate::prelude::*;
|
||||
use crate::commands::classified::external::{run_external_command, StreamNext};
|
||||
use crate::commands::classified::internal::run_internal_command;
|
||||
use crate::commands::classified::ClassifiedInputStream;
|
||||
use crate::context::Context;
|
||||
use crate::stream::OutputStream;
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::{ClassifiedCommand, ClassifiedPipeline};
|
||||
use nu_protocol::{ReturnSuccess, UntaggedValue, Value};
|
||||
use nu_source::Text;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Pipeline {
|
||||
pub(crate) commands: ClassifiedCommands,
|
||||
}
|
||||
pub(crate) async fn run_pipeline(
|
||||
pipeline: ClassifiedPipeline,
|
||||
ctx: &mut Context,
|
||||
mut input: ClassifiedInputStream,
|
||||
line: &str,
|
||||
) -> Result<(), ShellError> {
|
||||
let mut iter = pipeline.commands.list.into_iter().peekable();
|
||||
|
||||
impl Pipeline {
|
||||
pub fn commands(list: Vec<ClassifiedCommand>, span: impl Into<Span>) -> Pipeline {
|
||||
Pipeline {
|
||||
commands: ClassifiedCommands {
|
||||
list,
|
||||
span: span.into(),
|
||||
},
|
||||
}
|
||||
loop {
|
||||
let item: Option<ClassifiedCommand> = iter.next();
|
||||
let next: Option<&ClassifiedCommand> = iter.peek();
|
||||
|
||||
input = match (item, next) {
|
||||
(Some(ClassifiedCommand::Dynamic(_)), _) | (_, Some(ClassifiedCommand::Dynamic(_))) => {
|
||||
return Err(ShellError::unimplemented("Dynamic commands"))
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::Expr(_)), _) | (_, Some(ClassifiedCommand::Expr(_))) => {
|
||||
return Err(ShellError::unimplemented("Expression-only commands"))
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::Internal(left)), _) => {
|
||||
let stream = run_internal_command(left, ctx, input, Text::from(line)).await?;
|
||||
ClassifiedInputStream::from_input_stream(stream)
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), Some(ClassifiedCommand::External(_))) => {
|
||||
run_external_command(left, ctx, input, StreamNext::External).await?
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), Some(_)) => {
|
||||
run_external_command(left, ctx, input, StreamNext::Internal).await?
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), None) => {
|
||||
run_external_command(left, ctx, input, StreamNext::Last).await?
|
||||
}
|
||||
|
||||
(None, _) => break,
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) async fn run(
|
||||
self,
|
||||
ctx: &mut Context,
|
||||
mut input: ClassifiedInputStream,
|
||||
line: &str,
|
||||
) -> Result<(), ShellError> {
|
||||
let mut iter = self.commands.list.into_iter().peekable();
|
||||
|
||||
loop {
|
||||
let item: Option<ClassifiedCommand> = iter.next();
|
||||
let next: Option<&ClassifiedCommand> = iter.peek();
|
||||
|
||||
input = match (item, next) {
|
||||
(Some(ClassifiedCommand::Dynamic(_)), _)
|
||||
| (_, Some(ClassifiedCommand::Dynamic(_))) => {
|
||||
return Err(ShellError::unimplemented("Dynamic commands"))
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::Expr(_)), _) | (_, Some(ClassifiedCommand::Expr(_))) => {
|
||||
return Err(ShellError::unimplemented("Expression-only commands"))
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::Internal(left)), _) => {
|
||||
let stream = left.run(ctx, input, Text::from(line))?;
|
||||
ClassifiedInputStream::from_input_stream(stream)
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), Some(ClassifiedCommand::External(_))) => {
|
||||
left.run(ctx, input, StreamNext::External).await?
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), Some(_)) => {
|
||||
left.run(ctx, input, StreamNext::Internal).await?
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::External(left)), None) => {
|
||||
left.run(ctx, input, StreamNext::Last).await?
|
||||
}
|
||||
|
||||
(None, _) => break,
|
||||
};
|
||||
}
|
||||
|
||||
use futures::stream::TryStreamExt;
|
||||
let mut output_stream: OutputStream = input.objects.into();
|
||||
loop {
|
||||
match output_stream.try_next().await {
|
||||
Ok(Some(ReturnSuccess::Value(Value {
|
||||
value: UntaggedValue::Error(e),
|
||||
..
|
||||
}))) => return Err(e),
|
||||
Ok(Some(_item)) => {
|
||||
if ctx.ctrl_c.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
use futures::stream::TryStreamExt;
|
||||
let mut output_stream: OutputStream = input.objects.into();
|
||||
loop {
|
||||
match output_stream.try_next().await {
|
||||
Ok(Some(ReturnSuccess::Value(Value {
|
||||
value: UntaggedValue::Error(e),
|
||||
..
|
||||
}))) => return Err(e),
|
||||
Ok(Some(_item)) => {
|
||||
if ctx.ctrl_c.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClassifiedCommands {
|
||||
pub list: Vec<ClassifiedCommand>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl HasSpan for Pipeline {
|
||||
fn span(&self) -> Span {
|
||||
self.commands.span
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebugWithSource for Pipeline {
|
||||
fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
|
||||
b::intersperse(
|
||||
self.commands.list.iter().map(|c| c.pretty_debug(source)),
|
||||
b::operator(" | "),
|
||||
)
|
||||
.or(b::delimit("<", b::description("empty pipeline"), ">"))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
pub mod clipboard {
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use futures::stream::StreamExt;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnValue, Signature, Value};
|
||||
|
||||
use clipboard::{ClipboardContext, ClipboardProvider};
|
||||
|
||||
@ -67,7 +68,7 @@ pub mod clipboard {
|
||||
}
|
||||
|
||||
let string: String = match i.as_string() {
|
||||
Ok(string) => string,
|
||||
Ok(string) => string.to_string(),
|
||||
Err(_) => {
|
||||
return OutputStream::one(Err(ShellError::labeled_error(
|
||||
"Given non-string data",
|
||||
|
@ -1,14 +1,14 @@
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::evaluate::Scope;
|
||||
use crate::parser::hir;
|
||||
use crate::parser::{registry, ConfigDeserializer};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::deserializer::ConfigDeserializer;
|
||||
use crate::evaluate::evaluate_args::evaluate_args;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use getset::Getters;
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::hir;
|
||||
use nu_protocol::{CallInfo, EvaluatedArgs, ReturnValue, Scope, Signature, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
@ -21,10 +21,10 @@ pub struct UnevaluatedCallInfo {
|
||||
impl UnevaluatedCallInfo {
|
||||
pub fn evaluate(
|
||||
self,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
scope: &Scope,
|
||||
) -> Result<CallInfo, ShellError> {
|
||||
let args = self.args.evaluate(registry, scope, &self.source)?;
|
||||
let args = evaluate_args(&self.args, registry, scope, &self.source)?;
|
||||
|
||||
Ok(CallInfo {
|
||||
args,
|
||||
@ -33,14 +33,16 @@ impl UnevaluatedCallInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct CallInfo {
|
||||
pub args: registry::EvaluatedArgs,
|
||||
pub name_tag: Tag,
|
||||
pub trait CallInfoExt {
|
||||
fn process<'de, T: Deserialize<'de>>(
|
||||
&self,
|
||||
shell_manager: &ShellManager,
|
||||
callback: fn(T, &RunnablePerItemContext) -> Result<OutputStream, ShellError>,
|
||||
) -> Result<RunnablePerItemArgs<T>, ShellError>;
|
||||
}
|
||||
|
||||
impl CallInfo {
|
||||
pub fn process<'de, T: Deserialize<'de>>(
|
||||
impl CallInfoExt for CallInfo {
|
||||
fn process<'de, T: Deserialize<'de>>(
|
||||
&self,
|
||||
shell_manager: &ShellManager,
|
||||
callback: fn(T, &RunnablePerItemContext) -> Result<OutputStream, ShellError>,
|
||||
@ -87,10 +89,6 @@ impl RawCommandArgs {
|
||||
input: input.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source(&self) -> Text {
|
||||
self.call_info.source.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for CommandArgs {
|
||||
@ -102,7 +100,7 @@ impl std::fmt::Debug for CommandArgs {
|
||||
impl CommandArgs {
|
||||
pub fn evaluate_once(
|
||||
self,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
||||
let host = self.host.clone();
|
||||
let ctrl_c = self.ctrl_c.clone();
|
||||
@ -198,12 +196,6 @@ pub struct RunnablePerItemContext {
|
||||
pub name: Tag,
|
||||
}
|
||||
|
||||
impl RunnablePerItemContext {
|
||||
pub fn cwd(&self) -> PathBuf {
|
||||
PathBuf::from(self.shell_manager.path())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RunnableContext {
|
||||
pub input: InputStream,
|
||||
pub shell_manager: ShellManager,
|
||||
@ -295,7 +287,7 @@ impl EvaluatedWholeStreamCommandArgs {
|
||||
self.args.call_info.name_tag.clone()
|
||||
}
|
||||
|
||||
pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) {
|
||||
pub fn parts(self) -> (InputStream, EvaluatedArgs) {
|
||||
let EvaluatedWholeStreamCommandArgs { args, input } = self;
|
||||
|
||||
(input, args.call_info.args)
|
||||
@ -349,112 +341,19 @@ pub struct EvaluatedCommandArgs {
|
||||
}
|
||||
|
||||
impl EvaluatedCommandArgs {
|
||||
pub fn call_args(&self) -> ®istry::EvaluatedArgs {
|
||||
&self.call_info.args
|
||||
}
|
||||
|
||||
pub fn nth(&self, pos: usize) -> Option<&Value> {
|
||||
self.call_info.args.nth(pos)
|
||||
}
|
||||
|
||||
pub fn expect_nth(&self, pos: usize) -> Result<&Value, ShellError> {
|
||||
self.call_info.args.expect_nth(pos)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.call_info.args.len()
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Option<&Value> {
|
||||
self.call_info.args.get(name)
|
||||
}
|
||||
|
||||
pub fn slice_from(&self, from: usize) -> Vec<Value> {
|
||||
let positional = &self.call_info.args.positional;
|
||||
|
||||
match positional {
|
||||
None => vec![],
|
||||
Some(list) => list[from..].to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has(&self, name: &str) -> bool {
|
||||
self.call_info.args.has(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum CommandAction {
|
||||
ChangePath(String),
|
||||
Exit,
|
||||
Error(ShellError),
|
||||
EnterShell(String),
|
||||
EnterValueShell(Value),
|
||||
EnterHelpShell(Value),
|
||||
PreviousShell,
|
||||
NextShell,
|
||||
LeaveShell,
|
||||
}
|
||||
|
||||
impl PrettyDebug for CommandAction {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
match self {
|
||||
CommandAction::ChangePath(path) => b::typed("change path", b::description(path)),
|
||||
CommandAction::Exit => b::description("exit"),
|
||||
CommandAction::Error(_) => b::error("error"),
|
||||
CommandAction::EnterShell(s) => b::typed("enter shell", b::description(s)),
|
||||
CommandAction::EnterValueShell(v) => b::typed("enter value shell", v.pretty()),
|
||||
CommandAction::EnterHelpShell(v) => b::typed("enter help shell", v.pretty()),
|
||||
CommandAction::PreviousShell => b::description("previous shell"),
|
||||
CommandAction::NextShell => b::description("next shell"),
|
||||
CommandAction::LeaveShell => b::description("leave shell"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ReturnSuccess {
|
||||
Value(Value),
|
||||
DebugValue(Value),
|
||||
Action(CommandAction),
|
||||
}
|
||||
|
||||
impl PrettyDebug for ReturnSuccess {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
match self {
|
||||
ReturnSuccess::Value(value) => b::typed("value", value.pretty()),
|
||||
ReturnSuccess::DebugValue(value) => b::typed("debug value", value.pretty()),
|
||||
ReturnSuccess::Action(action) => b::typed("action", action.pretty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type ReturnValue = Result<ReturnSuccess, ShellError>;
|
||||
|
||||
impl From<Value> for ReturnValue {
|
||||
fn from(input: Value) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(input))
|
||||
}
|
||||
}
|
||||
|
||||
impl ReturnSuccess {
|
||||
pub fn change_cwd(path: String) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Action(CommandAction::ChangePath(path)))
|
||||
}
|
||||
|
||||
pub fn value(input: impl Into<Value>) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(input.into()))
|
||||
}
|
||||
|
||||
pub fn debug_value(input: impl Into<Value>) -> ReturnValue {
|
||||
Ok(ReturnSuccess::DebugValue(input.into()))
|
||||
}
|
||||
|
||||
pub fn action(input: CommandAction) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Action(input))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WholeStreamCommand: Send + Sync {
|
||||
fn name(&self) -> &str;
|
||||
|
||||
@ -474,7 +373,7 @@ pub trait WholeStreamCommand: Send + Sync {
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError>;
|
||||
|
||||
fn is_binary(&self) -> bool {
|
||||
@ -570,7 +469,7 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&self, args: CommandArgs, registry: ®istry::CommandRegistry) -> OutputStream {
|
||||
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
|
||||
match self {
|
||||
Command::WholeStream(command) => match command.run(args, registry) {
|
||||
Ok(stream) => stream,
|
||||
@ -637,7 +536,7 @@ impl WholeStreamCommand for FnFilterCommand {
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let CommandArgs {
|
||||
host,
|
||||
@ -649,7 +548,7 @@ impl WholeStreamCommand for FnFilterCommand {
|
||||
|
||||
let host: Arc<Mutex<dyn Host>> = host.clone();
|
||||
let shell_manager = shell_manager.clone();
|
||||
let registry: registry::CommandRegistry = registry.clone();
|
||||
let registry: CommandRegistry = registry.clone();
|
||||
let func = self.func;
|
||||
|
||||
let result = input.values.map(move |it| {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::UntaggedValue;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use futures::stream::StreamExt;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Compact;
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{config, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::{self};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::config;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -55,7 +55,7 @@ impl WholeStreamCommand for Config {
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, config)?.run()
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use futures::stream::StreamExt;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, Value};
|
||||
|
||||
pub struct Count;
|
||||
|
||||
@ -39,7 +40,7 @@ pub fn count(
|
||||
let stream = async_stream! {
|
||||
let rows: Vec<Value> = input.values.collect().await;
|
||||
|
||||
yield ReturnSuccess::value(UntaggedValue::int(rows.len()).into_value(name))
|
||||
yield ReturnSuccess::value(value::int(rows.len()).into_value(name))
|
||||
};
|
||||
|
||||
Ok(stream.to_output_stream())
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::command::RunnablePerItemContext;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
use crate::data::{Dictionary, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Local, Utc};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Value};
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::data::value;
|
||||
use chrono::{Datelike, TimeZone, Timelike};
|
||||
use core::fmt::Display;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::{Signature, UntaggedValue};
|
||||
|
||||
pub struct Date;
|
||||
|
||||
@ -41,35 +42,23 @@ where
|
||||
{
|
||||
let mut indexmap = IndexMap::new();
|
||||
|
||||
indexmap.insert(
|
||||
"year".to_string(),
|
||||
UntaggedValue::int(dt.year()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"month".to_string(),
|
||||
UntaggedValue::int(dt.month()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"day".to_string(),
|
||||
UntaggedValue::int(dt.day()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"hour".to_string(),
|
||||
UntaggedValue::int(dt.hour()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("year".to_string(), value::int(dt.year()).into_value(&tag));
|
||||
indexmap.insert("month".to_string(), value::int(dt.month()).into_value(&tag));
|
||||
indexmap.insert("day".to_string(), value::int(dt.day()).into_value(&tag));
|
||||
indexmap.insert("hour".to_string(), value::int(dt.hour()).into_value(&tag));
|
||||
indexmap.insert(
|
||||
"minute".to_string(),
|
||||
UntaggedValue::int(dt.minute()).into_value(&tag),
|
||||
value::int(dt.minute()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"second".to_string(),
|
||||
UntaggedValue::int(dt.second()).into_value(&tag),
|
||||
value::int(dt.second()).into_value(&tag),
|
||||
);
|
||||
|
||||
let tz = dt.offset();
|
||||
indexmap.insert(
|
||||
"timezone".to_string(),
|
||||
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
|
||||
value::string(format!("{}", tz)).into_value(&tag),
|
||||
);
|
||||
|
||||
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
|
||||
|
@ -1,5 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature};
|
||||
|
||||
pub struct Debug;
|
||||
|
||||
@ -34,8 +37,6 @@ fn debug_value(
|
||||
) -> Result<impl ToOutputStream, ShellError> {
|
||||
Ok(input
|
||||
.values
|
||||
.map(|v| {
|
||||
ReturnSuccess::value(UntaggedValue::string(format!("{:?}", v)).into_untagged_value())
|
||||
})
|
||||
.map(|v| ReturnSuccess::value(value::string(format!("{:?}", v)).into_untagged_value()))
|
||||
.to_output_stream())
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::parser::registry::Signature;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct Echo;
|
||||
|
||||
@ -42,7 +41,7 @@ fn run(
|
||||
match i.as_string() {
|
||||
Ok(s) => {
|
||||
output.push(Ok(ReturnSuccess::Value(
|
||||
UntaggedValue::string(s).into_value(i.tag.clone()),
|
||||
value::string(s).into_value(i.tag.clone()),
|
||||
)));
|
||||
}
|
||||
_ => match i {
|
||||
|
@ -1,9 +1,12 @@
|
||||
use crate::commands::command::CommandAction;
|
||||
use crate::commands::PerItemCommand;
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, CommandAction, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Enter;
|
||||
@ -13,7 +16,7 @@ impl PerItemCommand for Enter {
|
||||
"enter"
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("enter").required(
|
||||
"location",
|
||||
SyntaxShape::Path,
|
||||
@ -28,7 +31,7 @@ impl PerItemCommand for Enter {
|
||||
fn run(
|
||||
&self,
|
||||
call_info: &CallInfo,
|
||||
registry: ®istry::CommandRegistry,
|
||||
registry: &CommandRegistry,
|
||||
raw_args: &RawCommandArgs,
|
||||
_input: Value,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
@ -51,12 +54,12 @@ impl PerItemCommand for Enter {
|
||||
|
||||
if registry.has(command) {
|
||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
||||
UntaggedValue::string(command).into_value(Tag::unknown()),
|
||||
value::string(command).into_value(Tag::unknown()),
|
||||
)))]
|
||||
.into())
|
||||
} else {
|
||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
||||
UntaggedValue::nothing().into_value(Tag::unknown()),
|
||||
value::nothing().into_value(Tag::unknown()),
|
||||
)))]
|
||||
.into())
|
||||
}
|
||||
@ -93,7 +96,7 @@ impl PerItemCommand for Enter {
|
||||
ctrl_c: raw_args.ctrl_c,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
|
@ -1,12 +1,11 @@
|
||||
use crate::cli::History;
|
||||
use crate::data::config;
|
||||
use crate::data::{Dictionary, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::{config, value};
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedDictBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Signature, UntaggedValue, Value};
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::registry::Signature;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub struct Env;
|
||||
@ -37,39 +36,24 @@ pub fn get_environment(tag: Tag) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
let mut indexmap = IndexMap::new();
|
||||
|
||||
let path = std::env::current_dir()?;
|
||||
indexmap.insert(
|
||||
"cwd".to_string(),
|
||||
UntaggedValue::path(path).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("cwd".to_string(), value::path(path).into_value(&tag));
|
||||
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
indexmap.insert(
|
||||
"home".to_string(),
|
||||
UntaggedValue::path(home).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("home".to_string(), value::path(home).into_value(&tag));
|
||||
}
|
||||
|
||||
let config = config::default_path()?;
|
||||
indexmap.insert(
|
||||
"config".to_string(),
|
||||
UntaggedValue::path(config).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("config".to_string(), value::path(config).into_value(&tag));
|
||||
|
||||
let history = History::path();
|
||||
indexmap.insert(
|
||||
"history".to_string(),
|
||||
UntaggedValue::path(history).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("history".to_string(), value::path(history).into_value(&tag));
|
||||
|
||||
let temp = std::env::temp_dir();
|
||||
indexmap.insert(
|
||||
"temp".to_string(),
|
||||
UntaggedValue::path(temp).into_value(&tag),
|
||||
);
|
||||
indexmap.insert("temp".to_string(), value::path(temp).into_value(&tag));
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
for v in std::env::vars() {
|
||||
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
||||
dict.insert_untagged(v.0, value::string(v.1));
|
||||
}
|
||||
if !dict.is_empty() {
|
||||
indexmap.insert("vars".to_string(), dict.into_value());
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::{SpannedItem, Tagged};
|
||||
|
||||
pub struct EvaluateBy;
|
||||
@ -71,7 +73,7 @@ pub fn evaluate_by(
|
||||
fn fetch(key: Option<String>) -> Box<dyn Fn(Value, Tag) -> Option<Value> + 'static> {
|
||||
Box::new(move |value: Value, tag| match &key {
|
||||
Some(key_given) => value.get_data_by_key(key_given[..].spanned(tag.span)),
|
||||
None => Some(UntaggedValue::int(1).into_value(tag)),
|
||||
None => Some(value::int(1).into_value(tag)),
|
||||
})
|
||||
}
|
||||
|
||||
@ -136,25 +138,26 @@ mod tests {
|
||||
use crate::commands::evaluate_by::{evaluate, fetch};
|
||||
use crate::commands::group_by::group;
|
||||
use crate::commands::t_sort_by::t_sort;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use crate::Value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use nu_source::TaggedItem;
|
||||
|
||||
fn int(s: impl Into<BigInt>) -> Value {
|
||||
UntaggedValue::int(s).into_untagged_value()
|
||||
value::int(s).into_untagged_value()
|
||||
}
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_sorted_by_date() -> Value {
|
||||
@ -222,7 +225,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
evaluator(subject, Tag::unknown()),
|
||||
Some(UntaggedValue::int(1).into_untagged_value())
|
||||
Some(value::int(1).into_untagged_value())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::command::{CommandAction, WholeStreamCommand};
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::commands::command::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature};
|
||||
|
||||
pub struct Exit;
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::data::base::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use mime::Mime;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::{AnchorLocation, Span};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
@ -91,7 +90,7 @@ fn run(
|
||||
ctrl_c: raw_args.ctrl_c,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
@ -147,7 +146,7 @@ pub async fn fetch(
|
||||
match (content_type.type_(), content_type.subtype()) {
|
||||
(mime::APPLICATION, mime::XML) => Ok((
|
||||
Some("xml".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -161,7 +160,7 @@ pub async fn fetch(
|
||||
)),
|
||||
(mime::APPLICATION, mime::JSON) => Ok((
|
||||
Some("json".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -183,7 +182,7 @@ pub async fn fetch(
|
||||
})?;
|
||||
Ok((
|
||||
None,
|
||||
UntaggedValue::binary(buf),
|
||||
value::binary(buf),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
@ -192,7 +191,7 @@ pub async fn fetch(
|
||||
}
|
||||
(mime::IMAGE, mime::SVG) => Ok((
|
||||
Some("svg".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load svg from remote url",
|
||||
"could not load",
|
||||
@ -214,7 +213,7 @@ pub async fn fetch(
|
||||
})?;
|
||||
Ok((
|
||||
Some(image_ty.to_string()),
|
||||
UntaggedValue::binary(buf),
|
||||
value::binary(buf),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
@ -223,7 +222,7 @@ pub async fn fetch(
|
||||
}
|
||||
(mime::TEXT, mime::HTML) => Ok((
|
||||
Some("html".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -249,7 +248,7 @@ pub async fn fetch(
|
||||
|
||||
Ok((
|
||||
path_extension,
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -264,10 +263,7 @@ pub async fn fetch(
|
||||
}
|
||||
(ty, sub_ty) => Ok((
|
||||
None,
|
||||
UntaggedValue::string(format!(
|
||||
"Not yet supported MIME type: {} {}",
|
||||
ty, sub_ty
|
||||
)),
|
||||
value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
@ -277,7 +273,7 @@ pub async fn fetch(
|
||||
}
|
||||
None => Ok((
|
||||
None,
|
||||
UntaggedValue::string(format!("No content type found")),
|
||||
value::string(format!("No content type found")),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct First;
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ExpectedRange;
|
||||
use crate::prelude::*;
|
||||
use bson::{decode_document, spec::BinarySubtype, Bson};
|
||||
use nu_errors::{ExpectedRange, ShellError};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use nu_source::SpannedItem;
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -72,8 +74,8 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Result<Value
|
||||
);
|
||||
collected.into_value()
|
||||
}
|
||||
Bson::I32(n) => UntaggedValue::number(n).into_value(&tag),
|
||||
Bson::I64(n) => UntaggedValue::number(n).into_value(&tag),
|
||||
Bson::I32(n) => value::number(n).into_value(&tag),
|
||||
Bson::I64(n) => value::number(n).into_value(&tag),
|
||||
Bson::Decimal128(n) => {
|
||||
// TODO: this really isn't great, and we should update this to do a higher
|
||||
// fidelity translation
|
||||
@ -108,10 +110,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Result<Value
|
||||
}
|
||||
Bson::TimeStamp(ts) => {
|
||||
let mut collected = TaggedDictBuilder::new(tag.clone());
|
||||
collected.insert_value(
|
||||
"$timestamp".to_string(),
|
||||
UntaggedValue::number(ts).into_value(&tag),
|
||||
);
|
||||
collected.insert_value("$timestamp".to_string(), value::number(ts).into_value(&tag));
|
||||
collected.into_value()
|
||||
}
|
||||
Bson::Binary(bst, bytes) => {
|
||||
@ -119,7 +118,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Result<Value
|
||||
collected.insert_value(
|
||||
"$binary_subtype".to_string(),
|
||||
match bst {
|
||||
BinarySubtype::UserDefined(u) => UntaggedValue::number(u),
|
||||
BinarySubtype::UserDefined(u) => value::number(u),
|
||||
_ => {
|
||||
UntaggedValue::Primitive(Primitive::String(binary_subtype_to_string(*bst)))
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::from_delimited_data::from_delimited_data;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct FromCSV;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use csv::ReaderBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||
|
||||
fn from_delimited_string_to_value(
|
||||
s: String,
|
||||
@ -54,19 +56,16 @@ pub fn from_delimited_data(
|
||||
for value in values {
|
||||
let value_tag = &value.tag;
|
||||
latest_tag = Some(value_tag.clone());
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_tag.clone(),
|
||||
"value originates from here",
|
||||
value_tag.clone(),
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct FromINI;
|
||||
@ -77,19 +79,16 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct FromJSON;
|
||||
|
||||
@ -36,10 +38,10 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -
|
||||
|
||||
match v {
|
||||
serde_hjson::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(&tag),
|
||||
serde_hjson::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(&tag),
|
||||
serde_hjson::Value::F64(n) => UntaggedValue::number(n).into_value(&tag),
|
||||
serde_hjson::Value::U64(n) => UntaggedValue::number(n).into_value(&tag),
|
||||
serde_hjson::Value::I64(n) => UntaggedValue::number(n).into_value(&tag),
|
||||
serde_hjson::Value::Bool(b) => value::boolean(*b).into_value(&tag),
|
||||
serde_hjson::Value::F64(n) => value::number(n).into_value(&tag),
|
||||
serde_hjson::Value::U64(n) => value::number(n).into_value(&tag),
|
||||
serde_hjson::Value::I64(n) => value::number(n).into_value(&tag),
|
||||
serde_hjson::Value::String(s) => {
|
||||
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(&tag)
|
||||
}
|
||||
@ -81,19 +83,17 @@ fn from_json(
|
||||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use rusqlite::{types::ValueRef, Connection, Row, NO_PARAMS};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
@ -105,14 +106,14 @@ fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into<Tag> + Clone
|
||||
ValueRef::Null => {
|
||||
UntaggedValue::Primitive(Primitive::String(String::from(""))).into_value(tag)
|
||||
}
|
||||
ValueRef::Integer(i) => UntaggedValue::number(i).into_value(tag),
|
||||
ValueRef::Real(f) => UntaggedValue::number(f).into_value(tag),
|
||||
ValueRef::Integer(i) => value::number(i).into_value(tag),
|
||||
ValueRef::Real(f) => value::number(f).into_value(tag),
|
||||
t @ ValueRef::Text(_) => {
|
||||
// this unwrap is safe because we know the ValueRef is Text.
|
||||
UntaggedValue::Primitive(Primitive::String(t.as_str().unwrap().to_string()))
|
||||
.into_value(tag)
|
||||
}
|
||||
ValueRef::Blob(u) => UntaggedValue::binary(u.to_owned()).into_value(tag),
|
||||
ValueRef::Blob(u) => value::binary(u.to_owned()).into_value(tag),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct FromSSV;
|
||||
@ -264,17 +266,17 @@ fn from_ssv(
|
||||
for value in values {
|
||||
let value_tag = value.tag.clone();
|
||||
latest_tag = Some(value_tag.clone());
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary (
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary (
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
&name,
|
||||
"value originates from here",
|
||||
&value_tag
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct FromTOML;
|
||||
|
||||
@ -30,9 +32,9 @@ pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> V
|
||||
let tag = tag.into();
|
||||
|
||||
match v {
|
||||
toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag),
|
||||
toml::Value::Integer(n) => UntaggedValue::number(n).into_value(tag),
|
||||
toml::Value::Float(n) => UntaggedValue::number(n).into_value(tag),
|
||||
toml::Value::Boolean(b) => value::boolean(*b).into_value(tag),
|
||||
toml::Value::Integer(n) => value::number(n).into_value(tag),
|
||||
toml::Value::Float(n) => value::number(n).into_value(tag),
|
||||
toml::Value::String(s) => {
|
||||
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag)
|
||||
}
|
||||
@ -80,19 +82,17 @@ pub fn from_toml(
|
||||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::from_delimited_data::from_delimited_data;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct FromTSV;
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::value;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, Value};
|
||||
|
||||
pub struct FromURL;
|
||||
|
||||
@ -41,18 +44,16 @@ fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +64,7 @@ fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
let mut row = TaggedDictBuilder::new(tag);
|
||||
|
||||
for (k,v) in result {
|
||||
row.insert_untagged(k, UntaggedValue::string(v));
|
||||
row.insert_untagged(k, value::string(v));
|
||||
}
|
||||
|
||||
yield ReturnSuccess::value(row.into_value());
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use crate::{TaggedDictBuilder, TaggedListBuilder};
|
||||
use calamine::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use std::io::Cursor;
|
||||
|
||||
pub struct FromXLSX;
|
||||
@ -69,12 +71,12 @@ fn from_xlsx(
|
||||
let mut row_output = TaggedDictBuilder::new(&tag);
|
||||
for (i, cell) in row.iter().enumerate() {
|
||||
let value = match cell {
|
||||
DataType::Empty => UntaggedValue::nothing(),
|
||||
DataType::String(s) => UntaggedValue::string(s),
|
||||
DataType::Float(f) => UntaggedValue::decimal(*f),
|
||||
DataType::Int(i) => UntaggedValue::int(*i),
|
||||
DataType::Bool(b) => UntaggedValue::boolean(*b),
|
||||
_ => UntaggedValue::nothing(),
|
||||
DataType::Empty => value::nothing(),
|
||||
DataType::String(s) => value::string(s),
|
||||
DataType::Float(f) => value::decimal(*f),
|
||||
DataType::Int(i) => value::int(*i),
|
||||
DataType::Bool(b) => value::boolean(*b),
|
||||
_ => value::nothing(),
|
||||
};
|
||||
|
||||
row_output.insert_untagged(&format!("Column{}", i), value);
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::{Primitive, UntaggedValue, Value};
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct FromXML;
|
||||
|
||||
@ -60,13 +61,13 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into<Tag>)
|
||||
|
||||
collected.into_value()
|
||||
} else if n.is_comment() {
|
||||
UntaggedValue::string("<comment>").into_value(tag)
|
||||
value::string("<comment>").into_value(tag)
|
||||
} else if n.is_pi() {
|
||||
UntaggedValue::string("<processing_instruction>").into_value(tag)
|
||||
value::string("<processing_instruction>").into_value(tag)
|
||||
} else if n.is_text() {
|
||||
UntaggedValue::string(n.text().unwrap()).into_value(tag)
|
||||
value::string(n.text().unwrap()).into_value(tag)
|
||||
} else {
|
||||
UntaggedValue::string("<unknown>").into_value(tag)
|
||||
value::string("<unknown>").into_value(tag)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,19 +96,17 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,20 +138,21 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
mod tests {
|
||||
|
||||
use crate::commands::from_xml;
|
||||
use crate::data::base::{UntaggedValue, Value};
|
||||
use crate::data::value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::*;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn parse(xml: &str) -> Value {
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct FromYAML;
|
||||
|
||||
@ -54,14 +56,14 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) ->
|
||||
let tag = tag.into();
|
||||
|
||||
match v {
|
||||
serde_yaml::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(tag),
|
||||
serde_yaml::Value::Bool(b) => value::boolean(*b).into_value(tag),
|
||||
serde_yaml::Value::Number(n) if n.is_i64() => {
|
||||
UntaggedValue::number(n.as_i64().unwrap()).into_value(tag)
|
||||
value::number(n.as_i64().unwrap()).into_value(tag)
|
||||
}
|
||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||
UntaggedValue::Primitive(Primitive::from(n.as_f64().unwrap())).into_value(tag)
|
||||
}
|
||||
serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag),
|
||||
serde_yaml::Value::String(s) => value::string(s).into_value(tag),
|
||||
serde_yaml::Value::Sequence(a) => UntaggedValue::Table(
|
||||
a.iter()
|
||||
.map(|x| convert_yaml_value_to_nu_value(x, &tag))
|
||||
@ -108,19 +110,17 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::property_get::get_data_by_column_path;
|
||||
use crate::data::base::shape::Shapes;
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use crate::utils::did_you_mean;
|
||||
use crate::ColumnPath;
|
||||
use futures_util::pin_mut;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
ColumnPath, ReturnSuccess, ReturnValue, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{span_for_spanned_list, PrettyDebug};
|
||||
|
||||
pub struct Get;
|
||||
@ -44,7 +46,8 @@ impl WholeStreamCommand for Get {
|
||||
pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result<Value, ShellError> {
|
||||
let fields = path.clone();
|
||||
|
||||
obj.get_data_by_column_path(
|
||||
get_data_by_column_path(
|
||||
obj,
|
||||
path,
|
||||
Box::new(move |(obj_source, column_path_tried, error)| {
|
||||
match &obj_source.value {
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::UntaggedValue;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct GroupBy;
|
||||
@ -69,10 +70,10 @@ pub fn group(
|
||||
) -> Result<Value, ShellError> {
|
||||
let tag = tag.into();
|
||||
|
||||
let mut groups = indexmap::IndexMap::new();
|
||||
let mut groups: indexmap::IndexMap<String, Vec<Value>> = indexmap::IndexMap::new();
|
||||
|
||||
for value in values {
|
||||
let group_key = value.get_data_by_key(column_name.borrow_spanned());
|
||||
let group_key = get_data_by_key(&value, column_name.borrow_spanned());
|
||||
|
||||
if group_key.is_none() {
|
||||
let possibilities = value.data_descriptors();
|
||||
@ -99,7 +100,7 @@ pub fn group(
|
||||
}
|
||||
}
|
||||
|
||||
let group_key = group_key.unwrap().as_string()?;
|
||||
let group_key = group_key.unwrap().as_string()?.to_string();
|
||||
let group = groups.entry(group_key).or_insert(vec![]);
|
||||
group.push(value);
|
||||
}
|
||||
@ -107,7 +108,7 @@ pub fn group(
|
||||
let mut out = TaggedDictBuilder::new(&tag);
|
||||
|
||||
for (k, v) in groups.iter() {
|
||||
out.insert_untagged(k, UntaggedValue::table(v));
|
||||
out.insert_untagged(k, value::table(v));
|
||||
}
|
||||
|
||||
Ok(out.into_value())
|
||||
@ -116,20 +117,21 @@ pub fn group(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::commands::group_by::group;
|
||||
use crate::data::base::{UntaggedValue, Value};
|
||||
use crate::data::value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::*;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_commiters() -> Vec<Value> {
|
||||
|
@ -1,8 +1,12 @@
|
||||
use crate::commands::PerItemCommand;
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::data::{command_dict, TaggedDictBuilder};
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::{self, NamedType, PositionalType};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, NamedType, PositionalType, Primitive, ReturnSuccess, Signature, SyntaxShape,
|
||||
UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::SpannedItem;
|
||||
|
||||
pub struct Help;
|
||||
@ -12,7 +16,7 @@ impl PerItemCommand for Help {
|
||||
"help"
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("help").rest(SyntaxShape::Any, "the name of command(s) to get help on")
|
||||
}
|
||||
|
||||
@ -45,8 +49,7 @@ impl PerItemCommand for Help {
|
||||
short_desc.insert_untagged("name", cmd);
|
||||
short_desc.insert_untagged(
|
||||
"description",
|
||||
value
|
||||
.get_data_by_key("usage".spanned_unknown())
|
||||
get_data_by_key(&value, "usage".spanned_unknown())
|
||||
.unwrap()
|
||||
.as_string()
|
||||
.unwrap(),
|
||||
@ -149,7 +152,7 @@ impl PerItemCommand for Help {
|
||||
}
|
||||
|
||||
help.push_back(ReturnSuccess::value(
|
||||
UntaggedValue::string(long_desc).into_value(tag.clone()),
|
||||
value::string(long_desc).into_value(tag.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -167,9 +170,7 @@ You can also learn more at https://book.nushell.sh"#;
|
||||
|
||||
let mut output_stream = VecDeque::new();
|
||||
|
||||
output_stream.push_back(ReturnSuccess::value(
|
||||
UntaggedValue::string(msg).into_value(tag),
|
||||
));
|
||||
output_stream.push_back(ReturnSuccess::value(value::string(msg).into_value(tag)));
|
||||
|
||||
Ok(output_stream.to_output_stream())
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ use crate::commands::reduce_by::reduce;
|
||||
use crate::commands::t_sort_by::columns_sorted;
|
||||
use crate::commands::t_sort_by::t_sort;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
@ -90,11 +91,11 @@ pub fn histogram(
|
||||
|
||||
let mut fact = TaggedDictBuilder::new(&name);
|
||||
let value: Tagged<String> = group_labels.get(idx).unwrap().clone();
|
||||
fact.insert_value(&column, UntaggedValue::string(value.item).into_value(value.tag));
|
||||
fact.insert_value(&column, value::string(value.item).into_value(value.tag));
|
||||
|
||||
if let Value { value: UntaggedValue::Primitive(Primitive::Int(ref num)), .. } = percentage.clone() {
|
||||
let string = std::iter::repeat("*").take(num.to_i32().unwrap() as usize).collect::<String>();
|
||||
fact.insert_untagged(&frequency_column_name, UntaggedValue::string(string));
|
||||
fact.insert_untagged(&frequency_column_name, value::string(string));
|
||||
}
|
||||
|
||||
idx = idx + 1;
|
||||
@ -145,9 +146,9 @@ fn percentages(values: &Value, max: Value, tag: impl Into<Tag>) -> Result<Value,
|
||||
|
||||
let n = { n.to_i32().unwrap() * 100 / max };
|
||||
|
||||
UntaggedValue::number(n).into_value(&tag)
|
||||
value::number(n).into_value(&tag)
|
||||
}
|
||||
_ => UntaggedValue::number(0).into_value(&tag),
|
||||
_ => value::number(0).into_value(&tag),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
UntaggedValue::Table(data).into_value(&tag)
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::cli::History as HistoryFile;
|
||||
use crate::commands::PerItemCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::{self};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, Signature, Value};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
@ -13,7 +14,7 @@ impl PerItemCommand for History {
|
||||
"history"
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("history")
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ impl PerItemCommand for History {
|
||||
let reader = BufReader::new(file);
|
||||
for line in reader.lines() {
|
||||
if let Ok(line) = line {
|
||||
yield ReturnSuccess::value(UntaggedValue::string(line).into_value(tag.clone()));
|
||||
yield ReturnSuccess::value(value::string(line).into_value(tag.clone()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Last;
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Primitive;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue};
|
||||
|
||||
pub struct Lines;
|
||||
|
||||
@ -38,8 +38,8 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let split_result: Vec<_> = s.lines().filter(|s| s.trim() != "").collect();
|
||||
|
||||
trace!("split result = {:?}", split_result);
|
||||
@ -47,12 +47,11 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
let mut result = VecDeque::new();
|
||||
for s in split_result {
|
||||
result.push_back(ReturnSuccess::value(
|
||||
UntaggedValue::Primitive(Primitive::String(s.into())).into_untagged_value(),
|
||||
UntaggedValue::Primitive(Primitive::Line(s.into())).into_untagged_value(),
|
||||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
let mut result = VecDeque::new();
|
||||
let value_span = v.tag.span;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -45,8 +45,8 @@ macro_rules! command {
|
||||
stringify!($config_name)
|
||||
}
|
||||
|
||||
fn config(&self) -> $crate::parser::registry::Signature {
|
||||
$crate::parser::registry::Signature {
|
||||
fn config(&self) -> $nu_parser::registry::Signature {
|
||||
$nu_parser::registry::Signature {
|
||||
name: self.name().to_string(),
|
||||
positional: vec![$($mandatory_positional)*],
|
||||
rest_positional: false,
|
||||
@ -54,13 +54,13 @@ macro_rules! command {
|
||||
is_sink: false,
|
||||
|
||||
named: {
|
||||
use $crate::parser::registry::NamedType;
|
||||
use $nu_parser::registry::NamedType;
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut named: indexmap::IndexMap<String, NamedType> = indexmap::IndexMap::new();
|
||||
|
||||
$(
|
||||
named.insert(stringify!($named_param).to_string(), $crate::parser::registry::NamedType::$named_kind);
|
||||
named.insert(stringify!($named_param).to_string(), $nu_parser::registry::NamedType::$named_kind);
|
||||
)*
|
||||
|
||||
named
|
||||
@ -250,7 +250,7 @@ macro_rules! command {
|
||||
Rest { $($rest)* }
|
||||
Signature {
|
||||
name: $config_name,
|
||||
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory_block(
|
||||
mandatory_positional: vec![ $($mandatory_positional)* $nu_parser::registry::PositionalType::mandatory_block(
|
||||
stringify!($param_name)
|
||||
), ],
|
||||
optional_positional: vec![ $($optional_positional)* ],
|
||||
@ -305,7 +305,7 @@ macro_rules! command {
|
||||
Rest { $($rest)* }
|
||||
Signature {
|
||||
name: $config_name,
|
||||
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory(
|
||||
mandatory_positional: vec![ $($mandatory_positional)* $nu_parser::registry::PositionalType::mandatory(
|
||||
stringify!($param_name), <$param_kind>::syntax_type()
|
||||
), ],
|
||||
optional_positional: vec![ $($optional_positional)* ],
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
@ -101,9 +103,9 @@ pub fn map_max(
|
||||
}
|
||||
_ => acc,
|
||||
});
|
||||
UntaggedValue::number(data).into_value(&tag)
|
||||
value::number(data).into_value(&tag)
|
||||
}
|
||||
_ => UntaggedValue::number(0).into_value(&tag),
|
||||
_ => value::number(0).into_value(&tag),
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -120,9 +122,9 @@ pub fn map_max(
|
||||
}
|
||||
_ => max,
|
||||
});
|
||||
UntaggedValue::number(datasets).into_value(&tag)
|
||||
value::number(datasets).into_value(&tag)
|
||||
}
|
||||
_ => UntaggedValue::number(-1).into_value(&tag),
|
||||
_ => value::number(-1).into_value(&tag),
|
||||
};
|
||||
|
||||
Ok(results)
|
||||
@ -137,20 +139,20 @@ mod tests {
|
||||
use crate::commands::reduce_by::reduce;
|
||||
use crate::commands::t_sort_by::t_sort;
|
||||
use crate::prelude::*;
|
||||
use crate::Value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use nu_source::*;
|
||||
|
||||
fn int(s: impl Into<BigInt>) -> Value {
|
||||
UntaggedValue::int(s).into_untagged_value()
|
||||
value::int(s).into_untagged_value()
|
||||
}
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_evaluated_by_default_one() -> Value {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::command::RunnablePerItemContext;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::command::RunnablePerItemContext;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::command::CommandAction;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature};
|
||||
|
||||
pub struct Next;
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -1,12 +1,11 @@
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_source::AnchorLocation;
|
||||
use nu_source::Span;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::{AnchorLocation, Span};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct Open;
|
||||
|
||||
impl PerItemCommand for Open {
|
||||
@ -91,7 +90,7 @@ fn run(
|
||||
ctrl_c: raw_args.ctrl_c,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
@ -141,7 +140,7 @@ pub async fn fetch(
|
||||
Ok(s) => Ok((
|
||||
cwd.extension()
|
||||
.map(|name| name.to_string_lossy().to_string()),
|
||||
UntaggedValue::string(s),
|
||||
value::string(s),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(cwd.to_string_lossy().to_string())),
|
||||
@ -159,7 +158,7 @@ pub async fn fetch(
|
||||
Ok(s) => Ok((
|
||||
cwd.extension()
|
||||
.map(|name| name.to_string_lossy().to_string()),
|
||||
UntaggedValue::string(s),
|
||||
value::string(s),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -169,7 +168,7 @@ pub async fn fetch(
|
||||
)),
|
||||
Err(_) => Ok((
|
||||
None,
|
||||
UntaggedValue::binary(bytes),
|
||||
value::binary(bytes),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -181,7 +180,7 @@ pub async fn fetch(
|
||||
} else {
|
||||
Ok((
|
||||
None,
|
||||
UntaggedValue::binary(bytes),
|
||||
value::binary(bytes),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -200,7 +199,7 @@ pub async fn fetch(
|
||||
Ok(s) => Ok((
|
||||
cwd.extension()
|
||||
.map(|name| name.to_string_lossy().to_string()),
|
||||
UntaggedValue::string(s),
|
||||
value::string(s),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -210,7 +209,7 @@ pub async fn fetch(
|
||||
)),
|
||||
Err(_) => Ok((
|
||||
None,
|
||||
UntaggedValue::binary(bytes),
|
||||
value::binary(bytes),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -222,7 +221,7 @@ pub async fn fetch(
|
||||
} else {
|
||||
Ok((
|
||||
None,
|
||||
UntaggedValue::binary(bytes),
|
||||
value::binary(bytes),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
@ -234,7 +233,7 @@ pub async fn fetch(
|
||||
}
|
||||
_ => Ok((
|
||||
None,
|
||||
UntaggedValue::binary(bytes),
|
||||
value::binary(bytes),
|
||||
Tag {
|
||||
span,
|
||||
anchor: Some(AnchorLocation::File(
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::base::select_fields;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -1,7 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedDictBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
|
||||
use nu_source::{SpannedItem, Tagged};
|
||||
|
||||
pub struct Pivot;
|
||||
@ -61,7 +64,7 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream,
|
||||
|
||||
let descs = merge_descriptors(&input);
|
||||
|
||||
let mut headers = vec![];
|
||||
let mut headers: Vec<String> = vec![];
|
||||
|
||||
if args.rest.len() > 0 && args.header_row {
|
||||
yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", context.name));
|
||||
@ -71,10 +74,10 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream,
|
||||
if args.header_row {
|
||||
for i in input.clone() {
|
||||
if let Some(desc) = descs.get(0) {
|
||||
match i.get_data_by_key(desc[..].spanned_unknown()) {
|
||||
match get_data_by_key(&i, desc[..].spanned_unknown()) {
|
||||
Some(x) => {
|
||||
if let Ok(s) = x.as_string() {
|
||||
headers.push(s);
|
||||
headers.push(s.to_string());
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error("Header row needs string headers", "used non-string headers", context.name));
|
||||
return;
|
||||
@ -111,17 +114,17 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream,
|
||||
let mut dict = TaggedDictBuilder::new(&context.name);
|
||||
|
||||
if !args.ignore_titles && !args.header_row {
|
||||
dict.insert_untagged(headers[column_num].clone(), UntaggedValue::string(desc.clone()));
|
||||
dict.insert_untagged(headers[column_num].clone(), value::string(desc.clone()));
|
||||
column_num += 1
|
||||
}
|
||||
|
||||
for i in input.clone() {
|
||||
match i.get_data_by_key(desc[..].spanned_unknown()) {
|
||||
match get_data_by_key(&i, desc[..].spanned_unknown()) {
|
||||
Some(x) => {
|
||||
dict.insert_value(headers[column_num].clone(), x.clone());
|
||||
}
|
||||
_ => {
|
||||
dict.insert_untagged(headers[column_num].clone(), UntaggedValue::nothing());
|
||||
dict.insert_untagged(headers[column_num].clone(), value::nothing());
|
||||
}
|
||||
}
|
||||
column_num += 1;
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value};
|
||||
use serde::{self, Deserialize, Serialize};
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
@ -39,7 +40,7 @@ pub enum NuResult {
|
||||
pub struct PluginCommand {
|
||||
name: String,
|
||||
path: String,
|
||||
config: registry::Signature,
|
||||
config: Signature,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for PluginCommand {
|
||||
@ -47,7 +48,7 @@ impl WholeStreamCommand for PluginCommand {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
self.config.clone()
|
||||
}
|
||||
|
||||
@ -264,7 +265,7 @@ pub fn filter_plugin(
|
||||
pub struct PluginSink {
|
||||
name: String,
|
||||
path: String,
|
||||
config: registry::Signature,
|
||||
config: Signature,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for PluginSink {
|
||||
@ -272,7 +273,7 @@ impl WholeStreamCommand for PluginSink {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
self.config.clone()
|
||||
}
|
||||
|
||||
@ -315,7 +316,7 @@ pub fn sink_plugin(
|
||||
|
||||
// Needed for async_stream to type check
|
||||
if false {
|
||||
yield ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value());
|
||||
yield ReturnSuccess::value(value::nothing().into_untagged_value());
|
||||
}
|
||||
};
|
||||
Ok(OutputStream::new(stream))
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::data::base::{UntaggedValue, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use base64::encode;
|
||||
use mime::Mime;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
CallInfo, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::AnchorLocation;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
@ -81,13 +82,16 @@ fn run(
|
||||
})? {
|
||||
file => file.clone(),
|
||||
};
|
||||
let path_str = path.as_string()?;
|
||||
let path_str = path.as_string()?.to_string();
|
||||
let has_raw = call_info.args.has("raw");
|
||||
let user = call_info.args.get("user").map(|x| x.as_string().unwrap());
|
||||
let user = call_info
|
||||
.args
|
||||
.get("user")
|
||||
.map(|x| x.as_string().unwrap().to_string());
|
||||
let password = call_info
|
||||
.args
|
||||
.get("password")
|
||||
.map(|x| x.as_string().unwrap());
|
||||
.map(|x| x.as_string().unwrap().to_string());
|
||||
let registry = registry.clone();
|
||||
let raw_args = raw_args.clone();
|
||||
|
||||
@ -115,7 +119,7 @@ fn run(
|
||||
ctrl_c: raw_args.ctrl_c,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
@ -259,7 +263,7 @@ pub async fn post(
|
||||
ctrl_c: raw_args.ctrl_c,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
@ -316,7 +320,7 @@ pub async fn post(
|
||||
match (content_type.type_(), content_type.subtype()) {
|
||||
(mime::APPLICATION, mime::XML) => Ok((
|
||||
Some("xml".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -330,7 +334,7 @@ pub async fn post(
|
||||
)),
|
||||
(mime::APPLICATION, mime::JSON) => Ok((
|
||||
Some("json".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -352,7 +356,7 @@ pub async fn post(
|
||||
})?;
|
||||
Ok((
|
||||
None,
|
||||
UntaggedValue::binary(buf),
|
||||
value::binary(buf),
|
||||
Tag {
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
span: tag.span,
|
||||
@ -369,7 +373,7 @@ pub async fn post(
|
||||
})?;
|
||||
Ok((
|
||||
Some(image_ty.to_string()),
|
||||
UntaggedValue::binary(buf),
|
||||
value::binary(buf),
|
||||
Tag {
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
span: tag.span,
|
||||
@ -378,7 +382,7 @@ pub async fn post(
|
||||
}
|
||||
(mime::TEXT, mime::HTML) => Ok((
|
||||
Some("html".to_string()),
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -404,7 +408,7 @@ pub async fn post(
|
||||
|
||||
Ok((
|
||||
path_extension,
|
||||
UntaggedValue::string(r.body_string().await.map_err(|_| {
|
||||
value::string(r.body_string().await.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Could not load text from remote url",
|
||||
"could not load",
|
||||
@ -419,7 +423,7 @@ pub async fn post(
|
||||
}
|
||||
(ty, sub_ty) => Ok((
|
||||
None,
|
||||
UntaggedValue::string(format!(
|
||||
value::string(format!(
|
||||
"Not yet supported MIME type: {} {}",
|
||||
ty, sub_ty
|
||||
)),
|
||||
@ -432,7 +436,7 @@ pub async fn post(
|
||||
}
|
||||
None => Ok((
|
||||
None,
|
||||
UntaggedValue::string(format!("No content type found")),
|
||||
value::string(format!("No content type found")),
|
||||
Tag {
|
||||
anchor: Some(AnchorLocation::Url(location.to_string())),
|
||||
span: tag.span,
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct PrependArgs {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::commands::command::CommandAction;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature};
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct PWD;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
@ -134,9 +135,9 @@ pub fn reduce(
|
||||
} = d
|
||||
{
|
||||
acc = reduce_with(acc, x.clone());
|
||||
UntaggedValue::number(acc).into_value(&tag)
|
||||
value::number(acc).into_value(&tag)
|
||||
} else {
|
||||
UntaggedValue::number(0).into_value(&tag)
|
||||
value::number(0).into_value(&tag)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@ -163,24 +164,24 @@ mod tests {
|
||||
use crate::commands::reduce_by::{reduce, reducer_for, Reduce};
|
||||
use crate::commands::t_sort_by::t_sort;
|
||||
use crate::prelude::*;
|
||||
use crate::Value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use nu_source::*;
|
||||
|
||||
fn int(s: impl Into<BigInt>) -> Value {
|
||||
UntaggedValue::int(s).into_untagged_value()
|
||||
value::int(s).into_untagged_value()
|
||||
}
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_sorted_by_date() -> Value {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::reject_fields;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct Reverse;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::command::RunnablePerItemContext;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::{UnevaluatedCallInfo, WholeStreamCommand};
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -146,7 +146,7 @@ fn save(
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (1)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
@ -154,7 +154,7 @@ fn save(
|
||||
},
|
||||
None => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (2)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
@ -162,7 +162,7 @@ fn save(
|
||||
}
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (3)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
@ -185,7 +185,7 @@ fn save(
|
||||
ctrl_c,
|
||||
shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
args: nu_parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub struct Shells;
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{TaggedDictBuilder, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, Value};
|
||||
|
||||
pub struct Size;
|
||||
|
||||
@ -34,17 +35,18 @@ fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
ReturnSuccess::value(count(s, &v.tag))
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
ReturnSuccess::value(count(&s, &v.tag))
|
||||
} else {
|
||||
Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
))
|
||||
}
|
||||
_ => Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
@ -76,11 +78,11 @@ fn count(contents: &str, tag: impl Into<Tag>) -> Value {
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
//TODO: add back in name when we have it in the tag
|
||||
//dict.insert("name", UntaggedValue::string(name));
|
||||
dict.insert_untagged("lines", UntaggedValue::int(lines));
|
||||
dict.insert_untagged("words", UntaggedValue::int(words));
|
||||
dict.insert_untagged("chars", UntaggedValue::int(chars));
|
||||
dict.insert_untagged("max length", UntaggedValue::int(bytes));
|
||||
//dict.insert("name", value::string(name));
|
||||
dict.insert_untagged("lines", value::int(lines));
|
||||
dict.insert_untagged("words", value::int(words));
|
||||
dict.insert_untagged("chars", value::int(chars));
|
||||
dict.insert_untagged("max length", value::int(bytes));
|
||||
|
||||
dict.into_value()
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::Block;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Evaluate, Scope, Signature, SyntaxShape};
|
||||
|
||||
pub struct SkipWhile;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SkipWhileArgs {
|
||||
condition: Block,
|
||||
condition: Evaluate,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for SkipWhile {
|
||||
@ -45,7 +45,7 @@ pub fn skip_while(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let objects = input.values.skip_while(move |item| {
|
||||
trace!("ITEM = {:?}", item);
|
||||
let result = condition.invoke(&item);
|
||||
let result = condition.invoke(&Scope::new(item.clone()));
|
||||
trace!("RESULT = {:?}", result);
|
||||
|
||||
let return_value = match result {
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct SortBy;
|
||||
@ -39,10 +41,10 @@ fn sort_by(
|
||||
Ok(OutputStream::new(async_stream! {
|
||||
let mut vec = context.input.drain_vec().await;
|
||||
|
||||
let calc_key = |item: &crate::data::base::Value| {
|
||||
let calc_key = |item: &Value| {
|
||||
rest.iter()
|
||||
.map(|f| item.get_data_by_key(f.borrow_spanned()).map(|i| i.clone()))
|
||||
.collect::<Vec<Option<crate::data::base::Value>>>()
|
||||
.map(|f| get_data_by_key(item, f.borrow_spanned()).map(|i| i.clone()))
|
||||
.collect::<Vec<Option<Value>>>()
|
||||
};
|
||||
vec.sort_by_cached_key(calc_key);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::UntaggedValue;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct SplitBy;
|
||||
@ -104,7 +104,7 @@ pub fn split(
|
||||
.or_insert(indexmap::IndexMap::new());
|
||||
s.insert(
|
||||
group_key.clone(),
|
||||
UntaggedValue::table(&subset).into_value(tag),
|
||||
value::table(&subset).into_value(tag),
|
||||
);
|
||||
}
|
||||
other => {
|
||||
@ -144,7 +144,7 @@ pub fn split(
|
||||
let mut out = TaggedDictBuilder::new(&origin_tag);
|
||||
|
||||
for (k, v) in splits.into_iter() {
|
||||
out.insert_untagged(k, UntaggedValue::row(v));
|
||||
out.insert_untagged(k, value::row(v));
|
||||
}
|
||||
|
||||
Ok(out.into_value())
|
||||
@ -154,20 +154,21 @@ mod tests {
|
||||
|
||||
use crate::commands::group_by::group;
|
||||
use crate::commands::split_by::split;
|
||||
use crate::data::base::{UntaggedValue, Value};
|
||||
use crate::data::value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::*;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_grouped_by_date() -> Value {
|
||||
@ -213,7 +214,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
split(&for_key, &nu_releases_grouped_by_date(), Tag::unknown()).unwrap(),
|
||||
UntaggedValue::row(indexmap! {
|
||||
value::row(indexmap! {
|
||||
"EC".into() => row(indexmap! {
|
||||
"August 23-2019".into() => table(&vec![
|
||||
row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => string("August 23-2019")})
|
||||
@ -260,7 +261,7 @@ mod tests {
|
||||
row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => string("August 23-2019")})
|
||||
]),
|
||||
"Sept 24-2019".into() => table(&vec![
|
||||
row(indexmap!{"name".into() => UntaggedValue::string("JT").into_value(Tag::from(Span::new(5,10))), "date".into() => string("Sept 24-2019")})
|
||||
row(indexmap!{"name".into() => value::string("JT").into_value(Tag::from(Span::new(5,10))), "date".into() => string("Sept 24-2019")})
|
||||
]),
|
||||
"October 10-2019".into() => table(&vec![
|
||||
row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => string("October 10-2019")})
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, TaggedDictBuilder};
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -56,8 +57,8 @@ fn split_column(
|
||||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let splitter = separator.replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
|
||||
@ -103,14 +104,15 @@ fn split_column(
|
||||
}
|
||||
ReturnSuccess::value(dict.into_value())
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
))
|
||||
}
|
||||
_ => Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Primitive;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -44,8 +44,8 @@ fn split_row(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let splitter = separator.item.replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
let split_result: Vec<_> = s.split(&splitter).filter(|s| s.trim() != "").collect();
|
||||
@ -59,8 +59,7 @@ fn split_row(
|
||||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
let mut result = VecDeque::new();
|
||||
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{TaggedDictBuilder, TaggedListBuilder};
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::data::{value, TaggedDictBuilder, TaggedListBuilder};
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, NaiveDate, Utc};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct TSortBy;
|
||||
@ -68,7 +70,7 @@ fn t_sort_by(
|
||||
|
||||
if show_columns {
|
||||
for label in columns_sorted(column_grouped_by_name, &values[0], &name).into_iter() {
|
||||
yield ReturnSuccess::value(UntaggedValue::string(label.item).into_value(label.tag));
|
||||
yield ReturnSuccess::value(value::string(label.item).into_value(label.tag));
|
||||
}
|
||||
} else {
|
||||
match t_sort(column_grouped_by_name, None, &values[0], name) {
|
||||
@ -102,7 +104,7 @@ pub fn columns_sorted(
|
||||
Ok(parsed) => UntaggedValue::Primitive(Primitive::Date(
|
||||
DateTime::<Utc>::from_utc(parsed.and_hms(12, 34, 56), Utc),
|
||||
)),
|
||||
Err(_) => UntaggedValue::string(k),
|
||||
Err(_) => value::string(k),
|
||||
};
|
||||
|
||||
date.into_untagged_value()
|
||||
@ -118,7 +120,7 @@ pub fn columns_sorted(
|
||||
value: UntaggedValue::Primitive(Primitive::Date(d)),
|
||||
..
|
||||
} => format!("{}", d.format("%B %d-%Y")),
|
||||
_ => k.as_string().unwrap(),
|
||||
_ => k.as_string().unwrap().to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -168,7 +170,7 @@ pub fn t_sort(
|
||||
let results: Vec<Vec<Value>> = split_labels
|
||||
.iter()
|
||||
.map(|split| {
|
||||
let groups = dataset.get_data_by_key(split.borrow_spanned());
|
||||
let groups = get_data_by_key(&dataset, split.borrow_spanned());
|
||||
|
||||
sorted_labels
|
||||
.clone()
|
||||
@ -195,10 +197,10 @@ pub fn t_sort(
|
||||
|
||||
return Ok(UntaggedValue::Table(outer.list).into_value(&origin_tag));
|
||||
}
|
||||
Some(_) => return Ok(UntaggedValue::nothing().into_value(&origin_tag)),
|
||||
Some(_) => return Ok(value::nothing().into_value(&origin_tag)),
|
||||
}
|
||||
}
|
||||
None => return Ok(UntaggedValue::nothing().into_value(&origin_tag)),
|
||||
None => return Ok(value::nothing().into_value(&origin_tag)),
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
@ -206,20 +208,21 @@ mod tests {
|
||||
|
||||
use crate::commands::group_by::group;
|
||||
use crate::commands::t_sort_by::{columns_sorted, t_sort};
|
||||
use crate::data::base::{UntaggedValue, Value};
|
||||
use crate::data::value;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use nu_source::*;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn nu_releases_grouped_by_date() -> Value {
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::value;
|
||||
use crate::format::TableView;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct Table;
|
||||
|
||||
@ -56,7 +58,7 @@ fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
}
|
||||
// Needed for async_stream to type check
|
||||
if false {
|
||||
yield ReturnSuccess::value(UntaggedValue::nothing().into_value(Tag::unknown()));
|
||||
yield ReturnSuccess::value(value::nothing().into_value(Tag::unknown()));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct Tags;
|
||||
|
||||
@ -37,16 +38,16 @@ fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||
let anchor = v.anchor();
|
||||
let span = v.tag.span;
|
||||
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||
dict.insert_untagged("start", UntaggedValue::int(span.start() as i64));
|
||||
dict.insert_untagged("end", UntaggedValue::int(span.end() as i64));
|
||||
dict.insert_untagged("start", value::int(span.start() as i64));
|
||||
dict.insert_untagged("end", value::int(span.end() as i64));
|
||||
tags.insert_value("span", dict.into_value());
|
||||
|
||||
match anchor {
|
||||
Some(AnchorLocation::File(source)) => {
|
||||
tags.insert_untagged("anchor", UntaggedValue::string(source));
|
||||
tags.insert_untagged("anchor", value::string(source));
|
||||
}
|
||||
Some(AnchorLocation::Url(source)) => {
|
||||
tags.insert_untagged("anchor", UntaggedValue::string(source));
|
||||
tags.insert_untagged("anchor", value::string(source));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Dictionary, Primitive, Value};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use crate::UnspannedPathMember;
|
||||
use bson::{encode_document, oid::ObjectId, spec::BinarySubtype, Bson, Document};
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{
|
||||
Dictionary, Primitive, ReturnSuccess, Signature, SpannedTypeName, UnspannedPathMember,
|
||||
UntaggedValue, Value,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub struct ToBSON;
|
||||
@ -52,6 +56,7 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => Bson::Null,
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => Bson::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => Bson::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => Bson::Array(
|
||||
path.iter()
|
||||
.map(|x| match &x.unspanned {
|
||||
@ -190,7 +195,7 @@ fn get_binary_subtype<'a>(tagged_value: &'a Value) -> Result<BinarySubtype, Shel
|
||||
)),
|
||||
_ => Err(ShellError::type_error(
|
||||
"bson binary",
|
||||
tagged_value.type_name().spanned(tagged_value.span()),
|
||||
tagged_value.spanned_type_name(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -269,7 +274,7 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||
|
||||
match bson_value_to_bytes(bson_value, name_tag.clone()) {
|
||||
Ok(x) => yield ReturnSuccess::value(
|
||||
UntaggedValue::binary(x).into_value(&name_tag),
|
||||
value::binary(x).into_value(&name_tag),
|
||||
),
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a table with BSON-compatible structure.tag() from pipeline",
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::to_delimited_data::to_delimited_data;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct ToCSV;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::data::base::property_get::get_data_by_key;
|
||||
use crate::prelude::*;
|
||||
use csv::WriterBuilder;
|
||||
use indexmap::{indexset, IndexSet};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||
use nu_source::Spanned;
|
||||
|
||||
fn from_value_to_delimited_string(
|
||||
@ -55,7 +57,7 @@ fn from_value_to_delimited_string(
|
||||
for l in list {
|
||||
let mut row = vec![];
|
||||
for desc in &merged_descriptors {
|
||||
match l.get_data_by_key(desc.borrow_spanned()) {
|
||||
match get_data_by_key(l, desc.borrow_spanned()) {
|
||||
Some(s) => {
|
||||
row.push(to_string_tagged_value(&s)?);
|
||||
}
|
||||
@ -129,12 +131,13 @@ fn to_string_tagged_value(v: &Value) -> Result<String, ShellError> {
|
||||
let tmp = format!("{}", b);
|
||||
Ok(tmp)
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?),
|
||||
UntaggedValue::Primitive(Primitive::Decimal(_)) => Ok(v.as_string()?),
|
||||
UntaggedValue::Primitive(Primitive::Int(_)) => Ok(v.as_string()?),
|
||||
UntaggedValue::Primitive(Primitive::Path(_)) => Ok(v.as_string()?),
|
||||
UntaggedValue::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Decimal(_)) => Ok(v.as_string()?.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Int(_)) => Ok(v.as_string()?.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Path(_)) => Ok(v.as_string()?.to_string()),
|
||||
UntaggedValue::Table(_) => return Ok(String::from("[Table]")),
|
||||
UntaggedValue::Row(_) => return Ok(String::from("[Row]")),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => return Ok(s.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => return Ok(s.to_string()),
|
||||
_ => {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::{Primitive, UntaggedValue, Value};
|
||||
use crate::prelude::*;
|
||||
use crate::UnspannedPathMember;
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UnspannedPathMember, UntaggedValue, Value};
|
||||
|
||||
pub struct ToJSON;
|
||||
|
||||
@ -54,6 +54,7 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => serde_json::Value::Array(
|
||||
path.iter()
|
||||
.map(|x| match &x.unspanned {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Dictionary, Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use hex::encode;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use rusqlite::{Connection, NO_PARAMS};
|
||||
use std::io::Read;
|
||||
|
||||
@ -93,6 +94,7 @@ fn nu_value_to_sqlite_string(v: Value) -> String {
|
||||
Primitive::Bytes(u) => format!("{}", u),
|
||||
Primitive::Pattern(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::String(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::Line(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::Boolean(true) => "1".into(),
|
||||
Primitive::Boolean(_) => "0".into(),
|
||||
Primitive::Date(d) => format!("'{}'", d),
|
||||
@ -195,7 +197,7 @@ fn sqlite_input_stream_to_bytes(values: Vec<Value>) -> Result<Value, std::io::Er
|
||||
}
|
||||
let mut out = Vec::new();
|
||||
tempfile.read_to_end(&mut out)?;
|
||||
Ok(UntaggedValue::binary(out).into_value(tag))
|
||||
Ok(value::binary(out).into_value(tag))
|
||||
}
|
||||
|
||||
fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use crate::UnspannedPathMember;
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UnspannedPathMember, UntaggedValue, Value};
|
||||
|
||||
pub struct ToTOML;
|
||||
|
||||
@ -50,6 +50,7 @@ pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Path(s)) => {
|
||||
toml::Value::String(s.display().to_string())
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::to_delimited_data::to_delimited_data;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct ToTSV;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Value;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct ToURL;
|
||||
|
||||
@ -41,7 +43,7 @@ fn to_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
for (k,v) in row.entries {
|
||||
match v.as_string() {
|
||||
Ok(s) => {
|
||||
row_vec.push((k.clone(), s));
|
||||
row_vec.push((k.clone(), s.to_string()));
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
@ -57,7 +59,7 @@ fn to_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
|
||||
match serde_urlencoded::to_string(row_vec) {
|
||||
Ok(s) => {
|
||||
yield ReturnSuccess::value(UntaggedValue::string(s).into_value(&tag));
|
||||
yield ReturnSuccess::value(value::string(s).into_value(&tag));
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use crate::UnspannedPathMember;
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UnspannedPathMember, UntaggedValue, Value};
|
||||
|
||||
pub struct ToYAML;
|
||||
|
||||
@ -51,6 +51,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => serde_yaml::Value::Null,
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
let mut out = vec![];
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature};
|
||||
|
||||
pub struct Trim;
|
||||
|
||||
@ -34,7 +35,7 @@ fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||
.values
|
||||
.map(move |v| {
|
||||
let string = String::extract(&v)?;
|
||||
ReturnSuccess::value(UntaggedValue::string(string.trim()).into_value(v.tag()))
|
||||
ReturnSuccess::value(value::string(string.trim()).into_value(v.tag()))
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Dictionary;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::prelude::*;
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Signature, UntaggedValue};
|
||||
|
||||
pub struct Version;
|
||||
|
||||
@ -36,7 +35,7 @@ pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||
let mut indexmap = IndexMap::new();
|
||||
indexmap.insert(
|
||||
"version".to_string(),
|
||||
UntaggedValue::string(clap::crate_version!()).into_value(&tag),
|
||||
value::string(clap::crate_version!()).into_value(&tag),
|
||||
);
|
||||
|
||||
let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag);
|
||||
|
@ -1,9 +1,12 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
|
||||
use crate::errors::ShellError;
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use futures::StreamExt;
|
||||
use futures_util::pin_mut;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, ReturnValue, Signature};
|
||||
use nu_source::PrettyDebug;
|
||||
|
||||
pub struct What;
|
||||
|
||||
@ -41,8 +44,8 @@ pub fn what(
|
||||
pin_mut!(values);
|
||||
|
||||
while let Some(row) = values.next().await {
|
||||
let name = row.format_leaf().plain_string(100000);
|
||||
yield ReturnSuccess::value(UntaggedValue::string(name).into_value(Tag::unknown_anchor(row.tag.span)));
|
||||
let name = value::format_leaf(&row).plain_string(100000);
|
||||
yield ReturnSuccess::value(value::string(name).into_value(Tag::unknown_anchor(row.tag.span)));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::PerItemCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxShape;
|
||||
use crate::parser::registry;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct Where;
|
||||
|
||||
@ -11,7 +11,7 @@ impl PerItemCommand for Where {
|
||||
"where"
|
||||
}
|
||||
|
||||
fn signature(&self) -> registry::Signature {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("where").required(
|
||||
"condition",
|
||||
SyntaxShape::Block,
|
||||
@ -26,7 +26,7 @@ impl PerItemCommand for Where {
|
||||
fn run(
|
||||
&self,
|
||||
call_info: &CallInfo,
|
||||
_registry: ®istry::CommandRegistry,
|
||||
_registry: &CommandRegistry,
|
||||
_raw_args: &RawCommandArgs,
|
||||
input: Value,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
@ -37,7 +37,7 @@ impl PerItemCommand for Where {
|
||||
value: UntaggedValue::Block(block),
|
||||
..
|
||||
} => {
|
||||
let result = block.invoke(&input_clone);
|
||||
let result = block.invoke(&Scope::new(input_clone.clone()));
|
||||
match result {
|
||||
Ok(v) => {
|
||||
if v.is_true() {
|
||||
|
@ -1,9 +1,7 @@
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::parser::registry::Signature;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct Which;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::commands::{command::CommandArgs, Command, UnevaluatedCallInfo};
|
||||
use crate::env::host::Host;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::{hir, hir::syntax_shape::ExpandContext};
|
||||
use crate::shell::shell_manager::ShellManager;
|
||||
use crate::stream::{InputStream, OutputStream};
|
||||
use indexmap::IndexMap;
|
||||
use nu_source::Tag;
|
||||
use nu_source::Text;
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::{hir, hir::syntax_shape::ExpandContext, hir::syntax_shape::SignatureRegistry};
|
||||
use nu_protocol::{errln, Signature};
|
||||
use nu_source::{Tag, Text};
|
||||
use std::error::Error;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -16,6 +16,17 @@ pub struct CommandRegistry {
|
||||
registry: Arc<Mutex<IndexMap<String, Arc<Command>>>>,
|
||||
}
|
||||
|
||||
impl SignatureRegistry for CommandRegistry {
|
||||
fn has(&self, name: &str) -> bool {
|
||||
let registry = self.registry.lock().unwrap();
|
||||
registry.contains_key(name)
|
||||
}
|
||||
fn get(&self, name: &str) -> Option<Signature> {
|
||||
let registry = self.registry.lock().unwrap();
|
||||
registry.get(name).map(|command| command.signature())
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandRegistry {
|
||||
pub fn new() -> CommandRegistry {
|
||||
CommandRegistry {
|
||||
@ -76,7 +87,11 @@ impl Context {
|
||||
&'context self,
|
||||
source: &'context Text,
|
||||
) -> ExpandContext<'context> {
|
||||
ExpandContext::new(&self.registry, source, self.shell_manager.homedir())
|
||||
ExpandContext::new(
|
||||
Box::new(self.registry.clone()),
|
||||
source,
|
||||
self.shell_manager.homedir(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn basic() -> Result<Context, Box<dyn Error>> {
|
||||
|
@ -3,10 +3,10 @@ pub(crate) mod command;
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod dict;
|
||||
pub(crate) mod files;
|
||||
pub(crate) mod into;
|
||||
pub mod primitive;
|
||||
pub(crate) mod types;
|
||||
pub mod value;
|
||||
|
||||
pub(crate) use base::{Primitive, Value};
|
||||
pub(crate) use command::command_dict;
|
||||
pub(crate) use dict::{Dictionary, TaggedDictBuilder, TaggedListBuilder};
|
||||
pub(crate) use dict::{TaggedDictBuilder, TaggedListBuilder};
|
||||
pub(crate) use files::dir_entry_dict;
|
||||
|
705
src/data/base.rs
705
src/data/base.rs
@ -1,222 +1,26 @@
|
||||
mod debug;
|
||||
mod property_get;
|
||||
pub(crate) mod property_get;
|
||||
pub(crate) mod shape;
|
||||
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::base::shape::{Column, InlineShape, TypeShape};
|
||||
use crate::data::TaggedDictBuilder;
|
||||
use crate::errors::ShellError;
|
||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||
use crate::parser::hir::path::{ColumnPath, PathMember};
|
||||
use crate::parser::{hir, Operator};
|
||||
use crate::prelude::*;
|
||||
use crate::data::base::property_get::ValueExt;
|
||||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::evaluate::evaluate_baseline_expr;
|
||||
use bigdecimal::BigDecimal;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono_humanize::Humanize;
|
||||
use derive_new::new;
|
||||
use indexmap::IndexMap;
|
||||
use log::trace;
|
||||
use nu_source::{AnchorLocation, PrettyDebug, SpannedItem, Tagged, TaggedItem, Text};
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::{hir, Operator};
|
||||
use nu_protocol::{
|
||||
Evaluate, EvaluateTrait, Primitive, Scope, ShellTypeName, SpannedTypeName, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{Tag, Text};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::Zero;
|
||||
use query_interface::{interfaces, vtable_for, ObjectHash};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTime;
|
||||
|
||||
mod serde_bigint {
|
||||
use num_traits::cast::FromPrimitive;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
pub fn serialize<S>(big_int: &super::BigInt, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serde::Serialize::serialize(
|
||||
&big_int
|
||||
.to_i64()
|
||||
.ok_or(serde::ser::Error::custom("expected a i64-sized bignum"))?,
|
||||
serializer,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<super::BigInt, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let x: i64 = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(super::BigInt::from_i64(x)
|
||||
.ok_or(serde::de::Error::custom("expected a i64-sized bignum"))?)
|
||||
}
|
||||
}
|
||||
|
||||
mod serde_bigdecimal {
|
||||
use num_traits::cast::FromPrimitive;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
pub fn serialize<S>(big_decimal: &super::BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serde::Serialize::serialize(
|
||||
&big_decimal
|
||||
.to_f64()
|
||||
.ok_or(serde::ser::Error::custom("expected a f64-sized bignum"))?,
|
||||
serializer,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<super::BigDecimal, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let x: f64 = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(super::BigDecimal::from_f64(x)
|
||||
.ok_or(serde::de::Error::custom("expected a f64-sized bigdecimal"))?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub enum Primitive {
|
||||
Nothing,
|
||||
#[serde(with = "serde_bigint")]
|
||||
Int(BigInt),
|
||||
#[serde(with = "serde_bigdecimal")]
|
||||
Decimal(BigDecimal),
|
||||
Bytes(u64),
|
||||
String(String),
|
||||
ColumnPath(ColumnPath),
|
||||
Pattern(String),
|
||||
Boolean(bool),
|
||||
Date(DateTime<Utc>),
|
||||
Duration(u64), // Duration in seconds
|
||||
Path(PathBuf),
|
||||
#[serde(with = "serde_bytes")]
|
||||
Binary(Vec<u8>),
|
||||
|
||||
// Stream markers (used as bookend markers rather than actual values)
|
||||
BeginningOfStream,
|
||||
EndOfStream,
|
||||
}
|
||||
|
||||
impl ShellTypeName for Primitive {
|
||||
fn type_name(&self) -> &'static str {
|
||||
match self {
|
||||
Primitive::Nothing => "nothing",
|
||||
Primitive::Int(_) => "integer",
|
||||
Primitive::Decimal(_) => "decimal",
|
||||
Primitive::Bytes(_) => "bytes",
|
||||
Primitive::String(_) => "string",
|
||||
Primitive::ColumnPath(_) => "column path",
|
||||
Primitive::Pattern(_) => "pattern",
|
||||
Primitive::Boolean(_) => "boolean",
|
||||
Primitive::Date(_) => "date",
|
||||
Primitive::Duration(_) => "duration",
|
||||
Primitive::Path(_) => "file path",
|
||||
Primitive::Binary(_) => "binary",
|
||||
Primitive::BeginningOfStream => "marker<beginning of stream>",
|
||||
Primitive::EndOfStream => "marker<end of stream>",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BigDecimal> for Primitive {
|
||||
fn from(decimal: BigDecimal) -> Primitive {
|
||||
Primitive::Decimal(decimal)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Primitive {
|
||||
fn from(float: f64) -> Primitive {
|
||||
Primitive::Decimal(BigDecimal::from_f64(float).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
pub fn number(number: impl Into<Number>) -> Primitive {
|
||||
let number = number.into();
|
||||
|
||||
match number {
|
||||
Number::Int(int) => Primitive::Int(int),
|
||||
Number::Decimal(decimal) => Primitive::Decimal(decimal),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(&self, field_name: Option<&String>) -> String {
|
||||
match self {
|
||||
Primitive::Nothing => String::new(),
|
||||
Primitive::BeginningOfStream => String::new(),
|
||||
Primitive::EndOfStream => String::new(),
|
||||
Primitive::Path(p) => format!("{}", p.display()),
|
||||
Primitive::Bytes(b) => {
|
||||
let byte = byte_unit::Byte::from_bytes(*b as u128);
|
||||
|
||||
if byte.get_bytes() == 0u128 {
|
||||
return "—".to_string();
|
||||
}
|
||||
|
||||
let byte = byte.get_appropriate_unit(false);
|
||||
|
||||
match byte.get_unit() {
|
||||
byte_unit::ByteUnit::B => format!("{} B ", byte.get_value()),
|
||||
_ => format!("{}", byte.format(1)),
|
||||
}
|
||||
}
|
||||
Primitive::Duration(sec) => format_duration(*sec),
|
||||
Primitive::Int(i) => format!("{}", i),
|
||||
Primitive::Decimal(decimal) => format!("{}", decimal),
|
||||
Primitive::Pattern(s) => format!("{}", s),
|
||||
Primitive::String(s) => format!("{}", s),
|
||||
Primitive::ColumnPath(p) => {
|
||||
let mut members = p.iter();
|
||||
let mut f = String::new();
|
||||
|
||||
f.push_str(
|
||||
&members
|
||||
.next()
|
||||
.expect("BUG: column path with zero members")
|
||||
.display(),
|
||||
);
|
||||
|
||||
for member in members {
|
||||
f.push_str(".");
|
||||
f.push_str(&member.display())
|
||||
}
|
||||
|
||||
f
|
||||
}
|
||||
Primitive::Boolean(b) => match (b, field_name) {
|
||||
(true, None) => format!("Yes"),
|
||||
(false, None) => format!("No"),
|
||||
(true, Some(s)) if !s.is_empty() => format!("{}", s),
|
||||
(false, Some(s)) if !s.is_empty() => format!(""),
|
||||
(true, Some(_)) => format!("Yes"),
|
||||
(false, Some(_)) => format!("No"),
|
||||
},
|
||||
Primitive::Binary(_) => format!("<binary>"),
|
||||
Primitive::Date(d) => format!("{}", d.humanize()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn style(&self) -> &'static str {
|
||||
match self {
|
||||
Primitive::Bytes(0) => "c", // centre 'missing' indicator
|
||||
Primitive::Int(_) | Primitive::Bytes(_) | Primitive::Decimal(_) => "r",
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_duration(sec: u64) -> String {
|
||||
let (minutes, seconds) = (sec / 60, sec % 60);
|
||||
let (hours, minutes) = (minutes / 60, minutes % 60);
|
||||
let (days, hours) = (hours / 24, hours % 24);
|
||||
|
||||
match (days, hours, minutes, seconds) {
|
||||
(0, 0, 0, 1) => format!("1 sec"),
|
||||
(0, 0, 0, s) => format!("{} secs", s),
|
||||
(0, 0, m, s) => format!("{}:{:02}", m, s),
|
||||
(0, h, m, s) => format!("{}:{:02}:{:02}", h, m, s),
|
||||
(d, h, m, s) => format!("{}:{:02}:{:02}:{:02}", d, h, m, s),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
|
||||
pub struct Operation {
|
||||
pub(crate) left: Value,
|
||||
@ -231,12 +35,13 @@ pub struct Block {
|
||||
pub(crate) tag: Tag,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn invoke(&self, value: &Value) -> Result<Value, ShellError> {
|
||||
let scope = Scope::new(value.clone());
|
||||
interfaces!(Block: dyn ObjectHash);
|
||||
|
||||
#[typetag::serde]
|
||||
impl EvaluateTrait for Block {
|
||||
fn invoke(&self, scope: &Scope) -> Result<Value, ShellError> {
|
||||
if self.expressions.len() == 0 {
|
||||
return Ok(UntaggedValue::nothing().into_value(&self.tag));
|
||||
return Ok(value::nothing().into_value(&self.tag));
|
||||
}
|
||||
|
||||
let mut last = None;
|
||||
@ -260,231 +65,10 @@ impl Block {
|
||||
|
||||
Ok(last.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Serialize, Deserialize)]
|
||||
pub enum UntaggedValue {
|
||||
Primitive(Primitive),
|
||||
Row(crate::data::Dictionary),
|
||||
Table(Vec<Value>),
|
||||
|
||||
// Errors are a type of value too
|
||||
Error(ShellError),
|
||||
|
||||
Block(Block),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Value {
|
||||
pub value: UntaggedValue,
|
||||
pub tag: Tag,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Value {
|
||||
type Target = UntaggedValue;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<UntaggedValue> for Value {
|
||||
fn into(self) -> UntaggedValue {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<&'a UntaggedValue> for &'a Value {
|
||||
fn into(self) -> &'a UntaggedValue {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSpan for Value {
|
||||
fn span(&self) -> Span {
|
||||
self.tag.span
|
||||
}
|
||||
}
|
||||
|
||||
impl ShellTypeName for Value {
|
||||
fn type_name(&self) -> &'static str {
|
||||
ShellTypeName::type_name(&self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ShellTypeName for UntaggedValue {
|
||||
fn type_name(&self) -> &'static str {
|
||||
match &self {
|
||||
UntaggedValue::Primitive(p) => p.type_name(),
|
||||
UntaggedValue::Row(_) => "row",
|
||||
UntaggedValue::Table(_) => "table",
|
||||
UntaggedValue::Error(_) => "error",
|
||||
UntaggedValue::Block(_) => "block",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<UntaggedValue> for Number {
|
||||
fn into(self) -> UntaggedValue {
|
||||
match self {
|
||||
Number::Int(int) => UntaggedValue::int(int),
|
||||
Number::Decimal(decimal) => UntaggedValue::decimal(decimal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<UntaggedValue> for &Number {
|
||||
fn into(self) -> UntaggedValue {
|
||||
match self {
|
||||
Number::Int(int) => UntaggedValue::int(int.clone()),
|
||||
Number::Decimal(decimal) => UntaggedValue::decimal(decimal.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn anchor(&self) -> Option<AnchorLocation> {
|
||||
self.tag.anchor()
|
||||
}
|
||||
|
||||
pub fn anchor_name(&self) -> Option<String> {
|
||||
self.tag.anchor_name()
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> Tag {
|
||||
self.tag.clone()
|
||||
}
|
||||
|
||||
pub fn into_parts(self) -> (UntaggedValue, Tag) {
|
||||
(self.value, self.tag)
|
||||
}
|
||||
|
||||
pub(crate) fn as_path(&self) -> Result<PathBuf, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(path_str)) => {
|
||||
Ok(PathBuf::from(&path_str).clone())
|
||||
}
|
||||
_ => Err(ShellError::type_error("Path", self.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tagged_type_name(&self) -> Tagged<String> {
|
||||
let name = self.type_name().to_string();
|
||||
name.tagged(self.tag.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn compare(
|
||||
&self,
|
||||
operator: &Operator,
|
||||
other: &Value,
|
||||
) -> Result<bool, (&'static str, &'static str)> {
|
||||
match operator {
|
||||
_ => {
|
||||
let coerced = coerce_compare(self, other)?;
|
||||
let ordering = coerced.compare();
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
let result = match (operator, ordering) {
|
||||
(Operator::Equal, Ordering::Equal) => true,
|
||||
(Operator::NotEqual, Ordering::Less)
|
||||
| (Operator::NotEqual, Ordering::Greater) => true,
|
||||
(Operator::LessThan, Ordering::Less) => true,
|
||||
(Operator::GreaterThan, Ordering::Greater) => true,
|
||||
(Operator::GreaterThanOrEqual, Ordering::Greater)
|
||||
| (Operator::GreaterThanOrEqual, Ordering::Equal) => true,
|
||||
(Operator::LessThanOrEqual, Ordering::Less)
|
||||
| (Operator::LessThanOrEqual, Ordering::Equal) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for &Value {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
PrettyDebug::pretty(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for Value {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(p) => p.pretty(),
|
||||
UntaggedValue::Row(row) => row.pretty_builder().nest(1).group().into(),
|
||||
UntaggedValue::Table(table) => {
|
||||
b::delimit("[", b::intersperse(table, b::space()), "]").nest()
|
||||
}
|
||||
UntaggedValue::Error(_) => b::error("error"),
|
||||
UntaggedValue::Block(_) => b::opaque("block"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&Value> for Block {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &Value) -> Result<Block, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Block(block) => Ok(block.clone()),
|
||||
_ => Err(ShellError::type_error(
|
||||
"Block",
|
||||
value.type_name().spanned(value.tag.span),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&Value> for i64 {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &Value) -> Result<i64, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(int)) => {
|
||||
int.tagged(&value.tag).coerce_into("converting to i64")
|
||||
}
|
||||
_ => Err(ShellError::type_error("Integer", value.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&Value> for String {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &Value) -> Result<String, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
_ => Err(ShellError::type_error("String", value.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&Value> for Vec<u8> {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &Value) -> Result<Vec<u8>, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::Binary(b)) => Ok(b.clone()),
|
||||
_ => Err(ShellError::type_error("Binary", value.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::convert::TryFrom<&'a Value> for &'a crate::data::Dictionary {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Value) -> Result<&'a crate::data::Dictionary, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Row(d) => Ok(d),
|
||||
_ => Err(ShellError::type_error(
|
||||
"Dictionary",
|
||||
value.spanned_type_name(),
|
||||
)),
|
||||
}
|
||||
fn clone_box(&self) -> Evaluate {
|
||||
let block = self.clone();
|
||||
Evaluate::new(block)
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,188 +92,6 @@ impl std::convert::TryFrom<Option<&Value>> for Switch {
|
||||
}
|
||||
}
|
||||
|
||||
impl UntaggedValue {
|
||||
pub fn into_value(self, tag: impl Into<Tag>) -> Value {
|
||||
Value {
|
||||
value: self,
|
||||
tag: tag.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_untagged_value(self) -> Value {
|
||||
Value {
|
||||
value: self,
|
||||
tag: Tag::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retag(self, tag: impl Into<Tag>) -> Value {
|
||||
Value {
|
||||
value: self,
|
||||
tag: tag.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_descriptors(&self) -> Vec<String> {
|
||||
match self {
|
||||
UntaggedValue::Primitive(_) => vec![],
|
||||
UntaggedValue::Row(columns) => columns
|
||||
.entries
|
||||
.keys()
|
||||
.into_iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect(),
|
||||
UntaggedValue::Block(_) => vec![],
|
||||
UntaggedValue::Table(_) => vec![],
|
||||
UntaggedValue::Error(_) => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn format_type(&self, width: usize) -> String {
|
||||
TypeShape::from_value(self).colored_string(width)
|
||||
}
|
||||
|
||||
pub(crate) fn format_leaf(&self) -> DebugDocBuilder {
|
||||
InlineShape::from_value(self).format().pretty()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn format_for_column(&self, column: impl Into<Column>) -> DebugDocBuilder {
|
||||
InlineShape::from_value(self)
|
||||
.format_for_column(column)
|
||||
.pretty()
|
||||
}
|
||||
|
||||
pub(crate) fn style_leaf(&self) -> &'static str {
|
||||
match self {
|
||||
UntaggedValue::Primitive(p) => p.style(),
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_true(&self) -> bool {
|
||||
match self {
|
||||
UntaggedValue::Primitive(Primitive::Boolean(true)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_some(&self) -> bool {
|
||||
!self.is_none()
|
||||
}
|
||||
|
||||
pub(crate) fn is_none(&self) -> bool {
|
||||
match self {
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_error(&self) -> bool {
|
||||
match self {
|
||||
UntaggedValue::Error(_err) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn expect_error(&self) -> ShellError {
|
||||
match self {
|
||||
UntaggedValue::Error(err) => err.clone(),
|
||||
_ => panic!("Don't call expect_error without first calling is_error"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_string(&self) -> &str {
|
||||
match self {
|
||||
UntaggedValue::Primitive(Primitive::String(string)) => &string[..],
|
||||
_ => panic!("expect_string assumes that the value must be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn row(entries: IndexMap<String, Value>) -> UntaggedValue {
|
||||
UntaggedValue::Row(entries.into())
|
||||
}
|
||||
|
||||
pub fn table(list: &Vec<Value>) -> UntaggedValue {
|
||||
UntaggedValue::Table(list.to_vec())
|
||||
}
|
||||
|
||||
pub fn string(s: impl Into<String>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::String(s.into()))
|
||||
}
|
||||
|
||||
pub fn column_path(s: Vec<impl Into<PathMember>>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new(
|
||||
s.into_iter().map(|p| p.into()).collect(),
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn int(i: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Int(i.into()))
|
||||
}
|
||||
|
||||
pub fn pattern(s: impl Into<String>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::String(s.into()))
|
||||
}
|
||||
|
||||
pub fn path(s: impl Into<PathBuf>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Path(s.into()))
|
||||
}
|
||||
|
||||
pub fn bytes(s: impl Into<u64>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Bytes(s.into()))
|
||||
}
|
||||
|
||||
pub fn decimal(s: impl Into<BigDecimal>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Decimal(s.into()))
|
||||
}
|
||||
|
||||
pub fn binary(binary: Vec<u8>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Binary(binary))
|
||||
}
|
||||
|
||||
pub fn number(s: impl Into<Number>) -> UntaggedValue {
|
||||
let num = s.into();
|
||||
|
||||
match num {
|
||||
Number::Int(int) => UntaggedValue::int(int),
|
||||
Number::Decimal(decimal) => UntaggedValue::decimal(decimal),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boolean(s: impl Into<bool>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Boolean(s.into()))
|
||||
}
|
||||
|
||||
pub fn duration(secs: u64) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Duration(secs))
|
||||
}
|
||||
|
||||
pub fn system_date(s: SystemTime) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Date(s.into()))
|
||||
}
|
||||
|
||||
pub fn date_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
|
||||
let date = DateTime::parse_from_rfc3339(s.item).map_err(|err| {
|
||||
ShellError::labeled_error(
|
||||
&format!("Date parse error: {}", err),
|
||||
"original value",
|
||||
s.tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
let date = date.with_timezone(&chrono::offset::Utc);
|
||||
|
||||
Ok(UntaggedValue::Primitive(Primitive::Date(date)))
|
||||
}
|
||||
|
||||
pub fn nothing() -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Nothing)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Value {
|
||||
let mut out = TaggedDictBuilder::new(tag);
|
||||
|
||||
@ -697,7 +99,7 @@ pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>)
|
||||
|
||||
for field in fields {
|
||||
match descs.iter().find(|d| *d == field) {
|
||||
None => out.insert_untagged(field, UntaggedValue::nothing()),
|
||||
None => out.insert_untagged(field, value::nothing()),
|
||||
Some(desc) => out.insert_value(desc.clone(), obj.get_data(desc).borrow().clone()),
|
||||
}
|
||||
}
|
||||
@ -721,7 +123,7 @@ pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>)
|
||||
out.into_value()
|
||||
}
|
||||
|
||||
enum CompareValues {
|
||||
pub(crate) enum CompareValues {
|
||||
Ints(BigInt, BigInt),
|
||||
Decimals(BigDecimal, BigDecimal),
|
||||
String(String, String),
|
||||
@ -730,7 +132,7 @@ enum CompareValues {
|
||||
}
|
||||
|
||||
impl CompareValues {
|
||||
fn compare(&self) -> std::cmp::Ordering {
|
||||
pub fn compare(&self) -> std::cmp::Ordering {
|
||||
match self {
|
||||
CompareValues::Ints(left, right) => left.cmp(right),
|
||||
CompareValues::Decimals(left, right) => left.cmp(right),
|
||||
@ -747,11 +149,11 @@ impl CompareValues {
|
||||
}
|
||||
}
|
||||
|
||||
fn coerce_compare(
|
||||
left: &Value,
|
||||
right: &Value,
|
||||
pub(crate) fn coerce_compare(
|
||||
left: &UntaggedValue,
|
||||
right: &UntaggedValue,
|
||||
) -> Result<CompareValues, (&'static str, &'static str)> {
|
||||
match (&left.value, &right.value) {
|
||||
match (left, right) {
|
||||
(UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => {
|
||||
coerce_compare_primitive(left, right)
|
||||
}
|
||||
@ -784,6 +186,9 @@ fn coerce_compare_primitive(
|
||||
CompareValues::Decimals(BigDecimal::from(*left), right.clone())
|
||||
}
|
||||
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Line(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(String(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Line(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Date(left), Date(right)) => CompareValues::Date(left.clone(), right.clone()),
|
||||
(Date(left), Duration(right)) => CompareValues::DateDuration(left.clone(), right.clone()),
|
||||
_ => return Err((left.type_name(), right.type_name())),
|
||||
@ -791,30 +196,28 @@ fn coerce_compare_primitive(
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::UntaggedValue;
|
||||
use crate::parser::hir::path::PathMember;
|
||||
use crate::ColumnPath as ColumnPathValue;
|
||||
use crate::ShellError;
|
||||
use crate::Value;
|
||||
use super::value;
|
||||
use crate::data::base::property_get::{as_column_path, ValueExt};
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ColumnPath as ColumnPathValue, PathMember, Value};
|
||||
use nu_source::*;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
UntaggedValue::string(input.into()).into_untagged_value()
|
||||
value::string(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn int(input: impl Into<BigInt>) -> Value {
|
||||
UntaggedValue::int(input.into()).into_untagged_value()
|
||||
value::int(input.into()).into_untagged_value()
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
UntaggedValue::row(entries).into_untagged_value()
|
||||
value::row(entries).into_untagged_value()
|
||||
}
|
||||
|
||||
fn table(list: &Vec<Value>) -> Value {
|
||||
UntaggedValue::table(list).into_untagged_value()
|
||||
value::table(list).into_untagged_value()
|
||||
}
|
||||
|
||||
fn error_callback(
|
||||
@ -824,14 +227,12 @@ mod tests {
|
||||
}
|
||||
|
||||
fn column_path(paths: &Vec<Value>) -> Tagged<ColumnPathValue> {
|
||||
table(&paths.iter().cloned().collect())
|
||||
.as_column_path()
|
||||
.unwrap()
|
||||
as_column_path(&table(&paths.iter().cloned().collect())).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gets_matching_field_from_a_row() {
|
||||
let row = UntaggedValue::row(indexmap! {
|
||||
let row = value::row(indexmap! {
|
||||
"amigos".into() => table(&vec![string("andres"),string("jonathan"),string("yehuda")])
|
||||
})
|
||||
.into_untagged_value();
|
||||
@ -852,7 +253,7 @@ mod tests {
|
||||
|
||||
let (version, tag) = string("0.4.0").into_parts();
|
||||
|
||||
let value = UntaggedValue::row(indexmap! {
|
||||
let value = value::row(indexmap! {
|
||||
"package".into() =>
|
||||
row(indexmap! {
|
||||
"name".into() => string("nu"),
|
||||
@ -875,7 +276,7 @@ mod tests {
|
||||
|
||||
let (_, tag) = string("Andrés N. Robalino").into_parts();
|
||||
|
||||
let value = UntaggedValue::row(indexmap! {
|
||||
let value = value::row(indexmap! {
|
||||
"package".into() => row(indexmap! {
|
||||
"name".into() => string("nu"),
|
||||
"version".into() => string("0.4.0"),
|
||||
@ -909,7 +310,7 @@ mod tests {
|
||||
|
||||
let (_, tag) = string("Andrés N. Robalino").into_parts();
|
||||
|
||||
let value = UntaggedValue::row(indexmap! {
|
||||
let value = value::row(indexmap! {
|
||||
"package".into() => row(indexmap! {
|
||||
"name".into() => string("nu"),
|
||||
"version".into() => string("0.4.0"),
|
||||
@ -926,7 +327,7 @@ mod tests {
|
||||
.into_value(tag)
|
||||
.get_data_by_column_path(&field_path, Box::new(error_callback("package.authors.0")))
|
||||
.unwrap(),
|
||||
UntaggedValue::row(indexmap! {
|
||||
value::row(indexmap! {
|
||||
"name".into() => string("Andrés N. Robalino")
|
||||
})
|
||||
);
|
||||
@ -938,7 +339,7 @@ mod tests {
|
||||
|
||||
let (_, tag) = string("Andrés N. Robalino").into_parts();
|
||||
|
||||
let value = UntaggedValue::row(indexmap! {
|
||||
let value = value::row(indexmap! {
|
||||
"package".into() => row(indexmap! {
|
||||
"name".into() => string("nu"),
|
||||
"version".into() => string("0.4.0"),
|
||||
@ -958,7 +359,7 @@ mod tests {
|
||||
Box::new(error_callback("package.authors.\"0\""))
|
||||
)
|
||||
.unwrap(),
|
||||
UntaggedValue::row(indexmap! {
|
||||
value::row(indexmap! {
|
||||
"name".into() => string("Andrés N. Robalino")
|
||||
})
|
||||
);
|
||||
@ -968,7 +369,7 @@ mod tests {
|
||||
fn replaces_matching_field_from_a_row() {
|
||||
let field_path = column_path(&vec![string("amigos")]);
|
||||
|
||||
let sample = UntaggedValue::row(indexmap! {
|
||||
let sample = value::row(indexmap! {
|
||||
"amigos".into() => table(&vec![
|
||||
string("andres"),
|
||||
string("jonathan"),
|
||||
@ -994,7 +395,7 @@ mod tests {
|
||||
string("los.3.caballeros"),
|
||||
]);
|
||||
|
||||
let sample = UntaggedValue::row(indexmap! {
|
||||
let sample = value::row(indexmap! {
|
||||
"package".into() => row(indexmap! {
|
||||
"authors".into() => row(indexmap! {
|
||||
"los.3.mosqueteros".into() => table(&vec![string("andres::yehuda::jonathan")]),
|
||||
@ -1014,7 +415,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
actual,
|
||||
UntaggedValue::row(indexmap! {
|
||||
value::row(indexmap! {
|
||||
"package".into() => row(indexmap! {
|
||||
"authors".into() => row(indexmap! {
|
||||
"los.3.mosqueteros".into() => table(&vec![string("andres::yehuda::jonathan")]),
|
||||
@ -1031,7 +432,7 @@ mod tests {
|
||||
string("nu.version.arepa"),
|
||||
]);
|
||||
|
||||
let sample = UntaggedValue::row(indexmap! {
|
||||
let sample = value::row(indexmap! {
|
||||
"shell_policy".into() => row(indexmap! {
|
||||
"releases".into() => table(&vec![
|
||||
row(indexmap! {
|
||||
@ -1066,7 +467,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
actual,
|
||||
UntaggedValue::row(indexmap! {
|
||||
value::row(indexmap! {
|
||||
"shell_policy".into() => row(indexmap! {
|
||||
"releases".into() => table(&vec![
|
||||
row(indexmap! {
|
||||
|
@ -1,60 +0,0 @@
|
||||
use crate::data::base::Primitive;
|
||||
use crate::traits::PrettyType;
|
||||
use nu_source::{b, DebugDocBuilder, PrettyDebug};
|
||||
|
||||
impl PrettyType for Primitive {
|
||||
fn pretty_type(&self) -> DebugDocBuilder {
|
||||
match self {
|
||||
Primitive::Nothing => ty("nothing"),
|
||||
Primitive::Int(_) => ty("integer"),
|
||||
Primitive::Decimal(_) => ty("decimal"),
|
||||
Primitive::Bytes(_) => ty("bytesize"),
|
||||
Primitive::String(_) => ty("string"),
|
||||
Primitive::ColumnPath(_) => ty("column-path"),
|
||||
Primitive::Pattern(_) => ty("pattern"),
|
||||
Primitive::Boolean(_) => ty("boolean"),
|
||||
Primitive::Date(_) => ty("date"),
|
||||
Primitive::Duration(_) => ty("duration"),
|
||||
Primitive::Path(_) => ty("path"),
|
||||
Primitive::Binary(_) => ty("binary"),
|
||||
Primitive::BeginningOfStream => b::keyword("beginning-of-stream"),
|
||||
Primitive::EndOfStream => b::keyword("end-of-stream"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for Primitive {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
match self {
|
||||
Primitive::Nothing => b::primitive("nothing"),
|
||||
Primitive::Int(int) => prim(format_args!("{}", int)),
|
||||
Primitive::Decimal(decimal) => prim(format_args!("{}", decimal)),
|
||||
Primitive::Bytes(bytes) => primitive_doc(bytes, "bytesize"),
|
||||
Primitive::String(string) => prim(string),
|
||||
Primitive::ColumnPath(path) => path.pretty(),
|
||||
Primitive::Pattern(pattern) => primitive_doc(pattern, "pattern"),
|
||||
Primitive::Boolean(boolean) => match boolean {
|
||||
true => b::primitive("$yes"),
|
||||
false => b::primitive("$no"),
|
||||
},
|
||||
Primitive::Date(date) => primitive_doc(date, "date"),
|
||||
Primitive::Duration(duration) => primitive_doc(duration, "seconds"),
|
||||
Primitive::Path(path) => primitive_doc(path, "path"),
|
||||
Primitive::Binary(_) => b::opaque("binary"),
|
||||
Primitive::BeginningOfStream => b::keyword("beginning-of-stream"),
|
||||
Primitive::EndOfStream => b::keyword("end-of-stream"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prim(name: impl std::fmt::Debug) -> DebugDocBuilder {
|
||||
b::primitive(format!("{:?}", name))
|
||||
}
|
||||
|
||||
fn ty(name: impl std::fmt::Debug) -> DebugDocBuilder {
|
||||
b::kind(format!("{:?}", name))
|
||||
}
|
||||
|
||||
fn primitive_doc(name: impl std::fmt::Debug, ty: impl Into<String>) -> DebugDocBuilder {
|
||||
b::primitive(format!("{:?}", name)) + b::delimit("(", b::kind(ty.into()), ")")
|
||||
}
|
@ -1,318 +1,416 @@
|
||||
use crate::errors::ExpectedRange;
|
||||
use crate::parser::hir::path::{PathMember, UnspannedPathMember};
|
||||
use crate::data::value;
|
||||
use crate::prelude::*;
|
||||
use crate::ColumnPath;
|
||||
use crate::SpannedTypeName;
|
||||
use nu_errors::{ExpectedRange, ShellError};
|
||||
use nu_protocol::{
|
||||
ColumnPath, PathMember, Primitive, ShellTypeName, SpannedTypeName, UnspannedPathMember,
|
||||
UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{Spanned, SpannedItem, Tagged};
|
||||
|
||||
impl Value {
|
||||
pub(crate) fn get_data_by_member(&self, name: &PathMember) -> Result<Value, ShellError> {
|
||||
match &self.value {
|
||||
// If the value is a row, the member is a column name
|
||||
UntaggedValue::Row(o) => match &name.unspanned {
|
||||
// If the member is a string, get the data
|
||||
UnspannedPathMember::String(string) => o
|
||||
.get_data_by_key(string[..].spanned(name.span))
|
||||
.ok_or_else(|| {
|
||||
ShellError::missing_property(
|
||||
"row".spanned(self.tag.span),
|
||||
string.spanned(name.span),
|
||||
)
|
||||
}),
|
||||
pub trait ValueExt {
|
||||
fn into_parts(self) -> (UntaggedValue, Tag);
|
||||
fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value>;
|
||||
fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value>;
|
||||
fn get_data_by_member(&self, name: &PathMember) -> Result<Value, ShellError>;
|
||||
fn get_data_by_column_path(
|
||||
&self,
|
||||
path: &ColumnPath,
|
||||
callback: Box<dyn FnOnce((&Value, &PathMember, ShellError)) -> ShellError>,
|
||||
) -> Result<Value, ShellError>;
|
||||
fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option<Value>;
|
||||
fn insert_data_at_member(
|
||||
&mut self,
|
||||
member: &PathMember,
|
||||
new_value: Value,
|
||||
) -> Result<(), ShellError>;
|
||||
fn insert_data_at_column_path(
|
||||
&self,
|
||||
split_path: &ColumnPath,
|
||||
new_value: Value,
|
||||
) -> Result<Value, ShellError>;
|
||||
fn replace_data_at_column_path(
|
||||
&self,
|
||||
split_path: &ColumnPath,
|
||||
replaced_value: Value,
|
||||
) -> Option<Value>;
|
||||
fn as_column_path(&self) -> Result<Tagged<ColumnPath>, ShellError>;
|
||||
fn as_path_member(&self) -> Result<PathMember, ShellError>;
|
||||
fn as_string(&self) -> Result<String, ShellError>;
|
||||
}
|
||||
|
||||
// If the member is a number, it's an error
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::invalid_integer_index(
|
||||
"row".spanned(self.tag.span),
|
||||
name.span,
|
||||
)),
|
||||
},
|
||||
|
||||
// If the value is a table
|
||||
UntaggedValue::Table(l) => {
|
||||
match &name.unspanned {
|
||||
// If the member is a string, map over the member
|
||||
UnspannedPathMember::String(string) => {
|
||||
let mut out = vec![];
|
||||
|
||||
for item in l {
|
||||
match item {
|
||||
Value {
|
||||
value: UntaggedValue::Row(o),
|
||||
..
|
||||
} => match o.get_data_by_key(string[..].spanned(name.span)) {
|
||||
Some(v) => out.push(v),
|
||||
None => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if out.len() == 0 {
|
||||
Err(ShellError::missing_property(
|
||||
"table".spanned(self.tag.span),
|
||||
string.spanned(name.span),
|
||||
))
|
||||
} else {
|
||||
Ok(UntaggedValue::Table(out)
|
||||
.into_value(Tag::new(self.anchor(), name.span)))
|
||||
}
|
||||
}
|
||||
UnspannedPathMember::Int(int) => {
|
||||
let index = int.to_usize().ok_or_else(|| {
|
||||
ShellError::range_error(
|
||||
ExpectedRange::Usize,
|
||||
&"massive integer".spanned(name.span),
|
||||
"indexing",
|
||||
)
|
||||
})?;
|
||||
|
||||
match self.get_data_by_index(index.spanned(self.tag.span)) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(ShellError::range_error(
|
||||
0..(l.len()),
|
||||
&int.spanned(name.span),
|
||||
"indexing",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
other => Err(ShellError::type_error(
|
||||
"row or table",
|
||||
other.type_name().spanned(self.tag.span),
|
||||
)),
|
||||
}
|
||||
impl ValueExt for Value {
|
||||
fn into_parts(self) -> (UntaggedValue, Tag) {
|
||||
(self.value, self.tag)
|
||||
}
|
||||
|
||||
pub fn get_data_by_column_path(
|
||||
fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
get_data(self, desc)
|
||||
}
|
||||
|
||||
fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
|
||||
get_data_by_key(self, name)
|
||||
}
|
||||
|
||||
fn get_data_by_member(&self, name: &PathMember) -> Result<Value, ShellError> {
|
||||
get_data_by_member(self, name)
|
||||
}
|
||||
|
||||
fn get_data_by_column_path(
|
||||
&self,
|
||||
path: &ColumnPath,
|
||||
callback: Box<dyn FnOnce((&Value, &PathMember, ShellError)) -> ShellError>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let mut current = self.clone();
|
||||
|
||||
for p in path.iter() {
|
||||
let value = current.get_data_by_member(p);
|
||||
|
||||
match value {
|
||||
Ok(v) => current = v.clone(),
|
||||
Err(e) => return Err(callback((¤t.clone(), &p.clone(), e))),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(current)
|
||||
get_data_by_column_path(self, path, callback)
|
||||
}
|
||||
|
||||
pub fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option<Value> {
|
||||
let mut new_obj = self.clone();
|
||||
|
||||
let split_path: Vec<_> = path.split(".").collect();
|
||||
|
||||
if let UntaggedValue::Row(ref mut o) = new_obj.value {
|
||||
let mut current = o;
|
||||
|
||||
if split_path.len() == 1 {
|
||||
// Special case for inserting at the top level
|
||||
current.entries.insert(
|
||||
path.to_string(),
|
||||
new_value.value.clone().into_value(&self.tag),
|
||||
);
|
||||
return Some(new_obj);
|
||||
}
|
||||
|
||||
for idx in 0..split_path.len() {
|
||||
match current.entries.get_mut(split_path[idx]) {
|
||||
Some(next) => {
|
||||
if idx == (split_path.len() - 2) {
|
||||
match &mut next.value {
|
||||
UntaggedValue::Row(o) => {
|
||||
o.entries.insert(
|
||||
split_path[idx + 1].to_string(),
|
||||
new_value.value.clone().into_value(&self.tag),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
return Some(new_obj.clone());
|
||||
} else {
|
||||
match next.value {
|
||||
UntaggedValue::Row(ref mut o) => {
|
||||
current = o;
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
fn insert_data_at_path(&self, path: &str, new_value: Value) -> Option<Value> {
|
||||
insert_data_at_path(self, path, new_value)
|
||||
}
|
||||
|
||||
pub fn insert_data_at_member(
|
||||
fn insert_data_at_member(
|
||||
&mut self,
|
||||
member: &PathMember,
|
||||
new_value: Value,
|
||||
) -> Result<(), ShellError> {
|
||||
match &mut self.value {
|
||||
UntaggedValue::Row(dict) => match &member.unspanned {
|
||||
UnspannedPathMember::String(key) => Ok({
|
||||
dict.insert_data_at_key(key, new_value);
|
||||
}),
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::type_error(
|
||||
"column name",
|
||||
"integer".spanned(member.span),
|
||||
)),
|
||||
},
|
||||
UntaggedValue::Table(array) => match &member.unspanned {
|
||||
UnspannedPathMember::String(_) => Err(ShellError::type_error(
|
||||
"list index",
|
||||
"string".spanned(member.span),
|
||||
)),
|
||||
UnspannedPathMember::Int(int) => Ok({
|
||||
let int = int.to_usize().ok_or_else(|| {
|
||||
ShellError::range_error(
|
||||
ExpectedRange::Usize,
|
||||
&"bigger number".spanned(member.span),
|
||||
"inserting into a list",
|
||||
)
|
||||
})?;
|
||||
|
||||
insert_data_at_index(array, int.tagged(member.span), new_value.clone())?;
|
||||
}),
|
||||
},
|
||||
other => match &member.unspanned {
|
||||
UnspannedPathMember::String(_) => Err(ShellError::type_error(
|
||||
"row",
|
||||
other.type_name().spanned(self.span()),
|
||||
)),
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::type_error(
|
||||
"table",
|
||||
other.type_name().spanned(self.span()),
|
||||
)),
|
||||
},
|
||||
}
|
||||
insert_data_at_member(self, member, new_value)
|
||||
}
|
||||
|
||||
pub fn insert_data_at_column_path(
|
||||
fn insert_data_at_column_path(
|
||||
&self,
|
||||
split_path: &ColumnPath,
|
||||
new_value: Value,
|
||||
) -> Result<Value, ShellError> {
|
||||
let (last, front) = split_path.split_last();
|
||||
let mut original = self.clone();
|
||||
|
||||
let mut current: &mut Value = &mut original;
|
||||
|
||||
for member in front {
|
||||
let type_name = current.spanned_type_name();
|
||||
|
||||
current = current.get_mut_data_by_member(&member).ok_or_else(|| {
|
||||
ShellError::missing_property(
|
||||
member.plain_string(std::usize::MAX).spanned(member.span),
|
||||
type_name,
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
current.insert_data_at_member(&last, new_value)?;
|
||||
|
||||
Ok(original)
|
||||
insert_data_at_column_path(self, split_path, new_value)
|
||||
}
|
||||
|
||||
pub fn replace_data_at_column_path(
|
||||
fn replace_data_at_column_path(
|
||||
&self,
|
||||
split_path: &ColumnPath,
|
||||
replaced_value: Value,
|
||||
) -> Option<Value> {
|
||||
let mut new_obj: Value = self.clone();
|
||||
let mut current = &mut new_obj;
|
||||
let split_path = split_path.members();
|
||||
replace_data_at_column_path(self, split_path, replaced_value)
|
||||
}
|
||||
|
||||
for idx in 0..split_path.len() {
|
||||
match current.get_mut_data_by_member(&split_path[idx]) {
|
||||
Some(next) => {
|
||||
if idx == (split_path.len() - 1) {
|
||||
*next = replaced_value.value.into_value(&self.tag);
|
||||
return Some(new_obj);
|
||||
fn as_column_path(&self) -> Result<Tagged<ColumnPath>, ShellError> {
|
||||
as_column_path(self)
|
||||
}
|
||||
|
||||
fn as_path_member(&self) -> Result<PathMember, ShellError> {
|
||||
as_path_member(self)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Result<String, ShellError> {
|
||||
as_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_by_member(value: &Value, name: &PathMember) -> Result<Value, ShellError> {
|
||||
match &value.value {
|
||||
// If the value is a row, the member is a column name
|
||||
UntaggedValue::Row(o) => match &name.unspanned {
|
||||
// If the member is a string, get the data
|
||||
UnspannedPathMember::String(string) => o
|
||||
.get_data_by_key(string[..].spanned(name.span))
|
||||
.ok_or_else(|| {
|
||||
ShellError::missing_property(
|
||||
"row".spanned(value.tag.span),
|
||||
string.spanned(name.span),
|
||||
)
|
||||
}),
|
||||
|
||||
// If the member is a number, it's an error
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::invalid_integer_index(
|
||||
"row".spanned(value.tag.span),
|
||||
name.span,
|
||||
)),
|
||||
},
|
||||
|
||||
// If the value is a table
|
||||
UntaggedValue::Table(l) => {
|
||||
match &name.unspanned {
|
||||
// If the member is a string, map over the member
|
||||
UnspannedPathMember::String(string) => {
|
||||
let mut out = vec![];
|
||||
|
||||
for item in l {
|
||||
match item {
|
||||
Value {
|
||||
value: UntaggedValue::Row(o),
|
||||
..
|
||||
} => match o.get_data_by_key(string[..].spanned(name.span)) {
|
||||
Some(v) => out.push(v),
|
||||
None => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if out.len() == 0 {
|
||||
Err(ShellError::missing_property(
|
||||
"table".spanned(value.tag.span),
|
||||
string.spanned(name.span),
|
||||
))
|
||||
} else {
|
||||
current = next;
|
||||
Ok(UntaggedValue::Table(out)
|
||||
.into_value(Tag::new(value.anchor(), name.span)))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return None;
|
||||
UnspannedPathMember::Int(int) => {
|
||||
let index = int.to_usize().ok_or_else(|| {
|
||||
ShellError::range_error(
|
||||
ExpectedRange::Usize,
|
||||
&"massive integer".spanned(name.span),
|
||||
"indexing",
|
||||
)
|
||||
})?;
|
||||
|
||||
match get_data_by_index(value, index.spanned(value.tag.span)) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(ShellError::range_error(
|
||||
0..(l.len()),
|
||||
&int.spanned(name.span),
|
||||
"indexing",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
other => Err(ShellError::type_error(
|
||||
"row or table",
|
||||
other.type_name().spanned(value.tag.span),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
pub fn get_data_by_column_path(
|
||||
value: &Value,
|
||||
path: &ColumnPath,
|
||||
callback: Box<dyn FnOnce((&Value, &PathMember, ShellError)) -> ShellError>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let mut current = value.clone();
|
||||
|
||||
for p in path.iter() {
|
||||
let value = get_data_by_member(¤t, p);
|
||||
|
||||
match value {
|
||||
Ok(v) => current = v.clone(),
|
||||
Err(e) => return Err(callback((¤t.clone(), &p.clone(), e))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_column_path(&self) -> Result<Tagged<ColumnPath>, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Table(table) => {
|
||||
let mut out: Vec<PathMember> = vec![];
|
||||
Ok(current)
|
||||
}
|
||||
|
||||
for item in table {
|
||||
out.push(item.as_path_member()?);
|
||||
pub fn insert_data_at_path(value: &Value, path: &str, new_value: Value) -> Option<Value> {
|
||||
let mut new_obj = value.clone();
|
||||
|
||||
let split_path: Vec<_> = path.split(".").collect();
|
||||
|
||||
if let UntaggedValue::Row(ref mut o) = new_obj.value {
|
||||
let mut current = o;
|
||||
|
||||
if split_path.len() == 1 {
|
||||
// Special case for inserting at the top level
|
||||
current.entries.insert(
|
||||
path.to_string(),
|
||||
new_value.value.clone().into_value(&value.tag),
|
||||
);
|
||||
return Some(new_obj);
|
||||
}
|
||||
|
||||
for idx in 0..split_path.len() {
|
||||
match current.entries.get_mut(split_path[idx]) {
|
||||
Some(next) => {
|
||||
if idx == (split_path.len() - 2) {
|
||||
match &mut next.value {
|
||||
UntaggedValue::Row(o) => {
|
||||
o.entries.insert(
|
||||
split_path[idx + 1].to_string(),
|
||||
new_value.value.clone().into_value(&value.tag),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
return Some(new_obj.clone());
|
||||
} else {
|
||||
match next.value {
|
||||
UntaggedValue::Row(ref mut o) => {
|
||||
current = o;
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ColumnPath::new(out).tagged(&self.tag))
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
Ok(ColumnPath::new(vec![PathMember::string(s, &self.tag.span)]).tagged(&self.tag))
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
Ok(path.clone().tagged(self.tag.clone()))
|
||||
}
|
||||
|
||||
other => Err(ShellError::type_error(
|
||||
"column path",
|
||||
other.type_name().spanned(self.span()),
|
||||
pub fn insert_data_at_member(
|
||||
value: &mut Value,
|
||||
member: &PathMember,
|
||||
new_value: Value,
|
||||
) -> Result<(), ShellError> {
|
||||
match &mut value.value {
|
||||
UntaggedValue::Row(dict) => match &member.unspanned {
|
||||
UnspannedPathMember::String(key) => Ok({
|
||||
dict.insert_data_at_key(key, new_value);
|
||||
}),
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::type_error(
|
||||
"column name",
|
||||
"integer".spanned(member.span),
|
||||
)),
|
||||
},
|
||||
UntaggedValue::Table(array) => match &member.unspanned {
|
||||
UnspannedPathMember::String(_) => Err(ShellError::type_error(
|
||||
"list index",
|
||||
"string".spanned(member.span),
|
||||
)),
|
||||
UnspannedPathMember::Int(int) => Ok({
|
||||
let int = int.to_usize().ok_or_else(|| {
|
||||
ShellError::range_error(
|
||||
ExpectedRange::Usize,
|
||||
&"bigger number".spanned(member.span),
|
||||
"inserting into a list",
|
||||
)
|
||||
})?;
|
||||
|
||||
insert_data_at_index(array, int.tagged(member.span), new_value.clone())?;
|
||||
}),
|
||||
},
|
||||
other => match &member.unspanned {
|
||||
UnspannedPathMember::String(_) => Err(ShellError::type_error(
|
||||
"row",
|
||||
other.type_name().spanned(value.span()),
|
||||
)),
|
||||
UnspannedPathMember::Int(_) => Err(ShellError::type_error(
|
||||
"table",
|
||||
other.type_name().spanned(value.span()),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_data_at_column_path(
|
||||
value: &Value,
|
||||
split_path: &ColumnPath,
|
||||
new_value: Value,
|
||||
) -> Result<Value, ShellError> {
|
||||
let (last, front) = split_path.split_last();
|
||||
let mut original = value.clone();
|
||||
|
||||
let mut current: &mut Value = &mut original;
|
||||
|
||||
for member in front {
|
||||
let type_name = current.spanned_type_name();
|
||||
|
||||
current = get_mut_data_by_member(current, &member).ok_or_else(|| {
|
||||
ShellError::missing_property(
|
||||
member.plain_string(std::usize::MAX).spanned(member.span),
|
||||
type_name,
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
insert_data_at_member(current, &last, new_value)?;
|
||||
|
||||
Ok(original)
|
||||
}
|
||||
|
||||
pub fn replace_data_at_column_path(
|
||||
value: &Value,
|
||||
split_path: &ColumnPath,
|
||||
replaced_value: Value,
|
||||
) -> Option<Value> {
|
||||
let mut new_obj: Value = value.clone();
|
||||
let mut current = &mut new_obj;
|
||||
let split_path = split_path.members();
|
||||
|
||||
for idx in 0..split_path.len() {
|
||||
match get_mut_data_by_member(current, &split_path[idx]) {
|
||||
Some(next) => {
|
||||
if idx == (split_path.len() - 1) {
|
||||
*next = replaced_value.value.into_value(&value.tag);
|
||||
return Some(new_obj);
|
||||
} else {
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_path_member(&self) -> Result<PathMember, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(primitive) => match primitive {
|
||||
Primitive::Int(int) => Ok(PathMember::int(int.clone(), self.tag.span)),
|
||||
Primitive::String(string) => Ok(PathMember::string(string, self.tag.span)),
|
||||
other => Err(ShellError::type_error(
|
||||
"path member",
|
||||
other.type_name().spanned(self.span()),
|
||||
)),
|
||||
},
|
||||
None
|
||||
}
|
||||
|
||||
pub fn as_column_path(value: &Value) -> Result<Tagged<ColumnPath>, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Table(table) => {
|
||||
let mut out: Vec<PathMember> = vec![];
|
||||
|
||||
for item in table {
|
||||
out.push(as_path_member(item)?);
|
||||
}
|
||||
|
||||
Ok(ColumnPath::new(out).tagged(&value.tag))
|
||||
}
|
||||
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
Ok(ColumnPath::new(vec![PathMember::string(s, &value.tag.span)]).tagged(&value.tag))
|
||||
}
|
||||
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
Ok(path.clone().tagged(value.tag.clone()))
|
||||
}
|
||||
|
||||
other => Err(ShellError::type_error(
|
||||
"column path",
|
||||
other.type_name().spanned(value.span()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_path_member(value: &Value) -> Result<PathMember, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(primitive) => match primitive {
|
||||
Primitive::Int(int) => Ok(PathMember::int(int.clone(), value.tag.span)),
|
||||
Primitive::String(string) => Ok(PathMember::string(string, value.tag.span)),
|
||||
other => Err(ShellError::type_error(
|
||||
"path member",
|
||||
other.type_name().spanned(self.span()),
|
||||
other.type_name().spanned(value.span()),
|
||||
)),
|
||||
}
|
||||
},
|
||||
other => Err(ShellError::type_error(
|
||||
"path member",
|
||||
other.type_name().spanned(value.span()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Result<String, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Bytes(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Path(x)) => Ok(format!("{}", x.display())),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
Ok(path.iter().map(|member| member.display()).join("."))
|
||||
}
|
||||
// TODO: this should definitely be more general with better errors
|
||||
other => Err(ShellError::labeled_error(
|
||||
"Expected string",
|
||||
other.type_name(),
|
||||
&self.tag,
|
||||
)),
|
||||
pub fn as_string(value: &Value) -> Result<String, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Bytes(x)) => Ok(format!("{}", x)),
|
||||
UntaggedValue::Primitive(Primitive::Path(x)) => Ok(format!("{}", x.display())),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
Ok(path.iter().map(|member| member.display()).join("."))
|
||||
}
|
||||
|
||||
// TODO: this should definitely be more general with better errors
|
||||
other => Err(ShellError::labeled_error(
|
||||
"Expected string",
|
||||
other.type_name(),
|
||||
&value.tag,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,88 +431,89 @@ fn insert_data_at_index(
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(_) => MaybeOwned::Borrowed(self),
|
||||
UntaggedValue::Row(o) => o.get_data(desc),
|
||||
UntaggedValue::Block(_) | UntaggedValue::Table(_) | UntaggedValue::Error(_) => {
|
||||
MaybeOwned::Owned(UntaggedValue::nothing().into_untagged_value())
|
||||
}
|
||||
pub fn get_data<'value>(value: &'value Value, desc: &String) -> MaybeOwned<'value, Value> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(_) => MaybeOwned::Borrowed(value),
|
||||
UntaggedValue::Row(o) => o.get_data(desc),
|
||||
UntaggedValue::Block(_) | UntaggedValue::Table(_) | UntaggedValue::Error(_) => {
|
||||
MaybeOwned::Owned(value::nothing().into_untagged_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_by_index(&self, idx: Spanned<usize>) -> Option<Value> {
|
||||
match &self.value {
|
||||
UntaggedValue::Table(value_set) => {
|
||||
let value = value_set.get(idx.item)?;
|
||||
Some(
|
||||
value
|
||||
.value
|
||||
.clone()
|
||||
.into_value(Tag::new(value.anchor(), idx.span)),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
pub(crate) fn get_data_by_index(value: &Value, idx: Spanned<usize>) -> Option<Value> {
|
||||
match &value.value {
|
||||
UntaggedValue::Table(value_set) => {
|
||||
let value = value_set.get(idx.item)?;
|
||||
Some(
|
||||
value
|
||||
.value
|
||||
.clone()
|
||||
.into_value(Tag::new(value.anchor(), idx.span)),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
|
||||
match &self.value {
|
||||
UntaggedValue::Row(o) => o.get_data_by_key(name),
|
||||
UntaggedValue::Table(l) => {
|
||||
let mut out = vec![];
|
||||
pub(crate) fn get_data_by_key(value: &Value, name: Spanned<&str>) -> Option<Value> {
|
||||
match &value.value {
|
||||
UntaggedValue::Row(o) => o.get_data_by_key(name),
|
||||
UntaggedValue::Table(l) => {
|
||||
let mut out = vec![];
|
||||
for item in l {
|
||||
match item {
|
||||
Value {
|
||||
value: UntaggedValue::Row(o),
|
||||
..
|
||||
} => match o.get_data_by_key(name) {
|
||||
Some(v) => out.push(v),
|
||||
None => out.push(value::nothing().into_untagged_value()),
|
||||
},
|
||||
_ => out.push(value::nothing().into_untagged_value()),
|
||||
}
|
||||
}
|
||||
|
||||
if out.len() > 0 {
|
||||
Some(UntaggedValue::Table(out).into_value(name.span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_data_by_member<'value>(
|
||||
value: &'value mut Value,
|
||||
name: &PathMember,
|
||||
) -> Option<&'value mut Value> {
|
||||
match &mut value.value {
|
||||
UntaggedValue::Row(o) => match &name.unspanned {
|
||||
UnspannedPathMember::String(string) => o.get_mut_data_by_key(&string),
|
||||
UnspannedPathMember::Int(_) => None,
|
||||
},
|
||||
UntaggedValue::Table(l) => match &name.unspanned {
|
||||
UnspannedPathMember::String(string) => {
|
||||
for item in l {
|
||||
match item {
|
||||
Value {
|
||||
value: UntaggedValue::Row(o),
|
||||
..
|
||||
} => match o.get_data_by_key(name) {
|
||||
Some(v) => out.push(v),
|
||||
None => out.push(UntaggedValue::nothing().into_untagged_value()),
|
||||
} => match o.get_mut_data_by_key(&string) {
|
||||
Some(v) => return Some(v),
|
||||
None => {}
|
||||
},
|
||||
_ => out.push(UntaggedValue::nothing().into_untagged_value()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if out.len() > 0 {
|
||||
Some(UntaggedValue::Table(out).into_value(name.span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_data_by_member(&mut self, name: &PathMember) -> Option<&mut Value> {
|
||||
match &mut self.value {
|
||||
UntaggedValue::Row(o) => match &name.unspanned {
|
||||
UnspannedPathMember::String(string) => o.get_mut_data_by_key(&string),
|
||||
UnspannedPathMember::Int(_) => None,
|
||||
},
|
||||
UntaggedValue::Table(l) => match &name.unspanned {
|
||||
UnspannedPathMember::String(string) => {
|
||||
for item in l {
|
||||
match item {
|
||||
Value {
|
||||
value: UntaggedValue::Row(o),
|
||||
..
|
||||
} => match o.get_mut_data_by_key(&string) {
|
||||
Some(v) => return Some(v),
|
||||
None => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
UnspannedPathMember::Int(int) => {
|
||||
let index = int.to_usize()?;
|
||||
l.get_mut(index)
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
UnspannedPathMember::Int(int) => {
|
||||
let index = int.to_usize()?;
|
||||
l.get_mut(index)
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::data::base::{Block, ColumnPath};
|
||||
use crate::data::dict::Dictionary;
|
||||
use crate::data::primitive::format_primitive;
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono_humanize::Humanize;
|
||||
use derive_new::new;
|
||||
use indexmap::IndexMap;
|
||||
use nu_source::DebugDoc;
|
||||
use nu_source::{b, PrettyDebug};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
ColumnPath, Dictionary, Evaluate, Primitive, ShellTypeName, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{b, DebugDoc, PrettyDebug};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
@ -31,6 +33,7 @@ pub enum TypeShape {
|
||||
Decimal,
|
||||
Bytesize,
|
||||
String,
|
||||
Line,
|
||||
ColumnPath,
|
||||
Pattern,
|
||||
Boolean,
|
||||
@ -60,6 +63,7 @@ impl TypeShape {
|
||||
Primitive::Decimal(_) => TypeShape::Decimal,
|
||||
Primitive::Bytes(_) => TypeShape::Bytesize,
|
||||
Primitive::String(_) => TypeShape::String,
|
||||
Primitive::Line(_) => TypeShape::Line,
|
||||
Primitive::ColumnPath(_) => TypeShape::ColumnPath,
|
||||
Primitive::Pattern(_) => TypeShape::Pattern,
|
||||
Primitive::Boolean(_) => TypeShape::Boolean,
|
||||
@ -112,6 +116,7 @@ impl PrettyDebug for TypeShape {
|
||||
TypeShape::Decimal => ty("decimal"),
|
||||
TypeShape::Bytesize => ty("bytesize"),
|
||||
TypeShape::String => ty("string"),
|
||||
TypeShape::Line => ty("line"),
|
||||
TypeShape::ColumnPath => ty("column-path"),
|
||||
TypeShape::Pattern => ty("pattern"),
|
||||
TypeShape::Boolean => ty("boolean"),
|
||||
@ -206,6 +211,7 @@ pub enum InlineShape {
|
||||
Decimal(BigDecimal),
|
||||
Bytesize(u64),
|
||||
String(String),
|
||||
Line(String),
|
||||
ColumnPath(ColumnPath),
|
||||
Pattern(String),
|
||||
Boolean(bool),
|
||||
@ -240,6 +246,7 @@ impl InlineShape {
|
||||
Primitive::Decimal(decimal) => InlineShape::Decimal(decimal.clone()),
|
||||
Primitive::Bytes(bytesize) => InlineShape::Bytesize(*bytesize),
|
||||
Primitive::String(string) => InlineShape::String(string.clone()),
|
||||
Primitive::Line(string) => InlineShape::Line(string.clone()),
|
||||
Primitive::ColumnPath(path) => InlineShape::ColumnPath(path.clone()),
|
||||
Primitive::Pattern(pattern) => InlineShape::Pattern(pattern.clone()),
|
||||
Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean),
|
||||
@ -325,6 +332,7 @@ impl PrettyDebug for FormatInlineShape {
|
||||
}
|
||||
}
|
||||
InlineShape::String(string) => b::primitive(format!("{}", string)),
|
||||
InlineShape::Line(string) => b::primitive(format!("{}", string)),
|
||||
InlineShape::ColumnPath(path) => {
|
||||
b::intersperse(path.iter().map(|member| member.pretty()), b::keyword("."))
|
||||
}
|
||||
@ -339,7 +347,7 @@ impl PrettyDebug for FormatInlineShape {
|
||||
}),
|
||||
InlineShape::Date(date) => b::primitive(date.humanize()),
|
||||
InlineShape::Duration(duration) => {
|
||||
b::description(Primitive::Duration(*duration).format(None))
|
||||
b::description(format_primitive(&Primitive::Duration(*duration), None))
|
||||
}
|
||||
InlineShape::Path(path) => b::primitive(path.display()),
|
||||
InlineShape::Binary => b::opaque("<binary>"),
|
||||
@ -475,13 +483,7 @@ pub enum Shape {
|
||||
Row(Vec<Column>),
|
||||
Table { from: usize, to: usize },
|
||||
Error(ShellError),
|
||||
Block(Block),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn shape(&self) -> Shape {
|
||||
Shape::for_value(self)
|
||||
}
|
||||
Block(Evaluate),
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
@ -502,32 +504,6 @@ impl Shape {
|
||||
Shape::Row(dict.keys().map(|key| Column::String(key.clone())).collect())
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> String {
|
||||
match self {
|
||||
Shape::Primitive(primitive) => primitive,
|
||||
Shape::Row(row) => {
|
||||
return row
|
||||
.iter()
|
||||
.map(|c| match c {
|
||||
Column::String(s) => s.clone(),
|
||||
Column::Value => format!("<value>"),
|
||||
})
|
||||
.join(", ")
|
||||
}
|
||||
Shape::Table { .. } => "table",
|
||||
Shape::Error(_) => "error",
|
||||
Shape::Block(_) => "block",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn describe_str(&self) -> String {
|
||||
let mut v = vec![];
|
||||
self.describe(&mut v)
|
||||
.expect("it isn't possible to fail to write into a memory buffer");
|
||||
String::from_utf8_lossy(&v[..]).to_string()
|
||||
}
|
||||
|
||||
pub fn describe(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
Shape::Primitive(desc) => write!(w, "[{}]", desc),
|
||||
@ -559,7 +535,7 @@ impl Shape {
|
||||
.expect("Writing into a Vec can't fail");
|
||||
let string = String::from_utf8_lossy(&out);
|
||||
|
||||
UntaggedValue::string(string).into_untagged_value()
|
||||
value::string(string).into_untagged_value()
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,7 +565,7 @@ impl Shapes {
|
||||
|
||||
vec![dict! {
|
||||
"type" => shape.to_value(),
|
||||
"rows" => UntaggedValue::string("all")
|
||||
"rows" => value::string("all")
|
||||
}]
|
||||
} else {
|
||||
self.shapes
|
||||
@ -599,7 +575,7 @@ impl Shapes {
|
||||
|
||||
dict! {
|
||||
"type" => shape.to_value(),
|
||||
"rows" => UntaggedValue::string(format!("[ {} ]", rows))
|
||||
"rows" => value::string(format!("[ {} ]", rows))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::command::Command;
|
||||
use crate::data::{TaggedDictBuilder, TaggedListBuilder, Value};
|
||||
use crate::parser::registry::{NamedType, PositionalType, Signature};
|
||||
use crate::data::{TaggedDictBuilder, TaggedListBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_protocol::{NamedType, PositionalType, Signature, Value};
|
||||
use std::ops::Deref;
|
||||
|
||||
pub(crate) fn command_dict(command: Arc<Command>, tag: impl Into<Tag>) -> Value {
|
||||
@ -9,18 +9,18 @@ pub(crate) fn command_dict(command: Arc<Command>, tag: impl Into<Tag>) -> Value
|
||||
|
||||
let mut cmd_dict = TaggedDictBuilder::new(&tag);
|
||||
|
||||
cmd_dict.insert_untagged("name", UntaggedValue::string(command.name()));
|
||||
cmd_dict.insert_untagged("name", value::string(command.name()));
|
||||
|
||||
cmd_dict.insert_untagged(
|
||||
"type",
|
||||
UntaggedValue::string(match command.deref() {
|
||||
value::string(match command.deref() {
|
||||
Command::WholeStream(_) => "Command",
|
||||
Command::PerItem(_) => "Filter",
|
||||
}),
|
||||
);
|
||||
|
||||
cmd_dict.insert_value("signature", signature_dict(command.signature(), tag));
|
||||
cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage()));
|
||||
cmd_dict.insert_untagged("usage", value::string(command.usage()));
|
||||
|
||||
cmd_dict.into_value()
|
||||
}
|
||||
@ -30,11 +30,11 @@ fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into<Tag>) -> Value
|
||||
|
||||
let mut spec = TaggedDictBuilder::new(tag);
|
||||
|
||||
spec.insert_untagged("name", UntaggedValue::string(name));
|
||||
spec.insert_untagged("type", UntaggedValue::string(ty));
|
||||
spec.insert_untagged("name", value::string(name));
|
||||
spec.insert_untagged("type", value::string(ty));
|
||||
spec.insert_untagged(
|
||||
"required",
|
||||
UntaggedValue::string(if required { "yes" } else { "no" }),
|
||||
value::string(if required { "yes" } else { "no" }),
|
||||
);
|
||||
|
||||
spec.into_value()
|
||||
|
@ -1,11 +1,11 @@
|
||||
use crate::commands::from_toml::convert_toml_value_to_nu_value;
|
||||
use crate::commands::to_toml::value_to_toml_value;
|
||||
use crate::data::{Dictionary, Value};
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use app_dirs::*;
|
||||
use indexmap::IndexMap;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, ShellTypeName, UntaggedValue, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io;
|
||||
|
111
src/data/dict.rs
111
src/data/dict.rs
@ -1,19 +1,8 @@
|
||||
use crate::data::base::{Primitive, UntaggedValue, Value};
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use getset::Getters;
|
||||
use indexmap::IndexMap;
|
||||
use nu_source::Spanned;
|
||||
use nu_source::{b, PrettyDebug};
|
||||
use pretty::{BoxAllocator, DocAllocator};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, Getters, new)]
|
||||
pub struct Dictionary {
|
||||
#[get = "pub"]
|
||||
pub entries: IndexMap<String, Value>,
|
||||
}
|
||||
use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value};
|
||||
use nu_source::{b, PrettyDebug, Spanned};
|
||||
|
||||
#[derive(Debug, new)]
|
||||
struct DebugEntry<'a> {
|
||||
@ -27,87 +16,17 @@ impl<'a> PrettyDebug for DebugEntry<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for Dictionary {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
BoxAllocator
|
||||
.text("(")
|
||||
.append(
|
||||
BoxAllocator
|
||||
.intersperse(
|
||||
self.entries()
|
||||
.iter()
|
||||
.map(|(key, value)| DebugEntry::new(key, value).to_doc()),
|
||||
BoxAllocator.space(),
|
||||
)
|
||||
.nest(1)
|
||||
.group(),
|
||||
)
|
||||
.append(BoxAllocator.text(")"))
|
||||
.into()
|
||||
}
|
||||
pub trait DictionaryExt {
|
||||
fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value>;
|
||||
|
||||
fn keys(&self) -> indexmap::map::Keys<String, Value>;
|
||||
fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value>;
|
||||
fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value>;
|
||||
fn insert_data_at_key(&mut self, name: &str, value: Value);
|
||||
}
|
||||
|
||||
impl PartialOrd for Dictionary {
|
||||
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
|
||||
let this: Vec<&String> = self.entries.keys().collect();
|
||||
let that: Vec<&String> = other.entries.keys().collect();
|
||||
|
||||
if this != that {
|
||||
return this.partial_cmp(&that);
|
||||
}
|
||||
|
||||
let this: Vec<&Value> = self.entries.values().collect();
|
||||
let that: Vec<&Value> = self.entries.values().collect();
|
||||
|
||||
this.partial_cmp(&that)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IndexMap<String, Value>> for Dictionary {
|
||||
fn from(input: IndexMap<String, Value>) -> Dictionary {
|
||||
let mut out = IndexMap::default();
|
||||
|
||||
for (key, value) in input {
|
||||
out.insert(key, value);
|
||||
}
|
||||
|
||||
Dictionary::new(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Dictionary {
|
||||
fn cmp(&self, other: &Dictionary) -> Ordering {
|
||||
let this: Vec<&String> = self.entries.keys().collect();
|
||||
let that: Vec<&String> = other.entries.keys().collect();
|
||||
|
||||
if this != that {
|
||||
return this.cmp(&that);
|
||||
}
|
||||
|
||||
let this: Vec<&Value> = self.entries.values().collect();
|
||||
let that: Vec<&Value> = self.entries.values().collect();
|
||||
|
||||
this.cmp(&that)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<Value> for Dictionary {
|
||||
fn partial_cmp(&self, _other: &Value) -> Option<Ordering> {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Value> for Dictionary {
|
||||
fn eq(&self, other: &Value) -> bool {
|
||||
match &other.value {
|
||||
UntaggedValue::Row(d) => self == d,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dictionary {
|
||||
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
impl DictionaryExt for Dictionary {
|
||||
fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
match self.entries.get(desc) {
|
||||
Some(v) => MaybeOwned::Borrowed(v),
|
||||
None => MaybeOwned::Owned(
|
||||
@ -116,11 +35,11 @@ impl Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys(&self) -> impl Iterator<Item = &String> {
|
||||
fn keys(&self) -> indexmap::map::Keys<String, Value> {
|
||||
self.entries.keys()
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
|
||||
fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
|
||||
let result = self
|
||||
.entries
|
||||
.iter()
|
||||
@ -135,7 +54,7 @@ impl Dictionary {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> {
|
||||
fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> {
|
||||
match self
|
||||
.entries
|
||||
.iter_mut()
|
||||
@ -146,7 +65,7 @@ impl Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_data_at_key(&mut self, name: &str, value: Value) {
|
||||
fn insert_data_at_key(&mut self, name: &str, value: Value) {
|
||||
self.entries.insert(name.to_string(), value);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user