Add first step of uuid generation and bookkeeping

This commit is contained in:
Jonathan Turner 2019-07-20 07:48:14 +12:00
parent d4ecf6dfa5
commit d5d4da0bf8
10 changed files with 128 additions and 32 deletions

2
Cargo.lock generated
View File

@ -1696,6 +1696,7 @@ dependencies = [
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"toml-query 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -3181,6 +3182,7 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]

View File

@ -75,6 +75,7 @@ crossterm = "0.9.6"
tempfile = "3.1.0" tempfile = "3.1.0"
image = "0.21.2" image = "0.21.2"
semver = "0.9.0" semver = "0.9.0"
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
[dev-dependencies] [dev-dependencies]
pretty_assertions = "0.6.1" pretty_assertions = "0.6.1"

View File

@ -494,6 +494,7 @@ fn classify_command(
Ok(ClassifiedCommand::Internal(InternalCommand { Ok(ClassifiedCommand::Internal(InternalCommand {
command, command,
name_span: Some(head.span().clone()), name_span: Some(head.span().clone()),
span_sources: context.span_sources.clone(),
args, args,
})) }))
} }

View File

@ -1,13 +1,16 @@
use crate::commands::command::Sink; use crate::commands::command::Sink;
use crate::context::SpanSource;
use crate::parser::{registry::Args, Span, Spanned, TokenNode}; use crate::parser::{registry::Args, Span, Spanned, TokenNode};
use crate::prelude::*; use crate::prelude::*;
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use futures::stream::StreamExt; use futures::stream::StreamExt;
use futures_codec::{Decoder, Encoder, Framed}; use futures_codec::{Decoder, Encoder, Framed};
use log::{log_enabled, trace}; use log::{log_enabled, trace};
use std::collections::HashMap;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::sync::Arc; use std::sync::Arc;
use subprocess::Exec; use subprocess::Exec;
use uuid::Uuid;
/// A simple `Codec` implementation that splits up data into lines. /// A simple `Codec` implementation that splits up data into lines.
pub struct LinesCodec {} pub struct LinesCodec {}
@ -116,6 +119,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: Option<Span>,
crate span_sources: HashMap<Uuid, SpanSource>,
crate args: Args, crate args: Args,
} }
@ -134,8 +138,13 @@ impl InternalCommand {
let objects: InputStream = let objects: InputStream =
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects); trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
let result = let result = context.run_command(
context.run_command(self.command, self.name_span.clone(), self.args, objects)?; self.command,
self.name_span.clone(),
self.span_sources,
self.args,
objects,
)?;
let mut result = result.values; let mut result = result.values;
@ -146,6 +155,9 @@ impl InternalCommand {
CommandAction::ChangePath(path) => { CommandAction::ChangePath(path) => {
context.env.lock().unwrap().path = path; context.env.lock().unwrap().path = path;
} }
CommandAction::AddSpanSource(uuid, span_source) => {
context.add_span_source(uuid, span_source);
}
CommandAction::Exit => std::process::exit(0), CommandAction::Exit => std::process::exit(0),
}, },

View File

@ -1,3 +1,4 @@
use crate::context::SpanSource;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::object::Value; use crate::object::Value;
use crate::parser::{ use crate::parser::{
@ -7,7 +8,9 @@ use crate::parser::{
use crate::prelude::*; use crate::prelude::*;
use getset::Getters; use getset::Getters;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use uuid::Uuid;
#[derive(Getters)] #[derive(Getters)]
#[get = "crate"] #[get = "crate"]
@ -15,6 +18,7 @@ pub struct CommandArgs {
pub host: Arc<Mutex<dyn Host + Send>>, pub host: Arc<Mutex<dyn Host + Send>>,
pub env: Arc<Mutex<Environment>>, pub env: Arc<Mutex<Environment>>,
pub name_span: Option<Span>, pub name_span: Option<Span>,
pub span_sources: HashMap<Uuid, SpanSource>,
pub args: Args, pub args: Args,
pub input: InputStream, pub input: InputStream,
} }
@ -49,6 +53,7 @@ impl CommandArgs {
pub struct SinkCommandArgs { pub struct SinkCommandArgs {
pub ctx: Context, pub ctx: Context,
pub name_span: Option<Span>, pub name_span: Option<Span>,
pub span_sources: HashMap<Uuid, SpanSource>,
pub args: Args, pub args: Args,
pub input: Vec<Spanned<Value>>, pub input: Vec<Spanned<Value>>,
} }
@ -56,6 +61,7 @@ pub struct SinkCommandArgs {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum CommandAction { pub enum CommandAction {
ChangePath(PathBuf), ChangePath(PathBuf),
AddSpanSource(Uuid, SpanSource),
Exit, Exit,
} }
@ -82,6 +88,10 @@ impl ReturnSuccess {
Ok(ReturnSuccess::Value(input.into())) Ok(ReturnSuccess::Value(input.into()))
} }
pub fn action(input: CommandAction) -> ReturnValue {
Ok(ReturnSuccess::Action(input))
}
pub fn spanned_value(input: Value, span: Span) -> ReturnValue { pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
Ok(ReturnSuccess::Value(Spanned::from_item(input, span))) Ok(ReturnSuccess::Value(Spanned::from_item(input, span)))
} }

View File

@ -1,3 +1,4 @@
use crate::context::SpanSource;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::object::{Primitive, Switch, Value}; use crate::object::{Primitive, Switch, Value};
use crate::parser::parse::span::Span; use crate::parser::parse::span::Span;
@ -5,6 +6,7 @@ use crate::prelude::*;
use mime::Mime; use mime::Mime;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use uuid::Uuid;
command! { command! {
Open as open(args, path: Spanned<PathBuf>, --raw: Switch,) { Open as open(args, path: Spanned<PathBuf>, --raw: Switch,) {
@ -21,19 +23,7 @@ command! {
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".spanned(path.span)))?; let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".spanned(path.span)))?;
let (file_extension, contents, contents_span) = fetch(&full_path, path_str, path.span)?; let (file_extension, contents, contents_span, span_source) = fetch(&full_path, path_str, path.span)?;
// let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
// Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
// _ => {
// return Err(ShellError::labeled_error(
// "Expected string value for filename",
// "expected filename",
// args.expect_nth(0)?.span,
// ));
// }
// };
let mut stream = VecDeque::new();
let file_extension = if raw.is_present() { let file_extension = if raw.is_present() {
None None
@ -41,6 +31,13 @@ command! {
file_extension file_extension
}; };
let mut stream = VecDeque::new();
if let Some(uuid) = contents_span.source {
// If we have loaded something, track its source
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source)))
}
match contents { match contents {
Value::Primitive(Primitive::String(string)) => Value::Primitive(Primitive::String(string)) =>
stream.push_back(ReturnSuccess::value(parse_as_value( stream.push_back(ReturnSuccess::value(parse_as_value(
@ -62,7 +59,7 @@ pub fn fetch(
cwd: &PathBuf, cwd: &PathBuf,
location: &str, location: &str,
span: Span, span: Span,
) -> Result<(Option<String>, Value, Span), ShellError> { ) -> Result<(Option<String>, Value, Span, 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);
@ -74,12 +71,14 @@ 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, Span::unknown_with_uuid(Uuid::new_v4()),
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, Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)), )),
(mime::APPLICATION, mime::OCTET_STREAM) => { (mime::APPLICATION, mime::OCTET_STREAM) => {
let mut buf: Vec<u8> = vec![]; let mut buf: Vec<u8> = vec![];
@ -90,7 +89,12 @@ pub fn fetch(
span, span,
) )
})?; })?;
Ok((None, Value::Binary(buf), span)) Ok((
None,
Value::Binary(buf),
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
))
} }
(mime::IMAGE, image_ty) => { (mime::IMAGE, image_ty) => {
let mut buf: Vec<u8> = vec![]; let mut buf: Vec<u8> = vec![];
@ -101,12 +105,18 @@ pub fn fetch(
span, span,
) )
})?; })?;
Ok((Some(image_ty.to_string()), Value::Binary(buf), span)) Ok((
Some(image_ty.to_string()),
Value::Binary(buf),
Span::unknown_with_uuid(Uuid::new_v4()),
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, Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)), )),
(mime::TEXT, mime::PLAIN) => { (mime::TEXT, mime::PLAIN) => {
let path_extension = r let path_extension = r
@ -120,16 +130,27 @@ pub fn fetch(
.map(|name| name.to_string_lossy().to_string()) .map(|name| name.to_string_lossy().to_string())
}); });
Ok((path_extension, Value::string(r.text().unwrap()), span)) Ok((
path_extension,
Value::string(r.text().unwrap()),
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
))
} }
(ty, sub_ty) => Ok(( (ty, sub_ty) => Ok((
None, None,
Value::string(format!("Not yet support MIME type: {} {}", ty, sub_ty)), Value::string(format!("Not yet support MIME type: {} {}", ty, sub_ty)),
span, Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)), )),
} }
} }
None => Ok((None, Value::string(format!("No content type found")), span)), None => Ok((
None,
Value::string(format!("No content type found")),
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)),
}, },
Err(_) => { Err(_) => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
@ -147,9 +168,15 @@ 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, Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::File(cwd.to_string_lossy().to_string()),
)),
Err(_) => Ok((
None,
Value::Binary(bytes),
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
Err(_) => Ok((None, Value::Binary(bytes), span)),
}, },
Err(_) => { Err(_) => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(

View File

@ -2,8 +2,6 @@ use crate::errors::ShellError;
use crate::object::Value; use crate::object::Value;
use crate::prelude::*; use crate::prelude::*;
// TODO: "Amount remaining" wrapper
pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> { pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;

View File

@ -4,15 +4,24 @@ use crate::parser::{
Span, Span,
}; };
use crate::prelude::*; use crate::prelude::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum SpanSource {
Url(String),
File(String),
}
#[derive(Clone)] #[derive(Clone)]
pub struct Context { pub struct Context {
commands: IndexMap<String, Arc<dyn Command>>, commands: IndexMap<String, Arc<dyn Command>>,
sinks: IndexMap<String, Arc<dyn Sink>>, sinks: IndexMap<String, Arc<dyn Sink>>,
crate span_sources: HashMap<Uuid, SpanSource>,
crate host: Arc<Mutex<dyn Host + Send>>, crate host: Arc<Mutex<dyn Host + Send>>,
crate env: Arc<Mutex<Environment>>, crate env: Arc<Mutex<Environment>>,
} }
@ -22,6 +31,7 @@ impl Context {
Ok(Context { Ok(Context {
commands: indexmap::IndexMap::new(), commands: indexmap::IndexMap::new(),
sinks: indexmap::IndexMap::new(), sinks: indexmap::IndexMap::new(),
span_sources: HashMap::new(),
host: Arc::new(Mutex::new(crate::env::host::BasicHost)), host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
env: Arc::new(Mutex::new(Environment::basic()?)), env: Arc::new(Mutex::new(Environment::basic()?)),
}) })
@ -39,6 +49,10 @@ impl Context {
} }
} }
pub fn add_span_source(&mut self, uuid: Uuid, span_source: SpanSource) {
self.span_sources.insert(uuid, span_source);
}
crate fn has_sink(&self, name: &str) -> bool { crate fn has_sink(&self, name: &str) -> bool {
self.sinks.contains_key(name) self.sinks.contains_key(name)
} }
@ -57,6 +71,7 @@ impl Context {
let command_args = SinkCommandArgs { let command_args = SinkCommandArgs {
ctx: self.clone(), ctx: self.clone(),
name_span, name_span,
span_sources: self.span_sources.clone(),
args, args,
input, input,
}; };
@ -80,6 +95,7 @@ impl Context {
&mut self, &mut self,
command: Arc<dyn Command>, command: Arc<dyn Command>,
name_span: Option<Span>, name_span: Option<Span>,
span_sources: HashMap<Uuid, SpanSource>,
args: Args, args: Args,
input: InputStream, input: InputStream,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
@ -87,6 +103,7 @@ impl Context {
host: self.host.clone(), host: self.host.clone(),
env: self.env.clone(), env: self.env.clone(),
name_span, name_span,
span_sources,
args, args,
input, input,
}; };

View File

@ -17,7 +17,12 @@ impl Description {
pub fn from(item: Spanned<impl Into<String>>) -> Description { pub fn from(item: Spanned<impl Into<String>>) -> Description {
match item { match item {
Spanned { Spanned {
span: Span { start: 0, end: 0 }, span:
Span {
start: 0,
end: 0,
source: None,
},
item, item,
} => Description::Synthetic(item.into()), } => Description::Synthetic(item.into()),
Spanned { span, item } => Description::Source(Spanned::from_item(item.into(), span)), Spanned { span, item } => Description::Source(Spanned::from_item(item.into(), span)),

View File

@ -3,6 +3,7 @@ use derive_new::new;
use getset::Getters; use getset::Getters;
use serde::Serialize; use serde::Serialize;
use serde_derive::Deserialize; use serde_derive::Deserialize;
use uuid::Uuid;
#[derive( #[derive(
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters, new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
@ -75,13 +76,17 @@ impl<T> Spanned<T> {
pub struct Span { pub struct Span {
crate start: usize, crate start: usize,
crate end: usize, crate end: usize,
// source: &'source str, 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 { start: 0, end: 0 }, None => Span {
start: 0,
end: 0,
source: None,
},
Some(span) => span, Some(span) => span,
} }
} }
@ -104,6 +109,7 @@ 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,
} }
} }
} }
@ -113,6 +119,7 @@ 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,
} }
} }
} }
@ -122,6 +129,7 @@ impl From<(usize, usize)> for Span {
Span { Span {
start: input.0, start: input.0,
end: input.1, end: input.1,
source: None,
} }
} }
} }
@ -131,13 +139,26 @@ impl From<&std::ops::Range<usize>> for Span {
Span { Span {
start: input.start, start: input.start,
end: input.end, end: input.end,
source: None,
} }
} }
} }
impl Span { impl Span {
pub fn unknown() -> Span { pub fn unknown() -> Span {
Span { start: 0, end: 0 } Span {
start: 0,
end: 0,
source: None,
}
}
pub fn unknown_with_uuid(uuid: Uuid) -> Span {
Span {
start: 0,
end: 0,
source: Some(uuid),
}
} }
pub fn is_unknown(&self) -> bool { pub fn is_unknown(&self) -> bool {
@ -154,6 +175,7 @@ impl language_reporting::ReportingSpan for Span {
Span { Span {
start, start,
end: self.end, end: self.end,
source: None,
} }
} }
@ -161,6 +183,7 @@ impl language_reporting::ReportingSpan for Span {
Span { Span {
start: self.start, start: self.start,
end, end,
source: None,
} }
} }