mirror of
https://github.com/nushell/nushell.git
synced 2025-01-24 23:29:52 +01:00
Tests pass
This commit is contained in:
parent
7b68739b52
commit
2da12aed56
@ -6,9 +6,9 @@ use std::path::PathBuf;
|
|||||||
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let env = args.env.lock().unwrap();
|
let env = args.env.lock().unwrap();
|
||||||
let latest = env.back().unwrap();
|
let latest = env.back().unwrap();
|
||||||
let obj = latest.obj;
|
let obj = &latest.obj;
|
||||||
|
|
||||||
match obj.item {
|
match obj.item() {
|
||||||
Value::Filesystem => {
|
Value::Filesystem => {
|
||||||
let cwd = latest.path().to_path_buf();
|
let cwd = latest.path().to_path_buf();
|
||||||
|
|
||||||
|
@ -86,6 +86,17 @@ crate enum ClassifiedCommand {
|
|||||||
External(ExternalCommand),
|
External(ExternalCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ClassifiedCommand {
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
ClassifiedCommand::Expr(token) => token.span(),
|
||||||
|
ClassifiedCommand::Internal(internal) => internal.name_span.into(),
|
||||||
|
ClassifiedCommand::Sink(sink) => sink.name_span.into(),
|
||||||
|
ClassifiedCommand::External(external) => external.name_span.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate struct SinkCommand {
|
crate struct SinkCommand {
|
||||||
crate command: Arc<dyn Sink>,
|
crate command: Arc<dyn Sink>,
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Option<Span>,
|
||||||
@ -190,6 +201,7 @@ impl ExternalCommand {
|
|||||||
) -> Result<ClassifiedInputStream, ShellError> {
|
) -> Result<ClassifiedInputStream, ShellError> {
|
||||||
let stdin = input.stdin;
|
let stdin = input.stdin;
|
||||||
let inputs: Vec<Spanned<Value>> = input.objects.into_vec().await;
|
let inputs: Vec<Spanned<Value>> = input.objects.into_vec().await;
|
||||||
|
let name_span = self.name_span.clone();
|
||||||
|
|
||||||
trace!("-> {}", self.name);
|
trace!("-> {}", self.name);
|
||||||
trace!("inputs = {:?}", inputs);
|
trace!("inputs = {:?}", inputs);
|
||||||
@ -320,9 +332,10 @@ impl ExternalCommand {
|
|||||||
let stdout = popen.stdout.take().unwrap();
|
let stdout = popen.stdout.take().unwrap();
|
||||||
let file = futures::io::AllowStdIo::new(stdout);
|
let file = futures::io::AllowStdIo::new(stdout);
|
||||||
let stream = Framed::new(file, LinesCodec {});
|
let stream = Framed::new(file, LinesCodec {});
|
||||||
let stream = stream.map(|line| Value::string(line.unwrap()));
|
let stream =
|
||||||
|
stream.map(move |line| Value::string(line.unwrap()).spanned(name_span));
|
||||||
Ok(ClassifiedInputStream::from_input_stream(
|
Ok(ClassifiedInputStream::from_input_stream(
|
||||||
stream.boxed() as BoxStream<'static, Value>
|
stream.boxed() as BoxStream<'static, Spanned<Value>>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.ok_or_else(|| ShellError::string(&format!("Missing key {} in config", key)))?;
|
.ok_or_else(|| ShellError::string(&format!("Missing key {} in config", key)))?;
|
||||||
|
|
||||||
return Ok(
|
return Ok(
|
||||||
stream![value.clone()], // futures::stream::once(futures::future::ready(ReturnSuccess::Value(value.clone()))).into(),
|
stream![value.clone()].into(), // futures::stream::once(futures::future::ready(ReturnSuccess::Value(value.clone()))).into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Ok(vec![Value::Object(result.into())].into());
|
return Ok(vec![Value::Object(result.into()).spanned(args.name_span)].into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ShellError::string(format!("Unimplemented")))
|
Err(ShellError::string(format!("Unimplemented")))
|
||||||
|
@ -1,29 +1,41 @@
|
|||||||
use crate::object::{Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn convert_ini_second_to_nu_value(v: &HashMap<String, String>) -> Value {
|
fn convert_ini_second_to_nu_value(
|
||||||
let mut second = Dictionary::new(IndexMap::new());
|
v: &HashMap<String, String>,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Spanned<Value> {
|
||||||
|
let mut second = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
for (key, value) in v.into_iter() {
|
for (key, value) in v.into_iter() {
|
||||||
second.add(
|
second.insert(key.clone(), Primitive::String(value.clone()));
|
||||||
key.clone(),
|
|
||||||
Value::Primitive(Primitive::String(value.clone())),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Value::Object(second)
|
|
||||||
}
|
second.into_spanned_value()
|
||||||
fn convert_ini_top_to_nu_value(v: &HashMap<String, HashMap<String, String>>) -> Value {
|
|
||||||
let mut top_level = Dictionary::new(IndexMap::new());
|
|
||||||
for (key, value) in v.iter() {
|
|
||||||
top_level.add(key.clone(), convert_ini_second_to_nu_value(value));
|
|
||||||
}
|
|
||||||
Value::Object(top_level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ini_string_to_value(s: String) -> Result<Value, Box<dyn std::error::Error>> {
|
fn convert_ini_top_to_nu_value(
|
||||||
|
v: &HashMap<String, HashMap<String, String>>,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Spanned<Value> {
|
||||||
|
let span = span.into();
|
||||||
|
let mut top_level = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
|
for (key, value) in v.iter() {
|
||||||
|
top_level.insert_spanned(key.clone(), convert_ini_second_to_nu_value(value, span));
|
||||||
|
}
|
||||||
|
|
||||||
|
top_level.into_spanned_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_ini_string_to_value(
|
||||||
|
s: String,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Result<Spanned<Value>, Box<dyn std::error::Error>> {
|
||||||
let v: HashMap<String, HashMap<String, String>> = serde_ini::from_str(&s)?;
|
let v: HashMap<String, HashMap<String, String>> = serde_ini::from_str(&s)?;
|
||||||
Ok(convert_ini_top_to_nu_value(&v))
|
Ok(convert_ini_top_to_nu_value(&v, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@ -32,7 +44,7 @@ pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_ini_string_to_value(s) {
|
Value::Primitive(Primitive::String(s)) => match from_ini_string_to_value(s, span) {
|
||||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||||
Err(e) => Err(ShellError::maybe_labeled_error(
|
Err(e) => Err(ShellError::maybe_labeled_error(
|
||||||
"Could not parse as INI",
|
"Could not parse as INI",
|
||||||
|
@ -1,33 +1,46 @@
|
|||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_json_value_to_nu_value(v: &serde_hjson::Value) -> Value {
|
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_hjson::Value::Null => Value::Primitive(Primitive::String(String::from(""))),
|
serde_hjson::Value::Null => {
|
||||||
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)),
|
Value::Primitive(Primitive::String(String::from(""))).spanned(span)
|
||||||
serde_hjson::Value::F64(n) => Value::Primitive(Primitive::Float(OF64::from(*n))),
|
}
|
||||||
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)),
|
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).spanned(span),
|
||||||
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)),
|
serde_hjson::Value::F64(n) => {
|
||||||
serde_hjson::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))),
|
Value::Primitive(Primitive::Float(OF64::from(*n))).spanned(span)
|
||||||
|
}
|
||||||
|
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).spanned(span),
|
||||||
|
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).spanned(span),
|
||||||
|
serde_hjson::Value::String(s) => {
|
||||||
|
Value::Primitive(Primitive::String(String::from(s))).spanned(span)
|
||||||
|
}
|
||||||
serde_hjson::Value::Array(a) => Value::List(
|
serde_hjson::Value::Array(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_json_value_to_nu_value(x).spanned_unknown())
|
.map(|x| convert_json_value_to_nu_value(x, span))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
)
|
||||||
|
.spanned(span),
|
||||||
serde_hjson::Value::Object(o) => {
|
serde_hjson::Value::Object(o) => {
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = SpannedDictBuilder::new(span);
|
||||||
for (k, v) in o.iter() {
|
for (k, v) in o.iter() {
|
||||||
collected.add(k.clone(), convert_json_value_to_nu_value(v));
|
collected.add(k.clone(), convert_json_value_to_nu_value(v, span));
|
||||||
}
|
}
|
||||||
Value::Object(collected)
|
|
||||||
|
collected.into_spanned_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_json_string_to_value(s: String) -> serde_hjson::Result<Value> {
|
pub fn from_json_string_to_value(
|
||||||
|
s: String,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> serde_hjson::Result<Spanned<Value>> {
|
||||||
let v: serde_hjson::Value = serde_hjson::from_str(&s)?;
|
let v: serde_hjson::Value = serde_hjson::from_str(&s)?;
|
||||||
Ok(convert_json_value_to_nu_value(&v))
|
Ok(convert_json_value_to_nu_value(&v, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@ -36,7 +49,7 @@ pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_json_string_to_value(s) {
|
Value::Primitive(Primitive::String(s)) => match from_json_string_to_value(s, span) {
|
||||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
"Could not parse as JSON",
|
"Could not parse as JSON",
|
||||||
|
@ -1,32 +1,44 @@
|
|||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_toml_value_to_nu_value(v: &toml::Value) -> Value {
|
fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
|
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).spanned(span),
|
||||||
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)),
|
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).spanned(span),
|
||||||
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))),
|
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).spanned(span),
|
||||||
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))),
|
toml::Value::String(s) => {
|
||||||
|
Value::Primitive(Primitive::String(String::from(s))).spanned(span)
|
||||||
|
}
|
||||||
toml::Value::Array(a) => Value::List(
|
toml::Value::Array(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_toml_value_to_nu_value(x).spanned_unknown())
|
.map(|x| convert_toml_value_to_nu_value(x, span))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
)
|
||||||
toml::Value::Datetime(dt) => Value::Primitive(Primitive::String(dt.to_string())),
|
.spanned(span),
|
||||||
|
toml::Value::Datetime(dt) => {
|
||||||
|
Value::Primitive(Primitive::String(dt.to_string())).spanned(span)
|
||||||
|
}
|
||||||
toml::Value::Table(t) => {
|
toml::Value::Table(t) => {
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
for (k, v) in t.iter() {
|
for (k, v) in t.iter() {
|
||||||
collected.add(k.clone(), convert_toml_value_to_nu_value(v));
|
collected.add(k.clone(), convert_toml_value_to_nu_value(v, span));
|
||||||
}
|
}
|
||||||
Value::Object(collected)
|
|
||||||
|
collected.into_spanned_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_toml_string_to_value(s: String) -> Result<Value, Box<dyn std::error::Error>> {
|
pub fn from_toml_string_to_value(
|
||||||
|
s: String,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Result<Spanned<Value>, Box<dyn std::error::Error>> {
|
||||||
let v: toml::Value = s.parse::<toml::Value>()?;
|
let v: toml::Value = s.parse::<toml::Value>()?;
|
||||||
Ok(convert_toml_value_to_nu_value(&v))
|
Ok(convert_toml_value_to_nu_value(&v, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@ -35,7 +47,7 @@ pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_toml_string_to_value(s) {
|
Value::Primitive(Primitive::String(s)) => match from_toml_string_to_value(s, span) {
|
||||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
"Could not parse as TOML",
|
"Could not parse as TOML",
|
||||||
|
@ -1,19 +1,27 @@
|
|||||||
use crate::object::{Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
fn from_node_to_value<'a, 'd>(
|
||||||
|
n: &roxmltree::Node<'a, 'd>,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Spanned<Value> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
if n.is_element() {
|
if n.is_element() {
|
||||||
let name = n.tag_name().name().trim().to_string();
|
let name = n.tag_name().name().trim().to_string();
|
||||||
|
|
||||||
let mut children_values = vec![];
|
let mut children_values = vec![];
|
||||||
for c in n.children() {
|
for c in n.children() {
|
||||||
children_values.push(from_node_to_value(&c));
|
children_values.push(from_node_to_value(&c, span));
|
||||||
}
|
}
|
||||||
|
|
||||||
let children_values: Vec<Spanned<Value>> = children_values
|
let children_values: Vec<Spanned<Value>> = children_values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| match x {
|
.filter(|x| match x {
|
||||||
Value::Primitive(Primitive::String(f)) => {
|
Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(f)),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
if f.trim() == "" {
|
if f.trim() == "" {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -22,31 +30,33 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
|||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
})
|
})
|
||||||
.map(|v| v.spanned_unknown())
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = Dictionary::default();
|
||||||
collected.add(name.clone(), Value::List(children_values));
|
collected.add(name.clone(), Value::List(children_values).spanned(span));
|
||||||
|
|
||||||
Value::Object(collected)
|
collected.into_spanned_value()
|
||||||
} else if n.is_comment() {
|
} else if n.is_comment() {
|
||||||
Value::string("<comment>")
|
Value::string("<comment>").spanned(span)
|
||||||
} else if n.is_pi() {
|
} else if n.is_pi() {
|
||||||
Value::string("<processing_instruction>")
|
Value::string("<processing_instruction>").spanned(span)
|
||||||
} else if n.is_text() {
|
} else if n.is_text() {
|
||||||
Value::string(n.text().unwrap())
|
Value::string(n.text().unwrap()).spanned(span)
|
||||||
} else {
|
} else {
|
||||||
Value::string("<unknown>")
|
Value::string("<unknown>").spanned(span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_document_to_value(d: &roxmltree::Document) -> Value {
|
fn from_document_to_value(d: &roxmltree::Document, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
from_node_to_value(&d.root_element())
|
from_node_to_value(&d.root_element(), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml_string_to_value(s: String) -> Result<Value, Box<dyn std::error::Error>> {
|
pub fn from_xml_string_to_value(
|
||||||
|
s: String,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Result<Spanned<Value>, Box<dyn std::error::Error>> {
|
||||||
let parsed = roxmltree::Document::parse(&s)?;
|
let parsed = roxmltree::Document::parse(&s)?;
|
||||||
Ok(from_document_to_value(&parsed))
|
Ok(from_document_to_value(&parsed, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@ -55,7 +65,7 @@ pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_xml_string_to_value(s) {
|
Value::Primitive(Primitive::String(s)) => match from_xml_string_to_value(s, span) {
|
||||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
"Could not parse as XML",
|
"Could not parse as XML",
|
||||||
|
@ -1,42 +1,50 @@
|
|||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value) -> Value {
|
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)),
|
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).spanned(span),
|
||||||
serde_yaml::Value::Number(n) if n.is_i64() => {
|
serde_yaml::Value::Number(n) if n.is_i64() => {
|
||||||
Value::Primitive(Primitive::Int(n.as_i64().unwrap()))
|
Value::Primitive(Primitive::Int(n.as_i64().unwrap())).spanned(span)
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||||
Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap())))
|
Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap()))).spanned(span)
|
||||||
}
|
}
|
||||||
serde_yaml::Value::String(s) => Value::string(s),
|
serde_yaml::Value::String(s) => Value::string(s).spanned(span),
|
||||||
serde_yaml::Value::Sequence(a) => Value::List(
|
serde_yaml::Value::Sequence(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_yaml_value_to_nu_value(x).spanned_unknown())
|
.map(|x| convert_yaml_value_to_nu_value(x, span))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
)
|
||||||
|
.spanned(span),
|
||||||
serde_yaml::Value::Mapping(t) => {
|
serde_yaml::Value::Mapping(t) => {
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
for (k, v) in t.iter() {
|
for (k, v) in t.iter() {
|
||||||
match k {
|
match k {
|
||||||
serde_yaml::Value::String(k) => {
|
serde_yaml::Value::String(k) => {
|
||||||
collected.add(k.clone(), convert_yaml_value_to_nu_value(v));
|
collected.add(k.clone(), convert_yaml_value_to_nu_value(v, span));
|
||||||
}
|
}
|
||||||
_ => unimplemented!("Unknown key type"),
|
_ => unimplemented!("Unknown key type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Object(collected)
|
|
||||||
|
collected.into_spanned_value()
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing),
|
serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing).spanned(span),
|
||||||
x => unimplemented!("Unsupported yaml case: {:?}", x),
|
x => unimplemented!("Unsupported yaml case: {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_yaml_string_to_value(s: String) -> serde_yaml::Result<Value> {
|
pub fn from_yaml_string_to_value(
|
||||||
|
s: String,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> serde_yaml::Result<Spanned<Value>> {
|
||||||
let v: serde_yaml::Value = serde_yaml::from_str(&s)?;
|
let v: serde_yaml::Value = serde_yaml::from_str(&s)?;
|
||||||
Ok(convert_yaml_value_to_nu_value(&v))
|
Ok(convert_yaml_value_to_nu_value(&v, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@ -45,7 +53,7 @@ pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_yaml_string_to_value(s) {
|
Value::Primitive(Primitive::String(s)) => match from_yaml_string_to_value(s, span) {
|
||||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
"Could not parse as YAML",
|
"Could not parse as YAML",
|
||||||
|
@ -44,8 +44,8 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let mut shell_entries = VecDeque::new();
|
let mut shell_entries = VecDeque::new();
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let value = Value::Object(dir_entry_dict(&entry?)?);
|
let value = dir_entry_dict(&entry?, args.name_span)?;
|
||||||
shell_entries.push_back(ReturnSuccess::value(value.spanned_unknown()))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
Ok(shell_entries.to_output_stream())
|
Ok(shell_entries.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -155,60 +155,72 @@ pub fn parse_as_value(
|
|||||||
name_span: Option<Span>,
|
name_span: Option<Span>,
|
||||||
) -> Result<Spanned<Value>, ShellError> {
|
) -> Result<Spanned<Value>, ShellError> {
|
||||||
match extension {
|
match extension {
|
||||||
Some(x) if x == "toml" => crate::commands::from_toml::from_toml_string_to_value(contents)
|
Some(x) if x == "toml" => {
|
||||||
.map(|c| c.spanned(contents_span))
|
crate::commands::from_toml::from_toml_string_to_value(contents, contents_span)
|
||||||
.map_err(move |_| {
|
.map(|c| c.spanned(contents_span))
|
||||||
ShellError::maybe_labeled_error(
|
.map_err(move |_| {
|
||||||
"Could not open as TOML",
|
ShellError::maybe_labeled_error(
|
||||||
"could not open as TOML",
|
"Could not open as TOML",
|
||||||
name_span,
|
"could not open as TOML",
|
||||||
)
|
name_span,
|
||||||
}),
|
)
|
||||||
Some(x) if x == "json" => crate::commands::from_json::from_json_string_to_value(contents)
|
})
|
||||||
.map(|c| c.spanned(contents_span))
|
}
|
||||||
.map_err(move |_| {
|
Some(x) if x == "json" => {
|
||||||
ShellError::maybe_labeled_error(
|
crate::commands::from_json::from_json_string_to_value(contents, contents_span)
|
||||||
"Could not open as JSON",
|
.map(|c| c.spanned(contents_span))
|
||||||
"could not open as JSON",
|
.map_err(move |_| {
|
||||||
name_span,
|
ShellError::maybe_labeled_error(
|
||||||
)
|
"Could not open as JSON",
|
||||||
}),
|
"could not open as JSON",
|
||||||
Some(x) if x == "ini" => crate::commands::from_ini::from_ini_string_to_value(contents)
|
name_span,
|
||||||
.map(|c| c.spanned(contents_span))
|
)
|
||||||
.map_err(move |_| {
|
})
|
||||||
ShellError::maybe_labeled_error(
|
}
|
||||||
"Could not open as INI",
|
Some(x) if x == "ini" => {
|
||||||
"could not open as INI",
|
crate::commands::from_ini::from_ini_string_to_value(contents, contents_span)
|
||||||
name_span,
|
.map(|c| c.spanned(contents_span))
|
||||||
)
|
.map_err(move |_| {
|
||||||
}),
|
ShellError::maybe_labeled_error(
|
||||||
Some(x) if x == "xml" => crate::commands::from_xml::from_xml_string_to_value(contents)
|
"Could not open as INI",
|
||||||
.map(|c| c.spanned(contents_span))
|
"could not open as INI",
|
||||||
.map_err(move |_| {
|
name_span,
|
||||||
ShellError::maybe_labeled_error(
|
)
|
||||||
"Could not open as XML",
|
})
|
||||||
"could not open as XML",
|
}
|
||||||
name_span,
|
Some(x) if x == "xml" => {
|
||||||
)
|
crate::commands::from_xml::from_xml_string_to_value(contents, contents_span).map_err(
|
||||||
}),
|
move |_| {
|
||||||
Some(x) if x == "yml" => crate::commands::from_yaml::from_yaml_string_to_value(contents)
|
ShellError::maybe_labeled_error(
|
||||||
.map(|c| c.spanned(contents_span))
|
"Could not open as XML",
|
||||||
.map_err(move |_| {
|
"could not open as XML",
|
||||||
ShellError::maybe_labeled_error(
|
name_span,
|
||||||
"Could not open as YAML",
|
)
|
||||||
"could not open as YAML",
|
},
|
||||||
name_span,
|
)
|
||||||
)
|
}
|
||||||
}),
|
Some(x) if x == "yml" => {
|
||||||
Some(x) if x == "yaml" => crate::commands::from_yaml::from_yaml_string_to_value(contents)
|
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err(
|
||||||
.map(|c| c.spanned(contents_span))
|
move |_| {
|
||||||
.map_err(move |_| {
|
ShellError::maybe_labeled_error(
|
||||||
ShellError::maybe_labeled_error(
|
"Could not open as YAML",
|
||||||
"Could not open as YAML",
|
"could not open as YAML",
|
||||||
"could not open as YAML",
|
name_span,
|
||||||
name_span,
|
)
|
||||||
)
|
},
|
||||||
}),
|
)
|
||||||
|
}
|
||||||
|
Some(x) if x == "yaml" => {
|
||||||
|
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err(
|
||||||
|
move |_| {
|
||||||
|
ShellError::maybe_labeled_error(
|
||||||
|
"Could not open as YAML",
|
||||||
|
"could not open as YAML",
|
||||||
|
name_span,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
_ => Ok(Value::string(contents).spanned(contents_span)),
|
_ => Ok(Value::string(contents).spanned(contents_span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let objects = input
|
let objects = input
|
||||||
.values
|
.values
|
||||||
.map(move |value| Value::Object(select_fields(&value.item, &fields)).spanned(value.span));
|
.map(move |value| select_fields(&value.item, &fields, value.span));
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
Ok(objects.from_input_stream())
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ pub fn ps(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let list = list
|
let list = list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(item, process)| Value::Object(process_dict(process)).spanned(args.name_span))
|
.map(|(item, process)| process_dict(process, args.name_span))
|
||||||
.collect::<VecDeque<_>>();
|
.collect::<VecDeque<_>>();
|
||||||
|
|
||||||
Ok(list.from_input_stream())
|
Ok(list.from_input_stream())
|
||||||
|
@ -4,6 +4,8 @@ use crate::object::Value;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let name_span = args.name_span;
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Reject requires fields",
|
"Reject requires fields",
|
||||||
@ -15,10 +17,11 @@ pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let fields: Result<Vec<String>, _> = args.positional_iter().map(|a| a.as_string()).collect();
|
let fields: Result<Vec<String>, _> = args.positional_iter().map(|a| a.as_string()).collect();
|
||||||
let fields = fields?;
|
let fields = fields?;
|
||||||
|
|
||||||
let stream = args
|
let stream = args.input.values.map(move |item| {
|
||||||
.input
|
reject_fields(&item, &fields, item.span)
|
||||||
.values
|
.into_spanned_value()
|
||||||
.map(move |item| Value::Object(reject_fields(&item, &fields)).spanned(args.name_span));
|
.spanned(name_span)
|
||||||
|
});
|
||||||
|
|
||||||
Ok(stream.from_input_stream())
|
Ok(stream.from_input_stream())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::dict::Dictionary;
|
use crate::object::{SpannedDictBuilder, Value};
|
||||||
use crate::object::Value;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
@ -30,14 +29,14 @@ pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let path = cwd.join(&name);
|
let path = cwd.join(&name);
|
||||||
let mut file = File::open(path)?;
|
let mut file = File::open(path)?;
|
||||||
file.read_to_string(&mut contents)?;
|
file.read_to_string(&mut contents)?;
|
||||||
list.push_back(count(&name, &contents).spanned(spanned_name).into());
|
list.push_back(count(&name, &contents, spanned_name).into());
|
||||||
contents.clear();
|
contents.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(list.to_output_stream())
|
Ok(list.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count(name: &str, contents: &str) -> Value {
|
fn count(name: &str, contents: &str, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
let mut lines: i64 = 0;
|
let mut lines: i64 = 0;
|
||||||
let mut words: i64 = 0;
|
let mut words: i64 = 0;
|
||||||
let mut chars: i64 = 0;
|
let mut chars: i64 = 0;
|
||||||
@ -62,12 +61,12 @@ fn count(name: &str, contents: &str) -> Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dict = Dictionary::default();
|
let mut dict = SpannedDictBuilder::new(span);
|
||||||
dict.add("name", Value::string(name));
|
dict.insert("name", Value::string(name));
|
||||||
dict.add("lines", Value::int(lines));
|
dict.insert("lines", Value::int(lines));
|
||||||
dict.add("words", Value::int(words));
|
dict.insert("words", Value::int(words));
|
||||||
dict.add("chars", Value::int(chars));
|
dict.insert("chars", Value::int(chars));
|
||||||
dict.add("max length", Value::int(bytes));
|
dict.insert("max length", Value::int(bytes));
|
||||||
|
|
||||||
Value::Object(dict)
|
dict.into_spanned_value()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::{Primitive, Value};
|
use crate::object::{Primitive, SpannedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
@ -36,29 +36,27 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
gen_columns.push(format!("Column{}", i + 1));
|
gen_columns.push(format!("Column{}", i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dict = crate::object::Dictionary::default();
|
let mut dict = SpannedDictBuilder::new(v.span);
|
||||||
for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
|
for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
|
||||||
dict.add(v.clone(), Value::Primitive(Primitive::String(k.into())));
|
dict.insert(v.clone(), Primitive::String(k.into()));
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
|
||||||
|
ReturnSuccess::value(dict.into_spanned_value())
|
||||||
} else if split_result.len() == (positional.len() - 1) {
|
} else if split_result.len() == (positional.len() - 1) {
|
||||||
let mut dict = crate::object::Dictionary::default();
|
let mut dict = SpannedDictBuilder::new(v.span);
|
||||||
for (&k, v) in split_result.iter().zip(positional.iter().skip(1)) {
|
for (&k, v) in split_result.iter().zip(positional.iter().skip(1)) {
|
||||||
dict.add(
|
dict.insert(
|
||||||
v.as_string().unwrap(),
|
v.as_string().unwrap(),
|
||||||
Value::Primitive(Primitive::String(k.into())),
|
Value::Primitive(Primitive::String(k.into())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
ReturnSuccess::value(dict.into_spanned_value())
|
||||||
} else {
|
} else {
|
||||||
let mut dict = crate::object::Dictionary::default();
|
let mut dict = SpannedDictBuilder::new(v.span);
|
||||||
for k in positional.iter().skip(1) {
|
for k in positional.iter().skip(1) {
|
||||||
dict.add(
|
dict.insert(k.as_string().unwrap().trim(), Primitive::String("".into()));
|
||||||
k.as_string().unwrap().trim(),
|
|
||||||
Value::Primitive(Primitive::String("".into())),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
ReturnSuccess::value(dict.into_spanned_value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::maybe_labeled_error(
|
||||||
|
@ -43,17 +43,17 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
|||||||
|
|
||||||
pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let name_span = args.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match serde_json::to_string(&a) {
|
.map(move |a| match serde_json::to_string(&a) {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).spanned(args.name_span))
|
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).spanned(name_span))
|
||||||
}
|
}
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
"Can not convert to JSON string",
|
"Can not convert to JSON string",
|
||||||
"can not convert piped data to JSON string",
|
"can not convert piped data to JSON string",
|
||||||
span,
|
name_span,
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
@ -33,18 +33,40 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
|||||||
|
|
||||||
pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let name_span = args.name_span;
|
||||||
|
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match toml::to_string(&a) {
|
.map(move |a| {
|
||||||
Ok(x) => {
|
match toml::to_string(&a) {
|
||||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).spanned(args.name_span))
|
Ok(val) => {
|
||||||
|
return ReturnSuccess::value(
|
||||||
|
Value::Primitive(Primitive::String(val)).spanned(name_span),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(err) => Err(ShellError::type_error(
|
||||||
|
"String",
|
||||||
|
format!("{:?} - {:?}", a.type_name(), err).spanned(name_span),
|
||||||
|
)), // toml::Value::String(String) => {
|
||||||
|
// return ReturnSuccess::value(
|
||||||
|
// Value::Primitive(Primitive::String(x)).spanned(name_span),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// toml::Value::Integer(i64) => "Integer",
|
||||||
|
// toml::Value::Float(f64) => "Decimal",
|
||||||
|
// toml::Value::Boolean(bool) => "Boolean",
|
||||||
|
// toml::Value::Datetime(Datetime) => "Date",
|
||||||
|
// toml::Value::Array(Array) => "Array",
|
||||||
|
// toml::Value::Table(Table) => "Table",
|
||||||
}
|
}
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
// return Err(ShellError::type_error("String", ty.spanned(name_span)));
|
||||||
"Can not convert to TOML string",
|
|
||||||
"can not convert piped data to TOML string",
|
// Err(_) => Err(ShellError::maybe_labeled_error(
|
||||||
span,
|
// "Can not convert to TOML string",
|
||||||
)),
|
// "can not convert piped data to TOML string",
|
||||||
|
// name_span,
|
||||||
|
// )),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.values
|
.values
|
||||||
.map(move |v| ReturnSuccess::value(String::check(&v)?.clone()))
|
.map(move |v| {
|
||||||
|
let string = String::extract(&v)?;
|
||||||
|
ReturnSuccess::value(Value::string(string.trim()).spanned(v.span))
|
||||||
|
})
|
||||||
// Value::Primitive(Primitive::String(s)) => {
|
// Value::Primitive(Primitive::String(s)) => {
|
||||||
// ReturnSuccess::value(Value::Primitive(Primitive::String(s.trim().into())))
|
// ReturnSuccess::value(Value::Primitive(Primitive::String(s.trim().into())))
|
||||||
// }
|
// }
|
||||||
|
@ -46,5 +46,5 @@ pub fn view(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let _ = printer.file(file.display().to_string());
|
let _ = printer.file(file.display().to_string());
|
||||||
|
|
||||||
Ok(VecDeque::new().into())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
162
src/errors.rs
162
src/errors.rs
@ -52,26 +52,9 @@ pub fn labelled(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub enum ShellError {
|
pub struct ShellError {
|
||||||
String(StringError),
|
error: ProximateShellError,
|
||||||
TypeError {
|
cause: Option<Box<ProximateShellError>>,
|
||||||
expected: String,
|
|
||||||
actual: Spanned<Option<String>>,
|
|
||||||
},
|
|
||||||
MissingProperty {
|
|
||||||
subpath: Description,
|
|
||||||
expr: Description,
|
|
||||||
},
|
|
||||||
ArgumentError {
|
|
||||||
command: String,
|
|
||||||
error: ArgumentError,
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
Diagnostic(ShellDiagnostic),
|
|
||||||
CoerceError {
|
|
||||||
left: Spanned<String>,
|
|
||||||
right: Spanned<String>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellError {
|
impl ShellError {
|
||||||
@ -79,10 +62,39 @@ impl ShellError {
|
|||||||
expected: impl Into<String>,
|
expected: impl Into<String>,
|
||||||
actual: Spanned<impl Into<String>>,
|
actual: Spanned<impl Into<String>>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ShellError::TypeError {
|
ProximateShellError::TypeError {
|
||||||
expected: expected.into(),
|
expected: expected.into(),
|
||||||
actual: actual.map(|i| Some(i.into())),
|
actual: actual.map(|i| Some(i.into())),
|
||||||
}
|
}
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn coerce_error(
|
||||||
|
left: Spanned<impl Into<String>>,
|
||||||
|
right: Spanned<impl Into<String>>,
|
||||||
|
) -> ShellError {
|
||||||
|
ProximateShellError::CoerceError {
|
||||||
|
left: left.map(|l| l.into()),
|
||||||
|
right: right.map(|r| r.into()),
|
||||||
|
}
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn missing_property(subpath: Description, expr: Description) -> ShellError {
|
||||||
|
ProximateShellError::MissingProperty { subpath, expr }.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn argument_error(
|
||||||
|
command: impl Into<String>,
|
||||||
|
kind: ArgumentError,
|
||||||
|
span: Span,
|
||||||
|
) -> ShellError {
|
||||||
|
ProximateShellError::ArgumentError {
|
||||||
|
command: command.into(),
|
||||||
|
error: kind,
|
||||||
|
span: span,
|
||||||
|
}
|
||||||
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn parse_error(
|
crate fn parse_error(
|
||||||
@ -97,40 +109,20 @@ impl ShellError {
|
|||||||
.with_label(Label::new_primary(Span::from(span.0)));
|
.with_label(Label::new_primary(Span::from(span.0)));
|
||||||
|
|
||||||
ShellError::diagnostic(diagnostic)
|
ShellError::diagnostic(diagnostic)
|
||||||
// nom::Context::Code(span, kind) => {
|
}
|
||||||
// let diagnostic =
|
|
||||||
// Diagnostic::new(Severity::Error, format!("{}", kind.description()))
|
|
||||||
// .with_label(Label::new_primary(Span::from(span)));
|
|
||||||
|
|
||||||
// ShellError::diagnostic(diagnostic)
|
|
||||||
// }
|
|
||||||
} // ParseError::UnrecognizedToken {
|
|
||||||
// token: (start, SpannedToken { token, .. }, end),
|
|
||||||
// expected,
|
|
||||||
// } => {
|
|
||||||
// let diagnostic = Diagnostic::new(
|
|
||||||
// Severity::Error,
|
|
||||||
// format!("Unexpected {:?}, expected {:?}", token, expected),
|
|
||||||
// )
|
|
||||||
// .with_label(Label::new_primary(Span::from((start, end))));
|
|
||||||
|
|
||||||
// ShellError::diagnostic(diagnostic)
|
|
||||||
// }
|
|
||||||
// ParseError::User { error } => error,
|
|
||||||
// other => ShellError::string(format!("{:?}", other)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
crate fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
||||||
ShellError::Diagnostic(ShellDiagnostic { diagnostic })
|
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn to_diagnostic(self) -> Diagnostic<Span> {
|
crate fn to_diagnostic(self) -> Diagnostic<Span> {
|
||||||
match self {
|
match self.error {
|
||||||
ShellError::String(StringError { title, .. }) => {
|
ProximateShellError::String(StringError { title, .. }) => {
|
||||||
Diagnostic::new(Severity::Error, title)
|
Diagnostic::new(Severity::Error, title)
|
||||||
}
|
}
|
||||||
ShellError::ArgumentError {
|
ProximateShellError::ArgumentError {
|
||||||
command,
|
command,
|
||||||
error,
|
error,
|
||||||
span,
|
span,
|
||||||
@ -166,7 +158,7 @@ impl ShellError {
|
|||||||
)
|
)
|
||||||
.with_label(Label::new_primary(span)),
|
.with_label(Label::new_primary(span)),
|
||||||
},
|
},
|
||||||
ShellError::TypeError {
|
ProximateShellError::TypeError {
|
||||||
expected,
|
expected,
|
||||||
actual:
|
actual:
|
||||||
Spanned {
|
Spanned {
|
||||||
@ -178,13 +170,13 @@ impl ShellError {
|
|||||||
.with_message(format!("Expected {}, found {}", expected, actual)),
|
.with_message(format!("Expected {}, found {}", expected, actual)),
|
||||||
),
|
),
|
||||||
|
|
||||||
ShellError::TypeError {
|
ProximateShellError::TypeError {
|
||||||
expected,
|
expected,
|
||||||
actual: Spanned { item: None, span },
|
actual: Spanned { item: None, span },
|
||||||
} => Diagnostic::new(Severity::Error, "Type Error")
|
} => Diagnostic::new(Severity::Error, "Type Error")
|
||||||
.with_label(Label::new_primary(span).with_message(expected)),
|
.with_label(Label::new_primary(span).with_message(expected)),
|
||||||
|
|
||||||
ShellError::MissingProperty { subpath, expr } => {
|
ProximateShellError::MissingProperty { subpath, expr } => {
|
||||||
let subpath = subpath.into_label();
|
let subpath = subpath.into_label();
|
||||||
let expr = expr.into_label();
|
let expr = expr.into_label();
|
||||||
|
|
||||||
@ -202,8 +194,8 @@ impl ShellError {
|
|||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellError::Diagnostic(diag) => diag.diagnostic,
|
ProximateShellError::Diagnostic(diag) => diag.diagnostic,
|
||||||
ShellError::CoerceError { left, right } => {
|
ProximateShellError::CoerceError { left, right } => {
|
||||||
Diagnostic::new(Severity::Error, "Coercion error")
|
Diagnostic::new(Severity::Error, "Coercion error")
|
||||||
.with_label(Label::new_primary(left.span).with_message(left.item))
|
.with_label(Label::new_primary(left.span).with_message(left.item))
|
||||||
.with_label(Label::new_secondary(right.span).with_message(right.item))
|
.with_label(Label::new_secondary(right.span).with_message(right.item))
|
||||||
@ -237,7 +229,7 @@ impl ShellError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string(title: impl Into<String>) -> ShellError {
|
pub fn string(title: impl Into<String>) -> ShellError {
|
||||||
ShellError::String(StringError::new(title.into(), Value::nothing()))
|
ProximateShellError::String(StringError::new(title.into(), Value::nothing())).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn unimplemented(title: impl Into<String>) -> ShellError {
|
crate fn unimplemented(title: impl Into<String>) -> ShellError {
|
||||||
@ -249,6 +241,37 @@ impl ShellError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
pub enum ProximateShellError {
|
||||||
|
String(StringError),
|
||||||
|
TypeError {
|
||||||
|
expected: String,
|
||||||
|
actual: Spanned<Option<String>>,
|
||||||
|
},
|
||||||
|
MissingProperty {
|
||||||
|
subpath: Description,
|
||||||
|
expr: Description,
|
||||||
|
},
|
||||||
|
ArgumentError {
|
||||||
|
command: String,
|
||||||
|
error: ArgumentError,
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
Diagnostic(ShellDiagnostic),
|
||||||
|
CoerceError {
|
||||||
|
left: Spanned<String>,
|
||||||
|
right: Spanned<String>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
impl ProximateShellError {
|
||||||
|
fn start(self) -> ShellError {
|
||||||
|
ShellError {
|
||||||
|
cause: None,
|
||||||
|
error: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ShellDiagnostic {
|
pub struct ShellDiagnostic {
|
||||||
crate diagnostic: Diagnostic<Span>,
|
crate diagnostic: Diagnostic<Span>,
|
||||||
@ -322,13 +345,13 @@ pub struct StringError {
|
|||||||
|
|
||||||
impl std::fmt::Display for ShellError {
|
impl std::fmt::Display for ShellError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match &self.error {
|
||||||
ShellError::String(s) => write!(f, "{}", &s.title),
|
ProximateShellError::String(s) => write!(f, "{}", &s.title),
|
||||||
ShellError::TypeError { .. } => write!(f, "TypeError"),
|
ProximateShellError::TypeError { .. } => write!(f, "TypeError"),
|
||||||
ShellError::MissingProperty { .. } => write!(f, "MissingProperty"),
|
ProximateShellError::MissingProperty { .. } => write!(f, "MissingProperty"),
|
||||||
ShellError::ArgumentError { .. } => write!(f, "ArgumentError"),
|
ProximateShellError::ArgumentError { .. } => write!(f, "ArgumentError"),
|
||||||
ShellError::Diagnostic(_) => write!(f, "<diagnostic>"),
|
ProximateShellError::Diagnostic(_) => write!(f, "<diagnostic>"),
|
||||||
ShellError::CoerceError { .. } => write!(f, "CoerceError"),
|
ProximateShellError::CoerceError { .. } => write!(f, "CoerceError"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,45 +360,40 @@ impl std::error::Error for ShellError {}
|
|||||||
|
|
||||||
impl std::convert::From<std::io::Error> for ShellError {
|
impl std::convert::From<std::io::Error> for ShellError {
|
||||||
fn from(input: std::io::Error) -> ShellError {
|
fn from(input: std::io::Error) -> ShellError {
|
||||||
ShellError::String(StringError {
|
ProximateShellError::String(StringError {
|
||||||
title: format!("{}", input),
|
title: format!("{}", input),
|
||||||
error: Value::nothing(),
|
error: Value::nothing(),
|
||||||
})
|
})
|
||||||
|
.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<futures_sink::VecSinkError> for ShellError {
|
impl std::convert::From<futures_sink::VecSinkError> for ShellError {
|
||||||
fn from(_input: futures_sink::VecSinkError) -> ShellError {
|
fn from(_input: futures_sink::VecSinkError) -> ShellError {
|
||||||
ShellError::String(StringError {
|
ProximateShellError::String(StringError {
|
||||||
title: format!("Unexpected Vec Sink Error"),
|
title: format!("Unexpected Vec Sink Error"),
|
||||||
error: Value::nothing(),
|
error: Value::nothing(),
|
||||||
})
|
})
|
||||||
|
.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<subprocess::PopenError> for ShellError {
|
impl std::convert::From<subprocess::PopenError> for ShellError {
|
||||||
fn from(input: subprocess::PopenError) -> ShellError {
|
fn from(input: subprocess::PopenError) -> ShellError {
|
||||||
ShellError::String(StringError {
|
ProximateShellError::String(StringError {
|
||||||
title: format!("{}", input),
|
title: format!("{}", input),
|
||||||
error: Value::nothing(),
|
error: Value::nothing(),
|
||||||
})
|
})
|
||||||
|
.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl std::convert::From<nom::Err<(&str, nom::ErrorKind)>> for ShellError {
|
|
||||||
// fn from(input: nom::Err<(&str, nom::ErrorKind)>) -> ShellError {
|
|
||||||
// ShellError::String(StringError {
|
|
||||||
// title: format!("{:?}", input),
|
|
||||||
// error: Value::nothing(),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl std::convert::From<toml::ser::Error> for ShellError {
|
impl std::convert::From<toml::ser::Error> for ShellError {
|
||||||
fn from(input: toml::ser::Error) -> ShellError {
|
fn from(input: toml::ser::Error) -> ShellError {
|
||||||
ShellError::String(StringError {
|
ProximateShellError::String(StringError {
|
||||||
title: format!("{:?}", input),
|
title: format!("{:?}", input),
|
||||||
error: Value::nothing(),
|
error: Value::nothing(),
|
||||||
})
|
})
|
||||||
|
.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,10 @@ crate fn evaluate_baseline_expr(
|
|||||||
|
|
||||||
match left.compare(binary.op(), &*right) {
|
match left.compare(binary.op(), &*right) {
|
||||||
Ok(result) => Ok(Spanned::from_item(Value::boolean(result), *expr.span())),
|
Ok(result) => Ok(Spanned::from_item(Value::boolean(result), *expr.span())),
|
||||||
Err((left_type, right_type)) => Err(ShellError::CoerceError {
|
Err((left_type, right_type)) => Err(ShellError::coerce_error(
|
||||||
left: binary.left().copy_span(left_type),
|
binary.left().copy_span(left_type),
|
||||||
right: binary.right().copy_span(right_type),
|
binary.right().copy_span(right_type),
|
||||||
}),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RawExpression::Block(block) => Ok(Spanned::from_item(
|
RawExpression::Block(block) => Ok(Spanned::from_item(
|
||||||
@ -58,10 +58,10 @@ crate fn evaluate_baseline_expr(
|
|||||||
|
|
||||||
match next {
|
match next {
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::MissingProperty {
|
return Err(ShellError::missing_property(
|
||||||
subpath: Description::from(item.spanned_type_name()),
|
Description::from(item.spanned_type_name()),
|
||||||
expr: Description::from(name.clone()),
|
Description::from(name.clone()),
|
||||||
})
|
))
|
||||||
}
|
}
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
item = Spanned::from_item(
|
item = Spanned::from_item(
|
||||||
@ -95,7 +95,7 @@ fn evaluate_reference(
|
|||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<Spanned<Value>, ShellError> {
|
) -> Result<Spanned<Value>, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
hir::Variable::It(span) => Ok(Spanned::from_item(scope.it.item, span)),
|
hir::Variable::It(span) => Ok(Spanned::from_item(scope.it.item.clone(), span)),
|
||||||
hir::Variable::Other(span) => Ok(scope
|
hir::Variable::Other(span) => Ok(scope
|
||||||
.vars
|
.vars
|
||||||
.get(span.slice(source))
|
.get(span.slice(source))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||||
|
use crate::object::SpannedDictBuilder;
|
||||||
use crate::parser::{hir, Operator, Span, Spanned};
|
use crate::parser::{hir, Operator, Span, Spanned};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::Text;
|
use crate::Text;
|
||||||
@ -505,34 +506,34 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn select_fields(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
|
crate fn select_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Spanned<Value> {
|
||||||
let mut out = crate::object::Dictionary::default();
|
let mut out = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
for field in fields {
|
for field in fields {
|
||||||
match descs.iter().find(|d| d.name.is_string(field)) {
|
match descs.iter().find(|d| d.name.is_string(field)) {
|
||||||
None => out.add(field, Value::nothing()),
|
None => out.insert(field, Value::nothing()),
|
||||||
Some(desc) => out.add(desc.clone(), obj.get_data(desc).borrow().clone()),
|
Some(desc) => out.insert(desc.clone(), obj.get_data(desc).borrow().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out
|
out.into_spanned_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
|
crate fn reject_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Spanned<Value> {
|
||||||
let mut out = crate::object::Dictionary::default();
|
let mut out = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
for desc in descs {
|
for desc in descs {
|
||||||
match desc {
|
match desc {
|
||||||
x if fields.iter().any(|field| *field == x) => continue,
|
x if fields.iter().any(|field| *field == x) => continue,
|
||||||
_ => out.add(desc.clone(), obj.get_data(&desc).borrow().clone()),
|
_ => out.insert(desc.clone(), obj.get_data(&desc).borrow().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out
|
out.into_spanned_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -27,10 +27,7 @@ crate fn write_config(config: &IndexMap<String, Spanned<Value>>) -> Result<(), S
|
|||||||
touch(&filename)?;
|
touch(&filename)?;
|
||||||
|
|
||||||
let contents = toml::to_string(&Config {
|
let contents = toml::to_string(&Config {
|
||||||
extra: config
|
extra: config.iter().map(|(k, v)| (k.clone(), v.clone())).collect(),
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.item.clone()))
|
|
||||||
.collect(),
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
fs::write(&filename, &contents)?;
|
fs::write(&filename, &contents)?;
|
||||||
@ -54,7 +51,6 @@ crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Spanned<Value>
|
|||||||
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
||||||
|
|
||||||
let parsed: Config = toml::from_str(&contents)
|
let parsed: Config = toml::from_str(&contents)
|
||||||
.map(|v| v.spanned(span))
|
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
|
||||||
|
|
||||||
Ok(parsed.extra)
|
Ok(parsed.extra)
|
||||||
|
@ -21,8 +21,8 @@ impl PartialOrd for Dictionary {
|
|||||||
return this.partial_cmp(&that);
|
return this.partial_cmp(&that);
|
||||||
}
|
}
|
||||||
|
|
||||||
let this: Vec<&Value> = self.entries.values().collect();
|
let this: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
|
||||||
let that: Vec<&Value> = self.entries.values().collect();
|
let that: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
|
||||||
|
|
||||||
this.partial_cmp(&that)
|
this.partial_cmp(&that)
|
||||||
}
|
}
|
||||||
@ -49,8 +49,8 @@ impl Ord for Dictionary {
|
|||||||
return this.cmp(&that);
|
return this.cmp(&that);
|
||||||
}
|
}
|
||||||
|
|
||||||
let this: Vec<&Value> = self.entries.values().collect();
|
let this: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
|
||||||
let that: Vec<&Value> = self.entries.values().collect();
|
let that: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
|
||||||
|
|
||||||
this.cmp(&that)
|
this.cmp(&that)
|
||||||
}
|
}
|
||||||
@ -72,8 +72,8 @@ impl PartialEq<Value> for Dictionary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Dictionary {
|
impl Dictionary {
|
||||||
crate fn add(&mut self, name: impl Into<String>, value: Value) {
|
crate fn add(&mut self, name: impl Into<String>, value: impl Into<Spanned<Value>>) {
|
||||||
self.entries.insert(name.into(), value);
|
self.entries.insert(name.into(), value.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn copy_dict(&self) -> Dictionary {
|
crate fn copy_dict(&self) -> Dictionary {
|
||||||
@ -115,6 +115,38 @@ impl Dictionary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SpannedListBuilder {
|
||||||
|
span: Span,
|
||||||
|
list: Vec<Spanned<Value>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpannedListBuilder {
|
||||||
|
pub fn new(span: impl Into<Span>) -> SpannedListBuilder {
|
||||||
|
SpannedListBuilder {
|
||||||
|
span: span.into(),
|
||||||
|
list: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, value: impl Into<Value>) {
|
||||||
|
self.list.push(value.into().spanned(self.span));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_spanned(&mut self, value: impl Into<Spanned<Value>>) {
|
||||||
|
self.list.push(value.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_spanned_value(self) -> Spanned<Value> {
|
||||||
|
Value::List(self.list).spanned(self.span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SpannedListBuilder> for Spanned<Value> {
|
||||||
|
fn from(input: SpannedListBuilder) -> Spanned<Value> {
|
||||||
|
input.into_spanned_value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpannedDictBuilder {
|
pub struct SpannedDictBuilder {
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -143,7 +175,11 @@ impl SpannedDictBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_spanned_value(self) -> Spanned<Value> {
|
pub fn into_spanned_value(self) -> Spanned<Value> {
|
||||||
Value::Object(Dictionary { entries: self.dict }).spanned(self.span)
|
self.into_spanned_dict().map(Value::Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_spanned_dict(self) -> Spanned<Dictionary> {
|
||||||
|
Dictionary { entries: self.dict }.spanned(self.span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::{Dictionary, Value};
|
use crate::object::{Dictionary, SpannedDictBuilder, Value};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FileType {
|
pub enum FileType {
|
||||||
@ -8,10 +9,13 @@ pub enum FileType {
|
|||||||
Symlink,
|
Symlink,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn dir_entry_dict(entry: &std::fs::DirEntry) -> Result<Dictionary, ShellError> {
|
crate fn dir_entry_dict(
|
||||||
let mut dict = Dictionary::default();
|
entry: &std::fs::DirEntry,
|
||||||
|
span: impl Into<Span>,
|
||||||
|
) -> Result<Spanned<Value>, ShellError> {
|
||||||
|
let mut dict = SpannedDictBuilder::new(span);
|
||||||
let filename = entry.file_name();
|
let filename = entry.file_name();
|
||||||
dict.add("file name", Value::string(filename.to_string_lossy()));
|
dict.insert("file name", Value::string(filename.to_string_lossy()));
|
||||||
|
|
||||||
let metadata = entry.metadata()?;
|
let metadata = entry.metadata()?;
|
||||||
|
|
||||||
@ -23,28 +27,28 @@ crate fn dir_entry_dict(entry: &std::fs::DirEntry) -> Result<Dictionary, ShellEr
|
|||||||
FileType::Symlink
|
FileType::Symlink
|
||||||
};
|
};
|
||||||
|
|
||||||
dict.add("file type", Value::string(format!("{:?}", kind)));
|
dict.insert("file type", Value::string(format!("{:?}", kind)));
|
||||||
dict.add(
|
dict.insert(
|
||||||
"readonly",
|
"readonly",
|
||||||
Value::boolean(metadata.permissions().readonly()),
|
Value::boolean(metadata.permissions().readonly()),
|
||||||
);
|
);
|
||||||
|
|
||||||
dict.add("size", Value::bytes(metadata.len() as u64));
|
dict.insert("size", Value::bytes(metadata.len() as u64));
|
||||||
|
|
||||||
match metadata.created() {
|
match metadata.created() {
|
||||||
Ok(c) => dict.add("created", Value::system_date(c)),
|
Ok(c) => dict.insert("created", Value::system_date(c)),
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match metadata.accessed() {
|
match metadata.accessed() {
|
||||||
Ok(a) => dict.add("accessed", Value::system_date(a)),
|
Ok(a) => dict.insert("accessed", Value::system_date(a)),
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match metadata.modified() {
|
match metadata.modified() {
|
||||||
Ok(m) => dict.add("modified", Value::system_date(m)),
|
Ok(m) => dict.insert("modified", Value::system_date(m)),
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(dict)
|
Ok(dict.into_spanned_value())
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::object::base::Value;
|
use crate::object::{SpannedDictBuilder, Value};
|
||||||
use crate::object::dict::Dictionary;
|
use crate::prelude::*;
|
||||||
use itertools::join;
|
use itertools::join;
|
||||||
use sysinfo::ProcessExt;
|
use sysinfo::ProcessExt;
|
||||||
|
|
||||||
crate fn process_dict(proc: &sysinfo::Process) -> Dictionary {
|
crate fn process_dict(proc: &sysinfo::Process, span: impl Into<Span>) -> Spanned<Value> {
|
||||||
let mut dict = Dictionary::default();
|
let mut dict = SpannedDictBuilder::new(span);
|
||||||
dict.add("name", Value::string(proc.name()));
|
dict.insert("name", Value::string(proc.name()));
|
||||||
|
|
||||||
let cmd = proc.cmd();
|
let cmd = proc.cmd();
|
||||||
|
|
||||||
@ -15,10 +15,10 @@ crate fn process_dict(proc: &sysinfo::Process) -> Dictionary {
|
|||||||
Value::string(join(cmd, ""))
|
Value::string(join(cmd, ""))
|
||||||
};
|
};
|
||||||
|
|
||||||
dict.add("cmd", cmd_value);
|
dict.insert("cmd", cmd_value);
|
||||||
dict.add("cpu", Value::float(proc.cpu_usage() as f64));
|
dict.insert("cpu", Value::float(proc.cpu_usage() as f64));
|
||||||
dict.add("pid", Value::int(proc.pid() as i64));
|
dict.insert("pid", Value::int(proc.pid() as i64));
|
||||||
dict.add("status", Value::string(proc.status().to_string()));
|
dict.insert("status", Value::string(proc.status().to_string()));
|
||||||
|
|
||||||
dict
|
dict.into_spanned_value()
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ pub trait Type: std::fmt::Debug + Send {
|
|||||||
type Extractor: ExtractType;
|
type Extractor: ExtractType;
|
||||||
|
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
|
|
||||||
fn coerce(&self) -> Option<hir::ExpressionKindHint> {
|
fn coerce(&self) -> Option<hir::ExpressionKindHint> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -28,10 +27,6 @@ impl Type for Any {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Any"
|
"Any"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for Spanned<Value> {
|
impl ExtractType for Spanned<Value> {
|
||||||
@ -39,7 +34,7 @@ impl ExtractType for Spanned<Value> {
|
|||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,16 +48,6 @@ impl Type for Integer {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Integer"
|
"Integer"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
|
||||||
match value {
|
|
||||||
v @ Spanned {
|
|
||||||
item: Value::Primitive(Primitive::Int(_)),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for i64 {
|
impl ExtractType for i64 {
|
||||||
@ -76,7 +61,7 @@ impl ExtractType for i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
v @ Spanned {
|
v @ Spanned {
|
||||||
item: Value::Primitive(Primitive::Int(_)),
|
item: Value::Primitive(Primitive::Int(_)),
|
||||||
@ -96,16 +81,6 @@ impl Type for NuString {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Integer"
|
"Integer"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
|
||||||
match value {
|
|
||||||
v @ Spanned {
|
|
||||||
item: Value::Primitive(Primitive::Int(_)),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractType for String {
|
impl ExtractType for String {
|
||||||
@ -119,13 +94,13 @@ impl ExtractType for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
v @ Spanned {
|
v @ Spanned {
|
||||||
item: Value::Primitive(Primitive::Int(_)),
|
item: Value::Primitive(Primitive::String(_)),
|
||||||
..
|
..
|
||||||
} => Ok(v),
|
} => Ok(v),
|
||||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
other => Err(ShellError::type_error("String", other.spanned_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,8 +114,10 @@ impl Type for Block {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Block"
|
"Block"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
impl ExtractType for value::Block {
|
||||||
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
v @ Spanned {
|
v @ Spanned {
|
||||||
item: Value::Block(_),
|
item: Value::Block(_),
|
||||||
@ -149,9 +126,7 @@ impl Type for Block {
|
|||||||
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtractType for value::Block {
|
|
||||||
fn extract(value: &Spanned<Value>) -> Result<value::Block, ShellError> {
|
fn extract(value: &Spanned<Value>) -> Result<value::Block, ShellError> {
|
||||||
match value {
|
match value {
|
||||||
Spanned {
|
Spanned {
|
||||||
@ -161,14 +136,4 @@ impl ExtractType for value::Block {
|
|||||||
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
|
||||||
match value {
|
|
||||||
v @ Spanned {
|
|
||||||
item: Value::Block(_),
|
|
||||||
..
|
|
||||||
} => Ok(v),
|
|
||||||
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,31 @@
|
|||||||
use crate::Text;
|
use crate::Text;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Serialize, Serializer};
|
||||||
|
use serde_derive::Deserialize;
|
||||||
|
|
||||||
#[derive(
|
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Hash, Getters)]
|
||||||
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
|
||||||
)]
|
|
||||||
#[get = "crate"]
|
#[get = "crate"]
|
||||||
pub struct Spanned<T> {
|
pub struct Spanned<T> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub item: T,
|
pub item: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Serialize> Serialize for Spanned<T> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
self.item.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Spanned<T> {
|
||||||
|
pub fn spanned(self, span: impl Into<Span>) -> Spanned<T> {
|
||||||
|
Spanned::from_item(self.item, span.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SpannedItem: Sized {
|
pub trait SpannedItem: Sized {
|
||||||
fn spanned(self, span: impl Into<Span>) -> Spanned<Self> {
|
fn spanned(self, span: impl Into<Span>) -> Spanned<Self> {
|
||||||
Spanned::from_item(self, span.into())
|
Spanned::from_item(self, span.into())
|
||||||
|
@ -93,11 +93,11 @@ fn parse_command_tail(
|
|||||||
tail.move_to(pos);
|
tail.move_to(pos);
|
||||||
|
|
||||||
if tail.at_end() {
|
if tail.at_end() {
|
||||||
return Err(ShellError::ArgumentError {
|
return Err(ShellError::argument_error(
|
||||||
command: config.name().clone(),
|
config.name.clone(),
|
||||||
error: ArgumentError::MissingValueForName(name.to_string()),
|
ArgumentError::MissingValueForName(name.to_string()),
|
||||||
span: flag.span,
|
flag.span,
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = hir::baseline_parse_next_expr(
|
let expr = hir::baseline_parse_next_expr(
|
||||||
@ -118,11 +118,11 @@ fn parse_command_tail(
|
|||||||
tail.move_to(pos);
|
tail.move_to(pos);
|
||||||
|
|
||||||
if tail.at_end() {
|
if tail.at_end() {
|
||||||
return Err(ShellError::ArgumentError {
|
return Err(ShellError::argument_error(
|
||||||
command: config.name().clone(),
|
config.name().clone(),
|
||||||
error: ArgumentError::MissingValueForName(name.to_string()),
|
ArgumentError::MissingValueForName(name.to_string()),
|
||||||
span: flag.span,
|
flag.span,
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = hir::baseline_parse_next_expr(
|
let expr = hir::baseline_parse_next_expr(
|
||||||
@ -154,11 +154,11 @@ fn parse_command_tail(
|
|||||||
match arg {
|
match arg {
|
||||||
PositionalType::Mandatory(..) => {
|
PositionalType::Mandatory(..) => {
|
||||||
if tail.len() == 0 {
|
if tail.len() == 0 {
|
||||||
return Err(ShellError::ArgumentError {
|
return Err(ShellError::argument_error(
|
||||||
command: config.name().clone(),
|
config.name().clone(),
|
||||||
error: ArgumentError::MissingMandatoryPositional(arg.name().to_string()),
|
ArgumentError::MissingMandatoryPositional(arg.name().to_string()),
|
||||||
span: command_span,
|
command_span,
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +215,11 @@ fn extract_mandatory(
|
|||||||
let flag = tokens.extract(|t| t.as_flag(name, source));
|
let flag = tokens.extract(|t| t.as_flag(name, source));
|
||||||
|
|
||||||
match flag {
|
match flag {
|
||||||
None => Err(ShellError::ArgumentError {
|
None => Err(ShellError::argument_error(
|
||||||
command: config.name().clone(),
|
config.name().clone(),
|
||||||
error: ArgumentError::MissingMandatoryFlag(name.to_string()),
|
ArgumentError::MissingMandatoryFlag(name.to_string()),
|
||||||
span,
|
span,
|
||||||
}),
|
)),
|
||||||
|
|
||||||
Some((pos, flag)) => {
|
Some((pos, flag)) => {
|
||||||
tokens.remove(pos);
|
tokens.remove(pos);
|
||||||
|
@ -102,7 +102,7 @@ impl fmt::Debug for DebugPositional<'a> {
|
|||||||
None => write!(f, "None"),
|
None => write!(f, "None"),
|
||||||
Some(positional) => f
|
Some(positional) => f
|
||||||
.debug_list()
|
.debug_list()
|
||||||
.entries(positional.iter().map(|p| p.item().debug()))
|
.entries(positional.iter().map(|p| p.debug()))
|
||||||
.finish(),
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ impl fmt::Debug for DebugNamed<'a> {
|
|||||||
None => write!(f, "None"),
|
None => write!(f, "None"),
|
||||||
Some(named) => f
|
Some(named) => f
|
||||||
.debug_map()
|
.debug_map()
|
||||||
.entries(named.iter().map(|(k, v)| (k, v.item().debug())))
|
.entries(named.iter().map(|(k, v)| (k, v.debug())))
|
||||||
.finish(),
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use nu::{
|
|||||||
serve_plugin, Args, CommandConfig, Plugin, PositionalType, Primitive, ReturnValue, ShellError,
|
serve_plugin, Args, CommandConfig, Plugin, PositionalType, Primitive, ReturnValue, ShellError,
|
||||||
Spanned, Value,
|
Spanned, Value,
|
||||||
};
|
};
|
||||||
use nu::{Primitive, ReturnSuccess, ReturnValue, ShellError, Spanned, Value};
|
use nu::{Primitive, ReturnSuccess, ReturnValue, ShellError, Spanned, SpannedItem, Value};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ fn send_error(error: ShellError) {
|
|||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub enum NuCommand {
|
pub enum NuCommand {
|
||||||
init { params: Vec<Spanned<Value>> },
|
init { params: Vec<Spanned<Value>> },
|
||||||
filter { params: Value },
|
filter { params: Spanned<Value> },
|
||||||
quit,
|
quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +62,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(NuCommand::filter { params }) => match params {
|
Ok(NuCommand::filter { params }) => match params {
|
||||||
Value::Primitive(Primitive::Int(i)) => {
|
Spanned {
|
||||||
send_response(vec![ReturnSuccess::value(Value::int(i + inc_by))]);
|
item: Value::Primitive(Primitive::Int(i)),
|
||||||
|
span,
|
||||||
|
} => {
|
||||||
|
send_response(vec![ReturnSuccess::value(
|
||||||
|
Value::int(i + inc_by).spanned(span),
|
||||||
|
)]);
|
||||||
}
|
}
|
||||||
Value::Primitive(Primitive::Bytes(b)) => {
|
Spanned {
|
||||||
send_response(vec![ReturnSuccess::value(Value::bytes(
|
item: Value::Primitive(Primitive::Bytes(b)),
|
||||||
b + inc_by as u128,
|
span,
|
||||||
))]);
|
} => {
|
||||||
|
send_response(vec![ReturnSuccess::value(
|
||||||
|
Value::bytes(b + inc_by as u128).spanned(span),
|
||||||
|
)]);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
send_error(ShellError::string("Unrecognized type in stream"));
|
send_error(ShellError::string("Unrecognized type in stream"));
|
||||||
|
@ -16,8 +16,8 @@ impl InputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BoxStream<'static, Value>> for InputStream {
|
impl From<BoxStream<'static, Spanned<Value>>> for InputStream {
|
||||||
fn from(input: BoxStream<'static, Value>) -> InputStream {
|
fn from(input: BoxStream<'static, Spanned<Value>>) -> InputStream {
|
||||||
InputStream { values: input }
|
InputStream { values: input }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,8 +30,8 @@ impl From<VecDeque<Spanned<Value>>> for InputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Value>> for InputStream {
|
impl From<Vec<Spanned<Value>>> for InputStream {
|
||||||
fn from(input: Vec<Value>) -> InputStream {
|
fn from(input: Vec<Spanned<Value>>) -> InputStream {
|
||||||
let mut list = VecDeque::default();
|
let mut list = VecDeque::default();
|
||||||
list.extend(input);
|
list.extend(input);
|
||||||
|
|
||||||
@ -46,6 +46,11 @@ pub struct OutputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OutputStream {
|
impl OutputStream {
|
||||||
|
pub fn empty() -> OutputStream {
|
||||||
|
let v: VecDeque<ReturnValue> = VecDeque::new();
|
||||||
|
v.into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_input(input: impl Stream<Item = Spanned<Value>> + Send + 'static) -> OutputStream {
|
pub fn from_input(input: impl Stream<Item = Spanned<Value>> + Send + 'static) -> OutputStream {
|
||||||
OutputStream {
|
OutputStream {
|
||||||
values: input.map(ReturnSuccess::value).boxed(),
|
values: input.map(ReturnSuccess::value).boxed(),
|
||||||
@ -61,8 +66,8 @@ impl From<InputStream> for OutputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BoxStream<'static, Value>> for OutputStream {
|
impl From<BoxStream<'static, Spanned<Value>>> for OutputStream {
|
||||||
fn from(input: BoxStream<'static, Value>) -> OutputStream {
|
fn from(input: BoxStream<'static, Spanned<Value>>) -> OutputStream {
|
||||||
OutputStream {
|
OutputStream {
|
||||||
values: input.map(ReturnSuccess::value).boxed(),
|
values: input.map(ReturnSuccess::value).boxed(),
|
||||||
}
|
}
|
||||||
@ -83,6 +88,18 @@ impl From<VecDeque<ReturnValue>> for OutputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<VecDeque<Spanned<Value>>> for OutputStream {
|
||||||
|
fn from(input: VecDeque<Spanned<Value>>) -> OutputStream {
|
||||||
|
OutputStream {
|
||||||
|
values: input
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| ReturnSuccess::value(i))
|
||||||
|
.collect::<VecDeque<ReturnValue>>()
|
||||||
|
.boxed(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<ReturnValue>> for OutputStream {
|
impl From<Vec<ReturnValue>> for OutputStream {
|
||||||
fn from(input: Vec<ReturnValue>) -> OutputStream {
|
fn from(input: Vec<ReturnValue>) -> OutputStream {
|
||||||
let mut list = VecDeque::default();
|
let mut list = VecDeque::default();
|
||||||
@ -94,8 +111,8 @@ impl From<Vec<ReturnValue>> for OutputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Value>> for OutputStream {
|
impl From<Vec<Spanned<Value>>> for OutputStream {
|
||||||
fn from(input: Vec<Value>) -> OutputStream {
|
fn from(input: Vec<Spanned<Value>>) -> OutputStream {
|
||||||
let mut list = VecDeque::default();
|
let mut list = VecDeque::default();
|
||||||
list.extend(input.into_iter().map(ReturnSuccess::value));
|
list.extend(input.into_iter().map(ReturnSuccess::value));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user