Merge pull request #248 from jonathandturner/new_error_tag

Move more parts to tags and away from spans
This commit is contained in:
Jonathan Turner 2019-08-05 21:12:27 +12:00 committed by GitHub
commit d8c4f73ca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 627 additions and 492 deletions

View File

@ -348,7 +348,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
Some(ClassifiedCommand::External(_)) => {} Some(ClassifiedCommand::External(_)) => {}
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand { _ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
command: sink("autoview", Box::new(autoview::autoview)), command: sink("autoview", Box::new(autoview::autoview)),
name_span: None, name_span: Span::unknown(),
args: registry::Args { args: registry::Args {
positional: None, positional: None,
named: None, named: None,
@ -382,7 +382,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
} }
(Some(ClassifiedCommand::Sink(SinkCommand { name_span, .. })), Some(_)) => { (Some(ClassifiedCommand::Sink(SinkCommand { name_span, .. })), Some(_)) => {
return LineResult::Error(line.clone(), ShellError::maybe_labeled_error("Commands like table, save, and autoview must come last in the pipeline", "must come last", name_span)); return LineResult::Error(line.clone(), ShellError::labeled_error("Commands like table, save, and autoview must come last in the pipeline", "must come last", name_span));
} }
(Some(ClassifiedCommand::Sink(left)), None) => { (Some(ClassifiedCommand::Sink(left)), None) => {
@ -496,7 +496,7 @@ fn classify_command(
Ok(ClassifiedCommand::Internal(InternalCommand { Ok(ClassifiedCommand::Internal(InternalCommand {
command, command,
name_span: Some(head.span().clone()), name_span: head.span().clone(),
args, args,
})) }))
} }
@ -510,7 +510,7 @@ fn classify_command(
Ok(ClassifiedCommand::Sink(SinkCommand { Ok(ClassifiedCommand::Sink(SinkCommand {
command, command,
name_span: Some(head.span().clone()), name_span: head.span().clone(),
args, args,
})) }))
} }
@ -521,7 +521,7 @@ fn classify_command(
.iter() .iter()
.filter_map(|i| match i { .filter_map(|i| match i {
TokenNode::Whitespace(_) => None, TokenNode::Whitespace(_) => None,
other => Some(Tagged::from_item( other => Some(Tagged::from_simple_spanned_item(
other.as_external_arg(source), other.as_external_arg(source),
other.span(), other.span(),
)), )),
@ -532,7 +532,7 @@ fn classify_command(
Ok(ClassifiedCommand::External(ExternalCommand { Ok(ClassifiedCommand::External(ExternalCommand {
name: name.to_string(), name: name.to_string(),
name_span: Some(head.span().clone()), name_span: head.span().clone(),
args: arg_list_strings, args: arg_list_strings,
})) }))
} }

View File

@ -10,7 +10,7 @@ pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
None => match dirs::home_dir() { None => match dirs::home_dir() {
Some(o) => o, Some(o) => o,
_ => { _ => {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Can not change to home directory", "Can not change to home directory",
"can not go to home", "can not go to home",
args.call_info.name_span, args.call_info.name_span,

View File

@ -99,7 +99,7 @@ impl ClassifiedCommand {
crate struct SinkCommand { crate struct SinkCommand {
crate command: Arc<dyn Sink>, crate command: Arc<dyn Sink>,
crate name_span: Option<Span>, crate name_span: Span,
crate args: Args, crate args: Args,
} }
@ -111,7 +111,7 @@ impl SinkCommand {
crate struct InternalCommand { crate struct InternalCommand {
crate command: Arc<dyn Command>, crate command: Arc<dyn Command>,
crate name_span: Option<Span>, crate name_span: Span,
crate args: Args, crate args: Args,
} }
@ -166,7 +166,7 @@ impl InternalCommand {
crate struct ExternalCommand { crate struct ExternalCommand {
crate name: String, crate name: String,
#[allow(unused)] #[allow(unused)]
crate name_span: Option<Span>, crate name_span: Span,
crate args: Vec<Tagged<String>>, crate args: Vec<Tagged<String>>,
} }
@ -240,7 +240,10 @@ impl ExternalCommand {
} else { } else {
for arg in &self.args { for arg in &self.args {
let arg_chars: Vec<_> = arg.chars().collect(); let arg_chars: Vec<_> = arg.chars().collect();
if arg_chars.len() > 1 && arg_chars[0] == '"' && arg_chars[arg_chars.len() - 1] == '"' { if arg_chars.len() > 1
&& arg_chars[0] == '"'
&& arg_chars[arg_chars.len() - 1] == '"'
{
// quoted string // quoted string
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect(); let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
process = process.arg(new_arg); process = process.arg(new_arg);
@ -258,13 +261,13 @@ impl ExternalCommand {
let mut first = true; let mut first = true;
for i in &inputs { for i in &inputs {
if i.as_string().is_err() { if i.as_string().is_err() {
let mut span = None; let mut span = name_span;
for arg in &self.args { for arg in &self.args {
if arg.item.contains("$it") { if arg.item.contains("$it") {
span = Some(arg.span()); span = arg.span();
} }
} }
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"External $it needs string data", "External $it needs string data",
"given object instead of string data", "given object instead of string data",
span, span,
@ -323,7 +326,9 @@ 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(move |line| Value::string(line.unwrap()).tagged(name_span)); let stream = stream.map(move |line| {
Tagged::from_simple_spanned_item(Value::string(line.unwrap()), name_span)
});
Ok(ClassifiedInputStream::from_input_stream( Ok(ClassifiedInputStream::from_input_stream(
stream.boxed() as BoxStream<'static, Tagged<Value>> stream.boxed() as BoxStream<'static, Tagged<Value>>
)) ))

View File

@ -13,7 +13,7 @@ use uuid::Uuid;
pub struct CallInfo { pub struct CallInfo {
pub args: Args, pub args: Args,
pub source_map: SourceMap, pub source_map: SourceMap,
pub name_span: Option<Span>, pub name_span: Span,
} }
#[derive(Getters)] #[derive(Getters)]
@ -93,7 +93,9 @@ impl ReturnSuccess {
} }
pub fn spanned_value(input: Value, span: Span) -> ReturnValue { pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
Ok(ReturnSuccess::Value(Tagged::from_item(input, span))) Ok(ReturnSuccess::Value(Tagged::from_simple_spanned_item(
input, span,
)))
} }
} }

View File

@ -61,10 +61,11 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
config::write_config(&result)?; config::write_config(&result)?;
return Ok( return Ok(stream![Tagged::from_simple_spanned_item(
stream![Tagged::from_item(Value::Object(result.into()), v.span())] Value::Object(result.into()),
.from_input_stream(), v.span()
); )]
.from_input_stream());
} }
} }
@ -73,9 +74,11 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
config::write_config(&result)?; config::write_config(&result)?;
return Ok( return Ok(stream![Tagged::from_simple_spanned_item(
stream![Tagged::from_item(Value::Object(result.into()), c.span())].from_input_stream(), Value::Object(result.into()),
); c.span()
)]
.from_input_stream());
} }
if let Some(v) = args.get("remove") { if let Some(v) = args.get("remove") {
@ -90,12 +93,14 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
))); )));
} }
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).tagged(v)]); let obj = VecDeque::from_iter(vec![Value::Object(result.into()).simple_spanned(v)]);
return Ok(obj.from_input_stream()); return Ok(obj.from_input_stream());
} }
if args.len() == 0 { if args.len() == 0 {
return Ok(vec![Value::Object(result.into()).tagged(args.call_info.name_span)].into()); return Ok(
vec![Value::Object(result.into()).simple_spanned(args.call_info.name_span)].into(),
);
} }
Err(ShellError::string(format!("Unimplemented"))) Err(ShellError::string(format!("Unimplemented")))

View File

@ -42,41 +42,41 @@ where
indexmap.insert( indexmap.insert(
"year".to_string(), "year".to_string(),
Tagged::from_item(Value::int(dt.year()), span), Tagged::from_simple_spanned_item(Value::int(dt.year()), span),
); );
indexmap.insert( indexmap.insert(
"month".to_string(), "month".to_string(),
Tagged::from_item(Value::int(dt.month()), span), Tagged::from_simple_spanned_item(Value::int(dt.month()), span),
); );
indexmap.insert( indexmap.insert(
"day".to_string(), "day".to_string(),
Tagged::from_item(Value::int(dt.day()), span), Tagged::from_simple_spanned_item(Value::int(dt.day()), span),
); );
indexmap.insert( indexmap.insert(
"hour".to_string(), "hour".to_string(),
Tagged::from_item(Value::int(dt.hour()), span), Tagged::from_simple_spanned_item(Value::int(dt.hour()), span),
); );
indexmap.insert( indexmap.insert(
"minute".to_string(), "minute".to_string(),
Tagged::from_item(Value::int(dt.minute()), span), Tagged::from_simple_spanned_item(Value::int(dt.minute()), span),
); );
indexmap.insert( indexmap.insert(
"second".to_string(), "second".to_string(),
Tagged::from_item(Value::int(dt.second()), span), Tagged::from_simple_spanned_item(Value::int(dt.second()), span),
); );
let tz = dt.offset(); let tz = dt.offset();
indexmap.insert( indexmap.insert(
"timezone".to_string(), "timezone".to_string(),
Tagged::from_item(Value::string(format!("{}", tz)), span), Tagged::from_simple_spanned_item(Value::string(format!("{}", tz)), span),
); );
Tagged::from_item(Value::Object(Dictionary::from(indexmap)), span) Tagged::from_simple_spanned_item(Value::Object(Dictionary::from(indexmap)), span)
} }
pub fn date(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn date(args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut date_out = VecDeque::new(); let mut date_out = VecDeque::new();
let span = args.call_info.name_span.unwrap(); let span = args.call_info.name_span;
let value = if args.has("utc") { let value = if args.has("utc") {
let utc: DateTime<Utc> = Utc::now(); let utc: DateTime<Utc> = Utc::now();

View File

@ -5,7 +5,7 @@ use crate::prelude::*;
pub fn first(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn first(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 { if args.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"First requires an amount", "First requires an amount",
"needs parameter", "needs parameter",
args.call_info.name_span, args.call_info.name_span,

View File

@ -4,12 +4,12 @@ use csv::ReaderBuilder;
pub fn from_csv_string_to_value( pub fn from_csv_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> { ) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
let mut reader = ReaderBuilder::new() let mut reader = ReaderBuilder::new()
.has_headers(false) .has_headers(false)
.from_reader(s.as_bytes()); .from_reader(s.as_bytes());
let span = span.into(); let tag = tag.into();
let mut fields: VecDeque<String> = VecDeque::new(); let mut fields: VecDeque<String> = VecDeque::new();
let mut iter = reader.records(); let mut iter = reader.records();
@ -27,12 +27,12 @@ pub fn from_csv_string_to_value(
if let Some(row_values) = iter.next() { if let Some(row_values) = iter.next() {
let row_values = row_values?; let row_values = row_values?;
let mut row = TaggedDictBuilder::new(span); let mut row = TaggedDictBuilder::new(tag);
for (idx, entry) in row_values.iter().enumerate() { for (idx, entry) in row_values.iter().enumerate() {
row.insert_tagged( row.insert_tagged(
fields.get(idx).unwrap(), fields.get(idx).unwrap(),
Value::Primitive(Primitive::String(String::from(entry))).tagged(span), Value::Primitive(Primitive::String(String::from(entry))).tagged(tag),
); );
} }
@ -42,7 +42,7 @@ pub fn from_csv_string_to_value(
} }
} }
Ok(Tagged::from_item(Value::List(rows), span)) Ok(Tagged::from_item(Value::List(rows), tag))
} }
pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -52,22 +52,26 @@ pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| { .map(move |a| {
let value_span = a.span(); let value_tag = a.tag();
match a.item { match a.item {
Value::Primitive(Primitive::String(s)) => { Value::Primitive(Primitive::String(s)) => {
match from_csv_string_to_value(s, value_span) { match from_csv_string_to_value(s, value_tag) {
Ok(x) => ReturnSuccess::value(x), Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as CSV", "Could not parse as CSV",
"piped data failed CSV parse", "input cannot be parsed as CSV",
span, span,
"value originates from here",
value_tag.span,
)), )),
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
} }
}) })

View File

@ -4,9 +4,9 @@ use std::collections::HashMap;
fn convert_ini_second_to_nu_value( fn convert_ini_second_to_nu_value(
v: &HashMap<String, String>, v: &HashMap<String, String>,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Tagged<Value> { ) -> Tagged<Value> {
let mut second = TaggedDictBuilder::new(span); let mut second = TaggedDictBuilder::new(tag);
for (key, value) in v.into_iter() { for (key, value) in v.into_iter() {
second.insert(key.clone(), Primitive::String(value.clone())); second.insert(key.clone(), Primitive::String(value.clone()));
@ -17,13 +17,13 @@ fn convert_ini_second_to_nu_value(
fn convert_ini_top_to_nu_value( fn convert_ini_top_to_nu_value(
v: &HashMap<String, HashMap<String, String>>, v: &HashMap<String, HashMap<String, String>>,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Tagged<Value> { ) -> Tagged<Value> {
let span = span.into(); let tag = tag.into();
let mut top_level = TaggedDictBuilder::new(span); let mut top_level = TaggedDictBuilder::new(tag);
for (key, value) in v.iter() { for (key, value) in v.iter() {
top_level.insert_tagged(key.clone(), convert_ini_second_to_nu_value(value, span)); top_level.insert_tagged(key.clone(), convert_ini_second_to_nu_value(value, tag));
} }
top_level.into_tagged_value() top_level.into_tagged_value()
@ -31,10 +31,10 @@ fn convert_ini_top_to_nu_value(
pub fn from_ini_string_to_value( pub fn from_ini_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> { ) -> Result<Tagged<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, span)) Ok(convert_ini_top_to_nu_value(&v, tag))
} }
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -43,22 +43,26 @@ pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| { .map(move |a| {
let value_span = a.span(); let value_tag = a.tag();
match a.item { match a.item {
Value::Primitive(Primitive::String(s)) => { Value::Primitive(Primitive::String(s)) => {
match from_ini_string_to_value(s, value_span) { match from_ini_string_to_value(s, value_tag) {
Ok(x) => ReturnSuccess::value(x), Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as INI", "Could not parse as INI",
"piped data failed INI parse", "input cannot be parsed as INI",
span, span,
"value originates from here",
value_tag.span,
)), )),
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
} }
}) })

View File

@ -2,32 +2,32 @@ use crate::object::base::OF64;
use crate::object::{Primitive, TaggedDictBuilder, Value}; use crate::object::{Primitive, TaggedDictBuilder, Value};
use crate::prelude::*; use crate::prelude::*;
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into<Span>) -> Tagged<Value> { fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -> Tagged<Value> {
let span = span.into(); let tag = tag.into();
match v { match v {
serde_hjson::Value::Null => { serde_hjson::Value::Null => {
Value::Primitive(Primitive::String(String::from(""))).tagged(span) Value::Primitive(Primitive::String(String::from(""))).tagged(tag)
} }
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span), serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
serde_hjson::Value::F64(n) => { serde_hjson::Value::F64(n) => {
Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(span) Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag)
} }
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(span), serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(span), serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
serde_hjson::Value::String(s) => { serde_hjson::Value::String(s) => {
Value::Primitive(Primitive::String(String::from(s))).tagged(span) Value::Primitive(Primitive::String(String::from(s))).tagged(tag)
} }
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, span)) .map(|x| convert_json_value_to_nu_value(x, tag))
.collect(), .collect(),
) )
.tagged(span), .tagged(tag),
serde_hjson::Value::Object(o) => { serde_hjson::Value::Object(o) => {
let mut collected = TaggedDictBuilder::new(span); let mut collected = TaggedDictBuilder::new(tag);
for (k, v) in o.iter() { for (k, v) in o.iter() {
collected.insert_tagged(k.clone(), convert_json_value_to_nu_value(v, span)); collected.insert_tagged(k.clone(), convert_json_value_to_nu_value(v, tag));
} }
collected.into_tagged_value() collected.into_tagged_value()
@ -37,10 +37,10 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into<Span>)
pub fn from_json_string_to_value( pub fn from_json_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> serde_hjson::Result<Tagged<Value>> { ) -> serde_hjson::Result<Tagged<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, span)) Ok(convert_json_value_to_nu_value(&v, tag))
} }
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -49,22 +49,26 @@ pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| { .map(move |a| {
let value_span = a.span(); let value_tag = a.tag();
match a.item { match a.item {
Value::Primitive(Primitive::String(s)) => { Value::Primitive(Primitive::String(s)) => {
match from_json_string_to_value(s, value_span) { match from_json_string_to_value(s, value_tag) {
Ok(x) => ReturnSuccess::value(x), Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as JSON", "Could not parse as JSON",
"piped data failed JSON parse", "input cannot be parsed as JSON",
span, span,
"value originates from here",
value_tag.span,
)), )),
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
} }
}) })

View File

@ -2,28 +2,28 @@ use crate::object::base::OF64;
use crate::object::{Primitive, TaggedDictBuilder, Value}; use crate::object::{Primitive, TaggedDictBuilder, Value};
use crate::prelude::*; use crate::prelude::*;
fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Tagged<Value> { fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Tagged<Value> {
let span = span.into(); let tag = tag.into();
match v { match v {
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span), toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(span), toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(tag),
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(span), toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag),
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(span), toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
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, span)) .map(|x| convert_toml_value_to_nu_value(x, tag))
.collect(), .collect(),
) )
.tagged(span), .tagged(tag),
toml::Value::Datetime(dt) => { toml::Value::Datetime(dt) => {
Value::Primitive(Primitive::String(dt.to_string())).tagged(span) Value::Primitive(Primitive::String(dt.to_string())).tagged(tag)
} }
toml::Value::Table(t) => { toml::Value::Table(t) => {
let mut collected = TaggedDictBuilder::new(span); let mut collected = TaggedDictBuilder::new(tag);
for (k, v) in t.iter() { for (k, v) in t.iter() {
collected.insert_tagged(k.clone(), convert_toml_value_to_nu_value(v, span)); collected.insert_tagged(k.clone(), convert_toml_value_to_nu_value(v, tag));
} }
collected.into_tagged_value() collected.into_tagged_value()
@ -33,10 +33,10 @@ fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Tag
pub fn from_toml_string_to_value( pub fn from_toml_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> { ) -> Result<Tagged<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, span)) Ok(convert_toml_value_to_nu_value(&v, tag))
} }
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -45,22 +45,26 @@ pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| { .map(move |a| {
let value_span = a.span(); let value_tag = a.tag();
match a.item { match a.item {
Value::Primitive(Primitive::String(s)) => { Value::Primitive(Primitive::String(s)) => {
match from_toml_string_to_value(s, value_span) { match from_toml_string_to_value(s, value_tag) {
Ok(x) => ReturnSuccess::value(x), Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as TOML", "Could not parse as TOML",
"piped data failed TOML parse", "input cannot be parsed as TOML",
span, span,
"value originates from here",
value_tag.span,
)), )),
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
} }
}) })

View File

@ -1,15 +1,15 @@
use crate::object::{Primitive, TaggedDictBuilder, Value}; use crate::object::{Primitive, TaggedDictBuilder, Value};
use crate::prelude::*; use crate::prelude::*;
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, span: impl Into<Span>) -> Tagged<Value> { fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into<Tag>) -> Tagged<Value> {
let span = span.into(); let tag = tag.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, span)); children_values.push(from_node_to_value(&c, tag));
} }
let children_values: Vec<Tagged<Value>> = children_values let children_values: Vec<Tagged<Value>> = children_values
@ -29,31 +29,31 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, span: impl Into<Span>
}) })
.collect(); .collect();
let mut collected = TaggedDictBuilder::new(span); let mut collected = TaggedDictBuilder::new(tag);
collected.insert(name.clone(), Value::List(children_values)); collected.insert(name.clone(), Value::List(children_values));
collected.into_tagged_value() collected.into_tagged_value()
} else if n.is_comment() { } else if n.is_comment() {
Value::string("<comment>").tagged(span) Value::string("<comment>").tagged(tag)
} else if n.is_pi() { } else if n.is_pi() {
Value::string("<processing_instruction>").tagged(span) Value::string("<processing_instruction>").tagged(tag)
} else if n.is_text() { } else if n.is_text() {
Value::string(n.text().unwrap()).tagged(span) Value::string(n.text().unwrap()).tagged(tag)
} else { } else {
Value::string("<unknown>").tagged(span) Value::string("<unknown>").tagged(tag)
} }
} }
fn from_document_to_value(d: &roxmltree::Document, span: impl Into<Span>) -> Tagged<Value> { fn from_document_to_value(d: &roxmltree::Document, tag: impl Into<Tag>) -> Tagged<Value> {
from_node_to_value(&d.root_element(), span) from_node_to_value(&d.root_element(), tag)
} }
pub fn from_xml_string_to_value( pub fn from_xml_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> { ) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
let parsed = roxmltree::Document::parse(&s)?; let parsed = roxmltree::Document::parse(&s)?;
Ok(from_document_to_value(&parsed, span)) Ok(from_document_to_value(&parsed, tag))
} }
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -61,20 +61,29 @@ pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let span = args.call_info.name_span; let span = args.call_info.name_span;
Ok(out Ok(out
.values .values
.map(move |a| match a.item { .map(move |a| {
Value::Primitive(Primitive::String(s)) => match from_xml_string_to_value(s, span) { let value_tag = a.tag();
Ok(x) => ReturnSuccess::value(x), match a.item {
Err(_) => Err(ShellError::maybe_labeled_error( Value::Primitive(Primitive::String(s)) => {
"Could not parse as XML", match from_xml_string_to_value(s, value_tag) {
"piped data failed XML parse", Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as XML",
"input cannot be parsed as XML",
span,
"value originates from here",
value_tag.span,
)),
}
}
_ => Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline",
"requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
}, }
_ => Err(ShellError::maybe_labeled_error(
"Expected string values from pipeline",
"expects strings from pipeline",
span,
)),
}) })
.to_output_stream()) .to_output_stream())
} }

View File

@ -2,31 +2,31 @@ use crate::object::base::OF64;
use crate::object::{Primitive, TaggedDictBuilder, Value}; use crate::object::{Primitive, TaggedDictBuilder, Value};
use crate::prelude::*; use crate::prelude::*;
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into<Span>) -> Tagged<Value> { fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) -> Tagged<Value> {
let span = span.into(); let tag = tag.into();
match v { match v {
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span), serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
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())).tagged(span) Value::Primitive(Primitive::Int(n.as_i64().unwrap())).tagged(tag)
} }
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()))).tagged(span) Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap()))).tagged(tag)
} }
serde_yaml::Value::String(s) => Value::string(s).tagged(span), serde_yaml::Value::String(s) => Value::string(s).tagged(tag),
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, span)) .map(|x| convert_yaml_value_to_nu_value(x, tag))
.collect(), .collect(),
) )
.tagged(span), .tagged(tag),
serde_yaml::Value::Mapping(t) => { serde_yaml::Value::Mapping(t) => {
let mut collected = TaggedDictBuilder::new(span); let mut collected = TaggedDictBuilder::new(tag);
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.insert_tagged(k.clone(), convert_yaml_value_to_nu_value(v, span)); collected.insert_tagged(k.clone(), convert_yaml_value_to_nu_value(v, tag));
} }
_ => unimplemented!("Unknown key type"), _ => unimplemented!("Unknown key type"),
} }
@ -34,17 +34,17 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into<Span>)
collected.into_tagged_value() collected.into_tagged_value()
} }
serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing).tagged(span), serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing).tagged(tag),
x => unimplemented!("Unsupported yaml case: {:?}", x), x => unimplemented!("Unsupported yaml case: {:?}", x),
} }
} }
pub fn from_yaml_string_to_value( pub fn from_yaml_string_to_value(
s: String, s: String,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> serde_yaml::Result<Tagged<Value>> { ) -> serde_yaml::Result<Tagged<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, span)) Ok(convert_yaml_value_to_nu_value(&v, tag))
} }
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -53,22 +53,26 @@ pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| { .map(move |a| {
let value_span = a.span(); let value_tag = a.tag();
match a.item { match a.item {
Value::Primitive(Primitive::String(s)) => { Value::Primitive(Primitive::String(s)) => {
match from_yaml_string_to_value(s, value_span) { match from_yaml_string_to_value(s, value_tag) {
Ok(x) => ReturnSuccess::value(x), Ok(x) => ReturnSuccess::value(x),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error_with_secondary(
"Could not parse as YAML", "Could not parse as YAML",
"piped data failed YAML parse", "input cannot be parsed as YAML",
span, span,
"value originates from here",
value_tag.span,
)), )),
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
a.span(),
)), )),
} }
}) })

View File

@ -22,7 +22,7 @@ fn get_member(path: &str, span: Span, obj: &Tagged<Value>) -> Result<Tagged<Valu
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 { if args.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Get requires a field or field path", "Get requires a field or field path",
"needs parameter", "needs parameter",
args.call_info.name_span, args.call_info.name_span,

View File

@ -27,10 +27,12 @@ pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
_ => { _ => {
let mut result = VecDeque::new(); let mut result = VecDeque::new();
result.push_back(Err(ShellError::maybe_labeled_error( result.push_back(Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
v.span(),
))); )));
result result
} }

View File

@ -37,7 +37,7 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
s.span(), s.span(),
)); ));
} else { } else {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
args.call_info.name_span, args.call_info.name_span,
@ -50,8 +50,11 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
let entry = entry?; let entry = entry?;
let filepath = entry.path(); let filepath = entry.path();
let filename = filepath.strip_prefix(&cwd).unwrap(); let filename = filepath.strip_prefix(&cwd).unwrap();
let value = let value = dir_entry_dict(
dir_entry_dict(filename, &entry.metadata()?, args.call_info.name_span)?; filename,
&entry.metadata()?,
Tag::unknown_origin(args.call_info.name_span),
)?;
shell_entries.push_back(ReturnSuccess::value(value)) shell_entries.push_back(ReturnSuccess::value(value))
} }
return Ok(shell_entries.to_output_stream()); return Ok(shell_entries.to_output_stream());
@ -64,7 +67,11 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
if let Ok(entry) = entry { if let Ok(entry) = entry {
let filename = entry.strip_prefix(&cwd).unwrap(); let filename = entry.strip_prefix(&cwd).unwrap();
let metadata = std::fs::metadata(&entry)?; let metadata = std::fs::metadata(&entry)?;
let value = dir_entry_dict(filename, &metadata, args.call_info.name_span)?; let value = dir_entry_dict(
filename,
&metadata,
Tag::unknown_origin(args.call_info.name_span),
)?;
shell_entries.push_back(ReturnSuccess::value(value)) shell_entries.push_back(ReturnSuccess::value(value))
} }
} }

View File

@ -20,9 +20,9 @@ command! {
let full_path = PathBuf::from(cwd); let full_path = PathBuf::from(cwd);
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".tagged(path.span())))?; let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".simple_spanned(path.span())))?;
let (file_extension, contents, contents_span, span_source) = fetch(&full_path, path_str, path.span())?; let (file_extension, contents, contents_tag, span_source) = fetch(&full_path, path_str, path.span())?;
let file_extension = if raw.is_present() { let file_extension = if raw.is_present() {
None None
@ -32,7 +32,7 @@ command! {
let mut stream = VecDeque::new(); let mut stream = VecDeque::new();
if let Some(uuid) = contents_span.source { if let Some(uuid) = contents_tag.origin {
// If we have loaded something, track its source // If we have loaded something, track its source
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source))) stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source)))
} }
@ -42,7 +42,7 @@ command! {
let value = parse_as_value( let value = parse_as_value(
file_extension, file_extension,
string, string,
contents_span, contents_tag,
span, span,
)?; )?;
@ -56,7 +56,7 @@ command! {
} }
}, },
other => stream.push_back(ReturnSuccess::value(other.tagged(contents_span))), other => stream.push_back(ReturnSuccess::value(other.tagged(contents_tag))),
}; };
stream stream
@ -67,7 +67,7 @@ pub fn fetch(
cwd: &PathBuf, cwd: &PathBuf,
location: &str, location: &str,
span: Span, span: Span,
) -> Result<(Option<String>, Value, Span, SpanSource), ShellError> { ) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
let mut cwd = cwd.clone(); let mut cwd = cwd.clone();
if location.starts_with("http:") || location.starts_with("https:") { if location.starts_with("http:") || location.starts_with("https:") {
let response = reqwest::get(location); let response = reqwest::get(location);
@ -79,13 +79,19 @@ pub fn fetch(
(mime::APPLICATION, mime::XML) => Ok(( (mime::APPLICATION, mime::XML) => Ok((
Some("xml".to_string()), Some("xml".to_string()),
Value::string(r.text().unwrap()), Value::string(r.text().unwrap()),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)), )),
(mime::APPLICATION, mime::JSON) => Ok(( (mime::APPLICATION, mime::JSON) => Ok((
Some("json".to_string()), Some("json".to_string()),
Value::string(r.text().unwrap()), Value::string(r.text().unwrap()),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)), )),
(mime::APPLICATION, mime::OCTET_STREAM) => { (mime::APPLICATION, mime::OCTET_STREAM) => {
@ -100,7 +106,10 @@ pub fn fetch(
Ok(( Ok((
None, None,
Value::Binary(buf), Value::Binary(buf),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)) ))
} }
@ -116,14 +125,20 @@ pub fn fetch(
Ok(( Ok((
Some(image_ty.to_string()), Some(image_ty.to_string()),
Value::Binary(buf), Value::Binary(buf),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)) ))
} }
(mime::TEXT, mime::HTML) => Ok(( (mime::TEXT, mime::HTML) => Ok((
Some("html".to_string()), Some("html".to_string()),
Value::string(r.text().unwrap()), Value::string(r.text().unwrap()),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)), )),
(mime::TEXT, mime::PLAIN) => { (mime::TEXT, mime::PLAIN) => {
@ -141,7 +156,10 @@ pub fn fetch(
Ok(( Ok((
path_extension, path_extension,
Value::string(r.text().unwrap()), Value::string(r.text().unwrap()),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)) ))
} }
@ -151,7 +169,10 @@ pub fn fetch(
"Not yet supported MIME type: {} {}", "Not yet supported MIME type: {} {}",
ty, sub_ty ty, sub_ty
)), )),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)), )),
} }
@ -159,7 +180,10 @@ pub fn fetch(
None => Ok(( None => Ok((
None, None,
Value::string(format!("No content type found")), Value::string(format!("No content type found")),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()), SpanSource::Url(r.url().to_string()),
)), )),
}, },
@ -179,13 +203,19 @@ pub fn fetch(
cwd.extension() cwd.extension()
.map(|name| name.to_string_lossy().to_string()), .map(|name| name.to_string_lossy().to_string()),
Value::string(s), Value::string(s),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
Err(_) => Ok(( Err(_) => Ok((
None, None,
Value::Binary(bytes), Value::Binary(bytes),
Span::unknown_with_uuid(Uuid::new_v4()), Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
}, },
@ -203,69 +233,57 @@ pub fn fetch(
pub fn parse_as_value( pub fn parse_as_value(
extension: Option<String>, extension: Option<String>,
contents: String, contents: String,
contents_span: Span, contents_tag: Tag,
name_span: Option<Span>, name_span: Span,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match extension { match extension {
Some(x) if x == "csv" => { Some(x) if x == "csv" => crate::commands::from_csv::from_csv_string_to_value(
crate::commands::from_csv::from_csv_string_to_value(contents, contents_span) contents,
.map(|c| c.tagged(contents_span)) contents_tag,
.map_err(move |_| { )
ShellError::maybe_labeled_error( .map_err(move |_| {
"Could not open as CSV", ShellError::labeled_error("Could not open as CSV", "could not open as CSV", name_span)
"could not open as CSV", }),
name_span,
)
})
}
Some(x) if x == "toml" => { Some(x) if x == "toml" => {
crate::commands::from_toml::from_toml_string_to_value(contents, contents_span) crate::commands::from_toml::from_toml_string_to_value(contents, contents_tag).map_err(
.map(|c| c.tagged(contents_span)) move |_| {
.map_err(move |_| { ShellError::labeled_error(
ShellError::maybe_labeled_error(
"Could not open as TOML", "Could not open as TOML",
"could not open as TOML", "could not open as TOML",
name_span, name_span,
) )
})
}
Some(x) if x == "json" => {
crate::commands::from_json::from_json_string_to_value(contents, contents_span)
.map(|c| c.tagged(contents_span))
.map_err(move |_| {
ShellError::maybe_labeled_error(
"Could not open as JSON",
"could not open as JSON",
name_span,
)
})
}
Some(x) if x == "ini" => {
crate::commands::from_ini::from_ini_string_to_value(contents, contents_span)
.map(|c| c.tagged(contents_span))
.map_err(move |_| {
ShellError::maybe_labeled_error(
"Could not open as INI",
"could not open as INI",
name_span,
)
})
}
Some(x) if x == "xml" => {
crate::commands::from_xml::from_xml_string_to_value(contents, contents_span).map_err(
move |_| {
ShellError::maybe_labeled_error(
"Could not open as XML",
"could not open as XML",
name_span,
)
}, },
) )
} }
Some(x) if x == "yml" => { Some(x) if x == "json" => {
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err( crate::commands::from_json::from_json_string_to_value(contents, contents_tag).map_err(
move |_| { move |_| {
ShellError::maybe_labeled_error( ShellError::labeled_error(
"Could not open as JSON",
"could not open as JSON",
name_span,
)
},
)
}
Some(x) if x == "ini" => crate::commands::from_ini::from_ini_string_to_value(
contents,
contents_tag,
)
.map_err(move |_| {
ShellError::labeled_error("Could not open as INI", "could not open as INI", name_span)
}),
Some(x) if x == "xml" => crate::commands::from_xml::from_xml_string_to_value(
contents,
contents_tag,
)
.map_err(move |_| {
ShellError::labeled_error("Could not open as XML", "could not open as XML", name_span)
}),
Some(x) if x == "yml" => {
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err(
move |_| {
ShellError::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,
@ -274,9 +292,9 @@ pub fn parse_as_value(
) )
} }
Some(x) if x == "yaml" => { Some(x) if x == "yaml" => {
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err( crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err(
move |_| { move |_| {
ShellError::maybe_labeled_error( ShellError::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,
@ -284,6 +302,6 @@ pub fn parse_as_value(
}, },
) )
} }
_ => Ok(Value::string(contents).tagged(contents_span)), _ => Ok(Value::string(contents).tagged(contents_tag)),
} }
} }

View File

@ -4,7 +4,7 @@ use crate::prelude::*;
pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 { if args.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Pick requires fields", "Pick requires fields",
"needs parameter", "needs parameter",
args.call_info.name_span, args.call_info.name_span,
@ -17,7 +17,7 @@ pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
let objects = input let objects = input
.values .values
.map(move |value| select_fields(&value.item, &fields, value.span())); .map(move |value| select_fields(&value.item, &fields, value.tag()));
Ok(objects.from_input_stream()) Ok(objects.from_input_stream())
} }

View File

@ -10,7 +10,7 @@ pub fn ps(args: CommandArgs) -> Result<OutputStream, ShellError> {
let list = list let list = list
.into_iter() .into_iter()
.map(|(_, process)| process_dict(process, args.call_info.name_span)) .map(|(_, process)| process_dict(process, Tag::unknown_origin(args.call_info.name_span)))
.collect::<VecDeque<_>>(); .collect::<VecDeque<_>>();
Ok(list.from_input_stream()) Ok(list.from_input_stream())

View File

@ -3,10 +3,8 @@ use crate::object::base::reject_fields;
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.call_info.name_span;
if args.len() == 0 { if args.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Reject requires fields", "Reject requires fields",
"needs parameter", "needs parameter",
args.call_info.name_span, args.call_info.name_span,
@ -16,11 +14,10 @@ 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.input.values.map(move |item| { let stream = args
reject_fields(&item, &fields, item.span()) .input
.into_tagged_value() .values
.tagged(name_span) .map(move |item| reject_fields(&item, &fields, item.tag()).into_tagged_value());
});
Ok(stream.from_input_stream()) Ok(stream.from_input_stream())
} }

View File

@ -61,7 +61,7 @@ pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"is a directory", "is a directory",
"", "",
args.call_info.name_span.unwrap(), args.call_info.name_span,
)); ));
} }
std::fs::remove_dir_all(&path).expect("can not remove directory"); std::fs::remove_dir_all(&path).expect("can not remove directory");

View File

@ -21,18 +21,14 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
if args.call_info.args.positional.is_none() { if args.call_info.args.positional.is_none() {
// If there is no filename, check the metadata for the origin filename // If there is no filename, check the metadata for the origin filename
if args.input.len() > 0 { if args.input.len() > 0 {
let span = args.input[0].span(); let origin = args.input[0].origin();
match span match origin.map(|x| args.call_info.source_map.get(&x)).flatten() {
.source
.map(|x| args.call_info.source_map.get(&x))
.flatten()
{
Some(path) => match path { Some(path) => match path {
SpanSource::File(file) => { SpanSource::File(file) => {
full_path.push(Path::new(file)); full_path.push(Path::new(file));
} }
_ => { _ => {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
args.call_info.name_span, args.call_info.name_span,
@ -40,7 +36,8 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
} }
}, },
None => { None => {
return Err(ShellError::maybe_labeled_error( println!("Could not find origin");
return Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
args.call_info.name_span, args.call_info.name_span,
@ -48,7 +45,7 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
} }
} }
} else { } else {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
args.call_info.name_span, args.call_info.name_span,

View File

@ -4,20 +4,23 @@ use crate::prelude::*;
pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
let span = args.call_info.name_span;
Ok(input Ok(input
.values .values
.map(move |v| match v.item { .map(move |v| match v.item {
Value::Primitive(Primitive::String(ref s)) => ReturnSuccess::value(count(s, v.span())), Value::Primitive(Primitive::String(ref s)) => ReturnSuccess::value(count(s, v.tag())),
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
Some(v.span()), span,
"value originates from here",
v.span(),
)), )),
}) })
.to_output_stream()) .to_output_stream())
} }
fn count(contents: &str, span: impl Into<Span>) -> Tagged<Value> { fn count(contents: &str, tag: impl Into<Tag>) -> Tagged<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;
@ -42,7 +45,7 @@ fn count(contents: &str, span: impl Into<Span>) -> Tagged<Value> {
} }
} }
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
//TODO: add back in name when we have it in the span //TODO: add back in name when we have it in the span
//dict.insert("name", Value::string(name)); //dict.insert("name", Value::string(name));
dict.insert("lines", Value::int(lines)); dict.insert("lines", Value::int(lines));

View File

@ -27,7 +27,7 @@ impl Command for SkipWhile {
pub fn skip_while(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn skip_while(args: CommandArgs) -> Result<OutputStream, ShellError> {
if args.len() == 0 { if args.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Where requires a condition", "Where requires a condition",
"needs condition", "needs condition",
args.call_info.name_span, args.call_info.name_span,

View File

@ -8,7 +8,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
let span = args.call_info.name_span; let span = args.call_info.name_span;
if positional.len() == 0 { if positional.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Split-column needs more information", "Split-column needs more information",
"needs parameter (eg split-column \",\")", "needs parameter (eg split-column \",\")",
args.call_info.name_span, args.call_info.name_span,
@ -34,14 +34,14 @@ 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 = TaggedDictBuilder::new(v.span()); let mut dict = TaggedDictBuilder::new(v.tag());
for (&k, v) in split_result.iter().zip(gen_columns.iter()) { for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
dict.insert(v.clone(), Primitive::String(k.into())); dict.insert(v.clone(), Primitive::String(k.into()));
} }
ReturnSuccess::value(dict.into_tagged_value()) ReturnSuccess::value(dict.into_tagged_value())
} else if split_result.len() == (positional.len() - 1) { } else if split_result.len() == (positional.len() - 1) {
let mut dict = TaggedDictBuilder::new(v.span()); let mut dict = TaggedDictBuilder::new(v.tag());
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.insert( dict.insert(
v.as_string().unwrap(), v.as_string().unwrap(),
@ -50,17 +50,19 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
ReturnSuccess::value(dict.into_tagged_value()) ReturnSuccess::value(dict.into_tagged_value())
} else { } else {
let mut dict = TaggedDictBuilder::new(v.span()); let mut dict = TaggedDictBuilder::new(v.tag());
for k in positional.iter().skip(1) { for k in positional.iter().skip(1) {
dict.insert(k.as_string().unwrap().trim(), Primitive::String("".into())); dict.insert(k.as_string().unwrap().trim(), Primitive::String("".into()));
} }
ReturnSuccess::value(dict.into_tagged_value()) ReturnSuccess::value(dict.into_tagged_value())
} }
} }
_ => Err(ShellError::maybe_labeled_error( _ => Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
v.span(),
)), )),
}) })
.to_output_stream()) .to_output_stream())

View File

@ -8,7 +8,7 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
let span = args.call_info.name_span; let span = args.call_info.name_span;
if positional.len() == 0 { if positional.len() == 0 {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Split-row needs more information", "Split-row needs more information",
"needs parameter (eg split-row \"\\n\")", "needs parameter (eg split-row \"\\n\")",
args.call_info.name_span, args.call_info.name_span,
@ -30,17 +30,19 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut result = VecDeque::new(); let mut result = VecDeque::new();
for s in split_result { for s in split_result {
result.push_back(ReturnSuccess::value( result.push_back(ReturnSuccess::value(
Value::Primitive(Primitive::String(s.into())).tagged(v.span()), Value::Primitive(Primitive::String(s.into())).simple_spanned(v.span()),
)); ));
} }
result result
} }
_ => { _ => {
let mut result = VecDeque::new(); let mut result = VecDeque::new();
result.push_back(Err(ShellError::maybe_labeled_error( result.push_back(Err(ShellError::labeled_error_with_secondary(
"Expected string values from pipeline", "Expected a string from pipeline",
"expects strings from pipeline", "requires string input",
span, span,
"value originates from here",
v.span(),
))); )));
result result
} }

View File

@ -8,18 +8,19 @@ pub fn tags(args: CommandArgs) -> Result<OutputStream, ShellError> {
.input .input
.values .values
.map(move |v| { .map(move |v| {
let mut tags = TaggedDictBuilder::new(v.span()); let mut tags = TaggedDictBuilder::new(v.tag());
{ {
let origin = v.origin();
let span = v.span(); let span = v.span();
let mut dict = TaggedDictBuilder::new(v.span()); let mut dict = TaggedDictBuilder::new(v.tag());
dict.insert("start", Value::int(span.start as i64)); dict.insert("start", Value::int(span.start as i64));
dict.insert("end", Value::int(span.end as i64)); dict.insert("end", Value::int(span.end as i64));
match span.source.map(|x| source_map.get(&x)).flatten() { match origin.map(|x| source_map.get(&x)).flatten() {
Some(SpanSource::File(source)) => { Some(SpanSource::File(source)) => {
dict.insert("source", Value::string(source)); dict.insert("origin", Value::string(source));
} }
Some(SpanSource::Url(source)) => { Some(SpanSource::Url(source)) => {
dict.insert("source", Value::string(source)); dict.insert("origin", Value::string(source));
} }
_ => {} _ => {}
} }

View File

@ -42,8 +42,10 @@ pub fn to_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(out Ok(out
.values .values
.map(move |a| match to_string(&value_to_csv_value(&a.item)) { .map(move |a| match to_string(&value_to_csv_value(&a.item)) {
Ok(x) => ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span)), Ok(x) => ReturnSuccess::value(
Err(_) => Err(ShellError::maybe_labeled_error( Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
),
Err(_) => Err(ShellError::labeled_error(
"Can not convert to CSV string", "Can not convert to CSV string",
"can not convert piped data to CSV string", "can not convert piped data to CSV string",
name_span, name_span,

View File

@ -48,10 +48,10 @@ pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
.values .values
.map( .map(
move |a| match serde_json::to_string(&value_to_json_value(&a)) { move |a| match serde_json::to_string(&value_to_json_value(&a)) {
Ok(x) => { Ok(x) => ReturnSuccess::value(
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span)) Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
} ),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::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",
name_span, name_span,

View File

@ -42,13 +42,13 @@ pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
.map(move |a| match toml::to_string(&value_to_toml_value(&a)) { .map(move |a| match toml::to_string(&value_to_toml_value(&a)) {
Ok(val) => { Ok(val) => {
return ReturnSuccess::value( return ReturnSuccess::value(
Value::Primitive(Primitive::String(val)).tagged(name_span), Value::Primitive(Primitive::String(val)).simple_spanned(name_span),
) )
} }
Err(err) => Err(ShellError::type_error( Err(err) => Err(ShellError::type_error(
"Can not convert to a TOML string", "Can not convert to a TOML string",
format!("{:?} - {:?}", a.type_name(), err).tagged(name_span), format!("{:?} - {:?}", a.type_name(), err).simple_spanned(name_span),
)), )),
}) })
.to_output_stream()) .to_output_stream())

View File

@ -46,10 +46,10 @@ pub fn to_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
.values .values
.map( .map(
move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)) { move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)) {
Ok(x) => { Ok(x) => ReturnSuccess::value(
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span)) Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
} ),
Err(_) => Err(ShellError::maybe_labeled_error( Err(_) => Err(ShellError::labeled_error(
"Can not convert to YAML string", "Can not convert to YAML string",
"can not convert piped data to YAML string", "can not convert piped data to YAML string",
name_span, name_span,

View File

@ -9,7 +9,7 @@ pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
.values .values
.map(move |v| { .map(move |v| {
let string = String::extract(&v)?; let string = String::extract(&v)?;
ReturnSuccess::value(Value::string(string.trim()).tagged(v.span())) ReturnSuccess::value(Value::string(string.trim()).simple_spanned(v.span()))
}) })
.to_output_stream()) .to_output_stream())
} }

View File

@ -79,7 +79,7 @@ impl Context {
crate fn run_sink( crate fn run_sink(
&mut self, &mut self,
command: Arc<dyn Sink>, command: Arc<dyn Sink>,
name_span: Option<Span>, name_span: Span,
args: Args, args: Args,
input: Vec<Tagged<Value>>, input: Vec<Tagged<Value>>,
) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
@ -111,7 +111,7 @@ impl Context {
crate fn run_command( crate fn run_command(
&mut self, &mut self,
command: Arc<dyn Command>, command: Arc<dyn Command>,
name_span: Option<Span>, name_span: Span,
source_map: SourceMap, source_map: SourceMap,
args: Args, args: Args,
input: InputStream, input: InputStream,

View File

@ -15,14 +15,11 @@ pub enum Description {
impl Description { impl Description {
pub fn from(value: Tagged<impl Into<String>>) -> Description { pub fn from(value: Tagged<impl Into<String>>) -> Description {
let value_span = value.span(); let value_span = value.span();
let value_tag = value.tag();
match value_span { match value_span {
Span { Span { start: 0, end: 0 } => Description::Synthetic(value.item.into()),
start: 0, _ => Description::Source(Tagged::from_item(value.item.into(), value_tag)),
end: 0,
source: None,
} => Description::Synthetic(value.item.into()),
_ => Description::Source(Tagged::from_item(value.item.into(), value_span)),
} }
} }
} }
@ -44,13 +41,13 @@ pub enum ArgumentError {
} }
pub fn labelled( pub fn labelled(
span: impl Into<Option<Span>>, span: impl Into<Span>,
heading: &'a str, heading: &'a str,
span_message: &'a str, span_message: &'a str,
) -> impl FnOnce(ShellError) -> ShellError + 'a { ) -> impl FnOnce(ShellError) -> ShellError + 'a {
let span = span.into(); let span = span.into();
move |_| ShellError::maybe_labeled_error(heading, span_message, span) move |_| ShellError::labeled_error(heading, span_message, span)
} }
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)] #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
@ -165,7 +162,7 @@ impl ShellError {
actual: actual:
Tagged { Tagged {
item: Some(actual), item: Some(actual),
tag: Tag { span }, tag: Tag { span, .. },
}, },
} => Diagnostic::new(Severity::Error, "Type Error").with_label( } => Diagnostic::new(Severity::Error, "Type Error").with_label(
Label::new_primary(span) Label::new_primary(span)
@ -177,7 +174,7 @@ impl ShellError {
actual: actual:
Tagged { Tagged {
item: None, item: None,
tag: Tag { span }, tag: Tag { 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)),
@ -220,18 +217,20 @@ impl ShellError {
) )
} }
pub fn maybe_labeled_error( pub fn labeled_error_with_secondary(
msg: impl Into<String>, msg: impl Into<String>,
label: impl Into<String>, primary_label: impl Into<String>,
span: Option<Span>, primary_span: Span,
secondary_label: impl Into<String>,
secondary_span: Span,
) -> ShellError { ) -> ShellError {
match span { ShellError::diagnostic(
Some(span) => ShellError::diagnostic( Diagnostic::new_error(msg.into())
Diagnostic::new(Severity::Error, msg.into()) .with_label(Label::new_primary(primary_span).with_message(primary_label.into()))
.with_label(Label::new_primary(span).with_message(label.into())), .with_label(
), Label::new_secondary(secondary_span).with_message(secondary_label.into()),
None => ShellError::string(msg), ),
} )
} }
pub fn string(title: impl Into<String>) -> ShellError { pub fn string(title: impl Into<String>) -> ShellError {

View File

@ -38,14 +38,17 @@ crate fn evaluate_baseline_expr(
let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?; let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?;
match left.compare(binary.op(), &*right) { match left.compare(binary.op(), &*right) {
Ok(result) => Ok(Tagged::from_item(Value::boolean(result), expr.span())), Ok(result) => Ok(Tagged::from_simple_spanned_item(
Value::boolean(result),
expr.span(),
)),
Err((left_type, right_type)) => Err(ShellError::coerce_error( Err((left_type, right_type)) => Err(ShellError::coerce_error(
binary.left().copy_span(left_type), binary.left().copy_span(left_type),
binary.right().copy_span(right_type), binary.right().copy_span(right_type),
)), )),
} }
} }
RawExpression::Block(block) => Ok(Tagged::from_item( RawExpression::Block(block) => Ok(Tagged::from_simple_spanned_item(
Value::Block(Block::new(block.clone(), source.clone(), expr.span())), Value::Block(Block::new(block.clone(), source.clone(), expr.span())),
expr.span(), expr.span(),
)), )),
@ -64,7 +67,7 @@ crate fn evaluate_baseline_expr(
)) ))
} }
Some(next) => { Some(next) => {
item = Tagged::from_item( item = Tagged::from_simple_spanned_item(
next.clone().item, next.clone().item,
(expr.span().start, name.span().end), (expr.span().start, name.span().end),
) )
@ -72,7 +75,10 @@ crate fn evaluate_baseline_expr(
}; };
} }
Ok(Tagged::from_item(item.item().clone(), expr.span())) Ok(Tagged::from_simple_spanned_item(
item.item().clone(),
expr.span(),
))
} }
RawExpression::Boolean(_boolean) => unimplemented!(), RawExpression::Boolean(_boolean) => unimplemented!(),
} }
@ -95,11 +101,11 @@ fn evaluate_reference(
source: &Text, source: &Text,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match name { match name {
hir::Variable::It(span) => Ok(Tagged::from_item(scope.it.item.clone(), span)), hir::Variable::It(span) => Ok(scope.it.item.clone().simple_spanned(span)),
hir::Variable::Other(span) => Ok(scope hir::Variable::Other(span) => Ok(scope
.vars .vars
.get(span.slice(source)) .get(span.slice(source))
.map(|v| v.clone()) .map(|v| v.clone())
.unwrap_or_else(|| Value::nothing().tagged(span))), .unwrap_or_else(|| Value::nothing().simple_spanned(span))),
} }
} }

View File

@ -168,7 +168,7 @@ impl Block {
let scope = Scope::new(value.clone()); let scope = Scope::new(value.clone());
if self.expressions.len() == 0 { if self.expressions.len() == 0 {
return Ok(Tagged::from_item(Value::nothing(), self.span)); return Ok(Value::nothing().simple_spanned(self.span));
} }
let mut last = None; let mut last = None;
@ -227,7 +227,7 @@ impl fmt::Debug for ValueDebug<'a> {
impl Tagged<Value> { impl Tagged<Value> {
crate fn tagged_type_name(&self) -> Tagged<String> { crate fn tagged_type_name(&self) -> Tagged<String> {
let name = self.type_name(); let name = self.type_name();
Tagged::from_item(name, self.span()) Tagged::from_simple_spanned_item(name, self.span())
} }
} }
@ -352,7 +352,7 @@ impl Value {
} }
} }
pub fn get_data_by_path(&'a self, span: Span, path: &str) -> Option<Tagged<&Value>> { pub fn get_data_by_path(&'a self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
let mut current = self; let mut current = self;
for p in path.split(".") { for p in path.split(".") {
match current.get_data_by_key(p) { match current.get_data_by_key(p) {
@ -361,12 +361,12 @@ impl Value {
} }
} }
Some(Tagged::from_item(current, span)) Some(Tagged::from_item(current, tag))
} }
pub fn insert_data_at_path( pub fn insert_data_at_path(
&'a self, &'a self,
span: Span, tag: Tag,
path: &str, path: &str,
new_value: Value, new_value: Value,
) -> Option<Tagged<Value>> { ) -> Option<Tagged<Value>> {
@ -384,13 +384,13 @@ impl Value {
Value::Object(o) => { Value::Object(o) => {
o.entries.insert( o.entries.insert(
split_path[idx + 1].to_string(), split_path[idx + 1].to_string(),
Tagged::from_item(new_value, span), Tagged::from_item(new_value, tag),
); );
} }
_ => {} _ => {}
} }
return Some(Tagged::from_item(new_obj, span)); return Some(Tagged::from_item(new_obj, tag));
} else { } else {
match next.item { match next.item {
Value::Object(ref mut o) => { Value::Object(ref mut o) => {
@ -410,7 +410,7 @@ impl Value {
pub fn replace_data_at_path( pub fn replace_data_at_path(
&'a self, &'a self,
span: Span, tag: Tag,
path: &str, path: &str,
replaced_value: Value, replaced_value: Value,
) -> Option<Tagged<Value>> { ) -> Option<Tagged<Value>> {
@ -424,8 +424,8 @@ impl Value {
match current.entries.get_mut(split_path[idx]) { match current.entries.get_mut(split_path[idx]) {
Some(next) => { Some(next) => {
if idx == (split_path.len() - 1) { if idx == (split_path.len() - 1) {
*next = Tagged::from_item(replaced_value, span); *next = Tagged::from_item(replaced_value, tag);
return Some(Tagged::from_item(new_obj, span)); return Some(Tagged::from_item(new_obj, tag));
} else { } else {
match next.item { match next.item {
Value::Object(ref mut o) => { Value::Object(ref mut o) => {
@ -601,8 +601,8 @@ impl Value {
} }
} }
crate fn select_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Tagged<Value> { crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
let mut out = TaggedDictBuilder::new(span); let mut out = TaggedDictBuilder::new(tag);
let descs = obj.data_descriptors(); let descs = obj.data_descriptors();
@ -616,8 +616,8 @@ crate fn select_fields(obj: &Value, fields: &[String], span: impl Into<Span>) ->
out.into_tagged_value() out.into_tagged_value()
} }
crate fn reject_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Tagged<Value> { crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
let mut out = TaggedDictBuilder::new(span); let mut out = TaggedDictBuilder::new(tag);
let descs = obj.data_descriptors(); let descs = obj.data_descriptors();

View File

@ -47,7 +47,7 @@ crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>
trace!("config file = {}", filename.display()); trace!("config file = {}", filename.display());
let contents = fs::read_to_string(filename) let contents = fs::read_to_string(filename)
.map(|v| v.tagged(span)) .map(|v| v.simple_spanned(span))
.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)

View File

@ -102,20 +102,20 @@ impl Dictionary {
} }
pub struct TaggedListBuilder { pub struct TaggedListBuilder {
span: Span, tag: Tag,
list: Vec<Tagged<Value>>, list: Vec<Tagged<Value>>,
} }
impl TaggedListBuilder { impl TaggedListBuilder {
pub fn new(span: impl Into<Span>) -> TaggedListBuilder { pub fn new(tag: impl Into<Tag>) -> TaggedListBuilder {
TaggedListBuilder { TaggedListBuilder {
span: span.into(), tag: tag.into(),
list: vec![], list: vec![],
} }
} }
pub fn push(&mut self, value: impl Into<Value>) { pub fn push(&mut self, value: impl Into<Value>) {
self.list.push(value.into().tagged(self.span)); self.list.push(value.into().tagged(self.tag));
} }
pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) { pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) {
@ -123,7 +123,7 @@ impl TaggedListBuilder {
} }
pub fn into_tagged_value(self) -> Tagged<Value> { pub fn into_tagged_value(self) -> Tagged<Value> {
Value::List(self.list).tagged(self.span) Value::List(self.list).tagged(self.tag)
} }
} }
@ -135,20 +135,20 @@ impl From<TaggedListBuilder> for Tagged<Value> {
#[derive(Debug)] #[derive(Debug)]
pub struct TaggedDictBuilder { pub struct TaggedDictBuilder {
span: Span, tag: Tag,
dict: IndexMap<String, Tagged<Value>>, dict: IndexMap<String, Tagged<Value>>,
} }
impl TaggedDictBuilder { impl TaggedDictBuilder {
pub fn new(span: impl Into<Span>) -> TaggedDictBuilder { pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
TaggedDictBuilder { TaggedDictBuilder {
span: span.into(), tag: tag.into(),
dict: IndexMap::default(), dict: IndexMap::default(),
} }
} }
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) { pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
self.dict.insert(key.into(), value.into().tagged(self.span)); self.dict.insert(key.into(), value.into().tagged(self.tag));
} }
pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) { pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) {
@ -160,7 +160,7 @@ impl TaggedDictBuilder {
} }
pub fn into_tagged_dict(self) -> Tagged<Dictionary> { pub fn into_tagged_dict(self) -> Tagged<Dictionary> {
Dictionary { entries: self.dict }.tagged(self.span) Dictionary { entries: self.dict }.tagged(self.tag)
} }
} }

View File

@ -12,9 +12,9 @@ pub enum FileType {
crate fn dir_entry_dict( crate fn dir_entry_dict(
filename: &std::path::Path, filename: &std::path::Path,
metadata: &std::fs::Metadata, metadata: &std::fs::Metadata,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
dict.insert("name", Value::string(filename.to_string_lossy())); dict.insert("name", Value::string(filename.to_string_lossy()));
let kind = if metadata.is_dir() { let kind = if metadata.is_dir() {

View File

@ -17,6 +17,6 @@ impl<T: Into<Value>> Tagged<T> {
pub fn into_tagged_value(self) -> Tagged<Value> { pub fn into_tagged_value(self) -> Tagged<Value> {
let value_span = self.span(); let value_span = self.span();
let value = self.item.into(); let value = self.item.into();
value.tagged(value_span) value.simple_spanned(value_span)
} }
} }

View File

@ -5,25 +5,32 @@ use serde::Serialize;
use serde_derive::Deserialize; use serde_derive::Deserialize;
use uuid::Uuid; use uuid::Uuid;
#[derive( #[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
)]
#[get = "crate"]
pub struct Tagged<T> { pub struct Tagged<T> {
pub tag: Tag, pub tag: Tag,
pub item: T, pub item: T,
} }
pub trait TaggedItem: Sized { pub trait TaggedItem: Sized {
fn tagged(self, span: impl Into<Span>) -> Tagged<Self> { fn tagged(self, tag: impl Into<Tag>) -> Tagged<Self> {
Tagged::from_item(self, span.into()) Tagged::from_item(self, tag.into())
}
fn simple_spanned(self, span: impl Into<Span>) -> Tagged<Self> {
Tagged::from_simple_spanned_item(self, span.into())
} }
// For now, this is a temporary facility. In many cases, there are other useful spans that we // For now, this is a temporary facility. In many cases, there are other useful spans that we
// could be using, such as the original source spans of JSON or Toml files, but we don't yet // could be using, such as the original source spans of JSON or Toml files, but we don't yet
// have the infrastructure to make that work. // have the infrastructure to make that work.
fn tagged_unknown(self) -> Tagged<Self> { fn tagged_unknown(self) -> Tagged<Self> {
Tagged::from_item(self, (0, 0)) Tagged::from_item(
self,
Tag {
span: Span::unknown(),
origin: None,
},
)
} }
} }
@ -38,28 +45,44 @@ impl<T> std::ops::Deref for Tagged<T> {
} }
impl<T> Tagged<T> { impl<T> Tagged<T> {
pub fn tagged(self, span: impl Into<Span>) -> Tagged<T> { pub fn spanned(self, span: impl Into<Span>) -> Tagged<T> {
Tagged::from_item(self.item, span.into()) Tagged::from_item(
self.item,
Tag {
span: span.into(),
origin: None,
},
)
} }
pub fn from_item(item: T, span: impl Into<Span>) -> Tagged<T> { pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
Tagged { Tagged {
item, item,
tag: Tag { span: span.into() }, tag: tag.into(),
} }
} }
pub fn from_simple_spanned_item(item: T, span: impl Into<Span>) -> Tagged<T> {
Tagged::from_item(
item,
Tag {
span: span.into(),
origin: None,
},
)
}
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> { pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
let span = self.span(); let tag = self.tag();
let mapped = input(self.item); let mapped = input(self.item);
Tagged::from_item(mapped, span) Tagged::from_item(mapped, tag.clone())
} }
crate fn copy_span<U>(&self, output: U) -> Tagged<U> { crate fn copy_span<U>(&self, output: U) -> Tagged<U> {
let span = self.span(); let span = self.span();
Tagged::from_item(output, span) Tagged::from_simple_spanned_item(output, span)
} }
pub fn source(&self, source: &Text) -> Text { pub fn source(&self, source: &Text) -> Text {
@ -69,6 +92,18 @@ impl<T> Tagged<T> {
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
self.tag.span self.tag.span
} }
pub fn tag(&self) -> Tag {
self.tag
}
pub fn origin(&self) -> Option<uuid::Uuid> {
self.tag.origin
}
pub fn item(&self) -> &T {
&self.item
}
} }
impl<T> From<&Tagged<T>> for Span { impl<T> From<&Tagged<T>> for Span {
@ -88,7 +123,6 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
Span { Span {
start: input.offset, start: input.offset,
end: input.offset + input.fragment.len(), end: input.offset + input.fragment.len(),
source: None,
} }
} }
} }
@ -98,7 +132,6 @@ impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Spa
Span { Span {
start: input.0.offset, start: input.0.offset,
end: input.1.offset, end: input.1.offset,
source: None,
} }
} }
} }
@ -108,7 +141,6 @@ impl From<(usize, usize)> for Span {
Span { Span {
start: input.0, start: input.0,
end: input.1, end: input.1,
source: None,
} }
} }
} }
@ -118,7 +150,6 @@ impl From<&std::ops::Range<usize>> for Span {
Span { Span {
start: input.start, start: input.start,
end: input.end, end: input.end,
source: None,
} }
} }
} }
@ -127,24 +158,33 @@ impl From<&std::ops::Range<usize>> for Span {
Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
)] )]
pub struct Tag { pub struct Tag {
pub origin: Option<Uuid>,
pub span: Span, pub span: Span,
} }
impl Tag {
pub fn unknown_origin(span: Span) -> Tag {
Tag { origin: None, span }
}
pub fn unknown() -> Tag {
Tag {
origin: None,
span: Span::unknown(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
pub struct Span { pub struct Span {
crate start: usize, crate start: usize,
crate end: usize, crate end: usize,
pub source: Option<Uuid>,
} }
impl From<Option<Span>> for Span { impl From<Option<Span>> for Span {
fn from(input: Option<Span>) -> Span { fn from(input: Option<Span>) -> Span {
match input { match input {
None => Span { None => Span { start: 0, end: 0 },
start: 0,
end: 0,
source: None,
},
Some(span) => span, Some(span) => span,
} }
} }
@ -152,13 +192,10 @@ impl From<Option<Span>> for Span {
impl Span { impl Span {
pub fn unknown() -> Span { pub fn unknown() -> Span {
Span { Span { start: 0, end: 0 }
start: 0,
end: 0,
source: None,
}
} }
/*
pub fn unknown_with_uuid(uuid: Uuid) -> Span { pub fn unknown_with_uuid(uuid: Uuid) -> Span {
Span { Span {
start: 0, start: 0,
@ -166,6 +203,7 @@ impl Span {
source: Some(uuid), source: Some(uuid),
} }
} }
*/
pub fn is_unknown(&self) -> bool { pub fn is_unknown(&self) -> bool {
self.start == 0 && self.end == 0 self.start == 0 && self.end == 0
@ -181,7 +219,6 @@ impl language_reporting::ReportingSpan for Span {
Span { Span {
start, start,
end: self.end, end: self.end,
source: None,
} }
} }
@ -189,7 +226,6 @@ impl language_reporting::ReportingSpan for Span {
Span { Span {
start: self.start, start: self.start,
end, end,
source: None,
} }
} }

View File

@ -3,8 +3,8 @@ use crate::prelude::*;
use itertools::join; use itertools::join;
use sysinfo::ProcessExt; use sysinfo::ProcessExt;
crate fn process_dict(proc: &sysinfo::Process, span: impl Into<Span>) -> Tagged<Value> { crate fn process_dict(proc: &sysinfo::Process, tag: impl Into<Tag>) -> Tagged<Value> {
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
let cmd = proc.cmd(); let cmd = proc.cmd();

View File

@ -21,7 +21,7 @@ pub trait ExtractType: Sized {
impl<T: ExtractType> ExtractType for Tagged<T> { impl<T: ExtractType> ExtractType for Tagged<T> {
fn extract(value: &Tagged<Value>) -> Result<Tagged<T>, ShellError> { fn extract(value: &Tagged<Value>) -> Result<Tagged<T>, ShellError> {
Ok(T::extract(value)?.tagged(value.span())) Ok(T::extract(value)?.simple_spanned(value.span()))
} }
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> { fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {

View File

@ -64,36 +64,36 @@ pub type Expression = Tagged<RawExpression>;
impl Expression { impl Expression {
fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression { fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
Tagged::from_item(RawExpression::Literal(Literal::Integer(i.into())), span) Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
} }
fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression { fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
Tagged::from_item( Tagged::from_simple_spanned_item(
RawExpression::Literal(Literal::Size(i.into(), unit.into())), RawExpression::Literal(Literal::Size(i.into(), unit.into())),
span, span,
) )
} }
fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
Tagged::from_item( Tagged::from_simple_spanned_item(
RawExpression::Literal(Literal::String(inner.into())), RawExpression::Literal(Literal::String(inner.into())),
outer.into(), outer.into(),
) )
} }
fn bare(span: impl Into<Span>) -> Expression { fn bare(span: impl Into<Span>) -> Expression {
Tagged::from_item(RawExpression::Literal(Literal::Bare), span.into()) Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
} }
fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
Tagged::from_item( Tagged::from_simple_spanned_item(
RawExpression::Variable(Variable::Other(inner.into())), RawExpression::Variable(Variable::Other(inner.into())),
outer.into(), outer.into(),
) )
} }
fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
Tagged::from_item( Tagged::from_simple_spanned_item(
RawExpression::Variable(Variable::It(inner.into())), RawExpression::Variable(Variable::It(inner.into())),
outer.into(), outer.into(),
) )

View File

@ -61,7 +61,7 @@ pub fn baseline_parse_next_expr(
(SyntaxType::Path, token) => { (SyntaxType::Path, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Path", "Path",
token.type_name().tagged(token.span()), token.type_name().simple_spanned(token.span()),
)) ))
} }
@ -81,10 +81,10 @@ pub fn baseline_parse_next_expr(
let second = match tokens.next() { let second = match tokens.next() {
None => { None => {
return Err(ShellError::maybe_labeled_error( return Err(ShellError::labeled_error(
"Expected something after an operator", "Expected something after an operator",
"operator", "operator",
Some(op.span()), op.span(),
)) ))
} }
Some(token) => baseline_parse_semantic_token(token, registry, source)?, Some(token) => baseline_parse_semantic_token(token, registry, source)?,
@ -97,7 +97,7 @@ pub fn baseline_parse_next_expr(
let span = (first.span().start, second.span().end); let span = (first.span().start, second.span().end);
let binary = hir::Binary::new(first, op, second); let binary = hir::Binary::new(first, op, second);
let binary = hir::RawExpression::Binary(Box::new(binary)); let binary = hir::RawExpression::Binary(Box::new(binary));
let binary = Tagged::from_item(binary, span); let binary = Tagged::from_simple_spanned_item(binary, span);
Ok(binary) Ok(binary)
} }
@ -108,11 +108,12 @@ pub fn baseline_parse_next_expr(
let path: Tagged<hir::RawExpression> = match first { let path: Tagged<hir::RawExpression> = match first {
Tagged { Tagged {
item: hir::RawExpression::Literal(hir::Literal::Bare), item: hir::RawExpression::Literal(hir::Literal::Bare),
tag: Tag { span }, tag: Tag { span, .. },
} => { } => {
let string = Tagged::from_item(span.slice(source).to_string(), span); let string =
Tagged::from_simple_spanned_item(span.slice(source).to_string(), span);
let path = hir::Path::new( let path = hir::Path::new(
Tagged::from_item( Tagged::from_simple_spanned_item(
// TODO: Deal with synthetic nodes that have no representation at all in source // TODO: Deal with synthetic nodes that have no representation at all in source
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
(0, 0), (0, 0),
@ -120,15 +121,16 @@ pub fn baseline_parse_next_expr(
vec![string], vec![string],
); );
let path = hir::RawExpression::Path(Box::new(path)); let path = hir::RawExpression::Path(Box::new(path));
Tagged::from_item(path, first.span()) Tagged::from_simple_spanned_item(path, first.span())
} }
Tagged { Tagged {
item: hir::RawExpression::Literal(hir::Literal::String(inner)), item: hir::RawExpression::Literal(hir::Literal::String(inner)),
tag: Tag { span }, tag: Tag { span, .. },
} => { } => {
let string = Tagged::from_item(inner.slice(source).to_string(), span); let string =
Tagged::from_simple_spanned_item(inner.slice(source).to_string(), span);
let path = hir::Path::new( let path = hir::Path::new(
Tagged::from_item( Tagged::from_simple_spanned_item(
// TODO: Deal with synthetic nodes that have no representation at all in source // TODO: Deal with synthetic nodes that have no representation at all in source
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
(0, 0), (0, 0),
@ -136,14 +138,14 @@ pub fn baseline_parse_next_expr(
vec![string], vec![string],
); );
let path = hir::RawExpression::Path(Box::new(path)); let path = hir::RawExpression::Path(Box::new(path));
Tagged::from_item(path, first.span()) Tagged::from_simple_spanned_item(path, first.span())
} }
Tagged { Tagged {
item: hir::RawExpression::Variable(..), item: hir::RawExpression::Variable(..),
.. ..
} => first, } => first,
Tagged { Tagged {
tag: Tag { span }, tag: Tag { span, .. },
item, item,
} => { } => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -156,10 +158,10 @@ pub fn baseline_parse_next_expr(
let binary = hir::Binary::new(path, op, second); let binary = hir::Binary::new(path, op, second);
let binary = hir::RawExpression::Binary(Box::new(binary)); let binary = hir::RawExpression::Binary(Box::new(binary));
let binary = Tagged::from_item(binary, span); let binary = Tagged::from_simple_spanned_item(binary, span);
let block = hir::RawExpression::Block(vec![binary]); let block = hir::RawExpression::Block(vec![binary]);
let block = Tagged::from_item(block, span); let block = Tagged::from_simple_spanned_item(block, span);
Ok(block) Ok(block)
} }
@ -204,7 +206,7 @@ pub fn baseline_parse_delimited(
baseline_parse_tokens(&mut TokensIterator::new(children), registry, source)?; baseline_parse_tokens(&mut TokensIterator::new(children), registry, source)?;
let expr = hir::RawExpression::Block(exprs); let expr = hir::RawExpression::Block(exprs);
Ok(Tagged::from_item(expr, token.span())) Ok(Tagged::from_simple_spanned_item(expr, token.span()))
} }
Delimiter::Paren => unimplemented!(), Delimiter::Paren => unimplemented!(),
Delimiter::Square => unimplemented!(), Delimiter::Square => unimplemented!(),
@ -228,7 +230,7 @@ pub fn baseline_parse_path(
RawToken::Integer(_) | RawToken::Size(..) | RawToken::Variable(_) => { RawToken::Integer(_) | RawToken::Size(..) | RawToken::Variable(_) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"String", "String",
token.type_name().tagged(part), token.type_name().simple_spanned(part),
)) ))
} }
}, },
@ -240,10 +242,10 @@ pub fn baseline_parse_path(
} }
.to_string(); .to_string();
tail.push(string.tagged(part)); tail.push(string.simple_spanned(part));
} }
Ok(hir::path(head, tail).tagged(token).into()) Ok(hir::path(head, tail).simple_spanned(token).into())
} }
#[derive(Debug, new)] #[derive(Debug, new)]

View File

@ -77,7 +77,7 @@ pub fn raw_integer(input: NomSpan) -> IResult<NomSpan, Tagged<i64>> {
Ok(( Ok((
input, input,
Tagged::from_item(int(num.fragment, neg), (start, end)), Tagged::from_simple_spanned_item(int(num.fragment, neg), (start, end)),
)) ))
}) })
} }
@ -231,7 +231,7 @@ pub fn raw_unit(input: NomSpan) -> IResult<NomSpan, Tagged<Unit>> {
Ok(( Ok((
input, input,
Tagged::from_item(Unit::from(unit.fragment), (start, end)), Tagged::from_simple_spanned_item(Unit::from(unit.fragment), (start, end)),
)) ))
}) })
} }
@ -1029,7 +1029,7 @@ mod tests {
right: usize, right: usize,
) -> TokenNode { ) -> TokenNode {
let node = DelimitedNode::new(delimiter, children); let node = DelimitedNode::new(delimiter, children);
let spanned = Tagged::from_item(node, (left, right)); let spanned = Tagged::from_simple_spanned_item(node, (left, right));
TokenNode::Delimited(spanned) TokenNode::Delimited(spanned)
} }
@ -1038,16 +1038,16 @@ mod tests {
Box::new(head), Box::new(head),
tail.into_iter().map(TokenNode::Token).collect(), tail.into_iter().map(TokenNode::Token).collect(),
); );
let spanned = Tagged::from_item(node, (left, right)); let spanned = Tagged::from_simple_spanned_item(node, (left, right));
TokenNode::Path(spanned) TokenNode::Path(spanned)
} }
fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode { fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode {
TokenNode::Token(Tagged::from_item(token, (left, right))) TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
} }
fn token(token: RawToken, left: usize, right: usize) -> TokenNode { fn token(token: RawToken, left: usize, right: usize) -> TokenNode {
TokenNode::Token(Tagged::from_item(token, (left, right))) TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
} }
fn build<T>(block: CurriedNode<T>) -> T { fn build<T>(block: CurriedNode<T>) -> T {

View File

@ -92,7 +92,7 @@ impl TokenTreeBuilder {
input: (Vec<PipelineElement>, Option<Span>), input: (Vec<PipelineElement>, Option<Span>),
span: impl Into<Span>, span: impl Into<Span>,
) -> TokenNode { ) -> TokenNode {
TokenNode::Pipeline(Tagged::from_item( TokenNode::Pipeline(Tagged::from_simple_spanned_item(
Pipeline::new(input.0, input.1.into()), Pipeline::new(input.0, input.1.into()),
span, span,
)) ))
@ -111,7 +111,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode { pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode {
TokenNode::Operator(Tagged::from_item(input.into(), span.into())) TokenNode::Operator(Tagged::from_simple_spanned_item(input.into(), span.into()))
} }
pub fn string(input: impl Into<String>) -> CurriedToken { pub fn string(input: impl Into<String>) -> CurriedToken {
@ -128,7 +128,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
TokenNode::Token(Tagged::from_item( TokenNode::Token(Tagged::from_simple_spanned_item(
RawToken::String(input.into()), RawToken::String(input.into()),
span.into(), span.into(),
)) ))
@ -146,7 +146,10 @@ impl TokenTreeBuilder {
} }
pub fn spanned_bare(input: impl Into<Span>) -> TokenNode { pub fn spanned_bare(input: impl Into<Span>) -> TokenNode {
TokenNode::Token(Tagged::from_item(RawToken::Bare, input.into())) TokenNode::Token(Tagged::from_simple_spanned_item(
RawToken::Bare,
input.into(),
))
} }
pub fn int(input: impl Into<i64>) -> CurriedToken { pub fn int(input: impl Into<i64>) -> CurriedToken {
@ -161,7 +164,10 @@ impl TokenTreeBuilder {
} }
pub fn spanned_int(input: impl Into<i64>, span: impl Into<Span>) -> TokenNode { pub fn spanned_int(input: impl Into<i64>, span: impl Into<Span>) -> TokenNode {
TokenNode::Token(Token::from_item(RawToken::Integer(input.into()), span)) TokenNode::Token(Token::from_simple_spanned_item(
RawToken::Integer(input.into()),
span,
))
} }
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken { pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
@ -183,7 +189,10 @@ impl TokenTreeBuilder {
) -> TokenNode { ) -> TokenNode {
let (int, unit) = (input.0.into(), input.1.into()); let (int, unit) = (input.0.into(), input.1.into());
TokenNode::Token(Tagged::from_item(RawToken::Size(int, unit), span)) TokenNode::Token(Tagged::from_simple_spanned_item(
RawToken::Size(int, unit),
span,
))
} }
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken { pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
@ -206,7 +215,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode { pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode {
TokenNode::Path(Tagged::from_item( TokenNode::Path(Tagged::from_simple_spanned_item(
PathNode::new(Box::new(input.0), input.1), PathNode::new(Box::new(input.0), input.1),
span, span,
)) ))
@ -224,7 +233,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
TokenNode::Token(Tagged::from_item( TokenNode::Token(Tagged::from_simple_spanned_item(
RawToken::Variable(input.into()), RawToken::Variable(input.into()),
span.into(), span.into(),
)) ))
@ -242,7 +251,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
TokenNode::Flag(Tagged::from_item( TokenNode::Flag(Tagged::from_simple_spanned_item(
Flag::new(FlagKind::Longhand, input.into()), Flag::new(FlagKind::Longhand, input.into()),
span.into(), span.into(),
)) ))
@ -260,7 +269,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
TokenNode::Flag(Tagged::from_item( TokenNode::Flag(Tagged::from_simple_spanned_item(
Flag::new(FlagKind::Shorthand, input.into()), Flag::new(FlagKind::Shorthand, input.into()),
span.into(), span.into(),
)) ))
@ -306,7 +315,7 @@ impl TokenTreeBuilder {
let head = input.next().unwrap(); let head = input.next().unwrap();
let tail = input.collect(); let tail = input.collect();
Tagged::from_item(CallNode::new(Box::new(head), tail), span) Tagged::from_simple_spanned_item(CallNode::new(Box::new(head), tail), span)
} }
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken { pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
@ -324,7 +333,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
TokenNode::Delimited(Tagged::from_item( TokenNode::Delimited(Tagged::from_simple_spanned_item(
DelimitedNode::new(Delimiter::Paren, input.into()), DelimitedNode::new(Delimiter::Paren, input.into()),
span, span,
)) ))
@ -345,7 +354,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
TokenNode::Delimited(Tagged::from_item( TokenNode::Delimited(Tagged::from_simple_spanned_item(
DelimitedNode::new(Delimiter::Square, input.into()), DelimitedNode::new(Delimiter::Square, input.into()),
span, span,
)) ))
@ -366,7 +375,7 @@ impl TokenTreeBuilder {
} }
pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
TokenNode::Delimited(Tagged::from_item( TokenNode::Delimited(Tagged::from_simple_spanned_item(
DelimitedNode::new(Delimiter::Brace, input.into()), DelimitedNode::new(Delimiter::Brace, input.into()),
span, span,
)) ))

View File

@ -48,8 +48,8 @@ fn parse_command_head(head: &TokenNode) -> Result<hir::Expression, ShellError> {
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::String(inner_span), item: RawToken::String(inner_span),
tag: Tag { span }, tag: Tag { span, origin: None },
}) => Ok(Tagged::from_item( }) => Ok(Tagged::from_simple_spanned_item(
hir::RawExpression::Literal(hir::Literal::String(*inner_span)), hir::RawExpression::Literal(hir::Literal::String(*inner_span)),
*span, *span,
)), )),

View File

@ -252,8 +252,10 @@ fn evaluate_args(
for (name, value) in n.named.iter() { for (name, value) in n.named.iter() {
match value { match value {
hir::named::NamedValue::PresentSwitch(span) => { hir::named::NamedValue::PresentSwitch(span) => {
results results.insert(
.insert(name.clone(), Tagged::from_item(Value::boolean(true), *span)); name.clone(),
Tagged::from_simple_spanned_item(Value::boolean(true), *span),
);
} }
hir::named::NamedValue::Value(expr) => { hir::named::NamedValue::Value(expr) => {
results.insert( results.insert(

View File

@ -17,10 +17,10 @@ impl Add {
} }
fn add(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> { fn add(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
let value_span = value.span(); let value_tag = value.tag();
match (value.item, self.value.clone()) { match (value.item, self.value.clone()) {
(obj @ Value::Object(_), Some(v)) => match &self.field { (obj @ Value::Object(_), Some(v)) => match &self.field {
Some(f) => match obj.insert_data_at_path(value_span, &f, v) { Some(f) => match obj.insert_data_at_path(value_tag, &f, v) {
Some(v) => return Ok(v), Some(v) => return Ok(v),
None => { None => {
return Err(ShellError::string( return Err(ShellError::string(

View File

@ -30,13 +30,10 @@ impl Plugin for BinaryView {
fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) { fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) {
for v in input { for v in input {
let value_span = v.span(); let value_origin = v.origin();
match v.item { match v.item {
Value::Binary(b) => { Value::Binary(b) => {
let source = value_span let source = value_origin.map(|x| call_info.source_map.get(&x)).flatten();
.source
.map(|x| call_info.source_map.get(&x))
.flatten();
let _ = view_binary(&b, source, call_info.args.has("lores")); let _ = view_binary(&b, source, call_info.args.has("lores"));
} }
_ => {} _ => {}

View File

@ -17,10 +17,10 @@ impl Edit {
} }
fn edit(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> { fn edit(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
let value_span = value.span(); let value_tag = value.tag();
match (value.item, self.value.clone()) { match (value.item, self.value.clone()) {
(obj @ Value::Object(_), Some(v)) => match &self.field { (obj @ Value::Object(_), Some(v)) => match &self.field {
Some(f) => match obj.replace_data_at_path(value_span, &f, v) { Some(f) => match obj.replace_data_at_path(value_tag, &f, v) {
Some(v) => return Ok(v), Some(v) => return Ok(v),
None => { None => {
return Err(ShellError::string( return Err(ShellError::string(

View File

@ -26,15 +26,15 @@ impl Inc {
field: &Option<String>, field: &Option<String>,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match value.item { match value.item {
Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.span())), Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.tag())),
Value::Primitive(Primitive::Bytes(b)) => { Value::Primitive(Primitive::Bytes(b)) => {
Ok(Value::bytes(b + 1 as u64).tagged(value.span())) Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
} }
Value::Primitive(Primitive::String(ref s)) => { Value::Primitive(Primitive::String(ref s)) => {
if let Ok(i) = s.parse::<u64>() { if let Ok(i) = s.parse::<u64>() {
Ok(Tagged::from_item( Ok(Tagged::from_item(
Value::string(format!("{}", i + 1)), Value::string(format!("{}", i + 1)),
value.span(), value.tag(),
)) ))
} else if let Ok(mut ver) = semver::Version::parse(&s) { } else if let Ok(mut ver) = semver::Version::parse(&s) {
if self.major { if self.major {
@ -47,7 +47,7 @@ impl Inc {
} }
Ok(Tagged::from_item( Ok(Tagged::from_item(
Value::string(ver.to_string()), Value::string(ver.to_string()),
value.span(), value.tag(),
)) ))
} else { } else {
Err(ShellError::string("string could not be incremented")) Err(ShellError::string("string could not be incremented"))
@ -55,7 +55,7 @@ impl Inc {
} }
Value::Object(_) => match field { Value::Object(_) => match field {
Some(f) => { Some(f) => {
let replacement = match value.item.get_data_by_path(value.span(), f) { let replacement = match value.item.get_data_by_path(value.tag(), f) {
Some(result) => self.inc(result.map(|x| x.clone()), &None)?, Some(result) => self.inc(result.map(|x| x.clone()), &None)?,
None => { None => {
return Err(ShellError::string("inc could not find field to replace")) return Err(ShellError::string("inc could not find field to replace"))
@ -63,7 +63,7 @@ impl Inc {
}; };
match value match value
.item .item
.replace_data_at_path(value.span(), f, replacement.item.clone()) .replace_data_at_path(value.tag(), f, replacement.item.clone())
{ {
Some(v) => return Ok(v), Some(v) => return Ok(v),
None => { None => {

View File

@ -86,11 +86,11 @@ impl Str {
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match value.item { match value.item {
Value::Primitive(Primitive::String(ref s)) => { Value::Primitive(Primitive::String(ref s)) => {
Ok(Tagged::from_item(self.apply(&s), value.span())) Ok(Tagged::from_item(self.apply(&s), value.tag()))
} }
Value::Object(_) => match field { Value::Object(_) => match field {
Some(f) => { Some(f) => {
let replacement = match value.item.get_data_by_path(value.span(), f) { let replacement = match value.item.get_data_by_path(value.tag(), f) {
Some(result) => self.strutils(result.map(|x| x.clone()), &None)?, Some(result) => self.strutils(result.map(|x| x.clone()), &None)?,
None => { None => {
return Err(ShellError::string("str could not find field to replace")) return Err(ShellError::string("str could not find field to replace"))
@ -98,7 +98,7 @@ impl Str {
}; };
match value match value
.item .item
.replace_data_at_path(value.span(), f, replacement.item.clone()) .replace_data_at_path(value.tag(), f, replacement.item.clone())
{ {
Some(v) => return Ok(v), Some(v) => return Ok(v),
None => { None => {
@ -194,7 +194,7 @@ mod tests {
use super::Str; use super::Str;
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
Args, CallInfo, Plugin, ReturnSuccess, SourceMap, Span, Tagged, TaggedDictBuilder, Args, CallInfo, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, TaggedDictBuilder,
TaggedItem, Value, TaggedItem, Value,
}; };
@ -214,28 +214,28 @@ mod tests {
fn with_long_flag(&mut self, name: &str) -> &mut Self { fn with_long_flag(&mut self, name: &str) -> &mut Self {
self.flags.insert( self.flags.insert(
name.to_string(), name.to_string(),
Value::boolean(true).tagged(Span::unknown()), Value::boolean(true).simple_spanned(Span::unknown()),
); );
self self
} }
fn with_parameter(&mut self, name: &str) -> &mut Self { fn with_parameter(&mut self, name: &str) -> &mut Self {
self.positionals self.positionals
.push(Value::string(name.to_string()).tagged(Span::unknown())); .push(Value::string(name.to_string()).simple_spanned(Span::unknown()));
self self
} }
fn create(&self) -> CallInfo { fn create(&self, name_span: Span) -> CallInfo {
CallInfo { CallInfo {
args: Args::new(Some(self.positionals.clone()), Some(self.flags.clone())), args: Args::new(Some(self.positionals.clone()), Some(self.flags.clone())),
source_map: SourceMap::new(), source_map: SourceMap::new(),
name_span: None, name_span,
} }
} }
} }
fn sample_record(key: &str, value: &str) -> Tagged<Value> { fn sample_record(key: &str, value: &str) -> Tagged<Value> {
let mut record = TaggedDictBuilder::new(Span::unknown()); let mut record = TaggedDictBuilder::new(Tag::unknown());
record.insert(key.clone(), Value::string(value)); record.insert(key.clone(), Value::string(value));
record.into_tagged_value() record.into_tagged_value()
} }
@ -256,7 +256,11 @@ mod tests {
let mut plugin = Str::new(); let mut plugin = Str::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("downcase").create()) .begin_filter(
CallStub::new()
.with_long_flag("downcase")
.create(Span::unknown())
)
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -266,7 +270,11 @@ mod tests {
let mut plugin = Str::new(); let mut plugin = Str::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("upcase").create()) .begin_filter(
CallStub::new()
.with_long_flag("upcase")
.create(Span::unknown())
)
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -276,7 +284,11 @@ mod tests {
let mut plugin = Str::new(); let mut plugin = Str::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("to-int").create()) .begin_filter(
CallStub::new()
.with_long_flag("to-int")
.create(Span::unknown())
)
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -289,7 +301,7 @@ mod tests {
.begin_filter( .begin_filter(
CallStub::new() CallStub::new()
.with_parameter("package.description") .with_parameter("package.description")
.create() .create(Span::unknown())
) )
.is_ok()); .is_ok());
@ -306,7 +318,7 @@ mod tests {
.with_long_flag("upcase") .with_long_flag("upcase")
.with_long_flag("downcase") .with_long_flag("downcase")
.with_long_flag("to-int") .with_long_flag("to-int")
.create(), .create(Span::unknown()),
) )
.is_err()); .is_err());
assert_eq!(plugin.error, Some("can only apply one".to_string())); assert_eq!(plugin.error, Some("can only apply one".to_string()));
@ -342,7 +354,7 @@ mod tests {
CallStub::new() CallStub::new()
.with_long_flag("upcase") .with_long_flag("upcase")
.with_parameter("name") .with_parameter("name")
.create() .create(Span::unknown())
) )
.is_ok()); .is_ok());
@ -370,7 +382,7 @@ mod tests {
CallStub::new() CallStub::new()
.with_long_flag("downcase") .with_long_flag("downcase")
.with_parameter("name") .with_parameter("name")
.create() .create(Span::unknown())
) )
.is_ok()); .is_ok());
@ -398,7 +410,7 @@ mod tests {
CallStub::new() CallStub::new()
.with_long_flag("to-int") .with_long_flag("to-int")
.with_parameter("Nu_birthday") .with_parameter("Nu_birthday")
.create() .create(Span::unknown())
) )
.is_ok()); .is_ok());

View File

@ -18,10 +18,11 @@ impl Sum {
match self.total { match self.total {
Some(Tagged { Some(Tagged {
item: Value::Primitive(Primitive::Int(j)), item: Value::Primitive(Primitive::Int(j)),
tag: Tag { span }, tag: Tag { span, .. },
}) => { }) => {
//TODO: handle overflow //TODO: handle overflow
self.total = Some(Tagged::from_item(Value::int(i + j), span)); self.total =
Some(Tagged::from_simple_spanned_item(Value::int(i + j), span));
Ok(()) Ok(())
} }
None => { None => {
@ -37,10 +38,11 @@ impl Sum {
match self.total { match self.total {
Some(Tagged { Some(Tagged {
item: Value::Primitive(Primitive::Bytes(j)), item: Value::Primitive(Primitive::Bytes(j)),
tag: Tag { span }, tag: Tag { span, .. },
}) => { }) => {
//TODO: handle overflow //TODO: handle overflow
self.total = Some(Tagged::from_item(Value::bytes(b + j), span)); self.total =
Some(Tagged::from_simple_spanned_item(Value::bytes(b + j), span));
Ok(()) Ok(())
} }
None => { None => {

View File

@ -6,7 +6,7 @@ use heim::{disk, memory};
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue, serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
ShellError, Span, Tagged, TaggedDictBuilder, Value, OF64, ShellError, Tag, Tagged, TaggedDictBuilder, Value, OF64,
}; };
use std::ffi::OsStr; use std::ffi::OsStr;
@ -19,9 +19,9 @@ impl Sys {
//TODO: add more error checking //TODO: add more error checking
async fn cpu(span: Span) -> Option<Tagged<Value>> { async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
if let (Ok(num_cpu), Ok(cpu_speed)) = (sys_info::cpu_num(), sys_info::cpu_speed()) { if let (Ok(num_cpu), Ok(cpu_speed)) = (sys_info::cpu_num(), sys_info::cpu_speed()) {
let mut cpu_idx = TaggedDictBuilder::new(span); let mut cpu_idx = TaggedDictBuilder::new(tag);
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64)); cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64)); cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
Some(cpu_idx.into_tagged_value()) Some(cpu_idx.into_tagged_value())
@ -30,8 +30,8 @@ async fn cpu(span: Span) -> Option<Tagged<Value>> {
} }
} }
async fn mem(span: Span) -> Tagged<Value> { async fn mem(tag: Tag) -> Tagged<Value> {
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
if let Ok(memory) = memory::memory().await { if let Ok(memory) = memory::memory().await {
dict.insert("total", Value::bytes(memory.total().get())); dict.insert("total", Value::bytes(memory.total().get()));
@ -45,8 +45,8 @@ async fn mem(span: Span) -> Tagged<Value> {
dict.into_tagged_value() dict.into_tagged_value()
} }
async fn host(span: Span) -> Tagged<Value> { async fn host(tag: Tag) -> Tagged<Value> {
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
// OS // OS
if let Ok(platform) = heim::host::platform().await { if let Ok(platform) = heim::host::platform().await {
@ -58,7 +58,7 @@ async fn host(span: Span) -> Tagged<Value> {
// Uptime // Uptime
if let Ok(uptime) = heim::host::uptime().await { if let Ok(uptime) = heim::host::uptime().await {
let mut uptime_dict = TaggedDictBuilder::new(span); let mut uptime_dict = TaggedDictBuilder::new(tag);
let uptime = uptime.get().round() as i64; let uptime = uptime.get().round() as i64;
let days = uptime / (60 * 60 * 24); let days = uptime / (60 * 60 * 24);
@ -79,7 +79,7 @@ async fn host(span: Span) -> Tagged<Value> {
let mut user_vec = vec![]; let mut user_vec = vec![];
while let Some(user) = users.next().await { while let Some(user) = users.next().await {
if let Ok(user) = user { if let Ok(user) = user {
user_vec.push(Tagged::from_item(Value::string(user.username()), span)); user_vec.push(Tagged::from_item(Value::string(user.username()), tag));
} }
} }
let user_list = Value::List(user_vec); let user_list = Value::List(user_vec);
@ -88,12 +88,12 @@ async fn host(span: Span) -> Tagged<Value> {
dict.into_tagged_value() dict.into_tagged_value()
} }
async fn disks(span: Span) -> Value { async fn disks(tag: Tag) -> Value {
let mut output = vec![]; let mut output = vec![];
let mut partitions = disk::partitions_physical(); let mut partitions = disk::partitions_physical();
while let Some(part) = partitions.next().await { while let Some(part) = partitions.next().await {
if let Ok(part) = part { if let Ok(part) = part {
let mut dict = TaggedDictBuilder::new(span); let mut dict = TaggedDictBuilder::new(tag);
dict.insert( dict.insert(
"device", "device",
Value::string( Value::string(
@ -117,14 +117,14 @@ async fn disks(span: Span) -> Value {
Value::List(output) Value::List(output)
} }
async fn temp(span: Span) -> Value { async fn temp(tag: Tag) -> Value {
use sysinfo::{ComponentExt, RefreshKind, SystemExt}; use sysinfo::{ComponentExt, RefreshKind, SystemExt};
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_system()); let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_system());
let components_list = system.get_components_list(); let components_list = system.get_components_list();
if components_list.len() > 0 { if components_list.len() > 0 {
let mut v: Vec<Tagged<Value>> = vec![]; let mut v: Vec<Tagged<Value>> = vec![];
for component in components_list { for component in components_list {
let mut component_idx = TaggedDictBuilder::new(span); let mut component_idx = TaggedDictBuilder::new(tag);
component_idx.insert("name", Primitive::String(component.get_label().to_string())); component_idx.insert("name", Primitive::String(component.get_label().to_string()));
component_idx.insert( component_idx.insert(
"temp", "temp",
@ -145,7 +145,7 @@ async fn temp(span: Span) -> Value {
} }
} }
async fn net(span: Span) -> Tagged<Value> { async fn net(tag: Tag) -> Tagged<Value> {
use sysinfo::{NetworkExt, RefreshKind, SystemExt}; use sysinfo::{NetworkExt, RefreshKind, SystemExt};
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_network()); let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_network());
@ -153,23 +153,23 @@ async fn net(span: Span) -> Tagged<Value> {
let incoming = network.get_income(); let incoming = network.get_income();
let outgoing = network.get_outcome(); let outgoing = network.get_outcome();
let mut network_idx = TaggedDictBuilder::new(span); let mut network_idx = TaggedDictBuilder::new(tag);
network_idx.insert("incoming", Value::bytes(incoming)); network_idx.insert("incoming", Value::bytes(incoming));
network_idx.insert("outgoing", Value::bytes(outgoing)); network_idx.insert("outgoing", Value::bytes(outgoing));
network_idx.into_tagged_value() network_idx.into_tagged_value()
} }
async fn sysinfo(span: Span) -> Vec<Tagged<Value>> { async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
let mut sysinfo = TaggedDictBuilder::new(span); let mut sysinfo = TaggedDictBuilder::new(tag);
sysinfo.insert_tagged("host", host(span).await); sysinfo.insert_tagged("host", host(tag).await);
if let Some(cpu) = cpu(span).await { if let Some(cpu) = cpu(tag).await {
sysinfo.insert_tagged("cpu", cpu); sysinfo.insert_tagged("cpu", cpu);
} }
sysinfo.insert("disks", disks(span).await); sysinfo.insert("disks", disks(tag).await);
sysinfo.insert_tagged("mem", mem(span).await); sysinfo.insert_tagged("mem", mem(tag).await);
sysinfo.insert("temp", temp(span).await); sysinfo.insert("temp", temp(tag).await);
sysinfo.insert_tagged("net", net(span).await); sysinfo.insert_tagged("net", net(tag).await);
vec![sysinfo.into_tagged_value()] vec![sysinfo.into_tagged_value()]
} }
@ -186,12 +186,10 @@ impl Plugin for Sys {
}) })
} }
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> { fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
Ok(block_on(sysinfo( Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
callinfo.name_span.unwrap_or_else(|| Span::unknown()), .into_iter()
)) .map(|x| ReturnSuccess::value(x))
.into_iter() .collect())
.map(|x| ReturnSuccess::value(x))
.collect())
} }
fn filter(&mut self, _: Tagged<Value>) -> Result<Vec<ReturnValue>, ShellError> { fn filter(&mut self, _: Tagged<Value>) -> Result<Vec<ReturnValue>, ShellError> {

View File

@ -210,10 +210,10 @@ fn scroll_view(s: &str) {
} }
fn view_text_value(value: &Tagged<Value>, source_map: &SourceMap) { fn view_text_value(value: &Tagged<Value>, source_map: &SourceMap) {
let value_span = value.span(); let value_origin = value.origin();
match value.item { match value.item {
Value::Primitive(Primitive::String(ref s)) => { Value::Primitive(Primitive::String(ref s)) => {
let source = value_span.source.map(|x| source_map.get(&x)).flatten(); let source = value_origin.map(|x| source_map.get(&x)).flatten();
if let Some(source) = source { if let Some(source) = source {
let extension: Option<String> = match source { let extension: Option<String> = match source {