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-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)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3181,6 +3182,7 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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]]

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,4 @@
use crate::context::SpanSource;
use crate::errors::ShellError;
use crate::object::{Primitive, Switch, Value};
use crate::parser::parse::span::Span;
@ -5,6 +6,7 @@ use crate::prelude::*;
use mime::Mime;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use uuid::Uuid;
command! {
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 (file_extension, contents, contents_span) = 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, contents, contents_span, span_source) = fetch(&full_path, path_str, path.span)?;
let file_extension = if raw.is_present() {
None
@ -41,6 +31,13 @@ command! {
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 {
Value::Primitive(Primitive::String(string)) =>
stream.push_back(ReturnSuccess::value(parse_as_value(
@ -62,7 +59,7 @@ pub fn fetch(
cwd: &PathBuf,
location: &str,
span: Span,
) -> Result<(Option<String>, Value, Span), ShellError> {
) -> Result<(Option<String>, Value, Span, SpanSource), ShellError> {
let mut cwd = cwd.clone();
if location.starts_with("http:") || location.starts_with("https:") {
let response = reqwest::get(location);
@ -74,12 +71,14 @@ pub fn fetch(
(mime::APPLICATION, mime::XML) => Ok((
Some("xml".to_string()),
Value::string(r.text().unwrap()),
span,
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)),
(mime::APPLICATION, mime::JSON) => Ok((
Some("json".to_string()),
Value::string(r.text().unwrap()),
span,
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)),
(mime::APPLICATION, mime::OCTET_STREAM) => {
let mut buf: Vec<u8> = vec![];
@ -90,7 +89,12 @@ pub fn fetch(
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) => {
let mut buf: Vec<u8> = vec![];
@ -101,12 +105,18 @@ pub fn fetch(
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((
Some("html".to_string()),
Value::string(r.text().unwrap()),
span,
Span::unknown_with_uuid(Uuid::new_v4()),
SpanSource::Url(r.url().to_string()),
)),
(mime::TEXT, mime::PLAIN) => {
let path_extension = r
@ -120,16 +130,27 @@ pub fn fetch(
.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((
None,
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(_) => {
return Err(ShellError::labeled_error(
@ -147,9 +168,15 @@ pub fn fetch(
cwd.extension()
.map(|name| name.to_string_lossy().to_string()),
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(_) => {
return Err(ShellError::labeled_error(

View File

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

View File

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

View File

@ -17,7 +17,12 @@ impl Description {
pub fn from(item: Spanned<impl Into<String>>) -> Description {
match item {
Spanned {
span: Span { start: 0, end: 0 },
span:
Span {
start: 0,
end: 0,
source: None,
},
item,
} => Description::Synthetic(item.into()),
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 serde::Serialize;
use serde_derive::Deserialize;
use uuid::Uuid;
#[derive(
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
@ -75,13 +76,17 @@ impl<T> Spanned<T> {
pub struct Span {
crate start: usize,
crate end: usize,
// source: &'source str,
pub source: Option<Uuid>,
}
impl From<Option<Span>> for Span {
fn from(input: Option<Span>) -> Span {
match input {
None => Span { start: 0, end: 0 },
None => Span {
start: 0,
end: 0,
source: None,
},
Some(span) => span,
}
}
@ -104,6 +109,7 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
Span {
start: input.offset,
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 {
start: input.0.offset,
end: input.1.offset,
source: None,
}
}
}
@ -122,6 +129,7 @@ impl From<(usize, usize)> for Span {
Span {
start: input.0,
end: input.1,
source: None,
}
}
}
@ -131,13 +139,26 @@ impl From<&std::ops::Range<usize>> for Span {
Span {
start: input.start,
end: input.end,
source: None,
}
}
}
impl 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 {
@ -154,6 +175,7 @@ impl language_reporting::ReportingSpan for Span {
Span {
start,
end: self.end,
source: None,
}
}
@ -161,6 +183,7 @@ impl language_reporting::ReportingSpan for Span {
Span {
start: self.start,
end,
source: None,
}
}