Merge remote-tracking branch 'upstream/master' into range

This commit is contained in:
Sebastian Jung
2019-12-03 20:23:49 +01:00
226 changed files with 4276 additions and 3459 deletions

View File

@ -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(),

View File

@ -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;

View File

@ -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 {

View File

@ -1,4 +1,4 @@
use crate::data::Value;
use nu_protocol::Value;
#[derive(Debug)]
pub enum LogLevel {}

View File

@ -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());
}
}))
}

View File

@ -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;

View File

@ -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 {

View File

@ -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,
));
}
}

View File

@ -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())
}

View File

@ -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(),
}
}
}

View File

@ -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(())
}

View File

@ -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",

View File

@ -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: &registry::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: &registry::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) -> &registry::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: &registry::CommandRegistry,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError>;
fn is_binary(&self) -> bool {
@ -570,7 +469,7 @@ impl Command {
}
}
pub fn run(&self, args: CommandArgs, registry: &registry::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: &registry::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| {

View File

@ -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;

View File

@ -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: &registry::CommandRegistry,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, config)?.run()
}

View File

@ -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())

View File

@ -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;

View File

@ -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)

View File

@ -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())
}

View File

@ -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)]

View File

@ -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 {

View File

@ -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: &registry::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,

View File

@ -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());

View File

@ -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())
);
}

View File

@ -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;

View File

@ -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())),

View File

@ -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;

View File

@ -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)))
}

View File

@ -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;

View File

@ -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(),
)),
))
}
}

View File

@ -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,
)),
))
}
}

View File

@ -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,
)),
))
}
}

View File

@ -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),
}
}

View File

@ -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
)),
))
}
}

View File

@ -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,
)),
))
}
}

View File

@ -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;

View File

@ -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());

View File

@ -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);

View File

@ -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 {

View File

@ -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,
)),
))
}
}

View File

@ -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 {

View File

@ -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> {

View File

@ -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())
}

View File

@ -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)

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)* ],

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)]

View File

@ -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(

View 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)]

View File

@ -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;

View File

@ -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))

View File

@ -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,

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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)]

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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()
}

View File

@ -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 {

View File

@ -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);

View File

@ -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")})

View File

@ -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())
}

View File

@ -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",

View File

@ -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 {

View File

@ -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()));
}
};

View File

@ -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));
}
_ => {}
}

View File

@ -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",

View File

@ -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;

View File

@ -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(

View File

@ -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 {

View File

@ -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> {

View File

@ -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())
}

View File

@ -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;

View File

@ -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(

View File

@ -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![];

View File

@ -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())
}

View File

@ -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);

View File

@ -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)));
}
};

View File

@ -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: &registry::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() {

View File

@ -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;

View File

@ -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>> {

View File

@ -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;

View File

@ -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! {

View File

@ -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()), ")")
}

View File

@ -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((&current.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(&current, p);
match value {
Ok(v) => current = v.clone(),
Err(e) => return Err(callback((&current.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,
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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;

View File

@ -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