Merge pull request #643 from nushell/improve-external-words

Migrate most uses of the Span concept to Tag
This commit is contained in:
Jonathan Turner 2019-09-11 17:18:54 +12:00 committed by GitHub
commit 4c2796f11c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 1174 additions and 1255 deletions

8
Cargo.lock generated
View file

@ -1474,8 +1474,8 @@ dependencies = [
] ]
[[package]] [[package]]
name = "nom5_locate" name = "nom_locate"
version = "0.1.1" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1531,7 +1531,7 @@ dependencies = [
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3129,7 +3129,7 @@ dependencies = [
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b" "checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d" "checksum nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f932834fd8e391fc7710e2ba17e8f9f8645d846b55aa63207e17e110a1e1ce35"
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602" "checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"

View file

@ -53,7 +53,7 @@ ctrlc = "3.1.3"
surf = "1.0.2" surf = "1.0.2"
url = "2.1.0" url = "2.1.0"
roxmltree = "0.7.0" roxmltree = "0.7.0"
nom5_locate = "0.1.1" nom_locate = "1.0.0"
enum-utils = "0.1.1" enum-utils = "0.1.1"
unicode-xid = "0.2.0" unicode-xid = "0.2.0"
serde_ini = "0.2.0" serde_ini = "0.2.0"

View file

@ -266,7 +266,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
context.shell_manager.clone(), context.shell_manager.clone(),
))); )));
let edit_mode = crate::data::config::config(Span::unknown())? let edit_mode = crate::data::config::config(Tag::unknown())?
.get("edit_mode") .get("edit_mode")
.map(|s| match s.as_string().unwrap().as_ref() { .map(|s| match s.as_string().unwrap().as_ref() {
"vi" => EditMode::Vi, "vi" => EditMode::Vi,
@ -344,7 +344,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()), Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
Ok(line) => { Ok(line) => {
let result = match crate::parser::parse(&line) { let result = match crate::parser::parse(&line, uuid::Uuid::nil()) {
Err(err) => { Err(err) => {
return LineResult::Error(line.clone(), err); return LineResult::Error(line.clone(), err);
} }
@ -366,7 +366,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
.commands .commands
.push(ClassifiedCommand::Internal(InternalCommand { .push(ClassifiedCommand::Internal(InternalCommand {
command: whole_stream_command(autoview::Autoview), command: whole_stream_command(autoview::Autoview),
name_span: Span::unknown(), name_tag: Tag::unknown(),
args: hir::Call::new( args: hir::Call::new(
Box::new(hir::Expression::synthetic_string("autoview")), Box::new(hir::Expression::synthetic_string("autoview")),
None, None,
@ -486,10 +486,10 @@ fn classify_command(
match call { match call {
// If the command starts with `^`, treat it as an external command no matter what // If the command starts with `^`, treat it as an external command no matter what
call if call.head().is_external() => { call if call.head().is_external() => {
let name_span = call.head().expect_external(); let name_tag = call.head().expect_external();
let name = name_span.slice(source); let name = name_tag.slice(source);
Ok(external_command(call, source, name.tagged(name_span))) Ok(external_command(call, source, name.tagged(name_tag)))
} }
// Otherwise, if the command is a bare word, we'll need to triage it // Otherwise, if the command is a bare word, we'll need to triage it
@ -511,19 +511,19 @@ fn classify_command(
Ok(ClassifiedCommand::Internal(InternalCommand { Ok(ClassifiedCommand::Internal(InternalCommand {
command, command,
name_span: head.span().clone(), name_tag: head.tag(),
args, args,
})) }))
} }
// otherwise, it's an external command // otherwise, it's an external command
false => Ok(external_command(call, source, name.tagged(head.span()))), false => Ok(external_command(call, source, name.tagged(head.tag()))),
} }
} }
// If the command is something else (like a number or a variable), that is currently unsupported. // If the command is something else (like a number or a variable), that is currently unsupported.
// We might support `$somevar` as a curried command in the future. // We might support `$somevar` as a curried command in the future.
call => Err(ShellError::invalid_command(call.head().span())), call => Err(ShellError::invalid_command(call.head().tag())),
} }
} }
@ -540,10 +540,7 @@ fn external_command(
.iter() .iter()
.filter_map(|i| match i { .filter_map(|i| match i {
TokenNode::Whitespace(_) => None, TokenNode::Whitespace(_) => None,
other => Some(Tagged::from_simple_spanned_item( other => Some(other.as_external_arg(source).tagged(other.tag())),
other.as_external_arg(source),
other.span(),
)),
}) })
.collect(), .collect(),
None => vec![], None => vec![],
@ -553,7 +550,7 @@ fn external_command(
ClassifiedCommand::External(ExternalCommand { ClassifiedCommand::External(ExternalCommand {
name: name.to_string(), name: name.to_string(),
name_span: tag.span, name_tag: tag,
args: arg_list_strings, args: arg_list_strings,
}) })
} }

View file

@ -10,8 +10,7 @@ impl WholeStreamCommand for CD {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("cd") Signature::build("cd").optional("directory", SyntaxShape::Path)
.optional("directory", SyntaxType::Path)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -86,7 +86,7 @@ pub(crate) enum ClassifiedCommand {
pub(crate) struct InternalCommand { pub(crate) struct InternalCommand {
pub(crate) command: Arc<Command>, pub(crate) command: Arc<Command>,
pub(crate) name_span: Span, pub(crate) name_tag: Tag,
pub(crate) args: hir::Call, pub(crate) args: hir::Call,
} }
@ -108,7 +108,7 @@ impl InternalCommand {
let result = context.run_command( let result = context.run_command(
self.command, self.command,
self.name_span.clone(), self.name_tag.clone(),
context.source_map.clone(), context.source_map.clone(),
self.args, self.args,
&source, &source,
@ -133,21 +133,18 @@ impl InternalCommand {
match value { match value {
Tagged { Tagged {
item: Value::Primitive(Primitive::String(cmd)), item: Value::Primitive(Primitive::String(cmd)),
.. tag,
} => { } => {
context.shell_manager.insert_at_current(Box::new( context.shell_manager.insert_at_current(Box::new(
HelpShell::for_command( HelpShell::for_command(
Tagged::from_simple_spanned_item( Value::string(cmd).tagged(tag),
Value::string(cmd), &context.registry(),
Span::unknown(),
),
&context.registry().clone(),
)?, )?,
)); ));
} }
_ => { _ => {
context.shell_manager.insert_at_current(Box::new( context.shell_manager.insert_at_current(Box::new(
HelpShell::index(&context.registry().clone())?, HelpShell::index(&context.registry())?,
)); ));
} }
} }
@ -189,7 +186,7 @@ impl InternalCommand {
pub(crate) struct ExternalCommand { pub(crate) struct ExternalCommand {
pub(crate) name: String, pub(crate) name: String,
pub(crate) name_span: Span, pub(crate) name_tag: Tag,
pub(crate) args: Vec<Tagged<String>>, pub(crate) args: Vec<Tagged<String>>,
} }
@ -208,7 +205,7 @@ impl ExternalCommand {
) -> Result<ClassifiedInputStream, ShellError> { ) -> Result<ClassifiedInputStream, ShellError> {
let stdin = input.stdin; let stdin = input.stdin;
let inputs: Vec<Tagged<Value>> = input.objects.into_vec().await; let inputs: Vec<Tagged<Value>> = input.objects.into_vec().await;
let name_span = self.name_span.clone(); let name_tag = self.name_tag.clone();
trace!(target: "nu::run::external", "-> {}", self.name); trace!(target: "nu::run::external", "-> {}", self.name);
trace!(target: "nu::run::external", "inputs = {:?}", inputs); trace!(target: "nu::run::external", "inputs = {:?}", inputs);
@ -227,17 +224,17 @@ impl ExternalCommand {
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 tag = None;
for arg in &self.args { for arg in &self.args {
if arg.item.contains("$it") { if arg.item.contains("$it") {
span = Some(arg.span()); tag = Some(arg.tag());
} }
} }
if let Some(span) = span { if let Some(tag) = tag {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"External $it needs string data", "External $it needs string data",
"given row instead of string data", "given row instead of string data",
span, tag,
)); ));
} else { } else {
return Err(ShellError::string("Error: $it needs string data")); return Err(ShellError::string("Error: $it needs string data"));
@ -314,9 +311,7 @@ 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| { let stream = stream.map(move |line| Value::string(line.unwrap()).tagged(name_tag));
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

@ -51,7 +51,7 @@ pub mod clipboard {
Ok(OutputStream::from(stream)) Ok(OutputStream::from(stream))
} }
async fn inner_clip(input: Vec<Tagged<Value>>, name: Span) -> OutputStream { async fn inner_clip(input: Vec<Tagged<Value>>, name: Tag) -> OutputStream {
let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap(); let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap();
let mut new_copy_data = String::new(); let mut new_copy_data = String::new();

View file

@ -18,7 +18,7 @@ pub struct UnevaluatedCallInfo {
pub args: hir::Call, pub args: hir::Call,
pub source: Text, pub source: Text,
pub source_map: SourceMap, pub source_map: SourceMap,
pub name_span: Span, pub name_tag: Tag,
} }
impl ToDebug for UnevaluatedCallInfo { impl ToDebug for UnevaluatedCallInfo {
@ -38,7 +38,7 @@ impl UnevaluatedCallInfo {
Ok(CallInfo { Ok(CallInfo {
args, args,
source_map: self.source_map, source_map: self.source_map,
name_span: self.name_span, name_tag: self.name_tag,
}) })
} }
@ -74,7 +74,7 @@ impl UnevaluatedCallInfo {
pub struct CallInfo { pub struct CallInfo {
pub args: registry::EvaluatedArgs, pub args: registry::EvaluatedArgs,
pub source_map: SourceMap, pub source_map: SourceMap,
pub name_span: Span, pub name_tag: Tag,
} }
impl CallInfo { impl CallInfo {
@ -89,7 +89,7 @@ impl CallInfo {
args: T::deserialize(&mut deserializer)?, args: T::deserialize(&mut deserializer)?,
context: RunnablePerItemContext { context: RunnablePerItemContext {
shell_manager: shell_manager.clone(), shell_manager: shell_manager.clone(),
name: self.name_span, name: self.name_tag,
}, },
callback, callback,
}) })
@ -158,7 +158,7 @@ impl CommandArgs {
let host = self.host.clone(); let host = self.host.clone();
let args = self.evaluate_once(registry)?; let args = self.evaluate_once(registry)?;
let (input, args) = args.split(); let (input, args) = args.split();
let name_span = args.call_info.name_span; let name_tag = args.call_info.name_tag;
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info); let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
Ok(RunnableArgs { Ok(RunnableArgs {
@ -167,7 +167,7 @@ impl CommandArgs {
input, input,
commands: registry.clone(), commands: registry.clone(),
shell_manager, shell_manager,
name: name_span, name: name_tag,
source_map, source_map,
host, host,
}, },
@ -191,7 +191,7 @@ impl CommandArgs {
let host = self.host.clone(); let host = self.host.clone();
let args = self.evaluate_once(registry)?; let args = self.evaluate_once(registry)?;
let (input, args) = args.split(); let (input, args) = args.split();
let name_span = args.call_info.name_span; let name_tag = args.call_info.name_tag;
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info); let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
Ok(RunnableRawArgs { Ok(RunnableRawArgs {
@ -200,7 +200,7 @@ impl CommandArgs {
input, input,
commands: registry.clone(), commands: registry.clone(),
shell_manager, shell_manager,
name: name_span, name: name_tag,
source_map, source_map,
host, host,
}, },
@ -212,7 +212,7 @@ impl CommandArgs {
pub struct RunnablePerItemContext { pub struct RunnablePerItemContext {
pub shell_manager: ShellManager, pub shell_manager: ShellManager,
pub name: Span, pub name: Tag,
} }
impl RunnablePerItemContext { impl RunnablePerItemContext {
@ -227,7 +227,7 @@ pub struct RunnableContext {
pub host: Arc<Mutex<dyn Host>>, pub host: Arc<Mutex<dyn Host>>,
pub commands: CommandRegistry, pub commands: CommandRegistry,
pub source_map: SourceMap, pub source_map: SourceMap,
pub name: Span, pub name: Tag,
} }
impl RunnableContext { impl RunnableContext {
@ -311,8 +311,8 @@ impl EvaluatedWholeStreamCommandArgs {
} }
} }
pub fn name_span(&self) -> Span { pub fn name_tag(&self) -> Tag {
self.args.call_info.name_span self.args.call_info.name_tag
} }
pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) { pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) {
@ -471,12 +471,6 @@ impl ReturnSuccess {
pub fn action(input: CommandAction) -> ReturnValue { pub fn action(input: CommandAction) -> ReturnValue {
Ok(ReturnSuccess::Action(input)) Ok(ReturnSuccess::Action(input))
} }
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
Ok(ReturnSuccess::Value(Tagged::from_simple_spanned_item(
input, span,
)))
}
} }
pub trait WholeStreamCommand: Send + Sync { pub trait WholeStreamCommand: Send + Sync {

View file

@ -1,7 +1,7 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::data::{config, Value}; use crate::data::{config, Value};
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::{self}; use crate::parser::registry::{self};
use crate::prelude::*; use crate::prelude::*;
use std::iter::FromIterator; use std::iter::FromIterator;
@ -26,10 +26,10 @@ impl WholeStreamCommand for Config {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("config") Signature::build("config")
.named("load", SyntaxType::Path) .named("load", SyntaxShape::Path)
.named("set", SyntaxType::Any) .named("set", SyntaxShape::Any)
.named("get", SyntaxType::Any) .named("get", SyntaxShape::Any)
.named("remove", SyntaxType::Any) .named("remove", SyntaxShape::Any)
.switch("clear") .switch("clear")
.switch("path") .switch("path")
} }
@ -96,41 +96,21 @@ pub fn config(
config::write(&result, &configuration)?; config::write(&result, &configuration)?;
return Ok(stream![Tagged::from_simple_spanned_item( return Ok(stream![Value::Row(result.into()).tagged(value.tag())].from_input_stream());
Value::Row(result.into()),
value.span()
)]
.from_input_stream());
} }
if let Tagged { if let Tagged { item: true, tag } = clear {
item: true,
tag: Tag { span, .. },
} = clear
{
result.clear(); result.clear();
config::write(&result, &configuration)?; config::write(&result, &configuration)?;
return Ok(stream![Tagged::from_simple_spanned_item( return Ok(stream![Value::Row(result.into()).tagged(tag)].from_input_stream());
Value::Row(result.into()),
span
)]
.from_input_stream());
} }
if let Tagged { if let Tagged { item: true, tag } = path {
item: true,
tag: Tag { span, .. },
} = path
{
let path = config::default_path_for(&configuration)?; let path = config::default_path_for(&configuration)?;
return Ok(stream![Tagged::from_simple_spanned_item( return Ok(stream![Value::Primitive(Primitive::Path(path)).tagged(tag)].from_input_stream());
Value::Primitive(Primitive::Path(path)),
span
)]
.from_input_stream());
} }
if let Some(v) = remove { if let Some(v) = remove {
@ -146,9 +126,9 @@ pub fn config(
))); )));
} }
let obj = VecDeque::from_iter(vec![Value::Row(result.into()).simple_spanned(v.span())]); let obj = VecDeque::from_iter(vec![Value::Row(result.into()).tagged(v.tag())]);
return Ok(obj.from_input_stream()); return Ok(obj.from_input_stream());
} }
return Ok(vec![Value::Row(result.into()).simple_spanned(name)].into()); return Ok(vec![Value::Row(result.into()).tagged(name)].into());
} }

View file

@ -1,6 +1,6 @@
use crate::commands::command::RunnablePerItemContext; use crate::commands::command::RunnablePerItemContext;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::{CommandRegistry, Signature}; use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*; use crate::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
@ -21,9 +21,9 @@ impl PerItemCommand for Cpy {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("cp") Signature::build("cp")
.required("src", SyntaxType::Pattern) .required("src", SyntaxShape::Pattern)
.required("dst", SyntaxType::Path) .required("dst", SyntaxShape::Path)
.named("file", SyntaxType::Any) .named("file", SyntaxShape::Any)
.switch("recursive") .switch("recursive")
} }

View file

@ -1,5 +1,5 @@
use crate::errors::ShellError;
use crate::data::{Dictionary, Value}; use crate::data::{Dictionary, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use chrono::{DateTime, Local, Utc}; use chrono::{DateTime, Local, Utc};
@ -33,58 +33,40 @@ impl WholeStreamCommand for Date {
} }
} }
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, span: Span) -> Tagged<Value> pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag) -> Tagged<Value>
where where
T::Offset: Display, T::Offset: Display,
{ {
let mut indexmap = IndexMap::new(); let mut indexmap = IndexMap::new();
indexmap.insert( indexmap.insert("year".to_string(), Value::int(dt.year()).tagged(tag));
"year".to_string(), indexmap.insert("month".to_string(), Value::int(dt.month()).tagged(tag));
Tagged::from_simple_spanned_item(Value::int(dt.year()), span), indexmap.insert("day".to_string(), Value::int(dt.day()).tagged(tag));
); indexmap.insert("hour".to_string(), Value::int(dt.hour()).tagged(tag));
indexmap.insert( indexmap.insert("minute".to_string(), Value::int(dt.minute()).tagged(tag));
"month".to_string(), indexmap.insert("second".to_string(), Value::int(dt.second()).tagged(tag));
Tagged::from_simple_spanned_item(Value::int(dt.month()), span),
);
indexmap.insert(
"day".to_string(),
Tagged::from_simple_spanned_item(Value::int(dt.day()), span),
);
indexmap.insert(
"hour".to_string(),
Tagged::from_simple_spanned_item(Value::int(dt.hour()), span),
);
indexmap.insert(
"minute".to_string(),
Tagged::from_simple_spanned_item(Value::int(dt.minute()), span),
);
indexmap.insert(
"second".to_string(),
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_simple_spanned_item(Value::string(format!("{}", tz)), span), Value::string(format!("{}", tz)).tagged(tag),
); );
Tagged::from_simple_spanned_item(Value::Row(Dictionary::from(indexmap)), span) Value::Row(Dictionary::from(indexmap)).tagged(tag)
} }
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let mut date_out = VecDeque::new(); let mut date_out = VecDeque::new();
let span = args.call_info.name_span; let tag = args.call_info.name_tag;
let value = if args.has("utc") { let value = if args.has("utc") {
let utc: DateTime<Utc> = Utc::now(); let utc: DateTime<Utc> = Utc::now();
date_to_value(utc, span) date_to_value(utc, tag)
} else { } else {
let local: DateTime<Local> = Local::now(); let local: DateTime<Local> = Local::now();
date_to_value(local, span) date_to_value(local, tag)
}; };
date_out.push_back(value); date_out.push_back(value);

View file

@ -12,7 +12,7 @@ impl PerItemCommand for Echo {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("echo").rest(SyntaxType::Any) Signature::build("echo").rest(SyntaxShape::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -35,7 +35,7 @@ fn run(
_registry: &CommandRegistry, _registry: &CommandRegistry,
_raw_args: &RawCommandArgs, _raw_args: &RawCommandArgs,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name = call_info.name_span; let name = call_info.name_tag;
let mut output = String::new(); let mut output = String::new();
@ -57,7 +57,7 @@ fn run(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expect a string from pipeline", "Expect a string from pipeline",
"not a string-compatible value", "not a string-compatible value",
i.span(), i.tag(),
)); ));
} }
} }
@ -65,7 +65,7 @@ fn run(
} }
let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value( let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value(
Value::string(output).simple_spanned(name), Value::string(output).tagged(name),
))]); ))]);
Ok(stream.to_output_stream()) Ok(stream.to_output_stream())

View file

@ -14,7 +14,7 @@ impl PerItemCommand for Enter {
} }
fn signature(&self) -> registry::Signature { fn signature(&self) -> registry::Signature {
Signature::build("enter").required("location", SyntaxType::Block) Signature::build("enter").required("location", SyntaxShape::Block)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -70,7 +70,7 @@ impl PerItemCommand for Enter {
crate::commands::open::fetch( crate::commands::open::fetch(
&full_path, &full_path,
&location_clone, &location_clone,
Span::unknown(), Tag::unknown(),
) )
.await.unwrap(); .await.unwrap();
@ -103,7 +103,7 @@ impl PerItemCommand for Enter {
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
}, },
}; };
let mut result = converter.run( let mut result = converter.run(

View file

@ -2,14 +2,13 @@ use crate::commands::UnevaluatedCallInfo;
use crate::context::SpanSource; use crate::context::SpanSource;
use crate::data::Value; use crate::data::Value;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::Signature; use crate::parser::registry::Signature;
use crate::prelude::*; use crate::prelude::*;
use mime::Mime; use mime::Mime;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use surf::mime; use surf::mime;
use uuid::Uuid;
pub struct Fetch; pub struct Fetch;
impl PerItemCommand for Fetch { impl PerItemCommand for Fetch {
@ -19,7 +18,7 @@ impl PerItemCommand for Fetch {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.required("path", SyntaxType::Path) .required("path", SyntaxShape::Path)
.switch("raw") .switch("raw")
} }
@ -52,14 +51,14 @@ fn run(
}; };
let path_buf = path.as_path()?; let path_buf = path.as_path()?;
let path_str = path_buf.display().to_string(); let path_str = path_buf.display().to_string();
let path_span = path.span(); let path_tag = path.tag();
let has_raw = call_info.args.has("raw"); let has_raw = call_info.args.has("raw");
let registry = registry.clone(); let registry = registry.clone();
let raw_args = raw_args.clone(); let raw_args = raw_args.clone();
let stream = async_stream_block! { let stream = async_stream_block! {
let result = fetch(&path_str, path_span).await; let result = fetch(&path_str, path_tag).await;
if let Err(e) = result { if let Err(e) = result {
yield Err(e); yield Err(e);
@ -99,7 +98,7 @@ fn run(
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
} }
}; };
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry); let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry);
@ -130,13 +129,13 @@ fn run(
pub async fn fetch( pub async fn fetch(
location: &str, location: &str,
span: Span, tag: Tag,
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> { ) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
if let Err(_) = url::Url::parse(location) { if let Err(_) = url::Url::parse(location) {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Incomplete or incorrect url", "Incomplete or incorrect url",
"expected a full url", "expected a full url",
span, tag,
)); ));
} }
@ -152,13 +151,10 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::APPLICATION, mime::JSON) => Ok(( (mime::APPLICATION, mime::JSON) => Ok((
@ -167,13 +163,10 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::APPLICATION, mime::OCTET_STREAM) => { (mime::APPLICATION, mime::OCTET_STREAM) => {
@ -181,16 +174,13 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load binary file", "Could not load binary file",
"could not load", "could not load",
span, tag,
) )
})?; })?;
Ok(( Ok((
None, None,
Value::Binary(buf), Value::Binary(buf),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
@ -200,13 +190,10 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load svg from remote url", "Could not load svg from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::IMAGE, image_ty) => { (mime::IMAGE, image_ty) => {
@ -214,16 +201,13 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load image file", "Could not load image file",
"could not load", "could not load",
span, tag,
) )
})?; })?;
Ok(( Ok((
Some(image_ty.to_string()), Some(image_ty.to_string()),
Value::Binary(buf), Value::Binary(buf),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
@ -233,13 +217,10 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::TEXT, mime::PLAIN) => { (mime::TEXT, mime::PLAIN) => {
@ -260,23 +241,17 @@ pub async fn fetch(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
(ty, sub_ty) => Ok(( (ty, sub_ty) => Ok((
None, None,
Value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)), Value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
} }
@ -284,10 +259,7 @@ pub async fn fetch(
None => Ok(( None => Ok((
None, None,
Value::string(format!("No content type found")), Value::string(format!("No content type found")),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
}, },
@ -295,7 +267,7 @@ pub async fn fetch(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"URL could not be opened", "URL could not be opened",
"url not found", "url not found",
span, tag,
)); ));
} }
} }

View file

@ -17,7 +17,7 @@ impl WholeStreamCommand for First {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("first") Signature::build("first")
.required("amount", SyntaxType::Literal) .required("amount", SyntaxShape::Literal)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ExpectedRange;
use crate::data::{Primitive, TaggedDictBuilder, Value}; use crate::data::{Primitive, TaggedDictBuilder, Value};
use crate::errors::ExpectedRange;
use crate::prelude::*; use crate::prelude::*;
use bson::{decode_document, spec::BinarySubtype, Bson}; use bson::{decode_document, spec::BinarySubtype, Bson};
use std::str::FromStr; use std::str::FromStr;
@ -198,7 +198,7 @@ pub fn from_bson_bytes_to_value(
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -208,24 +208,24 @@ fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
let value_tag = value.tag(); let value_tag = value.tag();
match value.item { match value.item {
Value::Binary(vb) => Value::Binary(vb) =>
match from_bson_bytes_to_value(vb, span) { match from_bson_bytes_to_value(vb, tag) {
Ok(x) => yield ReturnSuccess::value(x), Ok(x) => yield ReturnSuccess::value(x),
Err(_) => { Err(_) => {
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as BSON", "Could not parse as BSON",
"input cannot be parsed as BSON", "input cannot be parsed as BSON",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)) ))
} }
} }
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }

View file

@ -86,7 +86,7 @@ fn from_csv(
}: FromCSVArgs, }: FromCSVArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let stream = async_stream_block! { let stream = async_stream_block! {
let values: Vec<Tagged<Value>> = input.values.collect().await; let values: Vec<Tagged<Value>> = input.values.collect().await;
@ -105,15 +105,15 @@ fn from_csv(
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
name_span, name_tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_csv_string_to_value(concat_string, skip_headers, name_span) { match from_csv_string_to_value(concat_string, skip_headers, name_tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -126,9 +126,9 @@ fn from_csv(
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as CSV", "Could not parse as CSV",
"input cannot be parsed as CSV", "input cannot be parsed as CSV",
name_span, name_tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -64,7 +64,7 @@ pub fn from_ini_string_to_value(
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -84,15 +84,15 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_ini_string_to_value(concat_string, span) { match from_ini_string_to_value(concat_string, tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -105,9 +105,9 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as INI", "Could not parse as INI",
"input cannot be parsed as INI", "input cannot be parsed as INI",
span, tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -72,7 +72,7 @@ fn from_json(
FromJSONArgs { objects }: FromJSONArgs, FromJSONArgs { objects }: FromJSONArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let stream = async_stream_block! { let stream = async_stream_block! {
let values: Vec<Tagged<Value>> = input.values.collect().await; let values: Vec<Tagged<Value>> = input.values.collect().await;
@ -91,9 +91,9 @@ fn from_json(
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
name_span, name_tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
@ -106,7 +106,7 @@ fn from_json(
continue; continue;
} }
match from_json_string_to_value(json_str.to_string(), name_span) { match from_json_string_to_value(json_str.to_string(), name_tag) {
Ok(x) => Ok(x) =>
yield ReturnSuccess::value(x), yield ReturnSuccess::value(x),
Err(_) => { Err(_) => {
@ -114,15 +114,15 @@ fn from_json(
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could nnot parse as JSON", "Could nnot parse as JSON",
"input cannot be parsed as JSON", "input cannot be parsed as JSON",
name_span, name_tag,
"value originates from here", "value originates from here",
last_tag.span)) last_tag))
} }
} }
} }
} }
} else { } else {
match from_json_string_to_value(concat_string, name_span) { match from_json_string_to_value(concat_string, name_tag) {
Ok(x) => Ok(x) =>
match x { match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
@ -137,9 +137,9 @@ fn from_json(
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as JSON", "Could not parse as JSON",
"input cannot be parsed as JSON", "input cannot be parsed as JSON",
name_span, name_tag,
"value originates from here", "value originates from here",
last_tag.span)) last_tag))
} }
} }
} }

View file

@ -128,7 +128,7 @@ pub fn from_sqlite_bytes_to_value(
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -138,7 +138,7 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
let value_tag = value.tag(); let value_tag = value.tag();
match value.item { match value.item {
Value::Binary(vb) => Value::Binary(vb) =>
match from_sqlite_bytes_to_value(vb, span) { match from_sqlite_bytes_to_value(vb, tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -151,18 +151,18 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as SQLite", "Could not parse as SQLite",
"input cannot be parsed as SQLite", "input cannot be parsed as SQLite",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)) ))
} }
} }
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }

View file

@ -68,7 +68,7 @@ pub fn from_toml(
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -88,15 +88,15 @@ pub fn from_toml(
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_toml_string_to_value(concat_string, span) { match from_toml_string_to_value(concat_string, tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -109,9 +109,9 @@ pub fn from_toml(
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as TOML", "Could not parse as TOML",
"input cannot be parsed as TOML", "input cannot be parsed as TOML",
span, tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -87,7 +87,7 @@ fn from_tsv(
}: FromTSVArgs, }: FromTSVArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let stream = async_stream_block! { let stream = async_stream_block! {
let values: Vec<Tagged<Value>> = input.values.collect().await; let values: Vec<Tagged<Value>> = input.values.collect().await;
@ -106,15 +106,15 @@ fn from_tsv(
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
name_span, name_tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_tsv_string_to_value(concat_string, skip_headers, name_span) { match from_tsv_string_to_value(concat_string, skip_headers, name_tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -127,9 +127,9 @@ fn from_tsv(
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as TSV", "Could not parse as TSV",
"input cannot be parsed as TSV", "input cannot be parsed as TSV",
name_span, name_tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -83,7 +83,7 @@ pub fn from_xml_string_to_value(
fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -103,15 +103,15 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_xml_string_to_value(concat_string, span) { match from_xml_string_to_value(concat_string, tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -124,9 +124,9 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as XML", "Could not parse as XML",
"input cannot be parsed as XML", "input cannot be parsed as XML",
span, tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -97,7 +97,7 @@ pub fn from_yaml_string_to_value(
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let stream = async_stream_block! { let stream = async_stream_block! {
@ -117,15 +117,15 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
value_tag.span, value_tag,
)), )),
} }
} }
match from_yaml_string_to_value(concat_string, span) { match from_yaml_string_to_value(concat_string, tag) {
Ok(x) => match x { Ok(x) => match x {
Tagged { item: Value::Table(list), .. } => { Tagged { item: Value::Table(list), .. } => {
for l in list { for l in list {
@ -138,9 +138,9 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Could not parse as YAML", "Could not parse as YAML",
"input cannot be parsed as YAML", "input cannot be parsed as YAML",
span, tag,
"value originates from here", "value originates from here",
last_tag.span, last_tag,
)) ))
} , } ,
} }

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::Value; use crate::data::Value;
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
pub struct Get; pub struct Get;
@ -16,7 +16,7 @@ impl WholeStreamCommand for Get {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("get").rest(SyntaxType::Member) Signature::build("get").rest(SyntaxShape::Member)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -47,7 +47,7 @@ fn get_member(path: &Tagged<String>, obj: &Tagged<Value>) -> Result<Tagged<Value
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Unknown column", "Unknown column",
"table missing column", "table missing column",
path.span(), path.tag(),
)); ));
} }
} }

View file

@ -1,7 +1,7 @@
use crate::commands::command::CommandAction; use crate::commands::command::CommandAction;
use crate::commands::PerItemCommand; use crate::commands::PerItemCommand;
use crate::errors::ShellError;
use crate::data::{command_dict, TaggedDictBuilder}; use crate::data::{command_dict, TaggedDictBuilder};
use crate::errors::ShellError;
use crate::parser::registry; use crate::parser::registry;
use crate::prelude::*; use crate::prelude::*;
@ -13,7 +13,7 @@ impl PerItemCommand for Help {
} }
fn signature(&self) -> registry::Signature { fn signature(&self) -> registry::Signature {
Signature::build("help").rest(SyntaxType::Any) Signature::build("help").rest(SyntaxShape::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -27,11 +27,11 @@ impl PerItemCommand for Help {
_raw_args: &RawCommandArgs, _raw_args: &RawCommandArgs,
_input: Tagged<Value>, _input: Tagged<Value>,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let span = call_info.name_span; let tag = call_info.name_tag;
if call_info.args.len() == 0 { if call_info.args.len() == 0 {
return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
Tagged::from_simple_spanned_item(Value::nothing(), span), Value::nothing().tagged(tag),
)))] )))]
.into()); .into());
} }

View file

@ -16,7 +16,7 @@ impl WholeStreamCommand for Last {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("last").required("amount", SyntaxType::Number) Signature::build("last").required("amount", SyntaxShape::Number)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{Primitive, Value}; use crate::data::{Primitive, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use log::trace; use log::trace;
@ -32,7 +32,7 @@ impl WholeStreamCommand for Lines {
fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.name_span(); let tag = args.name_tag();
let input = args.input; let input = args.input;
let input: InputStream = trace_stream!(target: "nu::trace_stream::lines", "input" = input); let input: InputStream = trace_stream!(target: "nu::trace_stream::lines", "input" = input);
@ -58,9 +58,9 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
result.push_back(Err(ShellError::labeled_error_with_secondary( result.push_back(Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
v.span(), v.tag(),
))); )));
result result
} }

View file

@ -1,16 +1,22 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use std::path::PathBuf;
pub struct LS; pub struct LS;
#[derive(Deserialize)]
pub struct LsArgs {
path: Option<Tagged<PathBuf>>,
}
impl WholeStreamCommand for LS { impl WholeStreamCommand for LS {
fn name(&self) -> &str { fn name(&self) -> &str {
"ls" "ls"
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("ls").optional("path", SyntaxType::Pattern) Signature::build("ls").optional("path", SyntaxShape::Pattern)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -22,12 +28,11 @@ impl WholeStreamCommand for LS {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
ls(args, registry) args.process(registry, ls)?.run()
// ls(args, registry)
} }
} }
fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn ls(LsArgs { path }: LsArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
let shell_manager = args.shell_manager.clone(); context.shell_manager.ls(path, context.name)
let args = args.evaluate_once(registry)?;
shell_manager.ls(args)
} }

View file

@ -17,7 +17,7 @@ impl PerItemCommand for Mkdir {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("mkdir").rest(SyntaxType::Path) Signature::build("mkdir").rest(SyntaxShape::Path)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,6 +1,6 @@
use crate::commands::command::RunnablePerItemContext; use crate::commands::command::RunnablePerItemContext;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::{CommandRegistry, Signature}; use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*; use crate::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
@ -20,9 +20,9 @@ impl PerItemCommand for Move {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("mv") Signature::build("mv")
.required("source", SyntaxType::Path) .required("source", SyntaxShape::Pattern)
.required("destination", SyntaxType::Path) .required("destination", SyntaxShape::Path)
.named("file", SyntaxType::Any) .named("file", SyntaxShape::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -16,7 +16,7 @@ impl WholeStreamCommand for Nth {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("nth").required("amount", SyntaxType::Any) Signature::build("nth").required("amount", SyntaxShape::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -2,11 +2,10 @@ use crate::commands::UnevaluatedCallInfo;
use crate::context::SpanSource; use crate::context::SpanSource;
use crate::data::Value; use crate::data::Value;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::Signature; use crate::parser::registry::Signature;
use crate::prelude::*; use crate::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uuid::Uuid;
pub struct Open; pub struct Open;
impl PerItemCommand for Open { impl PerItemCommand for Open {
@ -16,7 +15,7 @@ impl PerItemCommand for Open {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.required("path", SyntaxType::Path) .required("path", SyntaxShape::Path)
.switch("raw") .switch("raw")
} }
@ -53,7 +52,7 @@ fn run(
}; };
let path_buf = path.as_path()?; let path_buf = path.as_path()?;
let path_str = path_buf.display().to_string(); let path_str = path_buf.display().to_string();
let path_span = path.span(); let path_span = path.tag();
let has_raw = call_info.args.has("raw"); let has_raw = call_info.args.has("raw");
let registry = registry.clone(); let registry = registry.clone();
let raw_args = raw_args.clone(); let raw_args = raw_args.clone();
@ -100,7 +99,7 @@ fn run(
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
} }
}; };
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry); let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry);
@ -132,7 +131,7 @@ fn run(
pub async fn fetch( pub async fn fetch(
cwd: &PathBuf, cwd: &PathBuf,
location: &str, location: &str,
span: Span, tag: Tag,
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> { ) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
let mut cwd = cwd.clone(); let mut cwd = cwd.clone();
@ -144,10 +143,7 @@ pub async 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),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
Err(_) => { Err(_) => {
@ -163,19 +159,13 @@ pub async 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),
Tag { 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),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
} }
@ -183,10 +173,7 @@ pub async fn fetch(
Ok(( Ok((
None, None,
Value::Binary(bytes), Value::Binary(bytes),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)) ))
} }
@ -201,19 +188,13 @@ pub async 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),
Tag { 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),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
} }
@ -221,10 +202,7 @@ pub async fn fetch(
Ok(( Ok((
None, None,
Value::Binary(bytes), Value::Binary(bytes),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)) ))
} }
@ -232,10 +210,7 @@ pub async fn fetch(
_ => Ok(( _ => Ok((
None, None,
Value::Binary(bytes), Value::Binary(bytes),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::File(cwd.to_string_lossy().to_string()), SpanSource::File(cwd.to_string_lossy().to_string()),
)), )),
} }
@ -245,7 +220,7 @@ pub async fn fetch(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"File could not be opened", "File could not be opened",
"file not found", "file not found",
span, tag,
)); ));
} }
} }
@ -253,7 +228,7 @@ pub async fn fetch(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"File could not be opened", "File could not be opened",
"file not found", "file not found",
span, tag,
)); ));
} }
} }

View file

@ -17,7 +17,7 @@ impl WholeStreamCommand for Pick {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("pick").rest(SyntaxType::Any) Signature::build("pick").rest(SyntaxShape::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,8 +1,8 @@
use crate::commands::UnevaluatedCallInfo; use crate::commands::UnevaluatedCallInfo;
use crate::context::SpanSource; use crate::context::SpanSource;
use crate::errors::ShellError;
use crate::data::Value; use crate::data::Value;
use crate::parser::hir::SyntaxType; use crate::errors::ShellError;
use crate::parser::hir::SyntaxShape;
use crate::parser::registry::Signature; use crate::parser::registry::Signature;
use crate::prelude::*; use crate::prelude::*;
use base64::encode; use base64::encode;
@ -10,7 +10,7 @@ use mime::Mime;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use surf::mime; use surf::mime;
use uuid::Uuid;
pub struct Post; pub struct Post;
impl PerItemCommand for Post { impl PerItemCommand for Post {
@ -20,10 +20,10 @@ impl PerItemCommand for Post {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.required("path", SyntaxType::Any) .required("path", SyntaxShape::Any)
.required("body", SyntaxType::Any) .required("body", SyntaxShape::Any)
.named("user", SyntaxType::Any) .named("user", SyntaxShape::Any)
.named("password", SyntaxType::Any) .named("password", SyntaxShape::Any)
.switch("raw") .switch("raw")
} }
@ -63,7 +63,7 @@ fn run(
file => file.clone(), file => file.clone(),
}; };
let path_str = path.as_string()?; let path_str = path.as_string()?;
let path_span = path.span(); let path_span = path.tag();
let has_raw = call_info.args.has("raw"); let has_raw = call_info.args.has("raw");
let user = call_info.args.get("user").map(|x| x.as_string().unwrap()); let user = call_info.args.get("user").map(|x| x.as_string().unwrap());
let password = call_info let password = call_info
@ -109,7 +109,7 @@ fn run(
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
} }
}; };
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry); let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &registry);
@ -143,7 +143,7 @@ pub async fn post(
body: &Tagged<Value>, body: &Tagged<Value>,
user: Option<String>, user: Option<String>,
password: Option<String>, password: Option<String>,
span: Span, tag: Tag,
registry: &CommandRegistry, registry: &CommandRegistry,
raw_args: &RawCommandArgs, raw_args: &RawCommandArgs,
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> { ) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
@ -189,7 +189,7 @@ pub async fn post(
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
}, },
}; };
let mut result = converter.run( let mut result = converter.run(
@ -211,7 +211,7 @@ pub async fn post(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Save could not successfully save", "Save could not successfully save",
"unexpected data during save", "unexpected data during save",
span, *tag,
)); ));
} }
} }
@ -227,7 +227,7 @@ pub async fn post(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Could not automatically convert table", "Could not automatically convert table",
"needs manual conversion", "needs manual conversion",
tag.span, *tag,
)); ));
} }
} }
@ -243,13 +243,10 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::APPLICATION, mime::JSON) => Ok(( (mime::APPLICATION, mime::JSON) => Ok((
@ -258,13 +255,10 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::APPLICATION, mime::OCTET_STREAM) => { (mime::APPLICATION, mime::OCTET_STREAM) => {
@ -272,16 +266,13 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load binary file", "Could not load binary file",
"could not load", "could not load",
span, tag,
) )
})?; })?;
Ok(( Ok((
None, None,
Value::Binary(buf), Value::Binary(buf),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
@ -290,16 +281,13 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load image file", "Could not load image file",
"could not load", "could not load",
span, tag,
) )
})?; })?;
Ok(( Ok((
Some(image_ty.to_string()), Some(image_ty.to_string()),
Value::Binary(buf), Value::Binary(buf),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
@ -309,13 +297,10 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
(mime::TEXT, mime::PLAIN) => { (mime::TEXT, mime::PLAIN) => {
@ -336,13 +321,10 @@ pub async fn post(
ShellError::labeled_error( ShellError::labeled_error(
"Could not load text from remote url", "Could not load text from remote url",
"could not load", "could not load",
span, tag,
) )
})?), })?),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)) ))
} }
@ -352,10 +334,7 @@ pub async fn post(
"Not yet supported MIME type: {} {}", "Not yet supported MIME type: {} {}",
ty, sub_ty ty, sub_ty
)), )),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
} }
@ -363,10 +342,7 @@ pub async fn post(
None => Ok(( None => Ok((
None, None,
Value::string(format!("No content type found")), Value::string(format!("No content type found")),
Tag { tag,
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(location.to_string()), SpanSource::Url(location.to_string()),
)), )),
}, },
@ -374,7 +350,7 @@ pub async fn post(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"URL could not be opened", "URL could not be opened",
"url not found", "url not found",
span, tag,
)); ));
} }
} }
@ -382,7 +358,7 @@ pub async fn post(
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"Expected a url", "Expected a url",
"needs a url", "needs a url",
span, tag,
)) ))
} }
} }

View file

@ -16,7 +16,7 @@ impl WholeStreamCommand for Reject {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("reject").rest(SyntaxType::Member) Signature::build("reject").rest(SyntaxShape::Member)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,6 +1,6 @@
use crate::commands::command::RunnablePerItemContext; use crate::commands::command::RunnablePerItemContext;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry::{CommandRegistry, Signature}; use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*; use crate::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
@ -20,7 +20,7 @@ impl PerItemCommand for Remove {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("rm") Signature::build("rm")
.required("path", SyntaxType::Path) .required("path", SyntaxShape::Pattern)
.switch("recursive") .switch("recursive")
} }

View file

@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
pub struct Save; pub struct Save;
macro_rules! process_string { macro_rules! process_string {
($input:ident, $name_span:ident) => {{ ($input:ident, $name_tag:ident) => {{
let mut result_string = String::new(); let mut result_string = String::new();
for res in $input { for res in $input {
match res { match res {
@ -21,7 +21,7 @@ macro_rules! process_string {
yield core::task::Poll::Ready(Err(ShellError::labeled_error( yield core::task::Poll::Ready(Err(ShellError::labeled_error(
"Save could not successfully save", "Save could not successfully save",
"unexpected data during save", "unexpected data during save",
$name_span, $name_tag,
))); )));
} }
} }
@ -31,7 +31,7 @@ macro_rules! process_string {
} }
macro_rules! process_string_return_success { macro_rules! process_string_return_success {
($result_vec:ident, $name_span:ident) => {{ ($result_vec:ident, $name_tag:ident) => {{
let mut result_string = String::new(); let mut result_string = String::new();
for res in $result_vec { for res in $result_vec {
match res { match res {
@ -45,7 +45,7 @@ macro_rules! process_string_return_success {
yield core::task::Poll::Ready(Err(ShellError::labeled_error( yield core::task::Poll::Ready(Err(ShellError::labeled_error(
"Save could not successfully save", "Save could not successfully save",
"unexpected data during text save", "unexpected data during text save",
$name_span, $name_tag,
))); )));
} }
} }
@ -55,7 +55,7 @@ macro_rules! process_string_return_success {
} }
macro_rules! process_binary_return_success { macro_rules! process_binary_return_success {
($result_vec:ident, $name_span:ident) => {{ ($result_vec:ident, $name_tag:ident) => {{
let mut result_binary: Vec<u8> = Vec::new(); let mut result_binary: Vec<u8> = Vec::new();
for res in $result_vec { for res in $result_vec {
match res { match res {
@ -71,7 +71,7 @@ macro_rules! process_binary_return_success {
yield core::task::Poll::Ready(Err(ShellError::labeled_error( yield core::task::Poll::Ready(Err(ShellError::labeled_error(
"Save could not successfully save", "Save could not successfully save",
"unexpected data during binary save", "unexpected data during binary save",
$name_span, $name_tag,
))); )));
} }
} }
@ -93,7 +93,7 @@ impl WholeStreamCommand for Save {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("save") Signature::build("save")
.optional("path", SyntaxType::Path) .optional("path", SyntaxShape::Path)
.switch("raw") .switch("raw")
} }
@ -127,7 +127,7 @@ fn save(
raw_args: RawCommandArgs, raw_args: RawCommandArgs,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let mut full_path = PathBuf::from(shell_manager.path()); let mut full_path = PathBuf::from(shell_manager.path());
let name_span = name; let name_tag = name;
let source_map = source_map.clone(); let source_map = source_map.clone();
let stream = async_stream_block! { let stream = async_stream_block! {
@ -145,7 +145,7 @@ fn save(
yield Err(ShellError::labeled_error( yield Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
name_span, name_tag,
)); ));
} }
}, },
@ -153,7 +153,7 @@ fn save(
yield Err(ShellError::labeled_error( yield Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
name_span, name_tag,
)); ));
} }
} }
@ -161,7 +161,7 @@ fn save(
yield Err(ShellError::labeled_error( yield Err(ShellError::labeled_error(
"Save requires a filepath", "Save requires a filepath",
"needs path", "needs path",
name_span, name_tag,
)); ));
} }
} else { } else {
@ -185,21 +185,21 @@ fn save(
}, },
source: raw_args.call_info.source, source: raw_args.call_info.source,
source_map: raw_args.call_info.source_map, source_map: raw_args.call_info.source_map,
name_span: raw_args.call_info.name_span, name_tag: raw_args.call_info.name_tag,
} }
}; };
let mut result = converter.run(new_args.with_input(input), &registry); let mut result = converter.run(new_args.with_input(input), &registry);
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await; let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await;
if converter.is_binary() { if converter.is_binary() {
process_binary_return_success!(result_vec, name_span) process_binary_return_success!(result_vec, name_tag)
} else { } else {
process_string_return_success!(result_vec, name_span) process_string_return_success!(result_vec, name_tag)
} }
} else { } else {
process_string!(input, name_span) process_string!(input, name_tag)
} }
} else { } else {
process_string!(input, name_span) process_string!(input, name_tag)
} }
} else { } else {
Ok(string_from(&input).into_bytes()) Ok(string_from(&input).into_bytes())

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::TaggedDictBuilder; use crate::data::TaggedDictBuilder;
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
pub struct Shells; pub struct Shells;
@ -29,10 +29,10 @@ impl WholeStreamCommand for Shells {
fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let mut shells_out = VecDeque::new(); let mut shells_out = VecDeque::new();
let span = args.call_info.name_span; let tag = args.call_info.name_tag;
for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() { for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() {
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span)); let mut dict = TaggedDictBuilder::new(tag);
if index == args.shell_manager.current_shell { if index == args.shell_manager.current_shell {
dict.insert(" ", "X".to_string()); dict.insert(" ", "X".to_string());

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{TaggedDictBuilder, Value}; use crate::data::{TaggedDictBuilder, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
pub struct Size; pub struct Size;
@ -29,7 +29,7 @@ impl WholeStreamCommand for Size {
fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
let span = args.call_info.name_span; let tag = args.call_info.name_tag;
Ok(input Ok(input
.values .values
.map(move |v| match v.item { .map(move |v| match v.item {
@ -37,9 +37,9 @@ fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
_ => Err(ShellError::labeled_error_with_secondary( _ => Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
span, tag,
"value originates from here", "value originates from here",
v.span(), v.tag(),
)), )),
}) })
.to_output_stream()) .to_output_stream())
@ -71,7 +71,7 @@ fn count(contents: &str, tag: impl Into<Tag>) -> Tagged<Value> {
} }
let mut dict = TaggedDictBuilder::new(tag); 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 tag
//dict.insert("name", Value::string(name)); //dict.insert("name", Value::string(name));
dict.insert("lines", Value::int(lines)); dict.insert("lines", Value::int(lines));
dict.insert("words", Value::int(words)); dict.insert("words", Value::int(words));

View file

@ -16,7 +16,7 @@ impl WholeStreamCommand for SkipWhile {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("skip-while") Signature::build("skip-while")
.required("condition", SyntaxType::Block) .required("condition", SyntaxShape::Block)
.filter() .filter()
} }

View file

@ -15,7 +15,7 @@ impl WholeStreamCommand for SortBy {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("sort-by").rest(SyntaxType::String) Signature::build("sort-by").rest(SyntaxShape::String)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{Primitive, TaggedDictBuilder, Value}; use crate::data::{Primitive, TaggedDictBuilder, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use log::trace; use log::trace;
@ -21,9 +21,9 @@ impl WholeStreamCommand for SplitColumn {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("split-column") Signature::build("split-column")
.required("separator", SyntaxType::Any) .required("separator", SyntaxShape::Any)
.switch("collapse-empty") .switch("collapse-empty")
.rest(SyntaxType::Member) .rest(SyntaxShape::Member)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -40,7 +40,11 @@ impl WholeStreamCommand for SplitColumn {
} }
fn split_column( fn split_column(
SplitColumnArgs { separator, rest, collapse_empty}: SplitColumnArgs, SplitColumnArgs {
separator,
rest,
collapse_empty,
}: SplitColumnArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
Ok(input Ok(input
@ -92,7 +96,7 @@ fn split_column(
"requires string input", "requires string input",
name, name,
"value originates from here", "value originates from here",
v.span(), v.tag(),
)), )),
}) })
.to_output_stream()) .to_output_stream())

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{Primitive, Value}; use crate::data::{Primitive, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use log::trace; use log::trace;
@ -17,8 +17,7 @@ impl WholeStreamCommand for SplitRow {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("split-row") Signature::build("split-row").required("separator", SyntaxShape::Any)
.required("separator", SyntaxType::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -63,7 +62,7 @@ fn split_row(
"requires string input", "requires string input",
name, name,
"value originates from here", "value originates from here",
v.span(), v.tag(),
))); )));
result result
} }

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{TaggedDictBuilder, Value}; use crate::data::{TaggedDictBuilder, Value};
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
pub struct Tags; pub struct Tags;
@ -36,7 +36,7 @@ fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
let mut tags = TaggedDictBuilder::new(v.tag()); let mut tags = TaggedDictBuilder::new(v.tag());
{ {
let origin = v.origin(); let origin = v.origin();
let span = v.span(); let span = v.tag().span;
let mut dict = TaggedDictBuilder::new(v.tag()); 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));

View file

@ -190,44 +190,40 @@ fn generic_object_value_to_bson(o: &Dictionary) -> Result<Bson, ShellError> {
Ok(Bson::Document(doc)) Ok(Bson::Document(doc))
} }
fn shell_encode_document( fn shell_encode_document(writer: &mut Vec<u8>, doc: Document, tag: Tag) -> Result<(), ShellError> {
writer: &mut Vec<u8>,
doc: Document,
span: Span,
) -> Result<(), ShellError> {
match encode_document(writer, &doc) { match encode_document(writer, &doc) {
Err(e) => Err(ShellError::labeled_error( Err(e) => Err(ShellError::labeled_error(
format!("Failed to encode document due to: {:?}", e), format!("Failed to encode document due to: {:?}", e),
"requires BSON-compatible document", "requires BSON-compatible document",
span, tag,
)), )),
_ => Ok(()), _ => Ok(()),
} }
} }
fn bson_value_to_bytes(bson: Bson, span: Span) -> Result<Vec<u8>, ShellError> { fn bson_value_to_bytes(bson: Bson, tag: Tag) -> Result<Vec<u8>, ShellError> {
let mut out = Vec::new(); let mut out = Vec::new();
match bson { match bson {
Bson::Array(a) => { Bson::Array(a) => {
for v in a.into_iter() { for v in a.into_iter() {
match v { match v {
Bson::Document(d) => shell_encode_document(&mut out, d, span)?, Bson::Document(d) => shell_encode_document(&mut out, d, tag)?,
_ => { _ => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("All top level values must be Documents, got {:?}", v), format!("All top level values must be Documents, got {:?}", v),
"requires BSON-compatible document", "requires BSON-compatible document",
span, tag,
)) ))
} }
} }
} }
} }
Bson::Document(d) => shell_encode_document(&mut out, d, span)?, Bson::Document(d) => shell_encode_document(&mut out, d, tag)?,
_ => { _ => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("All top level values must be Documents, got {:?}", bson), format!("All top level values must be Documents, got {:?}", bson),
"requires BSON-compatible document", "requires BSON-compatible document",
span, tag,
)) ))
} }
} }
@ -236,7 +232,7 @@ fn bson_value_to_bytes(bson: Bson, span: Span) -> Result<Vec<u8>, ShellError> {
fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let name_span = args.name_span(); let name_tag = args.name_tag();
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = args.input.values.collect().await; let input: Vec<Tagged<Value>> = args.input.values.collect().await;
@ -252,23 +248,23 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
for value in to_process_input { for value in to_process_input {
match value_to_bson_value(&value) { match value_to_bson_value(&value) {
Ok(bson_value) => { Ok(bson_value) => {
match bson_value_to_bytes(bson_value, name_span) { match bson_value_to_bytes(bson_value, name_tag) {
Ok(x) => yield ReturnSuccess::value( Ok(x) => yield ReturnSuccess::value(
Value::Binary(x).simple_spanned(name_span), Value::Binary(x).tagged(name_tag),
), ),
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with BSON-compatible structure.span() from pipeline", "Expected a table with BSON-compatible structure.tag() from pipeline",
"requires BSON-compatible input", "requires BSON-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)), )),
} }
} }
_ => yield Err(ShellError::labeled_error( _ => yield Err(ShellError::labeled_error(
"Expected a table with BSON-compatible structure from pipeline", "Expected a table with BSON-compatible structure from pipeline",
"requires BSON-compatible input", "requires BSON-compatible input",
name_span)) name_tag))
} }
} }
}; };

View file

@ -134,7 +134,7 @@ fn to_csv(
ToCSVArgs { headerless }: ToCSVArgs, ToCSVArgs { headerless }: ToCSVArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = input.values.collect().await; let input: Vec<Tagged<Value>> = input.values.collect().await;
@ -155,15 +155,15 @@ fn to_csv(
} else { } else {
x x
}; };
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).simple_spanned(name_span)) yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).tagged(name_tag))
} }
_ => { _ => {
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with CSV-compatible structure.span() from pipeline", "Expected a table with CSV-compatible structure.tag() from pipeline",
"requires CSV-compatible input", "requires CSV-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)) ))
} }
} }

View file

@ -80,7 +80,7 @@ fn json_list(input: &Vec<Tagged<Value>>) -> Result<Vec<serde_json::Value>, Shell
fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let name_span = args.name_span(); let name_tag = args.name_tag();
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = args.input.values.collect().await; let input: Vec<Tagged<Value>> = args.input.values.collect().await;
@ -98,21 +98,21 @@ fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
Ok(json_value) => { Ok(json_value) => {
match serde_json::to_string(&json_value) { match serde_json::to_string(&json_value) {
Ok(x) => yield ReturnSuccess::value( Ok(x) => yield ReturnSuccess::value(
Value::Primitive(Primitive::String(x)).simple_spanned(name_span), Value::Primitive(Primitive::String(x)).tagged(name_tag),
), ),
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with JSON-compatible structure.span() from pipeline", "Expected a table with JSON-compatible structure.tag() from pipeline",
"requires JSON-compatible input", "requires JSON-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)), )),
} }
} }
_ => yield Err(ShellError::labeled_error( _ => yield Err(ShellError::labeled_error(
"Expected a table with JSON-compatible structure from pipeline", "Expected a table with JSON-compatible structure from pipeline",
"requires JSON-compatible input", "requires JSON-compatible input",
name_span)) name_tag))
} }
} }
}; };

View file

@ -200,7 +200,7 @@ fn sqlite_input_stream_to_bytes(
fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let name_span = args.name_span(); let name_tag = args.name_tag();
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = args.input.values.collect().await; let input: Vec<Tagged<Value>> = args.input.values.collect().await;
@ -208,9 +208,9 @@ fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
Ok(out) => yield ReturnSuccess::value(out), Ok(out) => yield ReturnSuccess::value(out),
_ => { _ => {
yield Err(ShellError::labeled_error( yield Err(ShellError::labeled_error(
"Expected a table with SQLite-compatible structure.span() from pipeline", "Expected a table with SQLite-compatible structure.tag() from pipeline",
"requires SQLite-compatible input", "requires SQLite-compatible input",
name_span, name_tag,
)) ))
}, },
} }

View file

@ -75,7 +75,7 @@ fn collect_values(input: &Vec<Tagged<Value>>) -> Result<Vec<toml::Value>, ShellE
fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let name_span = args.name_span(); let name_tag = args.name_tag();
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = args.input.values.collect().await; let input: Vec<Tagged<Value>> = args.input.values.collect().await;
@ -93,21 +93,21 @@ fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
Ok(toml_value) => { Ok(toml_value) => {
match toml::to_string(&toml_value) { match toml::to_string(&toml_value) {
Ok(x) => yield ReturnSuccess::value( Ok(x) => yield ReturnSuccess::value(
Value::Primitive(Primitive::String(x)).simple_spanned(name_span), Value::Primitive(Primitive::String(x)).tagged(name_tag),
), ),
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with TOML-compatible structure.span() from pipeline", "Expected a table with TOML-compatible structure.tag() from pipeline",
"requires TOML-compatible input", "requires TOML-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)), )),
} }
} }
_ => yield Err(ShellError::labeled_error( _ => yield Err(ShellError::labeled_error(
"Expected a table with TOML-compatible structure from pipeline", "Expected a table with TOML-compatible structure from pipeline",
"requires TOML-compatible input", "requires TOML-compatible input",
name_span)) name_tag))
} }
} }
}; };

View file

@ -133,7 +133,7 @@ fn to_tsv(
ToTSVArgs { headerless }: ToTSVArgs, ToTSVArgs { headerless }: ToTSVArgs,
RunnableContext { input, name, .. }: RunnableContext, RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = input.values.collect().await; let input: Vec<Tagged<Value>> = input.values.collect().await;
@ -154,15 +154,15 @@ fn to_tsv(
} else { } else {
x x
}; };
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).simple_spanned(name_span)) yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).tagged(name_tag))
} }
_ => { _ => {
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with TSV-compatible structure.span() from pipeline", "Expected a table with TSV-compatible structure.tag() from pipeline",
"requires TSV-compatible input", "requires TSV-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)) ))
} }
} }

View file

@ -76,7 +76,7 @@ pub fn value_to_yaml_value(v: &Tagged<Value>) -> Result<serde_yaml::Value, Shell
fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let name_span = args.name_span(); let name_tag = args.name_tag();
let stream = async_stream_block! { let stream = async_stream_block! {
let input: Vec<Tagged<Value>> = args.input.values.collect().await; let input: Vec<Tagged<Value>> = args.input.values.collect().await;
@ -94,21 +94,21 @@ fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
Ok(yaml_value) => { Ok(yaml_value) => {
match serde_yaml::to_string(&yaml_value) { match serde_yaml::to_string(&yaml_value) {
Ok(x) => yield ReturnSuccess::value( Ok(x) => yield ReturnSuccess::value(
Value::Primitive(Primitive::String(x)).simple_spanned(name_span), Value::Primitive(Primitive::String(x)).tagged(name_tag),
), ),
_ => yield Err(ShellError::labeled_error_with_secondary( _ => yield Err(ShellError::labeled_error_with_secondary(
"Expected a table with YAML-compatible structure.span() from pipeline", "Expected a table with YAML-compatible structure.tag() from pipeline",
"requires YAML-compatible input", "requires YAML-compatible input",
name_span, name_tag,
"originates from here".to_string(), "originates from here".to_string(),
value.span(), value.tag(),
)), )),
} }
} }
_ => yield Err(ShellError::labeled_error( _ => yield Err(ShellError::labeled_error(
"Expected a table with YAML-compatible structure from pipeline", "Expected a table with YAML-compatible structure from pipeline",
"requires YAML-compatible input", "requires YAML-compatible input",
name_span)) name_tag))
} }
} }
}; };

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::Value; use crate::data::Value;
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
pub struct Trim; pub struct Trim;
@ -34,7 +34,7 @@ fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
.values .values
.map(move |v| { .map(move |v| {
let string = String::extract(&v)?; let string = String::extract(&v)?;
ReturnSuccess::value(Value::string(string.trim()).simple_spanned(v.span())) ReturnSuccess::value(Value::string(string.trim()).tagged(v.tag()))
}) })
.to_output_stream()) .to_output_stream())
} }

View file

@ -1,6 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::data::{Dictionary, Value}; use crate::data::{Dictionary, Value};
use crate::errors::ShellError;
use crate::parser::registry::Signature; use crate::parser::registry::Signature;
use crate::prelude::*; use crate::prelude::*;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -31,14 +31,14 @@ impl WholeStreamCommand for Version {
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let span = args.call_info.name_span; let tag = args.call_info.name_tag;
let mut indexmap = IndexMap::new(); let mut indexmap = IndexMap::new();
indexmap.insert( indexmap.insert(
"version".to_string(), "version".to_string(),
Tagged::from_simple_spanned_item(Value::string(clap::crate_version!()), span), Value::string(clap::crate_version!()).tagged(tag),
); );
let value = Tagged::from_simple_spanned_item(Value::Row(Dictionary::from(indexmap)), span); let value = Value::Row(Dictionary::from(indexmap)).tagged(tag);
Ok(OutputStream::one(value)) Ok(OutputStream::one(value))
} }

View file

@ -1,6 +1,6 @@
use crate::commands::PerItemCommand; use crate::commands::PerItemCommand;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxShape;
use crate::parser::registry; use crate::parser::registry;
use crate::prelude::*; use crate::prelude::*;
@ -12,8 +12,7 @@ impl PerItemCommand for Where {
} }
fn signature(&self) -> registry::Signature { fn signature(&self) -> registry::Signature {
Signature::build("where") Signature::build("where").required("condition", SyntaxShape::Block)
.required("condition", SyntaxType::Block)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -43,16 +42,14 @@ impl PerItemCommand for Where {
VecDeque::new() VecDeque::new()
} }
} }
Err(e) => { Err(e) => return Err(e),
return Err(e)
}
} }
} }
Tagged { tag, .. } => { Tagged { tag, .. } => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expected a condition", "Expected a condition",
"where needs a condition", "where needs a condition",
tag.span, *tag,
)) ))
} }
}; };

View file

@ -1,5 +1,5 @@
use crate::errors::ShellError;
use crate::data::Value; use crate::data::Value;
use crate::errors::ShellError;
use crate::prelude::*; use crate::prelude::*;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
@ -13,8 +13,7 @@ impl WholeStreamCommand for Which {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("which") Signature::build("which").required("name", SyntaxShape::Any)
.required("name", SyntaxType::Any)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -34,7 +33,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
let args = args.evaluate_once(registry)?; let args = args.evaluate_once(registry)?;
let mut which_out = VecDeque::new(); let mut which_out = VecDeque::new();
let span = args.call_info.name_span; let tag = args.call_info.name_tag;
if let Some(v) = &args.call_info.args.positional { if let Some(v) = &args.call_info.args.positional {
if v.len() > 0 { if v.len() > 0 {
@ -53,7 +52,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expected a filename to find", "Expected a filename to find",
"needs a filename", "needs a filename",
tag.span, *tag,
)); ));
} }
} }
@ -61,14 +60,14 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expected a binary to find", "Expected a binary to find",
"needs application name", "needs application name",
span, tag,
)); ));
} }
} else { } else {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expected a binary to find", "Expected a binary to find",
"needs application name", "needs application name",
span, tag,
)); ));
} }

View file

@ -120,13 +120,13 @@ impl Context {
pub(crate) fn run_command<'a>( pub(crate) fn run_command<'a>(
&mut self, &mut self,
command: Arc<Command>, command: Arc<Command>,
name_span: Span, name_tag: Tag,
source_map: SourceMap, source_map: SourceMap,
args: hir::Call, args: hir::Call,
source: &Text, source: &Text,
input: InputStream, input: InputStream,
) -> OutputStream { ) -> OutputStream {
let command_args = self.command_args(args, input, source, source_map, name_span); let command_args = self.command_args(args, input, source, source_map, name_tag);
command.run(command_args, self.registry()) command.run(command_args, self.registry())
} }
@ -135,13 +135,13 @@ impl Context {
args: hir::Call, args: hir::Call,
source: &Text, source: &Text,
source_map: SourceMap, source_map: SourceMap,
name_span: Span, name_tag: Tag,
) -> UnevaluatedCallInfo { ) -> UnevaluatedCallInfo {
UnevaluatedCallInfo { UnevaluatedCallInfo {
args, args,
source: source.clone(), source: source.clone(),
source_map, source_map,
name_span, name_tag,
} }
} }
@ -151,12 +151,12 @@ impl Context {
input: InputStream, input: InputStream,
source: &Text, source: &Text,
source_map: SourceMap, source_map: SourceMap,
name_span: Span, name_tag: Tag,
) -> CommandArgs { ) -> CommandArgs {
CommandArgs { CommandArgs {
host: self.host.clone(), host: self.host.clone(),
shell_manager: self.shell_manager.clone(), shell_manager: self.shell_manager.clone(),
call_info: self.call_info(args, source, source_map, name_span), call_info: self.call_info(args, source, source_map, name_tag),
input, input,
} }
} }

View file

@ -145,7 +145,7 @@ pub struct Operation {
pub struct Block { pub struct Block {
pub(crate) expressions: Vec<hir::Expression>, pub(crate) expressions: Vec<hir::Expression>,
pub(crate) source: Text, pub(crate) source: Text,
pub(crate) span: Span, pub(crate) tag: Tag,
} }
impl Block { impl Block {
@ -153,7 +153,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(Value::nothing().simple_spanned(self.span)); return Ok(Value::nothing().tagged(self.tag));
} }
let mut last = None; let mut last = None;
@ -247,7 +247,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for Block {
Value::Block(block) => Ok(block.clone()), Value::Block(block) => Ok(block.clone()),
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"Block", "Block",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
} }
} }
@ -263,7 +263,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for i64 {
} }
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"Integer", "Integer",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
} }
} }
@ -277,7 +277,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for String {
Value::Primitive(Primitive::String(s)) => Ok(s.clone()), Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"String", "String",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
} }
} }
@ -291,7 +291,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for Vec<u8> {
Value::Binary(b) => Ok(b.clone()), Value::Binary(b) => Ok(b.clone()),
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"Binary", "Binary",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
} }
} }
@ -305,7 +305,7 @@ impl<'a> std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::data::Dictionar
Value::Row(d) => Ok(d), Value::Row(d) => Ok(d),
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"Dictionary", "Dictionary",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
} }
} }
@ -327,7 +327,7 @@ impl std::convert::TryFrom<Option<&Tagged<Value>>> for Switch {
Value::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present), Value::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present),
v => Err(ShellError::type_error( v => Err(ShellError::type_error(
"Boolean", "Boolean",
value.copy_span(v.type_name()), value.copy_tag(v.type_name()),
)), )),
}, },
} }
@ -639,7 +639,7 @@ impl Tagged<Value> {
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()), Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
other => Err(ShellError::type_error( other => Err(ShellError::type_error(
"Path", "Path",
other.type_name().tagged(self.span()), other.type_name().tagged(self.tag()),
)), )),
} }
} }

View file

@ -50,7 +50,7 @@ pub fn default_path_for(file: &Option<PathBuf>) -> Result<PathBuf, ShellError> {
} }
pub fn read( pub fn read(
span: impl Into<Span>, tag: impl Into<Tag>,
at: &Option<PathBuf>, at: &Option<PathBuf>,
) -> Result<IndexMap<String, Tagged<Value>>, ShellError> { ) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
let filename = default_path()?; let filename = default_path()?;
@ -64,15 +64,15 @@ pub fn read(
trace!("config file = {}", filename.display()); trace!("config file = {}", filename.display());
let span = span.into(); let tag = tag.into();
let contents = fs::read_to_string(filename) let contents = fs::read_to_string(filename)
.map(|v| v.simple_spanned(span)) .map(|v| v.tagged(tag))
.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: toml::Value = toml::from_str(&contents) let parsed: toml::Value = toml::from_str(&contents)
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?; .map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
let value = convert_toml_value_to_nu_value(&parsed, Tag::unknown_origin(span)); let value = convert_toml_value_to_nu_value(&parsed, tag);
let tag = value.tag(); let tag = value.tag();
match value.item { match value.item {
Value::Row(Dictionary { entries }) => Ok(entries), Value::Row(Dictionary { entries }) => Ok(entries),
@ -83,8 +83,8 @@ pub fn read(
} }
} }
pub(crate) fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> { pub(crate) fn config(tag: impl Into<Tag>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
read(span, &None) read(tag, &None)
} }
pub fn write( pub fn write(

View file

@ -15,8 +15,8 @@ impl From<String> for Value {
impl<T: Into<Value>> Tagged<T> { 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_tag = self.tag();
let value = self.item.into(); let value = self.item.into();
value.simple_spanned(value_span) value.tagged(value_tag)
} }
} }

View file

@ -5,6 +5,7 @@ use derive_new::new;
use getset::Getters; use getset::Getters;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::path::{Path, PathBuf};
use uuid::Uuid; use uuid::Uuid;
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)] #[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
@ -13,9 +14,15 @@ pub struct Tagged<T> {
pub item: T, pub item: T,
} }
impl<T> HasSpan for Tagged<T> { impl<T> HasTag for Tagged<T> {
fn span(&self) -> Span { fn tag(&self) -> Tag {
self.tag.span self.tag
}
}
impl AsRef<Path> for Tagged<PathBuf> {
fn as_ref(&self) -> &Path {
self.item.as_ref()
} }
} }
@ -24,10 +31,6 @@ pub trait TaggedItem: Sized {
Tagged::from_item(self, tag.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.
@ -53,14 +56,8 @@ impl<T> std::ops::Deref for Tagged<T> {
} }
impl<T> Tagged<T> { impl<T> Tagged<T> {
pub fn spanned(self, span: impl Into<Span>) -> Tagged<T> { pub fn with_tag(self, tag: impl Into<Tag>) -> Tagged<T> {
Tagged::from_item( Tagged::from_item(self.item, tag)
self.item,
Tag {
span: span.into(),
origin: None,
},
)
} }
pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> { pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
@ -70,41 +67,26 @@ impl<T> Tagged<T> {
} }
} }
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 tag = self.tag(); let tag = self.tag();
let mapped = input(self.item); let mapped = input(self.item);
Tagged::from_item(mapped, tag.clone()) Tagged::from_item(mapped, tag)
} }
pub(crate) fn copy_span<U>(&self, output: U) -> Tagged<U> { pub(crate) fn copy_tag<U>(&self, output: U) -> Tagged<U> {
let span = self.span(); Tagged::from_item(output, self.tag())
Tagged::from_simple_spanned_item(output, span)
} }
pub fn source(&self, source: &Text) -> Text { pub fn source(&self, source: &Text) -> Text {
Text::from(self.span().slice(source)) Text::from(self.tag().slice(source))
}
pub fn span(&self) -> Span {
self.tag.span
} }
pub fn tag(&self) -> Tag { pub fn tag(&self) -> Tag {
self.tag self.tag
} }
// TODO: This should not be optional
pub fn origin(&self) -> Option<uuid::Uuid> { pub fn origin(&self) -> Option<uuid::Uuid> {
self.tag.origin self.tag.origin
} }
@ -126,20 +108,14 @@ impl<T> Tagged<T> {
} }
} }
impl<T> From<&Tagged<T>> for Span { impl From<&Tag> for Tag {
fn from(input: &Tagged<T>) -> Span { fn from(input: &Tag) -> Tag {
input.span()
}
}
impl From<&Span> for Span {
fn from(input: &Span) -> Span {
*input *input
} }
} }
impl From<nom5_locate::LocatedSpan<&str>> for Span { impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Span {
fn from(input: nom5_locate::LocatedSpan<&str>) -> Span { fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Span {
Span { Span {
start: input.offset, start: input.offset,
end: input.offset + input.fragment.len(), end: input.offset + input.fragment.len(),
@ -147,8 +123,18 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
} }
} }
impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Span { impl<T>
fn from(input: (nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)) -> Span { From<(
nom_locate::LocatedSpanEx<T, Uuid>,
nom_locate::LocatedSpanEx<T, Uuid>,
)> for Span
{
fn from(
input: (
nom_locate::LocatedSpanEx<T, Uuid>,
nom_locate::LocatedSpanEx<T, Uuid>,
),
) -> Span {
Span { Span {
start: input.0.offset, start: input.0.offset,
end: input.1.offset, end: input.1.offset,
@ -197,6 +183,36 @@ impl From<&Span> for Tag {
} }
} }
impl From<(usize, usize, Uuid)> for Tag {
fn from((start, end, origin): (usize, usize, Uuid)) -> Self {
Tag {
origin: Some(origin),
span: Span { start, end },
}
}
}
impl From<(usize, usize, Option<Uuid>)> for Tag {
fn from((start, end, origin): (usize, usize, Option<Uuid>)) -> Self {
Tag {
origin,
span: Span { start, end },
}
}
}
impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Tag {
fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Tag {
Tag {
origin: Some(input.extra),
span: Span {
start: input.offset,
end: input.offset + input.fragment.len(),
},
}
}
}
impl From<Tag> for Span { impl From<Tag> for Span {
fn from(tag: Tag) -> Self { fn from(tag: Tag) -> Self {
tag.span tag.span
@ -214,12 +230,36 @@ impl Tag {
Tag { origin: None, span } Tag { origin: None, span }
} }
pub fn unknown_span(origin: Uuid) -> Tag {
Tag {
origin: Some(origin),
span: Span::unknown(),
}
}
pub fn unknown() -> Tag { pub fn unknown() -> Tag {
Tag { Tag {
origin: None, origin: None,
span: Span::unknown(), span: Span::unknown(),
} }
} }
pub fn until(&self, other: impl Into<Tag>) -> Tag {
let other = other.into();
debug_assert!(self.origin == other.origin, "Can only merge two tags with the same origin");
Tag {
span: Span {
start: self.span.start,
end: other.span.end
},
origin: self.origin
}
}
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
self.span.slice(source)
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
@ -284,3 +324,33 @@ impl language_reporting::ReportingSpan for Span {
self.end self.end
} }
} }
impl language_reporting::ReportingSpan for Tag {
fn with_start(&self, start: usize) -> Self {
Tag {
span: Span {
start,
end: self.span.end,
},
origin: self.origin,
}
}
fn with_end(&self, end: usize) -> Self {
Tag {
span: Span {
start: self.span.start,
end,
},
origin: self.origin,
}
}
fn start(&self) -> usize {
self.span.start
}
fn end(&self) -> usize {
self.span.end
}
}

View file

@ -14,20 +14,22 @@ 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_tag = value.tag(); let value_tag = value.tag();
match value_span { match value_tag {
Span { start: 0, end: 0 } => Description::Synthetic(value.item.into()), Tag {
span: crate::data::meta::Span { start: 0, end: 0 },
..
} => Description::Synthetic(value.item.into()),
_ => Description::Source(Tagged::from_item(value.item.into(), value_tag)), _ => Description::Source(Tagged::from_item(value.item.into(), value_tag)),
} }
} }
} }
impl Description { impl Description {
fn into_label(self) -> Result<Label<Span>, String> { fn into_label(self) -> Result<Label<Tag>, String> {
match self { match self {
Description::Source(s) => Ok(Label::new_primary(s.span()).with_message(s.item)), Description::Source(s) => Ok(Label::new_primary(s.tag()).with_message(s.item)),
Description::Synthetic(s) => Err(s), Description::Synthetic(s) => Err(s),
} }
} }
@ -81,7 +83,7 @@ impl ShellError {
) -> ShellError { ) -> ShellError {
ProximateShellError::RangeError { ProximateShellError::RangeError {
kind: expected.into(), kind: expected.into(),
actual_kind: actual.copy_span(format!("{:?}", actual.item)), actual_kind: actual.copy_tag(format!("{:?}", actual.item)),
operation, operation,
} }
.start() .start()
@ -116,9 +118,9 @@ impl ShellError {
ProximateShellError::MissingProperty { subpath, expr }.start() ProximateShellError::MissingProperty { subpath, expr }.start()
} }
pub(crate) fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError { pub(crate) fn missing_value(tag: Option<Tag>, reason: impl Into<String>) -> ShellError {
ProximateShellError::MissingValue { ProximateShellError::MissingValue {
span, tag,
reason: reason.into(), reason: reason.into(),
} }
.start() .start()
@ -127,28 +129,31 @@ impl ShellError {
pub(crate) fn argument_error( pub(crate) fn argument_error(
command: impl Into<String>, command: impl Into<String>,
kind: ArgumentError, kind: ArgumentError,
span: Span, tag: Tag,
) -> ShellError { ) -> ShellError {
ProximateShellError::ArgumentError { ProximateShellError::ArgumentError {
command: command.into(), command: command.into(),
error: kind, error: kind,
span, tag,
} }
.start() .start()
} }
pub(crate) fn invalid_external_word(span: Span) -> ShellError { pub(crate) fn invalid_external_word(tag: Tag) -> ShellError {
ProximateShellError::ArgumentError { ProximateShellError::ArgumentError {
command: "Invalid argument to Nu command (did you mean to call an external command?)" command: "Invalid argument to Nu command (did you mean to call an external command?)"
.into(), .into(),
error: ArgumentError::InvalidExternalWord, error: ArgumentError::InvalidExternalWord,
span, tag,
} }
.start() .start()
} }
pub(crate) fn parse_error( pub(crate) fn parse_error(
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>, error: nom::Err<(
nom_locate::LocatedSpanEx<&str, uuid::Uuid>,
nom::error::ErrorKind,
)>,
) -> ShellError { ) -> ShellError {
use language_reporting::*; use language_reporting::*;
@ -164,34 +169,34 @@ impl ShellError {
} }
nom::Err::Failure(span) | nom::Err::Error(span) => { nom::Err::Failure(span) | nom::Err::Error(span) => {
let diagnostic = Diagnostic::new(Severity::Error, format!("Parse Error")) let diagnostic = Diagnostic::new(Severity::Error, format!("Parse Error"))
.with_label(Label::new_primary(Span::from(span.0))); .with_label(Label::new_primary(Tag::from(span.0)));
ShellError::diagnostic(diagnostic) ShellError::diagnostic(diagnostic)
} }
} }
} }
pub(crate) fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError { pub(crate) fn diagnostic(diagnostic: Diagnostic<Tag>) -> ShellError {
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start() ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
} }
pub(crate) fn to_diagnostic(self) -> Diagnostic<Span> { pub(crate) fn to_diagnostic(self) -> Diagnostic<Tag> {
match self.error { match self.error {
ProximateShellError::String(StringError { title, .. }) => { ProximateShellError::String(StringError { title, .. }) => {
Diagnostic::new(Severity::Error, title) Diagnostic::new(Severity::Error, title)
} }
ProximateShellError::InvalidCommand { command } => { ProximateShellError::InvalidCommand { command } => {
Diagnostic::new(Severity::Error, "Invalid command") Diagnostic::new(Severity::Error, "Invalid command")
.with_label(Label::new_primary(command.span)) .with_label(Label::new_primary(command))
} }
ProximateShellError::MissingValue { span, reason } => { ProximateShellError::MissingValue { tag, reason } => {
let mut d = Diagnostic::new( let mut d = Diagnostic::new(
Severity::Bug, Severity::Bug,
format!("Internal Error (missing value) :: {}", reason), format!("Internal Error (missing value) :: {}", reason),
); );
if let Some(span) = span { if let Some(tag) = tag {
d = d.with_label(Label::new_primary(span)); d = d.with_label(Label::new_primary(tag));
} }
d d
@ -199,12 +204,12 @@ impl ShellError {
ProximateShellError::ArgumentError { ProximateShellError::ArgumentError {
command, command,
error, error,
span, tag,
} => match error { } => match error {
ArgumentError::InvalidExternalWord => Diagnostic::new( ArgumentError::InvalidExternalWord => Diagnostic::new(
Severity::Error, Severity::Error,
format!("Invalid bare word for Nu command (did you intend to invoke an external command?)")) format!("Invalid bare word for Nu command (did you intend to invoke an external command?)"))
.with_label(Label::new_primary(span)), .with_label(Label::new_primary(tag)),
ArgumentError::MissingMandatoryFlag(name) => Diagnostic::new( ArgumentError::MissingMandatoryFlag(name) => Diagnostic::new(
Severity::Error, Severity::Error,
format!( format!(
@ -214,7 +219,7 @@ impl ShellError {
Color::Black.bold().paint(name) Color::Black.bold().paint(name)
), ),
) )
.with_label(Label::new_primary(span)), .with_label(Label::new_primary(tag)),
ArgumentError::MissingMandatoryPositional(name) => Diagnostic::new( ArgumentError::MissingMandatoryPositional(name) => Diagnostic::new(
Severity::Error, Severity::Error,
format!( format!(
@ -224,7 +229,7 @@ impl ShellError {
), ),
) )
.with_label( .with_label(
Label::new_primary(span).with_message(format!("requires {} parameter", name)), Label::new_primary(tag).with_message(format!("requires {} parameter", name)),
), ),
ArgumentError::MissingValueForName(name) => Diagnostic::new( ArgumentError::MissingValueForName(name) => Diagnostic::new(
Severity::Error, Severity::Error,
@ -235,17 +240,17 @@ impl ShellError {
Color::Black.bold().paint(name) Color::Black.bold().paint(name)
), ),
) )
.with_label(Label::new_primary(span)), .with_label(Label::new_primary(tag)),
}, },
ProximateShellError::TypeError { ProximateShellError::TypeError {
expected, expected,
actual: actual:
Tagged { Tagged {
item: Some(actual), item: Some(actual),
tag: Tag { span, .. }, tag,
}, },
} => Diagnostic::new(Severity::Error, "Type Error").with_label( } => Diagnostic::new(Severity::Error, "Type Error").with_label(
Label::new_primary(span) Label::new_primary(tag)
.with_message(format!("Expected {}, found {}", expected, actual)), .with_message(format!("Expected {}, found {}", expected, actual)),
), ),
@ -254,10 +259,10 @@ impl ShellError {
actual: actual:
Tagged { Tagged {
item: None, item: None,
tag: Tag { span, .. }, tag
}, },
} => 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(tag).with_message(expected)),
ProximateShellError::RangeError { ProximateShellError::RangeError {
kind, kind,
@ -265,10 +270,10 @@ impl ShellError {
actual_kind: actual_kind:
Tagged { Tagged {
item, item,
tag: Tag { span, .. }, tag
}, },
} => Diagnostic::new(Severity::Error, "Range Error").with_label( } => Diagnostic::new(Severity::Error, "Range Error").with_label(
Label::new_primary(span).with_message(format!( Label::new_primary(tag).with_message(format!(
"Expected to convert {} to {} while {}, but it was out of range", "Expected to convert {} to {} while {}, but it was out of range",
item, item,
kind.desc(), kind.desc(),
@ -279,11 +284,11 @@ impl ShellError {
ProximateShellError::SyntaxError { ProximateShellError::SyntaxError {
problem: problem:
Tagged { Tagged {
tag: Tag { span, .. }, tag,
.. ..
}, },
} => Diagnostic::new(Severity::Error, "Syntax Error") } => Diagnostic::new(Severity::Error, "Syntax Error")
.with_label(Label::new_primary(span).with_message("Unexpected external command")), .with_label(Label::new_primary(tag).with_message("Unexpected external command")),
ProximateShellError::MissingProperty { subpath, expr } => { ProximateShellError::MissingProperty { subpath, expr } => {
let subpath = subpath.into_label(); let subpath = subpath.into_label();
@ -306,8 +311,8 @@ impl ShellError {
ProximateShellError::Diagnostic(diag) => diag.diagnostic, ProximateShellError::Diagnostic(diag) => diag.diagnostic,
ProximateShellError::CoerceError { left, right } => { ProximateShellError::CoerceError { left, right } => {
Diagnostic::new(Severity::Error, "Coercion error") Diagnostic::new(Severity::Error, "Coercion error")
.with_label(Label::new_primary(left.span()).with_message(left.item)) .with_label(Label::new_primary(left.tag()).with_message(left.item))
.with_label(Label::new_secondary(right.span()).with_message(right.item)) .with_label(Label::new_secondary(right.tag()).with_message(right.item))
} }
} }
} }
@ -315,26 +320,29 @@ impl ShellError {
pub fn labeled_error( pub fn labeled_error(
msg: impl Into<String>, msg: impl Into<String>,
label: impl Into<String>, label: impl Into<String>,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> ShellError { ) -> ShellError {
ShellError::diagnostic( ShellError::diagnostic(
Diagnostic::new(Severity::Error, msg.into()) Diagnostic::new(Severity::Error, msg.into())
.with_label(Label::new_primary(span.into()).with_message(label.into())), .with_label(Label::new_primary(tag.into()).with_message(label.into())),
) )
} }
pub fn labeled_error_with_secondary( pub fn labeled_error_with_secondary(
msg: impl Into<String>, msg: impl Into<String>,
primary_label: impl Into<String>, primary_label: impl Into<String>,
primary_span: Span, primary_span: impl Into<Tag>,
secondary_label: impl Into<String>, secondary_label: impl Into<String>,
secondary_span: Span, secondary_span: impl Into<Tag>,
) -> ShellError { ) -> ShellError {
ShellError::diagnostic( ShellError::diagnostic(
Diagnostic::new_error(msg.into()) Diagnostic::new_error(msg.into())
.with_label(Label::new_primary(primary_span).with_message(primary_label.into()))
.with_label( .with_label(
Label::new_secondary(secondary_span).with_message(secondary_label.into()), Label::new_primary(primary_span.into()).with_message(primary_label.into()),
)
.with_label(
Label::new_secondary(secondary_span.into())
.with_message(secondary_label.into()),
), ),
) )
} }
@ -409,13 +417,13 @@ pub enum ProximateShellError {
expr: Description, expr: Description,
}, },
MissingValue { MissingValue {
span: Option<Span>, tag: Option<Tag>,
reason: String, reason: String,
}, },
ArgumentError { ArgumentError {
command: String, command: String,
error: ArgumentError, error: ArgumentError,
span: Span, tag: Tag,
}, },
RangeError { RangeError {
kind: ExpectedRange, kind: ExpectedRange,
@ -447,7 +455,7 @@ impl ToDebug for ProximateShellError {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ShellDiagnostic { pub struct ShellDiagnostic {
pub(crate) diagnostic: Diagnostic<Span>, pub(crate) diagnostic: Diagnostic<Tag>,
} }
impl PartialEq for ShellDiagnostic { impl PartialEq for ShellDiagnostic {

View file

@ -38,13 +38,13 @@ pub(crate) fn evaluate_baseline_expr(
source: &Text, source: &Text,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match &expr.item { match &expr.item {
RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_span(literal), source)), RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_tag(literal), source)),
RawExpression::ExternalWord => Err(ShellError::argument_error( RawExpression::ExternalWord => Err(ShellError::argument_error(
"Invalid external word", "Invalid external word",
ArgumentError::InvalidExternalWord, ArgumentError::InvalidExternalWord,
expr.span(), expr.tag(),
)), )),
RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.span())), RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.tag())),
RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()), RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()),
RawExpression::Variable(var) => evaluate_reference(var, scope, source), RawExpression::Variable(var) => evaluate_reference(var, scope, source),
RawExpression::ExternalCommand(external) => evaluate_external(external, scope, source), RawExpression::ExternalCommand(external) => evaluate_external(external, scope, source),
@ -53,13 +53,10 @@ pub(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_simple_spanned_item( Ok(result) => Ok(Value::boolean(result).tagged(expr.tag())),
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_tag(left_type),
binary.right().copy_span(right_type), binary.right().copy_tag(right_type),
)), )),
} }
} }
@ -71,12 +68,14 @@ pub(crate) fn evaluate_baseline_expr(
exprs.push(expr); exprs.push(expr);
} }
Ok(Value::Table(exprs).tagged(Tag::unknown_origin(expr.span()))) Ok(Value::Table(exprs).tagged(expr.tag()))
}
RawExpression::Block(block) => {
Ok(
Value::Block(Block::new(block.clone(), source.clone(), expr.tag()))
.tagged(expr.tag()),
)
} }
RawExpression::Block(block) => Ok(Tagged::from_simple_spanned_item(
Value::Block(Block::new(block.clone(), source.clone(), expr.span())),
expr.span(),
)),
RawExpression::Path(path) => { RawExpression::Path(path) => {
let value = evaluate_baseline_expr(path.head(), registry, scope, source)?; let value = evaluate_baseline_expr(path.head(), registry, scope, source)?;
let mut item = value; let mut item = value;
@ -92,18 +91,12 @@ pub(crate) fn evaluate_baseline_expr(
)) ))
} }
Some(next) => { Some(next) => {
item = Tagged::from_simple_spanned_item( item = next.clone().item.tagged(expr.tag());
next.clone().item,
(expr.span().start, name.span().end),
)
} }
}; };
} }
Ok(Tagged::from_simple_spanned_item( Ok(item.item().clone().tagged(expr.tag()))
item.item().clone(),
expr.span(),
))
} }
RawExpression::Boolean(_boolean) => unimplemented!(), RawExpression::Boolean(_boolean) => unimplemented!(),
} }
@ -113,9 +106,9 @@ fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged<Val
let result = match literal.item { let result = match literal.item {
hir::Literal::Number(int) => int.into(), hir::Literal::Number(int) => int.into(),
hir::Literal::Size(int, unit) => unit.compute(int), hir::Literal::Size(int, unit) => unit.compute(int),
hir::Literal::String(span) => Value::string(span.slice(source)), hir::Literal::String(tag) => Value::string(tag.slice(source)),
hir::Literal::GlobPattern => Value::pattern(literal.span().slice(source)), hir::Literal::GlobPattern => Value::pattern(literal.tag().slice(source)),
hir::Literal::Bare => Value::string(literal.span().slice(source)), hir::Literal::Bare => Value::string(literal.tag().slice(source)),
}; };
literal.map(|_| result) literal.map(|_| result)
@ -127,12 +120,12 @@ fn evaluate_reference(
source: &Text, source: &Text,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
match name { match name {
hir::Variable::It(span) => Ok(scope.it.item.clone().simple_spanned(span)), hir::Variable::It(tag) => Ok(scope.it.item.clone().tagged(*tag)),
hir::Variable::Other(span) => Ok(scope hir::Variable::Other(tag) => Ok(scope
.vars .vars
.get(span.slice(source)) .get(tag.slice(source))
.map(|v| v.clone()) .map(|v| v.clone())
.unwrap_or_else(|| Value::nothing().simple_spanned(span))), .unwrap_or_else(|| Value::nothing().tagged(*tag))),
} }
} }
@ -142,6 +135,6 @@ fn evaluate_external(
_source: &Text, _source: &Text,
) -> Result<Tagged<Value>, ShellError> { ) -> Result<Tagged<Value>, ShellError> {
Err(ShellError::syntax_error( Err(ShellError::syntax_error(
"Unexpected external command".tagged(external.name()), "Unexpected external command".tagged(*external.name()),
)) ))
} }

View file

@ -204,7 +204,7 @@ impl RenderView for TableView {
let mut table = Table::new(); let mut table = Table::new();
let table_mode = crate::data::config::config(Span::unknown())? let table_mode = crate::data::config::config(Tag::unknown())?
.get("table_mode") .get("table_mode")
.map(|s| match s.as_string().unwrap().as_ref() { .map(|s| match s.as_string().unwrap().as_ref() {
"light" => TableMode::Light, "light" => TableMode::Light,

View file

@ -23,7 +23,7 @@ mod utils;
pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue}; pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue};
pub use crate::context::{SourceMap, SpanSource}; pub use crate::context::{SourceMap, SpanSource};
pub use crate::env::host::BasicHost; pub use crate::env::host::BasicHost;
pub use crate::parser::hir::SyntaxType; pub use crate::parser::hir::SyntaxShape;
pub use crate::parser::parse::token_tree_builder::TokenTreeBuilder; pub use crate::parser::parse::token_tree_builder::TokenTreeBuilder;
pub use crate::plugin::{serve_plugin, Plugin}; pub use crate::plugin::{serve_plugin, Plugin};
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath}; pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
@ -31,7 +31,7 @@ pub use cli::cli;
pub use data::config::{APP_INFO, config_path}; pub use data::config::{APP_INFO, config_path};
pub use data::base::{Primitive, Value}; pub use data::base::{Primitive, Value};
pub use data::dict::{Dictionary, TaggedDictBuilder}; pub use data::dict::{Dictionary, TaggedDictBuilder};
pub use data::meta::{Span, Tag, Tagged, TaggedItem}; pub use data::meta::{Tag, Tagged, TaggedItem};
pub use errors::{CoerceInto, ShellError}; pub use errors::{CoerceInto, ShellError};
pub use num_traits::cast::ToPrimitive; pub use num_traits::cast::ToPrimitive;
pub use parser::parse::text::Text; pub use parser::parse::text::Text;

View file

@ -21,10 +21,10 @@ pub(crate) use parse::unit::Unit;
pub(crate) use parse_command::parse_command; pub(crate) use parse_command::parse_command;
pub(crate) use registry::CommandRegistry; pub(crate) use registry::CommandRegistry;
pub fn parse(input: &str) -> Result<TokenNode, ShellError> { pub fn parse(input: &str, origin: uuid::Uuid) -> Result<TokenNode, ShellError> {
let _ = pretty_env_logger::try_init(); let _ = pretty_env_logger::try_init();
match pipeline(nom_input(input)) { match pipeline(nom_input(input, origin)) {
Ok((_rest, val)) => Ok(val), Ok((_rest, val)) => Ok(val),
Err(err) => Err(ShellError::parse_error(err)), Err(err) => Err(ShellError::parse_error(err)),
} }

View file

@ -37,7 +37,7 @@ impl<'de> ConfigDeserializer<'de> {
let value: Option<Tagged<Value>> = if name == "rest" { let value: Option<Tagged<Value>> = if name == "rest" {
let positional = self.call.args.slice_from(self.position); let positional = self.call.args.slice_from(self.position);
self.position += positional.len(); self.position += positional.len();
Some(Value::Table(positional).tagged_unknown()) // TODO: correct span Some(Value::Table(positional).tagged_unknown()) // TODO: correct tag
} else { } else {
if self.call.args.has(name) { if self.call.args.has(name) {
self.call.args.get(name).map(|x| x.clone()) self.call.args.get(name).map(|x| x.clone())
@ -52,9 +52,7 @@ impl<'de> ConfigDeserializer<'de> {
self.stack.push(DeserializerItem { self.stack.push(DeserializerItem {
key_struct_field: Some((name.to_string(), name)), key_struct_field: Some((name.to_string(), name)),
val: value.unwrap_or_else(|| { val: value.unwrap_or_else(|| Value::nothing().tagged(self.call.name_tag)),
Value::nothing().tagged(Tag::unknown_origin(self.call.name_span))
}),
}); });
Ok(()) Ok(())

View file

@ -25,7 +25,7 @@ pub(crate) use self::external_command::ExternalCommand;
pub(crate) use self::named::NamedArguments; pub(crate) use self::named::NamedArguments;
pub(crate) use self::path::Path; pub(crate) use self::path::Path;
pub use self::baseline_parse_tokens::SyntaxType; pub use self::baseline_parse_tokens::SyntaxShape;
pub fn path(head: impl Into<Expression>, tail: Vec<Tagged<impl Into<String>>>) -> Path { pub fn path(head: impl Into<Expression>, tail: Vec<Tagged<impl Into<String>>>) -> Path {
Path::new( Path::new(
@ -131,72 +131,57 @@ impl RawExpression {
pub type Expression = Tagged<RawExpression>; pub type Expression = Tagged<RawExpression>;
impl Expression { impl Expression {
pub(crate) fn number(i: impl Into<Number>, span: impl Into<Span>) -> Expression { pub(crate) fn number(i: impl Into<Number>, tag: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Number(i.into())), span) RawExpression::Literal(Literal::Number(i.into())).tagged(tag.into())
} }
pub(crate) fn size( pub(crate) fn size(
i: impl Into<Number>, i: impl Into<Number>,
unit: impl Into<Unit>, unit: impl Into<Unit>,
span: impl Into<Span>, tag: impl Into<Tag>,
) -> Expression { ) -> Expression {
Tagged::from_simple_spanned_item( RawExpression::Literal(Literal::Size(i.into(), unit.into())).tagged(tag.into())
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
span,
)
} }
pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression { pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression {
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown() RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
} }
pub(crate) fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { pub(crate) fn string(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item( RawExpression::Literal(Literal::String(inner.into())).tagged(outer.into())
RawExpression::Literal(Literal::String(inner.into())),
outer.into(),
)
} }
pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression { pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into()) RawExpression::FilePath(path.into()).tagged(outer)
} }
pub(crate) fn bare(span: impl Into<Span>) -> Expression { pub(crate) fn bare(tag: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into()) RawExpression::Literal(Literal::Bare).tagged(tag)
} }
pub(crate) fn pattern(tag: impl Into<Tag>) -> Expression { pub(crate) fn pattern(tag: impl Into<Tag>) -> Expression {
RawExpression::Literal(Literal::GlobPattern).tagged(tag.into()) RawExpression::Literal(Literal::GlobPattern).tagged(tag.into())
} }
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { pub(crate) fn variable(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item( RawExpression::Variable(Variable::Other(inner.into())).tagged(outer)
RawExpression::Variable(Variable::Other(inner.into())),
outer.into(),
)
} }
pub(crate) fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { pub(crate) fn external_command(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item( RawExpression::ExternalCommand(ExternalCommand::new(inner.into())).tagged(outer)
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())),
outer.into(),
)
} }
pub(crate) fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression { pub(crate) fn it_variable(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
Tagged::from_simple_spanned_item( RawExpression::Variable(Variable::It(inner.into())).tagged(outer)
RawExpression::Variable(Variable::It(inner.into())),
outer.into(),
)
} }
} }
impl ToDebug for Expression { impl ToDebug for Expression {
fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result { fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result {
match self.item() { match self.item() {
RawExpression::Literal(l) => l.tagged(self.span()).fmt_debug(f, source), RawExpression::Literal(l) => l.tagged(self.tag()).fmt_debug(f, source),
RawExpression::FilePath(p) => write!(f, "{}", p.display()), RawExpression::FilePath(p) => write!(f, "{}", p.display()),
RawExpression::ExternalWord => write!(f, "{}", self.span().slice(source)), RawExpression::ExternalWord => write!(f, "{}", self.tag().slice(source)),
RawExpression::Synthetic(Synthetic::String(s)) => write!(f, "{:?}", s), RawExpression::Synthetic(Synthetic::String(s)) => write!(f, "{:?}", s),
RawExpression::Variable(Variable::It(_)) => write!(f, "$it"), RawExpression::Variable(Variable::It(_)) => write!(f, "$it"),
RawExpression::Variable(Variable::Other(s)) => write!(f, "${}", s.slice(source)), RawExpression::Variable(Variable::Other(s)) => write!(f, "${}", s.slice(source)),
@ -242,7 +227,7 @@ impl From<Tagged<Path>> for Expression {
pub enum Literal { pub enum Literal {
Number(Number), Number(Number),
Size(Number, Unit), Size(Number, Unit),
String(Span), String(Tag),
GlobPattern, GlobPattern,
Bare, Bare,
} }
@ -252,9 +237,9 @@ impl ToDebug for Tagged<&Literal> {
match self.item() { match self.item() {
Literal::Number(number) => write!(f, "{:?}", *number), Literal::Number(number) => write!(f, "{:?}", *number),
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit), Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
Literal::String(span) => write!(f, "{}", span.slice(source)), Literal::String(tag) => write!(f, "{}", tag.slice(source)),
Literal::GlobPattern => write!(f, "{}", self.span().slice(source)), Literal::GlobPattern => write!(f, "{}", self.tag().slice(source)),
Literal::Bare => write!(f, "{}", self.span().slice(source)), Literal::Bare => write!(f, "{}", self.tag().slice(source)),
} }
} }
} }
@ -273,6 +258,6 @@ impl Literal {
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Variable { pub enum Variable {
It(Span), It(Tag),
Other(Span), Other(Tag),
} }

View file

@ -10,19 +10,19 @@ pub fn baseline_parse_single_token(
source: &Text, source: &Text,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
Ok(match *token.item() { Ok(match *token.item() {
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()), RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.tag()),
RawToken::Size(int, unit) => { RawToken::Size(int, unit) => {
hir::Expression::size(int.to_number(source), unit, token.span()) hir::Expression::size(int.to_number(source), unit, token.tag())
} }
RawToken::String(span) => hir::Expression::string(span, token.span()), RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
RawToken::Variable(span) if span.slice(source) == "it" => { RawToken::Variable(tag) if tag.slice(source) == "it" => {
hir::Expression::it_variable(span, token.span()) hir::Expression::it_variable(tag, token.tag())
} }
RawToken::Variable(span) => hir::Expression::variable(span, token.span()), RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()), RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())), RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
RawToken::GlobPattern => hir::Expression::pattern(token.span()), RawToken::GlobPattern => hir::Expression::pattern(token.tag()),
RawToken::Bare => hir::Expression::bare(token.span()), RawToken::Bare => hir::Expression::bare(token.tag()),
}) })
} }
@ -31,24 +31,24 @@ pub fn baseline_parse_token_as_number(
source: &Text, source: &Text,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
Ok(match *token.item() { Ok(match *token.item() {
RawToken::Variable(span) if span.slice(source) == "it" => { RawToken::Variable(tag) if tag.slice(source) == "it" => {
hir::Expression::it_variable(span, token.span()) hir::Expression::it_variable(tag, token.tag())
} }
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()), RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())), RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
RawToken::Variable(span) => hir::Expression::variable(span, token.span()), RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()), RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.tag()),
RawToken::Size(number, unit) => { RawToken::Size(number, unit) => {
hir::Expression::size(number.to_number(source), unit, token.span()) hir::Expression::size(number.to_number(source), unit, token.tag())
} }
RawToken::Bare => hir::Expression::bare(token.span()), RawToken::Bare => hir::Expression::bare(token.tag()),
RawToken::GlobPattern => { RawToken::GlobPattern => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Number", "Number",
"glob pattern".to_string().tagged(token.tag()), "glob pattern".to_string().tagged(token.tag()),
)) ))
} }
RawToken::String(span) => hir::Expression::string(span, token.span()), RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
}) })
} }
@ -57,22 +57,22 @@ pub fn baseline_parse_token_as_string(
source: &Text, source: &Text,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
Ok(match *token.item() { Ok(match *token.item() {
RawToken::Variable(span) if span.slice(source) == "it" => { RawToken::Variable(tag) if tag.slice(source) == "it" => {
hir::Expression::it_variable(span, token.span()) hir::Expression::it_variable(tag, token.tag())
} }
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()), RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())), RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
RawToken::Variable(span) => hir::Expression::variable(span, token.span()), RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
RawToken::Number(_) => hir::Expression::bare(token.span()), RawToken::Number(_) => hir::Expression::bare(token.tag()),
RawToken::Size(_, _) => hir::Expression::bare(token.span()), RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
RawToken::Bare => hir::Expression::bare(token.span()), RawToken::Bare => hir::Expression::bare(token.tag()),
RawToken::GlobPattern => { RawToken::GlobPattern => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"String", "String",
"glob pattern".tagged(token.tag()), "glob pattern".tagged(token.tag()),
)) ))
} }
RawToken::String(span) => hir::Expression::string(span, token.span()), RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
}) })
} }
@ -82,26 +82,25 @@ pub fn baseline_parse_token_as_path(
source: &Text, source: &Text,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
Ok(match *token.item() { Ok(match *token.item() {
RawToken::Variable(span) if span.slice(source) == "it" => { RawToken::Variable(tag) if tag.slice(source) == "it" => {
hir::Expression::it_variable(span, token.span()) hir::Expression::it_variable(tag, token.tag())
}
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
RawToken::Number(_) => hir::Expression::bare(token.tag()),
RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
RawToken::Bare => {
hir::Expression::file_path(expand_path(token.tag().slice(source), context), token.tag())
} }
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
RawToken::Number(_) => hir::Expression::bare(token.span()),
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
RawToken::Bare => hir::Expression::file_path(
expand_path(token.span().slice(source), context),
token.span(),
),
RawToken::GlobPattern => { RawToken::GlobPattern => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Path", "Path",
"glob pattern".tagged(token.tag()), "glob pattern".tagged(token.tag()),
)) ))
} }
RawToken::String(span) => { RawToken::String(tag) => {
hir::Expression::file_path(expand_path(span.slice(source), context), token.span()) hir::Expression::file_path(expand_path(tag.slice(source), context), token.tag())
} }
}) })
} }
@ -112,25 +111,24 @@ pub fn baseline_parse_token_as_pattern(
source: &Text, source: &Text,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
Ok(match *token.item() { Ok(match *token.item() {
RawToken::Variable(span) if span.slice(source) == "it" => { RawToken::Variable(tag) if tag.slice(source) == "it" => {
hir::Expression::it_variable(span, token.span()) hir::Expression::it_variable(tag, token.tag())
} }
RawToken::ExternalCommand(_) => { RawToken::ExternalCommand(_) => {
return Err(ShellError::syntax_error( return Err(ShellError::syntax_error(
"Invalid external command".to_string().tagged(token.tag()), "Invalid external command".to_string().tagged(token.tag()),
)) ))
} }
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())), RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
RawToken::Variable(span) => hir::Expression::variable(span, token.span()), RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
RawToken::Number(_) => hir::Expression::bare(token.span()), RawToken::Number(_) => hir::Expression::bare(token.tag()),
RawToken::Size(_, _) => hir::Expression::bare(token.span()), RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
RawToken::GlobPattern => hir::Expression::pattern(token.span()), RawToken::GlobPattern => hir::Expression::pattern(token.tag()),
RawToken::Bare => hir::Expression::file_path( RawToken::Bare => {
expand_path(token.span().slice(source), context), hir::Expression::file_path(expand_path(token.tag().slice(source), context), token.tag())
token.span(), }
), RawToken::String(tag) => {
RawToken::String(span) => { hir::Expression::file_path(expand_path(tag.slice(source), context), token.tag())
hir::Expression::file_path(expand_path(span.slice(source), context), token.span())
} }
}) })
} }

View file

@ -8,7 +8,7 @@ use crate::parser::{
}, },
DelimitedNode, Delimiter, PathNode, RawToken, TokenNode, DelimitedNode, Delimiter, PathNode, RawToken, TokenNode,
}; };
use crate::{Span, Tag, Tagged, TaggedItem, Text}; use crate::{Tag, Tagged, TaggedItem, Text};
use derive_new::new; use derive_new::new;
use log::trace; use log::trace;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -17,7 +17,7 @@ pub fn baseline_parse_tokens(
token_nodes: &mut TokensIterator<'_>, token_nodes: &mut TokensIterator<'_>,
context: &Context, context: &Context,
source: &Text, source: &Text,
syntax_type: SyntaxType, syntax_type: SyntaxShape,
) -> Result<Vec<hir::Expression>, ShellError> { ) -> Result<Vec<hir::Expression>, ShellError> {
let mut exprs: Vec<hir::Expression> = vec![]; let mut exprs: Vec<hir::Expression> = vec![];
@ -34,7 +34,7 @@ pub fn baseline_parse_tokens(
} }
#[derive(Debug, Copy, Clone, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum SyntaxType { pub enum SyntaxShape {
Any, Any,
List, List,
Literal, Literal,
@ -49,21 +49,21 @@ pub enum SyntaxType {
Boolean, Boolean,
} }
impl std::fmt::Display for SyntaxType { impl std::fmt::Display for SyntaxShape {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
SyntaxType::Any => write!(f, "Any"), SyntaxShape::Any => write!(f, "Any"),
SyntaxType::List => write!(f, "List"), SyntaxShape::List => write!(f, "List"),
SyntaxType::Literal => write!(f, "Literal"), SyntaxShape::Literal => write!(f, "Literal"),
SyntaxType::String => write!(f, "String"), SyntaxShape::String => write!(f, "String"),
SyntaxType::Member => write!(f, "Member"), SyntaxShape::Member => write!(f, "Member"),
SyntaxType::Variable => write!(f, "Variable"), SyntaxShape::Variable => write!(f, "Variable"),
SyntaxType::Number => write!(f, "Number"), SyntaxShape::Number => write!(f, "Number"),
SyntaxType::Path => write!(f, "Path"), SyntaxShape::Path => write!(f, "Path"),
SyntaxType::Pattern => write!(f, "Pattern"), SyntaxShape::Pattern => write!(f, "Pattern"),
SyntaxType::Binary => write!(f, "Binary"), SyntaxShape::Binary => write!(f, "Binary"),
SyntaxType::Block => write!(f, "Block"), SyntaxShape::Block => write!(f, "Block"),
SyntaxType::Boolean => write!(f, "Boolean"), SyntaxShape::Boolean => write!(f, "Boolean"),
} }
} }
} }
@ -72,7 +72,7 @@ pub fn baseline_parse_next_expr(
tokens: &mut TokensIterator, tokens: &mut TokensIterator,
context: &Context, context: &Context,
source: &Text, source: &Text,
syntax_type: SyntaxType, syntax_type: SyntaxShape,
) -> Result<hir::Expression, ShellError> { ) -> Result<hir::Expression, ShellError> {
let next = tokens let next = tokens
.next() .next()
@ -81,69 +81,69 @@ pub fn baseline_parse_next_expr(
trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", syntax_type, next); trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", syntax_type, next);
match (syntax_type, next) { match (syntax_type, next) {
(SyntaxType::Path, TokenNode::Token(token)) => { (SyntaxShape::Path, TokenNode::Token(token)) => {
return baseline_parse_token_as_path(token, context, source) return baseline_parse_token_as_path(token, context, source)
} }
(SyntaxType::Path, token) => { (SyntaxShape::Path, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Path", "Path",
token.type_name().simple_spanned(token.span()), token.type_name().tagged(token.tag()),
)) ))
} }
(SyntaxType::Pattern, TokenNode::Token(token)) => { (SyntaxShape::Pattern, TokenNode::Token(token)) => {
return baseline_parse_token_as_pattern(token, context, source) return baseline_parse_token_as_pattern(token, context, source)
} }
(SyntaxType::Pattern, token) => { (SyntaxShape::Pattern, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Path", "Path",
token.type_name().simple_spanned(token.span()), token.type_name().tagged(token.tag()),
)) ))
} }
(SyntaxType::String, TokenNode::Token(token)) => { (SyntaxShape::String, TokenNode::Token(token)) => {
return baseline_parse_token_as_string(token, source); return baseline_parse_token_as_string(token, source);
} }
(SyntaxType::String, token) => { (SyntaxShape::String, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"String", "String",
token.type_name().simple_spanned(token.span()), token.type_name().tagged(token.tag()),
)) ))
} }
(SyntaxType::Number, TokenNode::Token(token)) => { (SyntaxShape::Number, TokenNode::Token(token)) => {
return Ok(baseline_parse_token_as_number(token, source)?); return Ok(baseline_parse_token_as_number(token, source)?);
} }
(SyntaxType::Number, token) => { (SyntaxShape::Number, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"Numeric", "Numeric",
token.type_name().simple_spanned(token.span()), token.type_name().tagged(token.tag()),
)) ))
} }
// TODO: More legit member processing // TODO: More legit member processing
(SyntaxType::Member, TokenNode::Token(token)) => { (SyntaxShape::Member, TokenNode::Token(token)) => {
return baseline_parse_token_as_string(token, source); return baseline_parse_token_as_string(token, source);
} }
(SyntaxType::Member, token) => { (SyntaxShape::Member, token) => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"member", "member",
token.type_name().simple_spanned(token.span()), token.type_name().tagged(token.tag()),
)) ))
} }
(SyntaxType::Any, _) => {} (SyntaxShape::Any, _) => {}
(SyntaxType::List, _) => {} (SyntaxShape::List, _) => {}
(SyntaxType::Literal, _) => {} (SyntaxShape::Literal, _) => {}
(SyntaxType::Variable, _) => {} (SyntaxShape::Variable, _) => {}
(SyntaxType::Binary, _) => {} (SyntaxShape::Binary, _) => {}
(SyntaxType::Block, _) => {} (SyntaxShape::Block, _) => {}
(SyntaxType::Boolean, _) => {} (SyntaxShape::Boolean, _) => {}
}; };
let first = baseline_parse_semantic_token(next, context, source)?; let first = baseline_parse_semantic_token(next, context, source)?;
@ -162,7 +162,7 @@ pub fn baseline_parse_next_expr(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Expected something after an operator", "Expected something after an operator",
"operator", "operator",
op.span(), op.tag(),
)) ))
} }
Some(token) => baseline_parse_semantic_token(token, context, source)?, Some(token) => baseline_parse_semantic_token(token, context, source)?,
@ -171,75 +171,66 @@ pub fn baseline_parse_next_expr(
// We definitely have a binary expression here -- let's see if we should coerce it into a block // We definitely have a binary expression here -- let's see if we should coerce it into a block
match syntax_type { match syntax_type {
SyntaxType::Any => { SyntaxShape::Any => {
let span = (first.span().start, second.span().end); let tag = first.tag().until(second.tag());
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_simple_spanned_item(binary, span); let binary = binary.tagged(tag);
Ok(binary) Ok(binary)
} }
SyntaxType::Block => { SyntaxShape::Block => {
let span = (first.span().start, second.span().end); let tag = first.tag().until(second.tag());
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,
} => { } => {
let string = let string = tag.slice(source).to_string().tagged(tag);
Tagged::from_simple_spanned_item(span.slice(source).to_string(), span);
let path = hir::Path::new( let path = hir::Path::new(
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(Tag::unknown()))
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), .tagged(Tag::unknown()),
(0, 0),
),
vec![string], vec![string],
); );
let path = hir::RawExpression::Path(Box::new(path)); let path = hir::RawExpression::Path(Box::new(path));
Tagged::from_simple_spanned_item(path, first.span()) path.tagged(first.tag())
} }
Tagged { Tagged {
item: hir::RawExpression::Literal(hir::Literal::String(inner)), item: hir::RawExpression::Literal(hir::Literal::String(inner)),
tag: Tag { span, .. }, tag,
} => { } => {
let string = let string = inner.slice(source).to_string().tagged(tag);
Tagged::from_simple_spanned_item(inner.slice(source).to_string(), span);
let path = hir::Path::new( let path = hir::Path::new(
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(Tag::unknown()))
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), .tagged_unknown(),
(0, 0),
),
vec![string], vec![string],
); );
let path = hir::RawExpression::Path(Box::new(path)); let path = hir::RawExpression::Path(Box::new(path));
Tagged::from_simple_spanned_item(path, first.span()) path.tagged(first.tag())
} }
Tagged { Tagged {
item: hir::RawExpression::Variable(..), item: hir::RawExpression::Variable(..),
.. ..
} => first, } => first,
Tagged { Tagged { tag, item } => {
tag: Tag { span, .. },
item,
} => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"The first part of an un-braced block must be a column name", "The first part of an un-braced block must be a column name",
item.type_name(), item.type_name(),
span, tag,
)) ))
} }
}; };
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_simple_spanned_item(binary, span); let binary = binary.tagged(tag);
let block = hir::RawExpression::Block(vec![binary]); let block = hir::RawExpression::Block(vec![binary]);
let block = Tagged::from_simple_spanned_item(block, span); let block = block.tagged(tag);
Ok(block) Ok(block)
} }
@ -265,11 +256,11 @@ pub fn baseline_parse_semantic_token(
"Unexpected operator".tagged(op.tag), "Unexpected operator".tagged(op.tag),
)), )),
TokenNode::Flag(flag) => Err(ShellError::syntax_error("Unexpected flag".tagged(flag.tag))), TokenNode::Flag(flag) => Err(ShellError::syntax_error("Unexpected flag".tagged(flag.tag))),
TokenNode::Member(span) => Err(ShellError::syntax_error( TokenNode::Member(tag) => Err(ShellError::syntax_error(
"BUG: Top-level member".tagged(span), "BUG: Top-level member".tagged(*tag),
)), )),
TokenNode::Whitespace(span) => Err(ShellError::syntax_error( TokenNode::Whitespace(tag) => Err(ShellError::syntax_error(
"BUG: Whitespace found during parse".tagged(span), "BUG: Whitespace found during parse".tagged(*tag),
)), )),
TokenNode::Error(error) => Err(*error.item.clone()), TokenNode::Error(error) => Err(*error.item.clone()),
TokenNode::Path(path) => baseline_parse_path(path, context, source), TokenNode::Path(path) => baseline_parse_path(path, context, source),
@ -288,11 +279,11 @@ pub fn baseline_parse_delimited(
&mut TokensIterator::new(children), &mut TokensIterator::new(children),
context, context,
source, source,
SyntaxType::Any, SyntaxShape::Any,
)?; )?;
let expr = hir::RawExpression::Block(exprs); let expr = hir::RawExpression::Block(exprs);
Ok(Tagged::from_simple_spanned_item(expr, token.span())) Ok(expr.tagged(token.tag()))
} }
Delimiter::Paren => unimplemented!(), Delimiter::Paren => unimplemented!(),
Delimiter::Square => { Delimiter::Square => {
@ -301,11 +292,11 @@ pub fn baseline_parse_delimited(
&mut TokensIterator::new(children), &mut TokensIterator::new(children),
context, context,
source, source,
SyntaxType::Any, SyntaxShape::Any,
)?; )?;
let expr = hir::RawExpression::List(exprs); let expr = hir::RawExpression::List(exprs);
Ok(expr.tagged(Tag::unknown_origin(token.span()))) Ok(expr.tagged(token.tag()))
} }
} }
} }
@ -322,8 +313,8 @@ pub fn baseline_parse_path(
for part in token.tail() { for part in token.tail() {
let string = match part { let string = match part {
TokenNode::Token(token) => match token.item() { TokenNode::Token(token) => match token.item() {
RawToken::Bare => token.span().slice(source), RawToken::Bare => token.tag().slice(source),
RawToken::String(span) => span.slice(source), RawToken::String(tag) => tag.slice(source),
RawToken::Number(_) RawToken::Number(_)
| RawToken::Size(..) | RawToken::Size(..)
| RawToken::Variable(_) | RawToken::Variable(_)
@ -332,26 +323,26 @@ pub fn baseline_parse_path(
| RawToken::ExternalWord => { | RawToken::ExternalWord => {
return Err(ShellError::type_error( return Err(ShellError::type_error(
"String", "String",
token.type_name().simple_spanned(part), token.type_name().tagged(part.tag()),
)) ))
} }
}, },
TokenNode::Member(span) => span.slice(source), TokenNode::Member(tag) => tag.slice(source),
// TODO: Make this impossible // TODO: Make this impossible
other => { other => {
return Err(ShellError::syntax_error( return Err(ShellError::syntax_error(
format!("{} in path", other.type_name()).tagged(other.span()), format!("{} in path", other.type_name()).tagged(other.tag()),
)) ))
} }
} }
.to_string(); .to_string();
tail.push(string.simple_spanned(part)); tail.push(string.tagged(part.tag()));
} }
Ok(hir::path(head, tail).simple_spanned(token).into()) Ok(hir::path(head, tail).tagged(token.tag()).into())
} }
#[derive(Debug, new)] #[derive(Debug, new)]

View file

@ -9,7 +9,7 @@ use std::fmt;
)] )]
#[get = "pub(crate)"] #[get = "pub(crate)"]
pub struct ExternalCommand { pub struct ExternalCommand {
name: Span, name: Tag,
} }
impl ToDebug for ExternalCommand { impl ToDebug for ExternalCommand {

View file

@ -1,7 +1,6 @@
use crate::parser::hir::Expression; use crate::parser::hir::Expression;
use crate::parser::Flag; use crate::parser::Flag;
use crate::prelude::*; use crate::prelude::*;
use crate::Span;
use derive_new::new; use derive_new::new;
use indexmap::IndexMap; use indexmap::IndexMap;
use log::trace; use log::trace;
@ -11,7 +10,7 @@ use std::fmt;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum NamedValue { pub enum NamedValue {
AbsentSwitch, AbsentSwitch,
PresentSwitch(Span), PresentSwitch(Tag),
AbsentValue, AbsentValue,
Value(Expression), Value(Expression),
} }
@ -27,7 +26,7 @@ impl ToDebug for NamedArguments {
for (name, value) in &self.named { for (name, value) in &self.named {
match value { match value {
NamedValue::AbsentSwitch => continue, NamedValue::AbsentSwitch => continue,
NamedValue::PresentSwitch(span) => write!(f, " --{}", span.slice(source))?, NamedValue::PresentSwitch(tag) => write!(f, " --{}", tag.slice(source))?,
NamedValue::AbsentValue => continue, NamedValue::AbsentValue => continue,
NamedValue::Value(expr) => write!(f, " --{} {}", name, expr.debug(source))?, NamedValue::Value(expr) => write!(f, " --{} {}", name, expr.debug(source))?,
} }

View file

@ -1,6 +1,7 @@
use crate::Span; use crate::Tag;
use derive_new::new; use derive_new::new;
use language_reporting::{FileName, Location}; use language_reporting::{FileName, Location};
use uuid::Uuid;
#[derive(new, Debug, Clone)] #[derive(new, Debug, Clone)]
pub struct Files { pub struct Files {
@ -8,26 +9,30 @@ pub struct Files {
} }
impl language_reporting::ReportingFiles for Files { impl language_reporting::ReportingFiles for Files {
type Span = Span; type Span = Tag;
type FileId = usize; type FileId = Uuid;
fn byte_span( fn byte_span(
&self, &self,
_file: Self::FileId, file: Self::FileId,
from_index: usize, from_index: usize,
to_index: usize, to_index: usize,
) -> Option<Self::Span> { ) -> Option<Self::Span> {
Some(Span::from((from_index, to_index))) Some(Tag::from((from_index, to_index, file)))
} }
fn file_id(&self, _span: Self::Span) -> Self::FileId {
0 fn file_id(&self, tag: Self::Span) -> Self::FileId {
tag.origin.unwrap()
} }
fn file_name(&self, _file: Self::FileId) -> FileName { fn file_name(&self, _file: Self::FileId) -> FileName {
FileName::Verbatim(format!("shell")) FileName::Verbatim(format!("shell"))
} }
fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option<usize> { fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option<usize> {
unimplemented!("byte_index") unimplemented!("byte_index")
} }
fn location(&self, _file: Self::FileId, byte_index: usize) -> Option<Location> { fn location(&self, _file: Self::FileId, byte_index: usize) -> Option<Location> {
let source = &self.snippet; let source = &self.snippet;
let mut seen_lines = 0; let mut seen_lines = 0;
@ -51,14 +56,15 @@ impl language_reporting::ReportingFiles for Files {
None None
} }
} }
fn line_span(&self, _file: Self::FileId, lineno: usize) -> Option<Self::Span> {
fn line_span(&self, file: Self::FileId, lineno: usize) -> Option<Self::Span> {
let source = &self.snippet; let source = &self.snippet;
let mut seen_lines = 0; let mut seen_lines = 0;
let mut seen_bytes = 0; let mut seen_bytes = 0;
for (pos, _) in source.match_indices('\n') { for (pos, _) in source.match_indices('\n') {
if seen_lines == lineno { if seen_lines == lineno {
return Some(Span::from((seen_bytes, pos))); return Some(Tag::from((seen_bytes, pos, file)));
} else { } else {
seen_lines += 1; seen_lines += 1;
seen_bytes = pos + 1; seen_bytes = pos + 1;
@ -66,17 +72,18 @@ impl language_reporting::ReportingFiles for Files {
} }
if seen_lines == 0 { if seen_lines == 0 {
Some(Span::from((0, self.snippet.len() - 1))) Some(Tag::from((0, self.snippet.len() - 1, file)))
} else { } else {
None None
} }
} }
fn source(&self, span: Self::Span) -> Option<String> {
if span.start > span.end { fn source(&self, tag: Self::Span) -> Option<String> {
if tag.span.start > tag.span.end {
return None; return None;
} else if span.end >= self.snippet.len() { } else if tag.span.end >= self.snippet.len() {
return None; return None;
} }
Some(self.snippet[span.start..span.end].to_string()) Some(tag.slice(&self.snippet).to_string())
} }
} }

View file

@ -1,4 +1,4 @@
use crate::Span; use crate::Tag;
use derive_new::new; use derive_new::new;
use getset::Getters; use getset::Getters;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -13,5 +13,5 @@ pub enum FlagKind {
#[get = "pub(crate)"] #[get = "pub(crate)"]
pub struct Flag { pub struct Flag {
kind: FlagKind, kind: FlagKind,
name: Span, name: Tag,
} }

View file

@ -5,7 +5,7 @@ use crate::parser::parse::{
tokens::*, unit::*, tokens::*, unit::*,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::{Span, Tagged}; use crate::{Tag, Tagged};
use nom; use nom;
use nom::branch::*; use nom::branch::*;
use nom::bytes::complete::*; use nom::bytes::complete::*;
@ -18,15 +18,16 @@ use log::trace;
use nom::dbg; use nom::dbg;
use nom::*; use nom::*;
use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice}; use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice};
use nom5_locate::{position, LocatedSpan}; use nom_locate::{position, LocatedSpanEx};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use std::str::FromStr; use std::str::FromStr;
use uuid::Uuid;
pub type NomSpan<'a> = LocatedSpan<&'a str>; pub type NomSpan<'a> = LocatedSpanEx<&'a str, Uuid>;
pub fn nom_input(s: &str) -> NomSpan<'_> { pub fn nom_input(s: &str, origin: Uuid) -> NomSpan<'_> {
LocatedSpan::new(s) LocatedSpanEx::new_extra(s, origin)
} }
macro_rules! operator { macro_rules! operator {
@ -38,7 +39,7 @@ macro_rules! operator {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_op(tag.fragment, (start, end)), TokenTreeBuilder::tagged_op(tag.fragment, (start, end, input.extra)),
)) ))
} }
}; };
@ -159,14 +160,14 @@ pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<RawNumber>> {
Ok((input, dot)) => input, Ok((input, dot)) => input,
// it's just an integer // it's just an integer
Err(_) => return Ok((input, RawNumber::int((start, input.offset)))), Err(_) => return Ok((input, RawNumber::int((start, input.offset, input.extra)))),
}; };
let (input, tail) = digit1(input)?; let (input, tail) = digit1(input)?;
let end = input.offset; let end = input.offset;
Ok((input, RawNumber::decimal((start, end)))) Ok((input, RawNumber::decimal((start, end, input.extra))))
}) })
} }
@ -189,7 +190,7 @@ pub fn dq_string(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let end = input.offset; let end = input.offset;
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_string((start1, end1), (start, end)), TokenTreeBuilder::tagged_string((start1, end1, input.extra), (start, end, input.extra)),
)) ))
}) })
} }
@ -206,7 +207,7 @@ pub fn sq_string(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_string((start1, end1), (start, end)), TokenTreeBuilder::tagged_string((start1, end1, input.extra), (start, end, input.extra)),
)) ))
}) })
} }
@ -226,7 +227,7 @@ pub fn external(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_external(bare, (start, end)), TokenTreeBuilder::tagged_external(bare, (start, end, input.extra)),
)) ))
}) })
} }
@ -250,7 +251,10 @@ pub fn pattern(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let end = input.offset; let end = input.offset;
Ok((input, TokenTreeBuilder::spanned_pattern((start, end)))) Ok((
input,
TokenTreeBuilder::tagged_pattern((start, end, input.extra)),
))
}) })
} }
@ -263,7 +267,7 @@ pub fn bare(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let next_char = &input.fragment.chars().nth(0); let next_char = &input.fragment.chars().nth(0);
if let Some(next_char) = next_char { if let Some(next_char) = next_char {
if is_external_word_char(*next_char) || *next_char == '*' { if is_external_word_char(*next_char) || is_glob_specific_char(*next_char) {
return Err(nom::Err::Error(nom::error::make_error( return Err(nom::Err::Error(nom::error::make_error(
input, input,
nom::error::ErrorKind::TakeWhile1, nom::error::ErrorKind::TakeWhile1,
@ -273,7 +277,10 @@ pub fn bare(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let end = input.offset; let end = input.offset;
Ok((input, TokenTreeBuilder::spanned_bare((start, end)))) Ok((
input,
TokenTreeBuilder::tagged_bare((start, end, input.extra)),
))
}) })
} }
@ -283,7 +290,10 @@ pub fn external_word(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let (input, _) = take_while1(is_external_word_char)(input)?; let (input, _) = take_while1(is_external_word_char)(input)?;
let end = input.offset; let end = input.offset;
Ok((input, TokenTreeBuilder::spanned_external_word((start, end)))) Ok((
input,
TokenTreeBuilder::tagged_external_word((start, end, input.extra)),
))
}) })
} }
@ -296,7 +306,7 @@ pub fn var(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_var(bare.span(), (start, end)), TokenTreeBuilder::tagged_var(bare.tag(), (start, end, input.extra)),
)) ))
}) })
} }
@ -309,7 +319,10 @@ pub fn member(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let end = input.offset; let end = input.offset;
Ok((input, TokenTreeBuilder::spanned_member((start, end)))) Ok((
input,
TokenTreeBuilder::tagged_member((start, end, input.extra)),
))
}) })
} }
@ -322,7 +335,7 @@ pub fn flag(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_flag(bare.span(), (start, end)), TokenTreeBuilder::tagged_flag(bare.tag(), (start, end, input.extra)),
)) ))
}) })
} }
@ -336,7 +349,7 @@ pub fn shorthand(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_shorthand(bare.span(), (start, end)), TokenTreeBuilder::tagged_shorthand(bare.tag(), (start, end, input.extra)),
)) ))
}) })
} }
@ -369,7 +382,7 @@ pub fn raw_unit(input: NomSpan) -> IResult<NomSpan, Tagged<Unit>> {
Ok(( Ok((
input, input,
Tagged::from_simple_spanned_item(Unit::from(unit.fragment), (start, end)), Unit::from(unit.fragment).tagged((start, end, input.extra)),
)) ))
}) })
} }
@ -389,7 +402,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_size((number.item, *size), (start, end)), TokenTreeBuilder::tagged_size((number.item, *size), (start, end, input.extra)),
)) ))
} else { } else {
let end = input.offset; let end = input.offset;
@ -401,7 +414,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_number(number.item, number.tag), TokenTreeBuilder::tagged_number(number.item, number.tag),
)) ))
} }
}) })
@ -455,18 +468,18 @@ fn make_token_list(
let mut nodes = vec![]; let mut nodes = vec![];
if let Some(sp_left) = sp_left { if let Some(sp_left) = sp_left {
nodes.push(TokenNode::Whitespace(Span::from(sp_left))); nodes.push(TokenNode::Whitespace(Tag::from(sp_left)));
} }
nodes.push(first); nodes.push(first);
for (ws, token) in list { for (ws, token) in list {
nodes.push(TokenNode::Whitespace(Span::from(ws))); nodes.push(TokenNode::Whitespace(Tag::from(ws)));
nodes.push(token); nodes.push(token);
} }
if let Some(sp_right) = sp_right { if let Some(sp_right) = sp_right {
nodes.push(TokenNode::Whitespace(Span::from(sp_right))); nodes.push(TokenNode::Whitespace(Tag::from(sp_right)));
} }
nodes nodes
@ -478,7 +491,10 @@ pub fn whitespace(input: NomSpan) -> IResult<NomSpan, TokenNode> {
let (input, ws1) = space1(input)?; let (input, ws1) = space1(input)?;
let right = input.offset; let right = input.offset;
Ok((input, TokenTreeBuilder::spanned_ws((left, right)))) Ok((
input,
TokenTreeBuilder::tagged_ws((left, right, input.extra)),
))
}) })
} }
@ -508,7 +524,7 @@ pub fn delimited_paren(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_parens(items, (left, right)), TokenTreeBuilder::tagged_parens(items, (left, right, input.extra)),
)) ))
}) })
} }
@ -539,7 +555,7 @@ pub fn delimited_square(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_square(items, (left, right)), TokenTreeBuilder::tagged_square(items, (left, right, input.extra)),
)) ))
}) })
} }
@ -556,7 +572,10 @@ pub fn delimited_brace(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_brace(items.unwrap_or_else(|| vec![]), (left, right)), TokenTreeBuilder::tagged_brace(
items.unwrap_or_else(|| vec![]),
(left, right, input.extra),
),
)) ))
}) })
} }
@ -567,7 +586,10 @@ pub fn raw_call(input: NomSpan) -> IResult<NomSpan, Tagged<CallNode>> {
let (input, items) = token_list(input)?; let (input, items) = token_list(input)?;
let right = input.offset; let right = input.offset;
Ok((input, TokenTreeBuilder::spanned_call(items, (left, right)))) Ok((
input,
TokenTreeBuilder::tagged_call(items, (left, right, input.extra)),
))
}) })
} }
@ -581,7 +603,7 @@ pub fn path(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_path((head, tail), (left, right)), TokenTreeBuilder::tagged_path((head, tail), (left, right, input.extra)),
)) ))
}) })
} }
@ -628,9 +650,9 @@ pub fn pipeline(input: NomSpan) -> IResult<NomSpan, TokenNode> {
Ok(( Ok((
input, input,
TokenTreeBuilder::spanned_pipeline( TokenTreeBuilder::tagged_pipeline(
(make_call_list(head, items), tail.map(Span::from)), (make_call_list(head, items), tail.map(Tag::from)),
(start, end), (start, end, input.extra),
), ),
)) ))
}) })
@ -643,17 +665,17 @@ fn make_call_list(
let mut out = vec![]; let mut out = vec![];
if let Some(head) = head { if let Some(head) = head {
let el = PipelineElement::new(None, head.0.map(Span::from), head.1, head.2.map(Span::from)); let el = PipelineElement::new(None, head.0.map(Tag::from), head.1, head.2.map(Tag::from));
out.push(el); out.push(el);
} }
for (pipe, ws1, call, ws2) in items { for (pipe, ws1, call, ws2) in items {
let el = PipelineElement::new( let el = PipelineElement::new(
Some(pipe).map(Span::from), Some(pipe).map(Tag::from),
ws1.map(Span::from), ws1.map(Tag::from),
call, call,
ws2.map(Span::from), ws2.map(Tag::from),
); );
out.push(el); out.push(el);
@ -679,12 +701,17 @@ fn is_external_word_char(c: char) -> bool {
} }
} }
/// These characters appear in globs and not bare words
fn is_glob_specific_char(c: char) -> bool {
c == '*' || c == '?'
}
fn is_start_glob_char(c: char) -> bool { fn is_start_glob_char(c: char) -> bool {
is_start_bare_char(c) || c == '*' is_start_bare_char(c) || is_glob_specific_char(c)
} }
fn is_glob_char(c: char) -> bool { fn is_glob_char(c: char) -> bool {
is_bare_char(c) || c == '*' is_bare_char(c) || is_glob_specific_char(c)
} }
fn is_start_bare_char(c: char) -> bool { fn is_start_bare_char(c: char) -> bool {
@ -779,7 +806,7 @@ mod tests {
macro_rules! equal_tokens { macro_rules! equal_tokens {
($source:tt -> $tokens:expr) => { ($source:tt -> $tokens:expr) => {
let result = apply(pipeline, "pipeline", $source); let result = apply(pipeline, "pipeline", $source);
let (expected_tree, expected_source) = TokenTreeBuilder::build($tokens); let (expected_tree, expected_source) = TokenTreeBuilder::build(uuid::Uuid::nil(), $tokens);
if result != expected_tree { if result != expected_tree {
let debug_result = format!("{}", result.debug($source)); let debug_result = format!("{}", result.debug($source));
@ -818,12 +845,12 @@ mod tests {
fn test_integer() { fn test_integer() {
assert_leaf! { assert_leaf! {
parsers [ size ] parsers [ size ]
"123" -> 0..3 { Number(RawNumber::int((0, 3)).item) } "123" -> 0..3 { Number(RawNumber::int((0, 3, test_uuid())).item) }
} }
assert_leaf! { assert_leaf! {
parsers [ size ] parsers [ size ]
"-123" -> 0..4 { Number(RawNumber::int((0, 4)).item) } "-123" -> 0..4 { Number(RawNumber::int((0, 4, test_uuid())).item) }
} }
} }
@ -831,12 +858,12 @@ mod tests {
fn test_size() { fn test_size() {
assert_leaf! { assert_leaf! {
parsers [ size ] parsers [ size ]
"123MB" -> 0..5 { Size(RawNumber::int((0, 3)).item, Unit::MB) } "123MB" -> 0..5 { Size(RawNumber::int((0, 3, test_uuid())).item, Unit::MB) }
} }
assert_leaf! { assert_leaf! {
parsers [ size ] parsers [ size ]
"10GB" -> 0..4 { Size(RawNumber::int((0, 2)).item, Unit::GB) } "10GB" -> 0..4 { Size(RawNumber::int((0, 2, test_uuid())).item, Unit::GB) }
} }
} }
@ -874,12 +901,12 @@ mod tests {
fn test_string() { fn test_string() {
assert_leaf! { assert_leaf! {
parsers [ string dq_string ] parsers [ string dq_string ]
r#""hello world""# -> 0..13 { String(span(1, 12)) } r#""hello world""# -> 0..13 { String(tag(1, 12)) }
} }
assert_leaf! { assert_leaf! {
parsers [ string sq_string ] parsers [ string sq_string ]
r"'hello world'" -> 0..13 { String(span(1, 12)) } r"'hello world'" -> 0..13 { String(tag(1, 12)) }
} }
} }
@ -931,12 +958,12 @@ mod tests {
fn test_variable() { fn test_variable() {
assert_leaf! { assert_leaf! {
parsers [ var ] parsers [ var ]
"$it" -> 0..3 { Variable(span(1, 3)) } "$it" -> 0..3 { Variable(tag(1, 3)) }
} }
assert_leaf! { assert_leaf! {
parsers [ var ] parsers [ var ]
"$name" -> 0..5 { Variable(span(1, 5)) } "$name" -> 0..5 { Variable(tag(1, 5)) }
} }
} }
@ -944,7 +971,7 @@ mod tests {
fn test_external() { fn test_external() {
assert_leaf! { assert_leaf! {
parsers [ external ] parsers [ external ]
"^ls" -> 0..3 { ExternalCommand(span(1, 3)) } "^ls" -> 0..3 { ExternalCommand(tag(1, 3)) }
} }
} }
@ -1260,7 +1287,7 @@ mod tests {
desc: &str, desc: &str,
string: &str, string: &str,
) -> T { ) -> T {
match f(NomSpan::new(string)) { match f(NomSpan::new_extra(string, uuid::Uuid::nil())) {
Ok(v) => v.1, Ok(v) => v.1,
Err(other) => { Err(other) => {
println!("{:?}", other); println!("{:?}", other);
@ -1270,44 +1297,46 @@ mod tests {
} }
} }
fn span(left: usize, right: usize) -> Span { fn tag(left: usize, right: usize) -> Tag {
Span::from((left, right)) Tag::from((left, right, uuid::Uuid::nil()))
} }
fn delimited( fn delimited(
delimiter: Delimiter, delimiter: Tagged<Delimiter>,
children: Vec<TokenNode>, children: Vec<TokenNode>,
left: usize, left: usize,
right: usize, right: usize,
) -> TokenNode { ) -> TokenNode {
let node = DelimitedNode::new(delimiter, children); let node = DelimitedNode::new(*delimiter, children);
let spanned = Tagged::from_simple_spanned_item(node, (left, right)); let spanned = node.tagged((left, right, delimiter.tag.origin));
TokenNode::Delimited(spanned) TokenNode::Delimited(spanned)
} }
fn path(head: TokenNode, tail: Vec<Token>, left: usize, right: usize) -> TokenNode { fn path(head: TokenNode, tail: Vec<Token>, left: usize, right: usize) -> TokenNode {
let tag = head.tag();
let node = PathNode::new( let node = PathNode::new(
Box::new(head), Box::new(head),
tail.into_iter().map(TokenNode::Token).collect(), tail.into_iter().map(TokenNode::Token).collect(),
); );
let spanned = Tagged::from_simple_spanned_item(node, (left, right)); let spanned = node.tagged((left, right, tag.origin));
TokenNode::Path(spanned) TokenNode::Path(spanned)
} }
fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode {
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_simple_spanned_item(token, (left, right))) TokenNode::Token(token.tagged((left, right, uuid::Uuid::nil())))
} }
fn build<T>(block: CurriedNode<T>) -> T { fn build<T>(block: CurriedNode<T>) -> T {
let mut builder = TokenTreeBuilder::new(); let mut builder = TokenTreeBuilder::new(uuid::Uuid::nil());
block(&mut builder) block(&mut builder)
} }
fn build_token(block: CurriedToken) -> TokenNode { fn build_token(block: CurriedToken) -> TokenNode {
TokenTreeBuilder::build(block).0 TokenTreeBuilder::build(uuid::Uuid::nil(), block).0
}
fn test_uuid() -> uuid::Uuid {
uuid::Uuid::nil()
} }
} }

View file

@ -1,6 +1,6 @@
use crate::parser::CallNode; use crate::parser::CallNode;
use crate::traits::ToDebug; use crate::traits::ToDebug;
use crate::{Span, Tagged}; use crate::{Tag, Tagged};
use derive_new::new; use derive_new::new;
use getset::Getters; use getset::Getters;
use std::fmt; use std::fmt;
@ -8,7 +8,7 @@ use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
pub struct Pipeline { pub struct Pipeline {
pub(crate) parts: Vec<PipelineElement>, pub(crate) parts: Vec<PipelineElement>,
pub(crate) post_ws: Option<Span>, pub(crate) post_ws: Option<Tag>,
} }
impl ToDebug for Pipeline { impl ToDebug for Pipeline {
@ -27,11 +27,11 @@ impl ToDebug for Pipeline {
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)] #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
pub struct PipelineElement { pub struct PipelineElement {
pub pipe: Option<Span>, pub pipe: Option<Tag>,
pub pre_ws: Option<Span>, pub pre_ws: Option<Tag>,
#[get = "pub(crate)"] #[get = "pub(crate)"]
call: Tagged<CallNode>, call: Tagged<CallNode>,
pub post_ws: Option<Span>, pub post_ws: Option<Tag>,
} }
impl ToDebug for PipelineElement { impl ToDebug for PipelineElement {

View file

@ -1,7 +1,7 @@
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*}; use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*};
use crate::traits::ToDebug; use crate::traits::ToDebug;
use crate::{Span, Tagged, Text}; use crate::{Tag, Tagged, Text};
use derive_new::new; use derive_new::new;
use enum_utils::FromStr; use enum_utils::FromStr;
use getset::Getters; use getset::Getters;
@ -16,8 +16,8 @@ pub enum TokenNode {
Pipeline(Tagged<Pipeline>), Pipeline(Tagged<Pipeline>),
Operator(Tagged<Operator>), Operator(Tagged<Operator>),
Flag(Tagged<Flag>), Flag(Tagged<Flag>),
Member(Span), Member(Tag),
Whitespace(Span), Whitespace(Tag),
Error(Tagged<Box<ShellError>>), Error(Tagged<Box<ShellError>>),
Path(Tagged<PathNode>), Path(Tagged<PathNode>),
@ -78,31 +78,31 @@ impl fmt::Debug for DebugTokenNode<'_> {
) )
} }
TokenNode::Pipeline(pipeline) => write!(f, "{}", pipeline.debug(self.source)), TokenNode::Pipeline(pipeline) => write!(f, "{}", pipeline.debug(self.source)),
TokenNode::Error(s) => write!(f, "<error> for {:?}", s.span().slice(self.source)), TokenNode::Error(s) => write!(f, "<error> for {:?}", s.tag().slice(self.source)),
rest => write!(f, "{}", rest.span().slice(self.source)), rest => write!(f, "{}", rest.tag().slice(self.source)),
} }
} }
} }
impl From<&TokenNode> for Span { impl From<&TokenNode> for Tag {
fn from(token: &TokenNode) -> Span { fn from(token: &TokenNode) -> Tag {
token.span() token.tag()
} }
} }
impl TokenNode { impl TokenNode {
pub fn span(&self) -> Span { pub fn tag(&self) -> Tag {
match self { match self {
TokenNode::Token(t) => t.span(), TokenNode::Token(t) => t.tag(),
TokenNode::Call(s) => s.span(), TokenNode::Call(s) => s.tag(),
TokenNode::Delimited(s) => s.span(), TokenNode::Delimited(s) => s.tag(),
TokenNode::Pipeline(s) => s.span(), TokenNode::Pipeline(s) => s.tag(),
TokenNode::Operator(s) => s.span(), TokenNode::Operator(s) => s.tag(),
TokenNode::Flag(s) => s.span(), TokenNode::Flag(s) => s.tag(),
TokenNode::Member(s) => *s, TokenNode::Member(s) => *s,
TokenNode::Whitespace(s) => *s, TokenNode::Whitespace(s) => *s,
TokenNode::Error(s) => s.span(), TokenNode::Error(s) => s.tag(),
TokenNode::Path(s) => s.span(), TokenNode::Path(s) => s.tag(),
} }
} }
@ -127,11 +127,11 @@ impl TokenNode {
} }
pub fn as_external_arg(&self, source: &Text) -> String { pub fn as_external_arg(&self, source: &Text) -> String {
self.span().slice(source).to_string() self.tag().slice(source).to_string()
} }
pub fn source<'a>(&self, source: &'a Text) -> &'a str { pub fn source<'a>(&self, source: &'a Text) -> &'a str {
self.span().slice(source) self.tag().slice(source)
} }
pub fn is_bare(&self) -> bool { pub fn is_bare(&self) -> bool {
@ -154,12 +154,12 @@ impl TokenNode {
} }
} }
pub fn expect_external(&self) -> Span { pub fn expect_external(&self) -> Tag {
match self { match self {
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::ExternalCommand(span), item: RawToken::ExternalCommand(tag),
.. ..
}) => *span, }) => *tag,
_ => panic!("Only call expect_external if you checked is_external first"), _ => panic!("Only call expect_external if you checked is_external first"),
} }
} }

View file

@ -7,8 +7,8 @@ use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, Token
use crate::parser::parse::tokens::{RawNumber, RawToken}; use crate::parser::parse::tokens::{RawNumber, RawToken};
use crate::parser::parse::unit::Unit; use crate::parser::parse::unit::Unit;
use crate::parser::CallNode; use crate::parser::CallNode;
use crate::Span;
use derive_new::new; use derive_new::new;
use uuid::Uuid;
#[derive(new)] #[derive(new)]
pub struct TokenTreeBuilder { pub struct TokenTreeBuilder {
@ -17,14 +17,16 @@ pub struct TokenTreeBuilder {
#[new(default)] #[new(default)]
output: String, output: String,
origin: Uuid,
} }
pub type CurriedToken = Box<dyn FnOnce(&mut TokenTreeBuilder) -> TokenNode + 'static>; pub type CurriedToken = Box<dyn FnOnce(&mut TokenTreeBuilder) -> TokenNode + 'static>;
pub type CurriedCall = Box<dyn FnOnce(&mut TokenTreeBuilder) -> Tagged<CallNode> + 'static>; pub type CurriedCall = Box<dyn FnOnce(&mut TokenTreeBuilder) -> Tagged<CallNode> + 'static>;
impl TokenTreeBuilder { impl TokenTreeBuilder {
pub fn build(block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) { pub fn build(origin: Uuid, block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) {
let mut builder = TokenTreeBuilder::new(); let mut builder = TokenTreeBuilder::new(origin);
let node = block(&mut builder); let node = block(&mut builder);
(node, builder.output) (node, builder.output)
} }
@ -52,50 +54,37 @@ impl TokenTreeBuilder {
.expect("A pipeline must contain at least one element"); .expect("A pipeline must contain at least one element");
let pipe = None; let pipe = None;
let pre_span = pre.map(|pre| b.consume(&pre)); let pre_tag = pre.map(|pre| b.consume_tag(&pre));
let call = call(b); let call = call(b);
let post_span = post.map(|post| b.consume(&post)); let post_tag = post.map(|post| b.consume_tag(&post));
out.push(PipelineElement::new( out.push(PipelineElement::new(pipe, pre_tag, call, post_tag));
pipe,
pre_span.map(Span::from),
call,
post_span.map(Span::from),
));
loop { loop {
match input.next() { match input.next() {
None => break, None => break,
Some((pre, call, post)) => { Some((pre, call, post)) => {
let pipe = Some(Span::from(b.consume("|"))); let pipe = Some(b.consume_tag("|"));
let pre_span = pre.map(|pre| b.consume(&pre)); let pre_span = pre.map(|pre| b.consume_tag(&pre));
let call = call(b); let call = call(b);
let post_span = post.map(|post| b.consume(&post)); let post_span = post.map(|post| b.consume_tag(&post));
out.push(PipelineElement::new( out.push(PipelineElement::new(pipe, pre_span, call, post_span));
pipe,
pre_span.map(Span::from),
call,
post_span.map(Span::from),
));
} }
} }
} }
let end = b.pos; let end = b.pos;
TokenTreeBuilder::spanned_pipeline((out, None), (start, end)) TokenTreeBuilder::tagged_pipeline((out, None), (start, end, b.origin))
}) })
} }
pub fn spanned_pipeline( pub fn tagged_pipeline(
input: (Vec<PipelineElement>, Option<Span>), input: (Vec<PipelineElement>, Option<Tag>),
span: impl Into<Span>, tag: impl Into<Tag>,
) -> TokenNode { ) -> TokenNode {
TokenNode::Pipeline(Tagged::from_simple_spanned_item( TokenNode::Pipeline(Pipeline::new(input.0, input.1.into()).tagged(tag.into()))
Pipeline::new(input.0, input.1.into()),
span,
))
} }
pub fn op(input: impl Into<Operator>) -> CurriedToken { pub fn op(input: impl Into<Operator>) -> CurriedToken {
@ -106,12 +95,12 @@ impl TokenTreeBuilder {
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_op(input, (start, end)) TokenTreeBuilder::tagged_op(input, (start, end, b.origin))
}) })
} }
pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode { pub fn tagged_op(input: impl Into<Operator>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Operator(Tagged::from_simple_spanned_item(input.into(), span.into())) TokenNode::Operator(input.into().tagged(tag.into()))
} }
pub fn string(input: impl Into<String>) -> CurriedToken { pub fn string(input: impl Into<String>) -> CurriedToken {
@ -123,15 +112,15 @@ impl TokenTreeBuilder {
let (_, end) = b.consume("\""); let (_, end) = b.consume("\"");
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_string((inner_start, inner_end), (start, end)) TokenTreeBuilder::tagged_string(
(inner_start, inner_end, b.origin),
(start, end, b.origin),
)
}) })
} }
pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn tagged_string(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::String(input.into()).tagged(tag.into()))
RawToken::String(input.into()),
span.into(),
))
} }
pub fn bare(input: impl Into<String>) -> CurriedToken { pub fn bare(input: impl Into<String>) -> CurriedToken {
@ -141,15 +130,12 @@ impl TokenTreeBuilder {
let (start, end) = b.consume(&input); let (start, end) = b.consume(&input);
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_bare((start, end)) TokenTreeBuilder::tagged_bare((start, end, b.origin))
}) })
} }
pub fn spanned_bare(input: impl Into<Span>) -> TokenNode { pub fn tagged_bare(tag: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::Bare.tagged(tag.into()))
RawToken::Bare,
input.into(),
))
} }
pub fn pattern(input: impl Into<String>) -> CurriedToken { pub fn pattern(input: impl Into<String>) -> CurriedToken {
@ -159,15 +145,12 @@ impl TokenTreeBuilder {
let (start, end) = b.consume(&input); let (start, end) = b.consume(&input);
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_pattern((start, end)) TokenTreeBuilder::tagged_pattern((start, end, b.origin))
}) })
} }
pub fn spanned_pattern(input: impl Into<Span>) -> TokenNode { pub fn tagged_pattern(input: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::GlobPattern.tagged(input.into()))
RawToken::Bare,
input.into(),
))
} }
pub fn external_word(input: impl Into<String>) -> CurriedToken { pub fn external_word(input: impl Into<String>) -> CurriedToken {
@ -177,22 +160,16 @@ impl TokenTreeBuilder {
let (start, end) = b.consume(&input); let (start, end) = b.consume(&input);
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_external_word((start, end)) TokenTreeBuilder::tagged_external_word((start, end, b.origin))
}) })
} }
pub fn spanned_external_word(input: impl Into<Span>) -> TokenNode { pub fn tagged_external_word(input: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::ExternalWord.tagged(input.into()))
RawToken::ExternalWord,
input.into(),
))
} }
pub fn spanned_external(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn tagged_external(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::ExternalCommand(input.into()).tagged(tag.into()))
RawToken::ExternalCommand(input.into()),
span.into(),
))
} }
pub fn int(input: impl Into<BigInt>) -> CurriedToken { pub fn int(input: impl Into<BigInt>) -> CurriedToken {
@ -202,7 +179,10 @@ impl TokenTreeBuilder {
let (start, end) = b.consume(&int.to_string()); let (start, end) = b.consume(&int.to_string());
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_number(RawNumber::Int((start, end).into()), (start, end)) TokenTreeBuilder::tagged_number(
RawNumber::Int((start, end, b.origin).into()),
(start, end, b.origin),
)
}) })
} }
@ -213,15 +193,15 @@ impl TokenTreeBuilder {
let (start, end) = b.consume(&decimal.to_string()); let (start, end) = b.consume(&decimal.to_string());
b.pos = end; b.pos = end;
TokenTreeBuilder::spanned_number(RawNumber::Decimal((start, end).into()), (start, end)) TokenTreeBuilder::tagged_number(
RawNumber::Decimal((start, end, b.origin).into()),
(start, end, b.origin),
)
}) })
} }
pub fn spanned_number(input: impl Into<RawNumber>, span: impl Into<Span>) -> TokenNode { pub fn tagged_number(input: impl Into<RawNumber>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::Number(input.into()).tagged(tag.into()))
RawToken::Number(input.into()),
span.into(),
))
} }
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken { pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
@ -233,23 +213,20 @@ impl TokenTreeBuilder {
let (_, end_unit) = b.consume(unit.as_str()); let (_, end_unit) = b.consume(unit.as_str());
b.pos = end_unit; b.pos = end_unit;
TokenTreeBuilder::spanned_size( TokenTreeBuilder::tagged_size(
(RawNumber::Int((start_int, end_int).into()), unit), (RawNumber::Int((start_int, end_int, b.origin).into()), unit),
(start_int, end_unit), (start_int, end_unit, b.origin),
) )
}) })
} }
pub fn spanned_size( pub fn tagged_size(
input: (impl Into<RawNumber>, impl Into<Unit>), input: (impl Into<RawNumber>, impl Into<Unit>),
span: impl Into<Span>, tag: impl Into<Tag>,
) -> TokenNode { ) -> TokenNode {
let (int, unit) = (input.0.into(), input.1.into()); let (int, unit) = (input.0.into(), input.1.into());
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::Size(int, unit).tagged(tag.into()))
RawToken::Size(int, unit),
span,
))
} }
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken { pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
@ -267,15 +244,12 @@ impl TokenTreeBuilder {
let end = b.pos; let end = b.pos;
TokenTreeBuilder::spanned_path((head, output), (start, end)) TokenTreeBuilder::tagged_path((head, output), (start, end, b.origin))
}) })
} }
pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode { pub fn tagged_path(input: (TokenNode, Vec<TokenNode>), tag: impl Into<Tag>) -> TokenNode {
TokenNode::Path(Tagged::from_simple_spanned_item( TokenNode::Path(PathNode::new(Box::new(input.0), input.1).tagged(tag.into()))
PathNode::new(Box::new(input.0), input.1),
span,
))
} }
pub fn var(input: impl Into<String>) -> CurriedToken { pub fn var(input: impl Into<String>) -> CurriedToken {
@ -285,15 +259,12 @@ impl TokenTreeBuilder {
let (start, _) = b.consume("$"); let (start, _) = b.consume("$");
let (inner_start, end) = b.consume(&input); let (inner_start, end) = b.consume(&input);
TokenTreeBuilder::spanned_var((inner_start, end), (start, end)) TokenTreeBuilder::tagged_var((inner_start, end, b.origin), (start, end, b.origin))
}) })
} }
pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn tagged_var(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Token(Tagged::from_simple_spanned_item( TokenNode::Token(RawToken::Variable(input.into()).tagged(tag.into()))
RawToken::Variable(input.into()),
span.into(),
))
} }
pub fn flag(input: impl Into<String>) -> CurriedToken { pub fn flag(input: impl Into<String>) -> CurriedToken {
@ -303,15 +274,12 @@ impl TokenTreeBuilder {
let (start, _) = b.consume("--"); let (start, _) = b.consume("--");
let (inner_start, end) = b.consume(&input); let (inner_start, end) = b.consume(&input);
TokenTreeBuilder::spanned_flag((inner_start, end), (start, end)) TokenTreeBuilder::tagged_flag((inner_start, end, b.origin), (start, end, b.origin))
}) })
} }
pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn tagged_flag(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Flag(Tagged::from_simple_spanned_item( TokenNode::Flag(Flag::new(FlagKind::Longhand, input.into()).tagged(tag.into()))
Flag::new(FlagKind::Longhand, input.into()),
span.into(),
))
} }
pub fn shorthand(input: impl Into<String>) -> CurriedToken { pub fn shorthand(input: impl Into<String>) -> CurriedToken {
@ -321,15 +289,12 @@ impl TokenTreeBuilder {
let (start, _) = b.consume("-"); let (start, _) = b.consume("-");
let (inner_start, end) = b.consume(&input); let (inner_start, end) = b.consume(&input);
TokenTreeBuilder::spanned_shorthand((inner_start, end), (start, end)) TokenTreeBuilder::tagged_shorthand((inner_start, end, b.origin), (start, end, b.origin))
}) })
} }
pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode { pub fn tagged_shorthand(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Flag(Tagged::from_simple_spanned_item( TokenNode::Flag(Flag::new(FlagKind::Shorthand, input.into()).tagged(tag.into()))
Flag::new(FlagKind::Shorthand, input.into()),
span.into(),
))
} }
pub fn member(input: impl Into<String>) -> CurriedToken { pub fn member(input: impl Into<String>) -> CurriedToken {
@ -337,12 +302,12 @@ impl TokenTreeBuilder {
Box::new(move |b| { Box::new(move |b| {
let (start, end) = b.consume(&input); let (start, end) = b.consume(&input);
TokenTreeBuilder::spanned_member((start, end)) TokenTreeBuilder::tagged_member((start, end, b.origin))
}) })
} }
pub fn spanned_member(span: impl Into<Span>) -> TokenNode { pub fn tagged_member(tag: impl Into<Tag>) -> TokenNode {
TokenNode::Member(span.into()) TokenNode::Member(tag.into())
} }
pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall { pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall {
@ -358,11 +323,11 @@ impl TokenTreeBuilder {
let end = b.pos; let end = b.pos;
TokenTreeBuilder::spanned_call(nodes, (start, end)) TokenTreeBuilder::tagged_call(nodes, (start, end, b.origin))
}) })
} }
pub fn spanned_call(input: Vec<TokenNode>, span: impl Into<Span>) -> Tagged<CallNode> { pub fn tagged_call(input: Vec<TokenNode>, tag: impl Into<Tag>) -> Tagged<CallNode> {
if input.len() == 0 { if input.len() == 0 {
panic!("BUG: spanned call (TODO)") panic!("BUG: spanned call (TODO)")
} }
@ -372,7 +337,7 @@ impl TokenTreeBuilder {
let head = input.next().unwrap(); let head = input.next().unwrap();
let tail = input.collect(); let tail = input.collect();
Tagged::from_simple_spanned_item(CallNode::new(Box::new(head), tail), span) CallNode::new(Box::new(head), tail).tagged(tag.into())
} }
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken { pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
@ -385,15 +350,12 @@ impl TokenTreeBuilder {
let (_, end) = b.consume(")"); let (_, end) = b.consume(")");
TokenTreeBuilder::spanned_parens(output, (start, end)) TokenTreeBuilder::tagged_parens(output, (start, end, b.origin))
}) })
} }
pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn tagged_parens(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Delimited(Tagged::from_simple_spanned_item( TokenNode::Delimited(DelimitedNode::new(Delimiter::Paren, input.into()).tagged(tag.into()))
DelimitedNode::new(Delimiter::Paren, input.into()),
span,
))
} }
pub fn square(input: Vec<CurriedToken>) -> CurriedToken { pub fn square(input: Vec<CurriedToken>) -> CurriedToken {
@ -406,15 +368,12 @@ impl TokenTreeBuilder {
let (_, end) = b.consume("]"); let (_, end) = b.consume("]");
TokenTreeBuilder::spanned_square(output, (start, end)) TokenTreeBuilder::tagged_square(output, (start, end, b.origin))
}) })
} }
pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn tagged_square(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Delimited(Tagged::from_simple_spanned_item( TokenNode::Delimited(DelimitedNode::new(Delimiter::Square, input.into()).tagged(tag.into()))
DelimitedNode::new(Delimiter::Square, input.into()),
span,
))
} }
pub fn braced(input: Vec<CurriedToken>) -> CurriedToken { pub fn braced(input: Vec<CurriedToken>) -> CurriedToken {
@ -427,21 +386,18 @@ impl TokenTreeBuilder {
let (_, end) = b.consume(" }"); let (_, end) = b.consume(" }");
TokenTreeBuilder::spanned_brace(output, (start, end)) TokenTreeBuilder::tagged_brace(output, (start, end, b.origin))
}) })
} }
pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode { pub fn tagged_brace(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
TokenNode::Delimited(Tagged::from_simple_spanned_item( TokenNode::Delimited(DelimitedNode::new(Delimiter::Brace, input.into()).tagged(tag.into()))
DelimitedNode::new(Delimiter::Brace, input.into()),
span,
))
} }
pub fn sp() -> CurriedToken { pub fn sp() -> CurriedToken {
Box::new(|b| { Box::new(|b| {
let (start, end) = b.consume(" "); let (start, end) = b.consume(" ");
TokenNode::Whitespace(Span::from((start, end))) TokenNode::Whitespace(Tag::from((start, end, b.origin)))
}) })
} }
@ -450,14 +406,12 @@ impl TokenTreeBuilder {
Box::new(move |b| { Box::new(move |b| {
let (start, end) = b.consume(&input); let (start, end) = b.consume(&input);
TokenTreeBuilder::spanned_ws((start, end)) TokenTreeBuilder::tagged_ws((start, end, b.origin))
}) })
} }
pub fn spanned_ws(span: impl Into<Span>) -> TokenNode { pub fn tagged_ws(tag: impl Into<Tag>) -> TokenNode {
let span = span.into(); TokenNode::Whitespace(tag.into())
TokenNode::Whitespace(span.into())
} }
fn consume(&mut self, input: &str) -> (usize, usize) { fn consume(&mut self, input: &str) -> (usize, usize) {
@ -466,4 +420,11 @@ impl TokenTreeBuilder {
self.output.push_str(input); self.output.push_str(input);
(start, self.pos) (start, self.pos)
} }
fn consume_tag(&mut self, input: &str) -> Tag {
let start = self.pos;
self.pos += input.len();
self.output.push_str(input);
(start, self.pos, self.origin).into()
}
} }

View file

@ -1,6 +1,6 @@
use crate::parser::parse::unit::*; use crate::parser::parse::unit::*;
use crate::prelude::*; use crate::prelude::*;
use crate::{Span, Tagged, Text}; use crate::{Tagged, Text};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
@ -8,9 +8,9 @@ use std::str::FromStr;
pub enum RawToken { pub enum RawToken {
Number(RawNumber), Number(RawNumber),
Size(RawNumber, Unit), Size(RawNumber, Unit),
String(Span), String(Tag),
Variable(Span), Variable(Tag),
ExternalCommand(Span), ExternalCommand(Tag),
ExternalWord, ExternalWord,
GlobPattern, GlobPattern,
Bare, Bare,
@ -18,28 +18,28 @@ pub enum RawToken {
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum RawNumber { pub enum RawNumber {
Int(Span), Int(Tag),
Decimal(Span), Decimal(Tag),
} }
impl RawNumber { impl RawNumber {
pub fn int(span: impl Into<Span>) -> Tagged<RawNumber> { pub fn int(tag: impl Into<Tag>) -> Tagged<RawNumber> {
let span = span.into(); let tag = tag.into();
RawNumber::Int(span).tagged(span) RawNumber::Int(tag).tagged(tag)
} }
pub fn decimal(span: impl Into<Span>) -> Tagged<RawNumber> { pub fn decimal(tag: impl Into<Tag>) -> Tagged<RawNumber> {
let span = span.into(); let tag = tag.into();
RawNumber::Decimal(span).tagged(span) RawNumber::Decimal(tag).tagged(tag)
} }
pub(crate) fn to_number(self, source: &Text) -> Number { pub(crate) fn to_number(self, source: &Text) -> Number {
match self { match self {
RawNumber::Int(span) => Number::Int(BigInt::from_str(span.slice(source)).unwrap()), RawNumber::Int(tag) => Number::Int(BigInt::from_str(tag.slice(source)).unwrap()),
RawNumber::Decimal(span) => { RawNumber::Decimal(tag) => {
Number::Decimal(BigDecimal::from_str(span.slice(source)).unwrap()) Number::Decimal(BigDecimal::from_str(tag.slice(source)).unwrap())
} }
} }
} }
@ -78,6 +78,6 @@ pub struct DebugToken<'a> {
impl fmt::Debug for DebugToken<'_> { impl fmt::Debug for DebugToken<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.node.span().slice(self.source)) write!(f, "{}", self.node.tag().slice(self.source))
} }
} }

View file

@ -7,7 +7,7 @@ use crate::parser::{
Flag, RawToken, TokenNode, Flag, RawToken, TokenNode,
}; };
use crate::traits::ToDebug; use crate::traits::ToDebug;
use crate::{Span, Tag, Tagged, Text}; use crate::{Tag, Tagged, TaggedItem, Text};
use log::trace; use log::trace;
pub fn parse_command( pub fn parse_command(
@ -33,7 +33,7 @@ pub fn parse_command(
.collect() .collect()
}); });
match parse_command_tail(&config, context, children, source, call.span())? { match parse_command_tail(&config, context, children, source, call.tag())? {
None => Ok(hir::Call::new(Box::new(head), None, None)), None => Ok(hir::Call::new(Box::new(head), None, None)),
Some((positional, named)) => Ok(hir::Call::new(Box::new(head), positional, named)), Some((positional, named)) => Ok(hir::Call::new(Box::new(head), positional, named)),
} }
@ -49,12 +49,9 @@ fn parse_command_head(head: &TokenNode) -> Result<hir::Expression, ShellError> {
) => Ok(spanned.map(|_| hir::RawExpression::Literal(hir::Literal::Bare))), ) => Ok(spanned.map(|_| hir::RawExpression::Literal(hir::Literal::Bare))),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::String(inner_span), item: RawToken::String(inner_tag),
tag: Tag { span, origin: None }, tag,
}) => Ok(Tagged::from_simple_spanned_item( }) => Ok(hir::RawExpression::Literal(hir::Literal::String(*inner_tag)).tagged(*tag)),
hir::RawExpression::Literal(hir::Literal::String(*inner_span)),
*span,
)),
other => Err(ShellError::unexpected(&format!( other => Err(ShellError::unexpected(&format!(
"command head -> {:?}", "command head -> {:?}",
@ -68,7 +65,7 @@ fn parse_command_tail(
context: &Context, context: &Context,
tail: Option<Vec<TokenNode>>, tail: Option<Vec<TokenNode>>,
source: &Text, source: &Text,
command_span: Span, command_tag: Tag,
) -> Result<Option<(Option<Vec<hir::Expression>>, Option<NamedArguments>)>, ShellError> { ) -> Result<Option<(Option<Vec<hir::Expression>>, Option<NamedArguments>)>, ShellError> {
let tail = &mut match &tail { let tail = &mut match &tail {
None => hir::TokensIterator::new(&[]), None => hir::TokensIterator::new(&[]),
@ -89,7 +86,7 @@ fn parse_command_tail(
named.insert_switch(name, flag); named.insert_switch(name, flag);
} }
NamedType::Mandatory(syntax_type) => { NamedType::Mandatory(syntax_type) => {
match extract_mandatory(config, name, tail, source, command_span) { match extract_mandatory(config, name, tail, source, command_tag) {
Err(err) => return Err(err), // produce a correct diagnostic Err(err) => return Err(err), // produce a correct diagnostic
Ok((pos, flag)) => { Ok((pos, flag)) => {
tail.move_to(pos); tail.move_to(pos);
@ -98,7 +95,7 @@ fn parse_command_tail(
return Err(ShellError::argument_error( return Err(ShellError::argument_error(
config.name.clone(), config.name.clone(),
ArgumentError::MissingValueForName(name.to_string()), ArgumentError::MissingValueForName(name.to_string()),
flag.span(), flag.tag(),
)); ));
} }
@ -119,7 +116,7 @@ fn parse_command_tail(
return Err(ShellError::argument_error( return Err(ShellError::argument_error(
config.name.clone(), config.name.clone(),
ArgumentError::MissingValueForName(name.to_string()), ArgumentError::MissingValueForName(name.to_string()),
flag.span(), flag.tag(),
)); ));
} }
@ -150,7 +147,7 @@ fn parse_command_tail(
return Err(ShellError::argument_error( return Err(ShellError::argument_error(
config.name.clone(), config.name.clone(),
ArgumentError::MissingMandatoryPositional(arg.name().to_string()), ArgumentError::MissingMandatoryPositional(arg.name().to_string()),
command_span, command_tag,
)); ));
} }
} }
@ -208,7 +205,7 @@ fn extract_mandatory(
name: &str, name: &str,
tokens: &mut hir::TokensIterator<'_>, tokens: &mut hir::TokensIterator<'_>,
source: &Text, source: &Text,
span: Span, tag: Tag,
) -> Result<(usize, Tagged<Flag>), ShellError> { ) -> Result<(usize, Tagged<Flag>), ShellError> {
let flag = tokens.extract(|t| t.as_flag(name, source)); let flag = tokens.extract(|t| t.as_flag(name, source));
@ -216,7 +213,7 @@ fn extract_mandatory(
None => Err(ShellError::argument_error( None => Err(ShellError::argument_error(
config.name.clone(), config.name.clone(),
ArgumentError::MissingMandatoryFlag(name.to_string()), ArgumentError::MissingMandatoryFlag(name.to_string()),
span, tag,
)), )),
Some((pos, flag)) => { Some((pos, flag)) => {

View file

@ -1,7 +1,7 @@
// TODO: Temporary redirect // TODO: Temporary redirect
pub(crate) use crate::context::CommandRegistry; pub(crate) use crate::context::CommandRegistry;
use crate::evaluate::{evaluate_baseline_expr, Scope}; use crate::evaluate::{evaluate_baseline_expr, Scope};
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode}; use crate::parser::{hir, hir::SyntaxShape, parse_command, CallNode};
use crate::prelude::*; use crate::prelude::*;
use derive_new::new; use derive_new::new;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -12,35 +12,35 @@ use std::fmt;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub enum NamedType { pub enum NamedType {
Switch, Switch,
Mandatory(SyntaxType), Mandatory(SyntaxShape),
Optional(SyntaxType), Optional(SyntaxShape),
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PositionalType { pub enum PositionalType {
Mandatory(String, SyntaxType), Mandatory(String, SyntaxShape),
Optional(String, SyntaxType), Optional(String, SyntaxShape),
} }
impl PositionalType { impl PositionalType {
pub fn mandatory(name: &str, ty: SyntaxType) -> PositionalType { pub fn mandatory(name: &str, ty: SyntaxShape) -> PositionalType {
PositionalType::Mandatory(name.to_string(), ty) PositionalType::Mandatory(name.to_string(), ty)
} }
pub fn mandatory_any(name: &str) -> PositionalType { pub fn mandatory_any(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Any) PositionalType::Mandatory(name.to_string(), SyntaxShape::Any)
} }
pub fn mandatory_block(name: &str) -> PositionalType { pub fn mandatory_block(name: &str) -> PositionalType {
PositionalType::Mandatory(name.to_string(), SyntaxType::Block) PositionalType::Mandatory(name.to_string(), SyntaxShape::Block)
} }
pub fn optional(name: &str, ty: SyntaxType) -> PositionalType { pub fn optional(name: &str, ty: SyntaxShape) -> PositionalType {
PositionalType::Optional(name.to_string(), ty) PositionalType::Optional(name.to_string(), ty)
} }
pub fn optional_any(name: &str) -> PositionalType { pub fn optional_any(name: &str) -> PositionalType {
PositionalType::Optional(name.to_string(), SyntaxType::Any) PositionalType::Optional(name.to_string(), SyntaxShape::Any)
} }
pub(crate) fn name(&self) -> &str { pub(crate) fn name(&self) -> &str {
@ -50,7 +50,7 @@ impl PositionalType {
} }
} }
pub(crate) fn syntax_type(&self) -> SyntaxType { pub(crate) fn syntax_type(&self) -> SyntaxShape {
match *self { match *self {
PositionalType::Mandatory(_, t) => t, PositionalType::Mandatory(_, t) => t,
PositionalType::Optional(_, t) => t, PositionalType::Optional(_, t) => t,
@ -66,7 +66,7 @@ pub struct Signature {
#[new(default)] #[new(default)]
pub positional: Vec<PositionalType>, pub positional: Vec<PositionalType>,
#[new(value = "None")] #[new(value = "None")]
pub rest_positional: Option<SyntaxType>, pub rest_positional: Option<SyntaxShape>,
#[new(default)] #[new(default)]
pub named: IndexMap<String, NamedType>, pub named: IndexMap<String, NamedType>,
#[new(value = "false")] #[new(value = "false")]
@ -83,21 +83,21 @@ impl Signature {
self self
} }
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature { pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
self.positional self.positional
.push(PositionalType::Mandatory(name.into(), ty.into())); .push(PositionalType::Mandatory(name.into(), ty.into()));
self self
} }
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature { pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
self.positional self.positional
.push(PositionalType::Optional(name.into(), ty.into())); .push(PositionalType::Optional(name.into(), ty.into()));
self self
} }
pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature { pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
self.named self.named
.insert(name.into(), NamedType::Optional(ty.into())); .insert(name.into(), NamedType::Optional(ty.into()));
@ -107,7 +107,7 @@ impl Signature {
pub fn required_named( pub fn required_named(
mut self, mut self,
name: impl Into<String>, name: impl Into<String>,
ty: impl Into<SyntaxType>, ty: impl Into<SyntaxShape>,
) -> Signature { ) -> Signature {
self.named self.named
.insert(name.into(), NamedType::Mandatory(ty.into())); .insert(name.into(), NamedType::Mandatory(ty.into()));
@ -126,7 +126,7 @@ impl Signature {
self self
} }
pub fn rest(mut self, ty: SyntaxType) -> Signature { pub fn rest(mut self, ty: SyntaxShape) -> Signature {
self.rest_positional = Some(ty); self.rest_positional = Some(ty);
self self
} }
@ -312,10 +312,10 @@ pub(crate) 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(tag) => {
results.insert( results.insert(
name.clone(), name.clone(),
Tagged::from_simple_spanned_item(Value::boolean(true), *span), Value::boolean(true).tagged(*tag),
); );
} }
hir::named::NamedValue::Value(expr) => { hir::named::NamedValue::Value(expr) => {

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tagged, Value, SyntaxShape, Tagged, Value,
}; };
struct Add { struct Add {
@ -44,9 +44,9 @@ impl Plugin for Add {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("add") Ok(Signature::build("add")
.desc("Add a new field to the table.") .desc("Add a new field to the table.")
.required("Field", SyntaxType::String) .required("Field", SyntaxShape::String)
.required("Value", SyntaxType::String) .required("Value", SyntaxShape::String)
.rest(SyntaxType::String) .rest(SyntaxShape::String)
.filter()) .filter())
} }

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tagged, Value, SyntaxShape, Tagged, Value,
}; };
struct Edit { struct Edit {
@ -43,8 +43,8 @@ impl Plugin for Edit {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("edit") Ok(Signature::build("edit")
.desc("Edit an existing column to have a new value.") .desc("Edit an existing column to have a new value.")
.required("Field", SyntaxType::String) .required("Field", SyntaxShape::String)
.required("Value", SyntaxType::String) .required("Value", SyntaxShape::String)
.filter()) .filter())
} }

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tag, Tagged, TaggedDictBuilder, Value, SyntaxShape, Tag, Tagged, TaggedDictBuilder, Value,
}; };
struct Embed { struct Embed {
@ -37,8 +37,8 @@ impl Plugin for Embed {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("embed") Ok(Signature::build("embed")
.desc("Embeds a new field to the table.") .desc("Embeds a new field to the table.")
.required("Field", SyntaxType::String) .required("Field", SyntaxShape::String)
.rest(SyntaxType::String) .rest(SyntaxShape::String)
.filter()) .filter())
} }

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tagged, TaggedItem, Value, SyntaxShape, Tagged, TaggedItem, Value,
}; };
enum Action { enum Action {
@ -120,7 +120,7 @@ impl Plugin for Inc {
.switch("major") .switch("major")
.switch("minor") .switch("minor")
.switch("patch") .switch("patch")
.rest(SyntaxType::String) .rest(SyntaxShape::String)
.filter()) .filter())
} }
@ -181,18 +181,20 @@ mod tests {
use super::{Inc, SemVerAction}; use super::{Inc, SemVerAction};
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Tag, Tagged, TaggedDictBuilder,
TaggedDictBuilder, TaggedItem, Value, TaggedItem, Value,
}; };
struct CallStub { struct CallStub {
origin: uuid::Uuid,
positionals: Vec<Tagged<Value>>, positionals: Vec<Tagged<Value>>,
flags: IndexMap<String, Tagged<Value>>, flags: IndexMap<String, Tagged<Value>>,
} }
impl CallStub { impl CallStub {
fn new() -> CallStub { fn new(origin: uuid::Uuid) -> CallStub {
CallStub { CallStub {
origin,
positionals: vec![], positionals: vec![],
flags: indexmap::IndexMap::new(), flags: indexmap::IndexMap::new(),
} }
@ -201,14 +203,14 @@ 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).simple_spanned(Span::unknown()), Value::boolean(true).tagged(Tag::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()).simple_spanned(Span::unknown())); .push(Value::string(name.to_string()).tagged(Tag::unknown_span(self.origin)));
self self
} }
@ -216,7 +218,7 @@ mod tests {
CallInfo { CallInfo {
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())), args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
source_map: SourceMap::new(), source_map: SourceMap::new(),
name_span: Span::unknown(), name_tag: Tag::unknown_span(self.origin),
} }
} }
} }
@ -243,7 +245,7 @@ mod tests {
let mut plugin = Inc::new(); let mut plugin = Inc::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("major").create()) .begin_filter(CallStub::new(test_uuid()).with_long_flag("major").create())
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -253,7 +255,7 @@ mod tests {
let mut plugin = Inc::new(); let mut plugin = Inc::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("minor").create()) .begin_filter(CallStub::new(test_uuid()).with_long_flag("minor").create())
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -263,7 +265,7 @@ mod tests {
let mut plugin = Inc::new(); let mut plugin = Inc::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_long_flag("patch").create()) .begin_filter(CallStub::new(test_uuid()).with_long_flag("patch").create())
.is_ok()); .is_ok());
assert!(plugin.action.is_some()); assert!(plugin.action.is_some());
} }
@ -274,7 +276,7 @@ mod tests {
assert!(plugin assert!(plugin
.begin_filter( .begin_filter(
CallStub::new() CallStub::new(test_uuid())
.with_long_flag("major") .with_long_flag("major")
.with_long_flag("minor") .with_long_flag("minor")
.create(), .create(),
@ -288,7 +290,11 @@ mod tests {
let mut plugin = Inc::new(); let mut plugin = Inc::new();
assert!(plugin assert!(plugin
.begin_filter(CallStub::new().with_parameter("package.version").create()) .begin_filter(
CallStub::new(test_uuid())
.with_parameter("package.version")
.create()
)
.is_ok()); .is_ok());
assert_eq!(plugin.field, Some("package.version".to_string())); assert_eq!(plugin.field, Some("package.version".to_string()));
@ -321,7 +327,7 @@ mod tests {
assert!(plugin assert!(plugin
.begin_filter( .begin_filter(
CallStub::new() CallStub::new(test_uuid())
.with_long_flag("major") .with_long_flag("major")
.with_parameter("version") .with_parameter("version")
.create() .create()
@ -349,7 +355,7 @@ mod tests {
assert!(plugin assert!(plugin
.begin_filter( .begin_filter(
CallStub::new() CallStub::new(test_uuid())
.with_long_flag("minor") .with_long_flag("minor")
.with_parameter("version") .with_parameter("version")
.create() .create()
@ -378,7 +384,7 @@ mod tests {
assert!(plugin assert!(plugin
.begin_filter( .begin_filter(
CallStub::new() CallStub::new(test_uuid())
.with_long_flag("patch") .with_long_flag("patch")
.with_parameter(&field) .with_parameter(&field)
.create() .create()
@ -399,4 +405,8 @@ mod tests {
_ => {} _ => {}
} }
} }
fn test_uuid() -> uuid::Uuid {
uuid::Uuid::nil()
}
} }

View file

@ -40,7 +40,7 @@ async fn ps(tag: Tag) -> Vec<Tagged<Value>> {
let mut output = vec![]; let mut output = vec![];
while let Some(res) = processes.next().await { while let Some(res) = processes.next().await {
if let Ok((process, usage)) = res { if let Ok((process, usage)) = res {
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(tag.span)); let mut dict = TaggedDictBuilder::new(tag);
dict.insert("pid", Value::int(process.pid())); dict.insert("pid", Value::int(process.pid()));
if let Ok(name) = process.name().await { if let Ok(name) = process.name().await {
dict.insert("name", Value::string(name)); dict.insert("name", Value::string(name));
@ -64,7 +64,7 @@ impl Plugin for Ps {
} }
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(ps(Tag::unknown_origin(callinfo.name_span))) Ok(block_on(ps(Tag::unknown_origin(callinfo.name_tag)))
.into_iter() .into_iter()
.map(ReturnSuccess::value) .map(ReturnSuccess::value)
.collect()) .collect())

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
Signature, SyntaxType, Tagged, TaggedItem, Value, Signature, SyntaxShape, Tagged, TaggedItem, Value,
}; };
struct Skip { struct Skip {
@ -15,9 +15,9 @@ impl Skip {
impl Plugin for Skip { impl Plugin for Skip {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("skip") Ok(Signature::build("skip")
.desc("Skip a number of rows") .desc("Skip a number of rows")
.rest(SyntaxType::Number) .rest(SyntaxShape::Number)
.filter()) .filter())
} }
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> { fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
@ -34,7 +34,7 @@ impl Plugin for Skip {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Unrecognized type in params", "Unrecognized type in params",
"expected an integer", "expected an integer",
arg.span(), arg.tag(),
)) ))
} }
} }

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tagged, Value, SyntaxShape, Tagged, Value,
}; };
use regex::Regex; use regex::Regex;
@ -174,7 +174,7 @@ impl Plugin for Str {
.switch("to-int") .switch("to-int")
.switch("replace") .switch("replace")
.switch("find-replace") .switch("find-replace")
.rest(SyntaxType::Member) .rest(SyntaxShape::Member)
.filter()) .filter())
} }
@ -261,7 +261,7 @@ mod tests {
use super::{Action, ReplaceAction, Str}; use super::{Action, ReplaceAction, Str};
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Span, Tag, Tagged, CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Tag, Tagged,
TaggedDictBuilder, TaggedItem, Value, TaggedDictBuilder, TaggedItem, Value,
}; };
use num_bigint::BigInt; use num_bigint::BigInt;
@ -277,6 +277,7 @@ mod tests {
} }
struct CallStub { struct CallStub {
origin: uuid::Uuid,
positionals: Vec<Tagged<Value>>, positionals: Vec<Tagged<Value>>,
flags: IndexMap<String, Tagged<Value>>, flags: IndexMap<String, Tagged<Value>>,
} }
@ -284,6 +285,7 @@ mod tests {
impl CallStub { impl CallStub {
fn new() -> CallStub { fn new() -> CallStub {
CallStub { CallStub {
origin: uuid::Uuid::nil(),
positionals: vec![], positionals: vec![],
flags: indexmap::IndexMap::new(), flags: indexmap::IndexMap::new(),
} }
@ -292,14 +294,14 @@ 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).simple_spanned(Span::unknown()), Value::boolean(true).tagged(Tag::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()).simple_spanned(Span::unknown())); .push(Value::string(name.to_string()).tagged(Tag::unknown()));
self self
} }
@ -307,7 +309,7 @@ mod tests {
CallInfo { CallInfo {
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())), args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
source_map: SourceMap::new(), source_map: SourceMap::new(),
name_span: Span::unknown(), name_tag: Tag::unknown_span(self.origin),
} }
} }
} }

View file

@ -1,6 +1,6 @@
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
Tag, Tagged, Value, Tagged, TaggedItem, Value,
}; };
struct Sum { struct Sum {
@ -18,11 +18,10 @@ 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,
}) => { }) => {
//TODO: handle overflow //TODO: handle overflow
self.total = self.total = Some(Value::int(i + j).tagged(*tag));
Some(Tagged::from_simple_spanned_item(Value::int(i + j), span));
Ok(()) Ok(())
} }
None => { None => {
@ -38,11 +37,10 @@ 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,
}) => { }) => {
//TODO: handle overflow //TODO: handle overflow
self.total = self.total = Some(Value::bytes(b + j).tagged(tag));
Some(Tagged::from_simple_spanned_item(Value::bytes(b + j), span));
Ok(()) Ok(())
} }
None => { None => {

View file

@ -315,7 +315,7 @@ 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(Tag::unknown_origin(callinfo.name_span))) Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_tag)))
.into_iter() .into_iter()
.map(ReturnSuccess::value) .map(ReturnSuccess::value)
.collect()) .collect())

View file

@ -62,7 +62,7 @@ pub(crate) use crate::data::{Primitive, Value};
pub(crate) use crate::env::host::handle_unexpected; pub(crate) use crate::env::host::handle_unexpected;
pub(crate) use crate::env::Host; pub(crate) use crate::env::Host;
pub(crate) use crate::errors::{CoerceInto, ShellError}; pub(crate) use crate::errors::{CoerceInto, ShellError};
pub(crate) use crate::parser::hir::SyntaxType; pub(crate) use crate::parser::hir::SyntaxShape;
pub(crate) use crate::parser::parse::parser::Number; pub(crate) use crate::parser::parse::parser::Number;
pub(crate) use crate::parser::registry::Signature; pub(crate) use crate::parser::registry::Signature;
pub(crate) use crate::shell::filesystem_shell::FilesystemShell; pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
@ -70,8 +70,7 @@ pub(crate) use crate::shell::help_shell::HelpShell;
pub(crate) use crate::shell::shell_manager::ShellManager; pub(crate) use crate::shell::shell_manager::ShellManager;
pub(crate) use crate::shell::value_shell::ValueShell; pub(crate) use crate::shell::value_shell::ValueShell;
pub(crate) use crate::stream::{InputStream, OutputStream}; pub(crate) use crate::stream::{InputStream, OutputStream};
pub(crate) use crate::traits::{HasSpan, ToDebug}; pub(crate) use crate::traits::{HasTag, ToDebug};
pub(crate) use crate::Span;
pub(crate) use crate::Text; pub(crate) use crate::Text;
pub(crate) use bigdecimal::BigDecimal; pub(crate) use bigdecimal::BigDecimal;
pub(crate) use futures::stream::BoxStream; pub(crate) use futures::stream::BoxStream;

View file

@ -81,23 +81,27 @@ impl Shell for FilesystemShell {
dirs::home_dir() dirs::home_dir()
} }
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { fn ls(
&self,
pattern: Option<Tagged<PathBuf>>,
command_tag: Tag,
) -> Result<OutputStream, ShellError> {
let cwd = self.path(); let cwd = self.path();
let mut full_path = PathBuf::from(self.path()); let mut full_path = PathBuf::from(self.path());
match &args.nth(0) { match &pattern {
Some(value) => full_path.push(Path::new(&value.as_path()?)), Some(value) => full_path.push((*value).as_ref()),
_ => {} _ => {}
} }
let entries: Vec<_> = match glob::glob(&full_path.to_string_lossy()) { let entries: Vec<_> = match glob::glob(&full_path.to_string_lossy()) {
Ok(files) => files.collect(), Ok(files) => files.collect(),
Err(_) => { Err(_) => {
if let Some(source) = args.nth(0) { if let Some(source) = pattern {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Invalid pattern", "Invalid pattern",
"Invalid pattern", "Invalid pattern",
source.span(), source.tag(),
)); ));
} else { } else {
return Err(ShellError::string("Invalid pattern.")); return Err(ShellError::string("Invalid pattern."));
@ -114,17 +118,17 @@ impl Shell for FilesystemShell {
let entries = std::fs::read_dir(&entry); let entries = std::fs::read_dir(&entry);
let entries = match entries { let entries = match entries {
Err(e) => { Err(e) => {
if let Some(s) = args.nth(0) { if let Some(s) = pattern {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
s.span(), s.tag(),
)); ));
} else { } else {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
args.name_span(), command_tag,
)); ));
} }
} }
@ -138,11 +142,7 @@ impl Shell for FilesystemShell {
} else { } else {
Path::new(&filepath) Path::new(&filepath)
}; };
let value = dir_entry_dict( let value = dir_entry_dict(filename, &entry.metadata()?, command_tag)?;
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());
@ -159,11 +159,7 @@ impl Shell for FilesystemShell {
Path::new(&entry) Path::new(&entry)
}; };
let metadata = std::fs::metadata(&entry)?; let metadata = std::fs::metadata(&entry)?;
let value = dir_entry_dict( let value = dir_entry_dict(filename, &metadata, command_tag)?;
filename,
&metadata,
Tag::unknown_origin(args.call_info.name_span),
)?;
shell_entries.push_back(ReturnSuccess::value(value)) shell_entries.push_back(ReturnSuccess::value(value))
} }
} }
@ -179,7 +175,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::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_tag,
)) ))
} }
}, },
@ -197,7 +193,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Can not change to directory", "Can not change to directory",
"directory not found", "directory not found",
v.span().clone(), v.tag().clone(),
)) ))
} }
} }
@ -207,8 +203,7 @@ impl Shell for FilesystemShell {
let mut stream = VecDeque::new(); let mut stream = VecDeque::new();
stream.push_back( stream.push_back(ReturnSuccess::change_cwd(
ReturnSuccess::change_cwd(
path.to_string_lossy().to_string(), path.to_string_lossy().to_string(),
)); ));
@ -222,10 +217,10 @@ impl Shell for FilesystemShell {
dst, dst,
recursive, recursive,
}: CopyArgs, }: CopyArgs,
name: Span, name: Tag,
path: &str, path: &str,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let mut source = PathBuf::from(path); let mut source = PathBuf::from(path);
let mut destination = PathBuf::from(path); let mut destination = PathBuf::from(path);
@ -280,7 +275,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -296,7 +291,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -332,7 +327,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -346,7 +341,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -360,7 +355,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Copy aborted. Not a valid path", "Copy aborted. Not a valid path",
"Copy aborted. Not a valid path", "Copy aborted. Not a valid path",
name_span, name_tag,
)) ))
} }
} }
@ -370,7 +365,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -406,7 +401,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -420,7 +415,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -453,7 +448,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Copy aborted. Not a valid path", "Copy aborted. Not a valid path",
"Copy aborted. Not a valid path", "Copy aborted. Not a valid path",
name_span, name_tag,
)) ))
} }
} }
@ -480,7 +475,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Copy aborted. Not a valid destination", "Copy aborted. Not a valid destination",
"Copy aborted. Not a valid destination", "Copy aborted. Not a valid destination",
name_span, name_tag,
)) ))
} }
} }
@ -489,7 +484,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("Copy aborted. (Does {:?} exist?)", destination_file_name), format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
format!("Copy aborted. (Does {:?} exist?)", destination_file_name), format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
&dst.span(), dst.tag(),
)); ));
} }
} }
@ -500,7 +495,7 @@ impl Shell for FilesystemShell {
fn mkdir( fn mkdir(
&self, &self,
MkdirArgs { rest: directories }: MkdirArgs, MkdirArgs { rest: directories }: MkdirArgs,
name: Span, name: Tag,
path: &str, path: &str,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let full_path = PathBuf::from(path); let full_path = PathBuf::from(path);
@ -525,7 +520,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
reason.to_string(), reason.to_string(),
reason.to_string(), reason.to_string(),
dir.span(), dir.tag(),
)) ))
} }
Ok(_) => {} Ok(_) => {}
@ -538,10 +533,10 @@ impl Shell for FilesystemShell {
fn mv( fn mv(
&self, &self,
MoveArgs { src, dst }: MoveArgs, MoveArgs { src, dst }: MoveArgs,
name: Span, name: Tag,
path: &str, path: &str,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
let mut source = PathBuf::from(path); let mut source = PathBuf::from(path);
let mut destination = PathBuf::from(path); let mut destination = PathBuf::from(path);
@ -567,7 +562,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Rename aborted. Not a valid destination", "Rename aborted. Not a valid destination",
"Rename aborted. Not a valid destination", "Rename aborted. Not a valid destination",
dst.span(), dst.tag(),
)) ))
} }
} }
@ -581,7 +576,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Rename aborted. Not a valid entry name", "Rename aborted. Not a valid entry name",
"Rename aborted. Not a valid entry name", "Rename aborted. Not a valid entry name",
name_span, name_tag,
)) ))
} }
}; };
@ -593,7 +588,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("Rename aborted. {:}", e.to_string()), format!("Rename aborted. {:}", e.to_string()),
format!("Rename aborted. {:}", e.to_string()), format!("Rename aborted. {:}", e.to_string()),
name_span, name_tag,
)) ))
} }
}; };
@ -617,7 +612,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -640,7 +635,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -662,7 +657,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -715,7 +710,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -739,7 +734,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -762,7 +757,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -794,7 +789,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Rename aborted. Not a valid entry name", "Rename aborted. Not a valid entry name",
"Rename aborted. Not a valid entry name", "Rename aborted. Not a valid entry name",
name_span, name_tag,
)) ))
} }
}; };
@ -818,7 +813,7 @@ impl Shell for FilesystemShell {
destination_file_name, destination_file_name,
e.to_string(), e.to_string(),
), ),
name_span, name_tag,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -830,7 +825,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("Rename aborted. (Does {:?} exist?)", destination_file_name), format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
format!("Rename aborted. (Does {:?} exist?)", destination_file_name), format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
dst.span(), dst.tag(),
)); ));
} }
} }
@ -841,16 +836,16 @@ impl Shell for FilesystemShell {
fn rm( fn rm(
&self, &self,
RemoveArgs { target, recursive }: RemoveArgs, RemoveArgs { target, recursive }: RemoveArgs,
name: Span, name: Tag,
path: &str, path: &str,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let name_span = name; let name_tag = name;
if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") { if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Remove aborted. \".\" or \"..\" may not be removed.", "Remove aborted. \".\" or \"..\" may not be removed.",
"Remove aborted. \".\" or \"..\" may not be removed.", "Remove aborted. \".\" or \"..\" may not be removed.",
target.span(), target.tag(),
)); ));
} }
@ -882,7 +877,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("{:?} is a directory. Try using \"--recursive\".", file), format!("{:?} is a directory. Try using \"--recursive\".", file),
format!("{:?} is a directory. Try using \"--recursive\".", file), format!("{:?} is a directory. Try using \"--recursive\".", file),
target.span(), target.tag(),
)); ));
} }
} }
@ -899,7 +894,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Remove aborted. Not a valid path", "Remove aborted. Not a valid path",
"Remove aborted. Not a valid path", "Remove aborted. Not a valid path",
name_span, name_tag,
)) ))
} }
} }
@ -919,7 +914,7 @@ impl Shell for FilesystemShell {
"Directory {:?} found somewhere inside. Try using \"--recursive\".", "Directory {:?} found somewhere inside. Try using \"--recursive\".",
path_file_name path_file_name
), ),
target.span(), target.tag(),
)); ));
} }
@ -933,7 +928,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!("Remove aborted. {:}", e.to_string()), format!("Remove aborted. {:}", e.to_string()),
format!("Remove aborted. {:}", e.to_string()), format!("Remove aborted. {:}", e.to_string()),
name_span, name_tag,
)) ))
} }
} }
@ -954,7 +949,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"unable to show current directory", "unable to show current directory",
"pwd command failed", "pwd command failed",
args.call_info.name_span, args.call_info.name_tag,
)); ));
} }
}; };
@ -962,7 +957,7 @@ impl Shell for FilesystemShell {
let mut stream = VecDeque::new(); let mut stream = VecDeque::new();
stream.push_back(ReturnSuccess::value( stream.push_back(ReturnSuccess::value(
Value::Primitive(Primitive::String(p.to_string_lossy().to_string())) Value::Primitive(Primitive::String(p.to_string_lossy().to_string()))
.simple_spanned(args.call_info.name_span), .tagged(args.call_info.name_tag),
)); ));
Ok(stream.into()) Ok(stream.into())

View file

@ -126,7 +126,11 @@ impl Shell for HelpShell {
self.path = path.clone(); self.path = path.clone();
} }
fn ls(&self, _args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { fn ls(
&self,
_pattern: Option<Tagged<PathBuf>>,
_command_tag: Tag,
) -> Result<OutputStream, ShellError> {
Ok(self Ok(self
.commands() .commands()
.map(|x| ReturnSuccess::value(x)) .map(|x| ReturnSuccess::value(x))
@ -161,24 +165,19 @@ impl Shell for HelpShell {
Ok(stream.into()) Ok(stream.into())
} }
fn cp(&self, _args: CopyArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn cp(&self, _args: CopyArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty()) Ok(OutputStream::empty())
} }
fn mv(&self, _args: MoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn mv(&self, _args: MoveArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty()) Ok(OutputStream::empty())
} }
fn mkdir( fn mkdir(&self, _args: MkdirArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
&self,
_args: MkdirArgs,
_name: Span,
_path: &str,
) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty()) Ok(OutputStream::empty())
} }
fn rm(&self, _args: RemoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn rm(&self, _args: RemoveArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty()) Ok(OutputStream::empty())
} }

View file

@ -66,7 +66,7 @@ impl Highlighter for Helper {
} }
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
let tokens = crate::parser::pipeline(nom_input(line)); let tokens = crate::parser::pipeline(nom_input(line, uuid::Uuid::nil()));
match tokens { match tokens {
Err(_) => Cow::Borrowed(line), Err(_) => Cow::Borrowed(line),
@ -106,47 +106,47 @@ impl Highlighter for Helper {
fn paint_token_node(token_node: &TokenNode, line: &str) -> String { fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
let styled = match token_node { let styled = match token_node {
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)), TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)), TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.tag().slice(line)),
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)), TokenNode::Flag(..) => Color::Black.bold().paint(token_node.tag().slice(line)),
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.span().slice(line)), TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)), TokenNode::Path(..) => Color::Green.bold().paint(token_node.tag().slice(line)),
TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)), TokenNode::Error(..) => Color::Red.bold().paint(token_node.tag().slice(line)),
TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)), TokenNode::Delimited(..) => Color::White.paint(token_node.tag().slice(line)),
TokenNode::Operator(..) => Color::White.normal().paint(token_node.span().slice(line)), TokenNode::Operator(..) => Color::White.normal().paint(token_node.tag().slice(line)),
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.span().slice(line)), TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::Number(..), item: RawToken::Number(..),
.. ..
}) => Color::Purple.bold().paint(token_node.span().slice(line)), }) => Color::Purple.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::Size(..), item: RawToken::Size(..),
.. ..
}) => Color::Purple.bold().paint(token_node.span().slice(line)), }) => Color::Purple.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::GlobPattern, item: RawToken::GlobPattern,
.. ..
}) => Color::Cyan.normal().paint(token_node.span().slice(line)), }) => Color::Cyan.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::String(..), item: RawToken::String(..),
.. ..
}) => Color::Green.normal().paint(token_node.span().slice(line)), }) => Color::Green.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::Variable(..), item: RawToken::Variable(..),
.. ..
}) => Color::Yellow.bold().paint(token_node.span().slice(line)), }) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::Bare, item: RawToken::Bare,
.. ..
}) => Color::Green.normal().paint(token_node.span().slice(line)), }) => Color::Green.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::ExternalCommand(..), item: RawToken::ExternalCommand(..),
.. ..
}) => Color::Cyan.bold().paint(token_node.span().slice(line)), }) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged { TokenNode::Token(Tagged {
item: RawToken::ExternalWord, item: RawToken::ExternalWord,
.. ..
}) => Color::Black.bold().paint(token_node.span().slice(line)), }) => Color::Black.bold().paint(token_node.tag().slice(line)),
}; };
styled.to_string() styled.to_string()
@ -166,7 +166,7 @@ fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> Str
styled.push_str( styled.push_str(
&Color::Cyan &Color::Cyan
.bold() .bold()
.paint(pipeline_element.call().head().span().slice(line)) .paint(pipeline_element.call().head().tag().slice(line))
.to_string(), .to_string(),
); );

View file

@ -13,12 +13,16 @@ pub trait Shell: std::fmt::Debug {
fn name(&self, source_map: &SourceMap) -> String; fn name(&self, source_map: &SourceMap) -> String;
fn homedir(&self) -> Option<PathBuf>; fn homedir(&self) -> Option<PathBuf>;
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>; fn ls(
&self,
pattern: Option<Tagged<PathBuf>>,
command_tag: Tag,
) -> Result<OutputStream, ShellError>;
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>; fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>; fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
fn mkdir(&self, args: MkdirArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>; fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
fn mv(&self, args: MoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>; fn mv(&self, args: MoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
fn rm(&self, args: RemoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>; fn rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
fn path(&self) -> String; fn path(&self) -> String;
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>; fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn set_path(&mut self, path: String); fn set_path(&mut self, path: String);

View file

@ -115,10 +115,14 @@ impl ShellManager {
env[self.current_shell].homedir() env[self.current_shell].homedir()
} }
pub fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { pub fn ls(
&self,
path: Option<Tagged<PathBuf>>,
command_tag: Tag,
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap(); let env = self.shells.lock().unwrap();
env[self.current_shell].ls(args) env[self.current_shell].ls(path, command_tag)
} }
pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {

View file

@ -87,13 +87,15 @@ impl Shell for ValueShell {
Some(PathBuf::from("/")) Some(PathBuf::from("/"))
} }
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { fn ls(
&self,
target: Option<Tagged<PathBuf>>,
command_name: Tag,
) -> Result<OutputStream, ShellError> {
let mut full_path = PathBuf::from(self.path()); let mut full_path = PathBuf::from(self.path());
let target = args.nth(0); match &target {
Some(value) => full_path.push(value.as_ref()),
match target {
Some(value) => full_path.push(Path::new(&value.as_path()?)),
_ => {} _ => {}
} }
@ -101,18 +103,18 @@ impl Shell for ValueShell {
value_system.walk_decorate(&self.value)?; value_system.walk_decorate(&self.value)?;
if !value_system.exists(&full_path) { if !value_system.exists(&full_path) {
if let Some(target) = target { if let Some(target) = &target {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Can not list entries inside", "Can not list entries inside",
"No such path exists", "No such path exists",
target.span(), target.tag(),
)); ));
} }
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Can not list entries inside", "Can not list entries inside",
"No such path exists", "No such path exists",
args.call_info.name_span, command_name,
)); ));
} }
@ -157,14 +159,14 @@ impl Shell for ValueShell {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Can not change to path inside", "Can not change to path inside",
"No such path exists", "No such path exists",
destination.span(), destination.tag(),
)); ));
} }
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Can not change to path inside", "Can not change to path inside",
"No such path exists", "No such path exists",
args.call_info.name_span, args.call_info.name_tag,
)); ));
} }
@ -173,7 +175,7 @@ impl Shell for ValueShell {
Ok(stream.into()) Ok(stream.into())
} }
fn cp(&self, _args: CopyArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn cp(&self, _args: CopyArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"cp not currently supported on values", "cp not currently supported on values",
"not currently supported", "not currently supported",
@ -181,7 +183,7 @@ impl Shell for ValueShell {
)) ))
} }
fn mv(&self, _args: MoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn mv(&self, _args: MoveArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"mv not currently supported on values", "mv not currently supported on values",
"not currently supported", "not currently supported",
@ -189,7 +191,7 @@ impl Shell for ValueShell {
)) ))
} }
fn mkdir(&self, _args: MkdirArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn mkdir(&self, _args: MkdirArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"mkdir not currently supported on values", "mkdir not currently supported on values",
"not currently supported", "not currently supported",
@ -197,7 +199,7 @@ impl Shell for ValueShell {
)) ))
} }
fn rm(&self, _args: RemoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> { fn rm(&self, _args: RemoveArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"rm not currently supported on values", "rm not currently supported on values",
"not currently supported", "not currently supported",
@ -213,7 +215,7 @@ impl Shell for ValueShell {
let mut stream = VecDeque::new(); let mut stream = VecDeque::new();
stream.push_back(ReturnSuccess::value(Tagged::from_item( stream.push_back(ReturnSuccess::value(Tagged::from_item(
Value::string(self.path()), Value::string(self.path()),
args.call_info.name_span, args.call_info.name_tag,
))); )));
Ok(stream.into()) Ok(stream.into())
} }

View file

@ -12,8 +12,8 @@ impl<T: ToDebug> fmt::Display for Debuggable<'_, T> {
} }
} }
pub trait HasSpan { pub trait HasTag {
fn span(&self) -> Span; fn tag(&self) -> Tag;
} }
pub trait ToDebug: Sized { pub trait ToDebug: Sized {