From 58b7800172fe754818ac21a8a210ea4d7970c5f5 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 10 Sep 2019 20:23:22 -0700 Subject: [PATCH] Migrate most uses of the Span concept to Tag Also migrate mv, rm and commands like that to taking a SyntaxType::Pattern instead of a SyntaxType::Path for their first argument. --- Cargo.lock | 8 +- Cargo.toml | 2 +- src/cli.rs | 25 ++- src/commands/cd.rs | 3 +- src/commands/classified.rs | 31 ++-- src/commands/clip.rs | 2 +- src/commands/command.rs | 30 ++-- src/commands/config.rs | 44 ++--- src/commands/cp.rs | 8 +- src/commands/date.rs | 44 ++--- src/commands/echo.rs | 8 +- src/commands/enter.rs | 6 +- src/commands/fetch.rs | 76 +++----- src/commands/first.rs | 2 +- src/commands/from_bson.rs | 14 +- src/commands/from_csv.rs | 12 +- src/commands/from_ini.rs | 12 +- src/commands/from_json.rs | 18 +- src/commands/from_sqlite.rs | 12 +- src/commands/from_toml.rs | 12 +- src/commands/from_tsv.rs | 12 +- src/commands/from_xml.rs | 12 +- src/commands/from_yaml.rs | 12 +- src/commands/get.rs | 6 +- src/commands/help.rs | 8 +- src/commands/last.rs | 2 +- src/commands/lines.rs | 8 +- src/commands/ls.rs | 17 +- src/commands/mkdir.rs | 2 +- src/commands/mv.rs | 8 +- src/commands/nth.rs | 2 +- src/commands/open.rs | 55 ++---- src/commands/pick.rs | 2 +- src/commands/post.rs | 82 ++++----- src/commands/reject.rs | 2 +- src/commands/rm.rs | 4 +- src/commands/save.rs | 32 ++-- src/commands/shells.rs | 6 +- src/commands/size.rs | 10 +- src/commands/skip_while.rs | 2 +- src/commands/sort_by.rs | 2 +- src/commands/split_column.rs | 14 +- src/commands/split_row.rs | 7 +- src/commands/tags.rs | 4 +- src/commands/to_bson.rs | 32 ++-- src/commands/to_csv.rs | 10 +- src/commands/to_json.rs | 12 +- src/commands/to_sqlite.rs | 6 +- src/commands/to_toml.rs | 12 +- src/commands/to_tsv.rs | 10 +- src/commands/to_yaml.rs | 12 +- src/commands/trim.rs | 4 +- src/commands/version.rs | 8 +- src/commands/where_.rs | 11 +- src/commands/which_.rs | 13 +- src/context.rs | 12 +- src/data/base.rs | 18 +- src/data/config.rs | 12 +- src/data/into.rs | 4 +- src/data/meta.rs | 164 +++++++++++++----- src/errors.rs | 96 +++++----- src/evaluate/evaluator.rs | 53 +++--- src/format/table.rs | 2 +- src/lib.rs | 4 +- src/parser.rs | 4 +- src/parser/deserializer.rs | 6 +- src/parser/hir.rs | 65 +++---- src/parser/hir/baseline_parse.rs | 106 ++++++------ src/parser/hir/baseline_parse_tokens.rs | 161 ++++++++--------- src/parser/hir/external_command.rs | 2 +- src/parser/hir/named.rs | 5 +- src/parser/parse/files.rs | 35 ++-- src/parser/parse/flag.rs | 4 +- src/parser/parse/parser.rs | 157 ++++++++++------- src/parser/parse/pipeline.rs | 10 +- src/parser/parse/token_tree.rs | 44 ++--- src/parser/parse/token_tree_builder.rs | 221 ++++++++++-------------- src/parser/parse/tokens.rs | 32 ++-- src/parser/parse_command.rs | 27 ++- src/parser/registry.rs | 38 ++-- src/plugins/add.rs | 8 +- src/plugins/edit.rs | 6 +- src/plugins/embed.rs | 6 +- src/plugins/inc.rs | 42 +++-- src/plugins/ps.rs | 4 +- src/plugins/skip.rs | 8 +- src/plugins/str.rs | 14 +- src/plugins/sum.rs | 12 +- src/plugins/sys.rs | 2 +- src/prelude.rs | 5 +- src/shell/filesystem_shell.rs | 115 ++++++------ src/shell/help_shell.rs | 19 +- src/shell/helper.rs | 38 ++-- src/shell/shell.rs | 14 +- src/shell/shell_manager.rs | 8 +- src/shell/value_shell.rs | 32 ++-- src/traits.rs | 4 +- 97 files changed, 1174 insertions(+), 1255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08fcb94a0..22af92884 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1474,8 +1474,8 @@ dependencies = [ ] [[package]] -name = "nom5_locate" -version = "0.1.1" +name = "nom_locate" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", "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)", - "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-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)", @@ -3129,7 +3129,7 @@ dependencies = [ "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 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 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" diff --git a/Cargo.toml b/Cargo.toml index f9e13c934..c4369b94b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ ctrlc = "3.1.3" surf = "1.0.2" url = "2.1.0" roxmltree = "0.7.0" -nom5_locate = "0.1.1" +nom_locate = "1.0.0" enum-utils = "0.1.1" unicode-xid = "0.2.0" serde_ini = "0.2.0" diff --git a/src/cli.rs b/src/cli.rs index ec8c7085c..c29617ca9 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -266,7 +266,7 @@ pub async fn cli() -> Result<(), Box> { 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") .map(|s| match s.as_string().unwrap().as_ref() { "vi" => EditMode::Vi, @@ -344,7 +344,7 @@ async fn process_line(readline: Result, ctx: &mut Context Ok(line) if line.trim() == "" => LineResult::Success(line.clone()), Ok(line) => { - let result = match crate::parser::parse(&line) { + let result = match crate::parser::parse(&line, uuid::Uuid::nil()) { Err(err) => { return LineResult::Error(line.clone(), err); } @@ -366,7 +366,7 @@ async fn process_line(readline: Result, ctx: &mut Context .commands .push(ClassifiedCommand::Internal(InternalCommand { command: whole_stream_command(autoview::Autoview), - name_span: Span::unknown(), + name_tag: Tag::unknown(), args: hir::Call::new( Box::new(hir::Expression::synthetic_string("autoview")), None, @@ -486,10 +486,10 @@ fn classify_command( match call { // If the command starts with `^`, treat it as an external command no matter what call if call.head().is_external() => { - let name_span = call.head().expect_external(); - let name = name_span.slice(source); + let name_tag = call.head().expect_external(); + 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 @@ -511,19 +511,19 @@ fn classify_command( Ok(ClassifiedCommand::Internal(InternalCommand { command, - name_span: head.span().clone(), + name_tag: head.tag(), args, })) } // 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. // 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() .filter_map(|i| match i { TokenNode::Whitespace(_) => None, - other => Some(Tagged::from_simple_spanned_item( - other.as_external_arg(source), - other.span(), - )), + other => Some(other.as_external_arg(source).tagged(other.tag())), }) .collect(), None => vec![], @@ -553,7 +550,7 @@ fn external_command( ClassifiedCommand::External(ExternalCommand { name: name.to_string(), - name_span: tag.span, + name_tag: tag, args: arg_list_strings, }) } diff --git a/src/commands/cd.rs b/src/commands/cd.rs index a84e66fce..a3f5a8d89 100644 --- a/src/commands/cd.rs +++ b/src/commands/cd.rs @@ -10,8 +10,7 @@ impl WholeStreamCommand for CD { } fn signature(&self) -> Signature { - Signature::build("cd") - .optional("directory", SyntaxType::Path) + Signature::build("cd").optional("directory", SyntaxShape::Path) } fn usage(&self) -> &str { diff --git a/src/commands/classified.rs b/src/commands/classified.rs index 277a92534..4d15bce12 100644 --- a/src/commands/classified.rs +++ b/src/commands/classified.rs @@ -86,7 +86,7 @@ pub(crate) enum ClassifiedCommand { pub(crate) struct InternalCommand { pub(crate) command: Arc, - pub(crate) name_span: Span, + pub(crate) name_tag: Tag, pub(crate) args: hir::Call, } @@ -108,7 +108,7 @@ impl InternalCommand { let result = context.run_command( self.command, - self.name_span.clone(), + self.name_tag.clone(), context.source_map.clone(), self.args, &source, @@ -133,21 +133,18 @@ impl InternalCommand { match value { Tagged { item: Value::Primitive(Primitive::String(cmd)), - .. + tag, } => { context.shell_manager.insert_at_current(Box::new( HelpShell::for_command( - Tagged::from_simple_spanned_item( - Value::string(cmd), - Span::unknown(), - ), - &context.registry().clone(), + Value::string(cmd).tagged(tag), + &context.registry(), )?, )); } _ => { 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) name: String, - pub(crate) name_span: Span, + pub(crate) name_tag: Tag, pub(crate) args: Vec>, } @@ -208,7 +205,7 @@ impl ExternalCommand { ) -> Result { let stdin = input.stdin; let inputs: Vec> = 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", "inputs = {:?}", inputs); @@ -227,17 +224,17 @@ impl ExternalCommand { for i in &inputs { if i.as_string().is_err() { - let mut span = None; + let mut tag = None; for arg in &self.args { 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( "External $it needs string data", "given row instead of string data", - span, + tag, )); } else { return Err(ShellError::string("Error: $it needs string data")); @@ -314,9 +311,7 @@ impl ExternalCommand { let stdout = popen.stdout.take().unwrap(); let file = futures::io::AllowStdIo::new(stdout); let stream = Framed::new(file, LinesCodec {}); - let stream = stream.map(move |line| { - Tagged::from_simple_spanned_item(Value::string(line.unwrap()), name_span) - }); + let stream = stream.map(move |line| Value::string(line.unwrap()).tagged(name_tag)); Ok(ClassifiedInputStream::from_input_stream( stream.boxed() as BoxStream<'static, Tagged> )) diff --git a/src/commands/clip.rs b/src/commands/clip.rs index 9bf7fa9f3..2ef5bfac1 100644 --- a/src/commands/clip.rs +++ b/src/commands/clip.rs @@ -51,7 +51,7 @@ pub mod clipboard { Ok(OutputStream::from(stream)) } - async fn inner_clip(input: Vec>, name: Span) -> OutputStream { + async fn inner_clip(input: Vec>, name: Tag) -> OutputStream { let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap(); let mut new_copy_data = String::new(); diff --git a/src/commands/command.rs b/src/commands/command.rs index 6be179895..99352a7b1 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -18,7 +18,7 @@ pub struct UnevaluatedCallInfo { pub args: hir::Call, pub source: Text, pub source_map: SourceMap, - pub name_span: Span, + pub name_tag: Tag, } impl ToDebug for UnevaluatedCallInfo { @@ -38,7 +38,7 @@ impl UnevaluatedCallInfo { Ok(CallInfo { args, 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 args: registry::EvaluatedArgs, pub source_map: SourceMap, - pub name_span: Span, + pub name_tag: Tag, } impl CallInfo { @@ -89,7 +89,7 @@ impl CallInfo { args: T::deserialize(&mut deserializer)?, context: RunnablePerItemContext { shell_manager: shell_manager.clone(), - name: self.name_span, + name: self.name_tag, }, callback, }) @@ -158,7 +158,7 @@ impl CommandArgs { let host = self.host.clone(); let args = self.evaluate_once(registry)?; 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); Ok(RunnableArgs { @@ -167,7 +167,7 @@ impl CommandArgs { input, commands: registry.clone(), shell_manager, - name: name_span, + name: name_tag, source_map, host, }, @@ -191,7 +191,7 @@ impl CommandArgs { let host = self.host.clone(); let args = self.evaluate_once(registry)?; 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); Ok(RunnableRawArgs { @@ -200,7 +200,7 @@ impl CommandArgs { input, commands: registry.clone(), shell_manager, - name: name_span, + name: name_tag, source_map, host, }, @@ -212,7 +212,7 @@ impl CommandArgs { pub struct RunnablePerItemContext { pub shell_manager: ShellManager, - pub name: Span, + pub name: Tag, } impl RunnablePerItemContext { @@ -227,7 +227,7 @@ pub struct RunnableContext { pub host: Arc>, pub commands: CommandRegistry, pub source_map: SourceMap, - pub name: Span, + pub name: Tag, } impl RunnableContext { @@ -311,8 +311,8 @@ impl EvaluatedWholeStreamCommandArgs { } } - pub fn name_span(&self) -> Span { - self.args.call_info.name_span + pub fn name_tag(&self) -> Tag { + self.args.call_info.name_tag } pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) { @@ -471,12 +471,6 @@ impl ReturnSuccess { pub fn action(input: CommandAction) -> ReturnValue { 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 { diff --git a/src/commands/config.rs b/src/commands/config.rs index 78f1ad399..c1eae9194 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -1,7 +1,7 @@ use crate::commands::WholeStreamCommand; use crate::data::{config, Value}; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::{self}; use crate::prelude::*; use std::iter::FromIterator; @@ -26,10 +26,10 @@ impl WholeStreamCommand for Config { fn signature(&self) -> Signature { Signature::build("config") - .named("load", SyntaxType::Path) - .named("set", SyntaxType::Any) - .named("get", SyntaxType::Any) - .named("remove", SyntaxType::Any) + .named("load", SyntaxShape::Path) + .named("set", SyntaxShape::Any) + .named("get", SyntaxShape::Any) + .named("remove", SyntaxShape::Any) .switch("clear") .switch("path") } @@ -96,41 +96,21 @@ pub fn config( config::write(&result, &configuration)?; - return Ok(stream![Tagged::from_simple_spanned_item( - Value::Row(result.into()), - value.span() - )] - .from_input_stream()); + return Ok(stream![Value::Row(result.into()).tagged(value.tag())].from_input_stream()); } - if let Tagged { - item: true, - tag: Tag { span, .. }, - } = clear - { + if let Tagged { item: true, tag } = clear { result.clear(); config::write(&result, &configuration)?; - return Ok(stream![Tagged::from_simple_spanned_item( - Value::Row(result.into()), - span - )] - .from_input_stream()); + return Ok(stream![Value::Row(result.into()).tagged(tag)].from_input_stream()); } - if let Tagged { - item: true, - tag: Tag { span, .. }, - } = path - { + if let Tagged { item: true, tag } = path { let path = config::default_path_for(&configuration)?; - return Ok(stream![Tagged::from_simple_spanned_item( - Value::Primitive(Primitive::Path(path)), - span - )] - .from_input_stream()); + return Ok(stream![Value::Primitive(Primitive::Path(path)).tagged(tag)].from_input_stream()); } 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(vec![Value::Row(result.into()).simple_spanned(name)].into()); + return Ok(vec![Value::Row(result.into()).tagged(name)].into()); } diff --git a/src/commands/cp.rs b/src/commands/cp.rs index 491e18b1a..bf20c74ce 100644 --- a/src/commands/cp.rs +++ b/src/commands/cp.rs @@ -1,6 +1,6 @@ use crate::commands::command::RunnablePerItemContext; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::{CommandRegistry, Signature}; use crate::prelude::*; use std::path::PathBuf; @@ -21,9 +21,9 @@ impl PerItemCommand for Cpy { fn signature(&self) -> Signature { Signature::build("cp") - .required("src", SyntaxType::Pattern) - .required("dst", SyntaxType::Path) - .named("file", SyntaxType::Any) + .required("src", SyntaxShape::Pattern) + .required("dst", SyntaxShape::Path) + .named("file", SyntaxShape::Any) .switch("recursive") } diff --git a/src/commands/date.rs b/src/commands/date.rs index 7d3307fe5..6df9e2720 100644 --- a/src/commands/date.rs +++ b/src/commands/date.rs @@ -1,5 +1,5 @@ -use crate::errors::ShellError; use crate::data::{Dictionary, Value}; +use crate::errors::ShellError; use crate::prelude::*; use chrono::{DateTime, Local, Utc}; @@ -33,58 +33,40 @@ impl WholeStreamCommand for Date { } } -pub fn date_to_value(dt: DateTime, span: Span) -> Tagged +pub fn date_to_value(dt: DateTime, tag: Tag) -> Tagged where T::Offset: Display, { let mut indexmap = IndexMap::new(); - indexmap.insert( - "year".to_string(), - Tagged::from_simple_spanned_item(Value::int(dt.year()), span), - ); - indexmap.insert( - "month".to_string(), - 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), - ); + indexmap.insert("year".to_string(), Value::int(dt.year()).tagged(tag)); + indexmap.insert("month".to_string(), Value::int(dt.month()).tagged(tag)); + indexmap.insert("day".to_string(), Value::int(dt.day()).tagged(tag)); + indexmap.insert("hour".to_string(), Value::int(dt.hour()).tagged(tag)); + indexmap.insert("minute".to_string(), Value::int(dt.minute()).tagged(tag)); + indexmap.insert("second".to_string(), Value::int(dt.second()).tagged(tag)); let tz = dt.offset(); indexmap.insert( "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 { let args = args.evaluate_once(registry)?; 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 utc: DateTime = Utc::now(); - date_to_value(utc, span) + date_to_value(utc, tag) } else { let local: DateTime = Local::now(); - date_to_value(local, span) + date_to_value(local, tag) }; date_out.push_back(value); diff --git a/src/commands/echo.rs b/src/commands/echo.rs index f464630de..453041bbc 100644 --- a/src/commands/echo.rs +++ b/src/commands/echo.rs @@ -12,7 +12,7 @@ impl PerItemCommand for Echo { } fn signature(&self) -> Signature { - Signature::build("echo").rest(SyntaxType::Any) + Signature::build("echo").rest(SyntaxShape::Any) } fn usage(&self) -> &str { @@ -35,7 +35,7 @@ fn run( _registry: &CommandRegistry, _raw_args: &RawCommandArgs, ) -> Result { - let name = call_info.name_span; + let name = call_info.name_tag; let mut output = String::new(); @@ -57,7 +57,7 @@ fn run( return Err(ShellError::labeled_error( "Expect a string from pipeline", "not a string-compatible value", - i.span(), + i.tag(), )); } } @@ -65,7 +65,7 @@ fn run( } let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value( - Value::string(output).simple_spanned(name), + Value::string(output).tagged(name), ))]); Ok(stream.to_output_stream()) diff --git a/src/commands/enter.rs b/src/commands/enter.rs index 7b42793e1..4148d03c5 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -14,7 +14,7 @@ impl PerItemCommand for Enter { } fn signature(&self) -> registry::Signature { - Signature::build("enter").required("location", SyntaxType::Block) + Signature::build("enter").required("location", SyntaxShape::Block) } fn usage(&self) -> &str { @@ -70,7 +70,7 @@ impl PerItemCommand for Enter { crate::commands::open::fetch( &full_path, &location_clone, - Span::unknown(), + Tag::unknown(), ) .await.unwrap(); @@ -103,7 +103,7 @@ impl PerItemCommand for Enter { }, source: raw_args.call_info.source, 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( diff --git a/src/commands/fetch.rs b/src/commands/fetch.rs index e87ddf834..07ef0c3e0 100644 --- a/src/commands/fetch.rs +++ b/src/commands/fetch.rs @@ -2,14 +2,13 @@ use crate::commands::UnevaluatedCallInfo; use crate::context::SpanSource; use crate::data::Value; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::Signature; use crate::prelude::*; use mime::Mime; use std::path::PathBuf; use std::str::FromStr; use surf::mime; -use uuid::Uuid; pub struct Fetch; impl PerItemCommand for Fetch { @@ -19,7 +18,7 @@ impl PerItemCommand for Fetch { fn signature(&self) -> Signature { Signature::build(self.name()) - .required("path", SyntaxType::Path) + .required("path", SyntaxShape::Path) .switch("raw") } @@ -52,14 +51,14 @@ fn run( }; let path_buf = path.as_path()?; 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 registry = registry.clone(); let raw_args = raw_args.clone(); 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 { yield Err(e); @@ -99,7 +98,7 @@ fn run( }, source: raw_args.call_info.source, 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]), ®istry); @@ -130,13 +129,13 @@ fn run( pub async fn fetch( location: &str, - span: Span, + tag: Tag, ) -> Result<(Option, Value, Tag, SpanSource), ShellError> { if let Err(_) = url::Url::parse(location) { return Err(ShellError::labeled_error( "Incomplete or incorrect url", "expected a full url", - span, + tag, )); } @@ -152,13 +151,10 @@ pub async fn fetch( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::APPLICATION, mime::JSON) => Ok(( @@ -167,13 +163,10 @@ pub async fn fetch( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::APPLICATION, mime::OCTET_STREAM) => { @@ -181,16 +174,13 @@ pub async fn fetch( ShellError::labeled_error( "Could not load binary file", "could not load", - span, + tag, ) })?; Ok(( None, Value::Binary(buf), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } @@ -200,13 +190,10 @@ pub async fn fetch( ShellError::labeled_error( "Could not load svg from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::IMAGE, image_ty) => { @@ -214,16 +201,13 @@ pub async fn fetch( ShellError::labeled_error( "Could not load image file", "could not load", - span, + tag, ) })?; Ok(( Some(image_ty.to_string()), Value::Binary(buf), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } @@ -233,13 +217,10 @@ pub async fn fetch( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::TEXT, mime::PLAIN) => { @@ -260,23 +241,17 @@ pub async fn fetch( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } (ty, sub_ty) => Ok(( None, Value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), } @@ -284,10 +259,7 @@ pub async fn fetch( None => Ok(( None, Value::string(format!("No content type found")), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), }, @@ -295,7 +267,7 @@ pub async fn fetch( return Err(ShellError::labeled_error( "URL could not be opened", "url not found", - span, + tag, )); } } diff --git a/src/commands/first.rs b/src/commands/first.rs index 6381d5def..77c9a4f69 100644 --- a/src/commands/first.rs +++ b/src/commands/first.rs @@ -17,7 +17,7 @@ impl WholeStreamCommand for First { fn signature(&self) -> Signature { Signature::build("first") - .required("amount", SyntaxType::Literal) + .required("amount", SyntaxShape::Literal) } fn usage(&self) -> &str { diff --git a/src/commands/from_bson.rs b/src/commands/from_bson.rs index e2f5421bd..b39754a19 100644 --- a/src/commands/from_bson.rs +++ b/src/commands/from_bson.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ExpectedRange; use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::errors::ExpectedRange; use crate::prelude::*; use bson::{decode_document, spec::BinarySubtype, Bson}; use std::str::FromStr; @@ -198,7 +198,7 @@ pub fn from_bson_bytes_to_value( fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -208,24 +208,24 @@ fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result - match from_bson_bytes_to_value(vb, span) { + match from_bson_bytes_to_value(vb, tag) { Ok(x) => yield ReturnSuccess::value(x), Err(_) => { yield Err(ShellError::labeled_error_with_secondary( "Could not parse as BSON", "input cannot be parsed as BSON", - span, + tag, "value originates from here", - value_tag.span, + value_tag, )) } } _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "value originates from here", - value_tag.span, + value_tag, )), } diff --git a/src/commands/from_csv.rs b/src/commands/from_csv.rs index c872e7736..68296eb11 100644 --- a/src/commands/from_csv.rs +++ b/src/commands/from_csv.rs @@ -86,7 +86,7 @@ fn from_csv( }: FromCSVArgs, RunnableContext { input, name, .. }: RunnableContext, ) -> Result { - let name_span = name; + let name_tag = name; let stream = async_stream_block! { let values: Vec> = input.values.collect().await; @@ -105,15 +105,15 @@ fn from_csv( _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - name_span, + name_tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -126,9 +126,9 @@ fn from_csv( yield Err(ShellError::labeled_error_with_secondary( "Could not parse as CSV", "input cannot be parsed as CSV", - name_span, + name_tag, "value originates from here", - last_tag.span, + last_tag, )) } , } diff --git a/src/commands/from_ini.rs b/src/commands/from_ini.rs index 0e128a22c..8409cf848 100644 --- a/src/commands/from_ini.rs +++ b/src/commands/from_ini.rs @@ -64,7 +64,7 @@ pub fn from_ini_string_to_value( fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -84,15 +84,15 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -105,9 +105,9 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result Result { - let name_span = name; + let name_tag = name; let stream = async_stream_block! { let values: Vec> = input.values.collect().await; @@ -91,9 +91,9 @@ fn from_json( _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - name_span, + name_tag, "value originates from here", - value_tag.span, + value_tag, )), } @@ -106,7 +106,7 @@ fn from_json( 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) => yield ReturnSuccess::value(x), Err(_) => { @@ -114,15 +114,15 @@ fn from_json( yield Err(ShellError::labeled_error_with_secondary( "Could nnot parse as JSON", "input cannot be parsed as JSON", - name_span, + name_tag, "value originates from here", - last_tag.span)) + last_tag)) } } } } } else { - match from_json_string_to_value(concat_string, name_span) { + match from_json_string_to_value(concat_string, name_tag) { Ok(x) => match x { Tagged { item: Value::Table(list), .. } => { @@ -137,9 +137,9 @@ fn from_json( yield Err(ShellError::labeled_error_with_secondary( "Could not parse as JSON", "input cannot be parsed as JSON", - name_span, + name_tag, "value originates from here", - last_tag.span)) + last_tag)) } } } diff --git a/src/commands/from_sqlite.rs b/src/commands/from_sqlite.rs index c19c4fef1..1b04a59fd 100644 --- a/src/commands/from_sqlite.rs +++ b/src/commands/from_sqlite.rs @@ -128,7 +128,7 @@ pub fn from_sqlite_bytes_to_value( fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -138,7 +138,7 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result - match from_sqlite_bytes_to_value(vb, span) { + match from_sqlite_bytes_to_value(vb, tag) { Ok(x) => match x { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -151,18 +151,18 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "value originates from here", - value_tag.span, + value_tag, )), } diff --git a/src/commands/from_toml.rs b/src/commands/from_toml.rs index c1338cb01..29db38a77 100644 --- a/src/commands/from_toml.rs +++ b/src/commands/from_toml.rs @@ -68,7 +68,7 @@ pub fn from_toml( registry: &CommandRegistry, ) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -88,15 +88,15 @@ pub fn from_toml( _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -109,9 +109,9 @@ pub fn from_toml( yield Err(ShellError::labeled_error_with_secondary( "Could not parse as TOML", "input cannot be parsed as TOML", - span, + tag, "value originates from here", - last_tag.span, + last_tag, )) } , } diff --git a/src/commands/from_tsv.rs b/src/commands/from_tsv.rs index 92696c1aa..66f070a5d 100644 --- a/src/commands/from_tsv.rs +++ b/src/commands/from_tsv.rs @@ -87,7 +87,7 @@ fn from_tsv( }: FromTSVArgs, RunnableContext { input, name, .. }: RunnableContext, ) -> Result { - let name_span = name; + let name_tag = name; let stream = async_stream_block! { let values: Vec> = input.values.collect().await; @@ -106,15 +106,15 @@ fn from_tsv( _ => yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - name_span, + name_tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -127,9 +127,9 @@ fn from_tsv( yield Err(ShellError::labeled_error_with_secondary( "Could not parse as TSV", "input cannot be parsed as TSV", - name_span, + name_tag, "value originates from here", - last_tag.span, + last_tag, )) } , } diff --git a/src/commands/from_xml.rs b/src/commands/from_xml.rs index 2c3f94cdd..f80d428f4 100644 --- a/src/commands/from_xml.rs +++ b/src/commands/from_xml.rs @@ -83,7 +83,7 @@ pub fn from_xml_string_to_value( fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -103,15 +103,15 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -124,9 +124,9 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let stream = async_stream_block! { @@ -117,15 +117,15 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "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 { Tagged { item: Value::Table(list), .. } => { for l in list { @@ -138,9 +138,9 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result Signature { - Signature::build("get").rest(SyntaxType::Member) + Signature::build("get").rest(SyntaxShape::Member) } fn usage(&self) -> &str { @@ -47,7 +47,7 @@ fn get_member(path: &Tagged, obj: &Tagged) -> Result registry::Signature { - Signature::build("help").rest(SyntaxType::Any) + Signature::build("help").rest(SyntaxShape::Any) } fn usage(&self) -> &str { @@ -27,11 +27,11 @@ impl PerItemCommand for Help { _raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - let span = call_info.name_span; + let tag = call_info.name_tag; if call_info.args.len() == 0 { return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - Tagged::from_simple_spanned_item(Value::nothing(), span), + Value::nothing().tagged(tag), )))] .into()); } diff --git a/src/commands/last.rs b/src/commands/last.rs index 1f9cc62a7..fd7a3ecea 100644 --- a/src/commands/last.rs +++ b/src/commands/last.rs @@ -16,7 +16,7 @@ impl WholeStreamCommand for Last { } fn signature(&self) -> Signature { - Signature::build("last").required("amount", SyntaxType::Number) + Signature::build("last").required("amount", SyntaxShape::Number) } fn usage(&self) -> &str { diff --git a/src/commands/lines.rs b/src/commands/lines.rs index 15a467224..d2a9cdffd 100644 --- a/src/commands/lines.rs +++ b/src/commands/lines.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::{Primitive, Value}; +use crate::errors::ShellError; use crate::prelude::*; use log::trace; @@ -32,7 +32,7 @@ impl WholeStreamCommand for Lines { fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let span = args.name_span(); + let tag = args.name_tag(); let input = args.input; let input: InputStream = trace_stream!(target: "nu::trace_stream::lines", "input" = input); @@ -58,9 +58,9 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result>, +} + impl WholeStreamCommand for LS { fn name(&self) -> &str { "ls" } fn signature(&self) -> Signature { - Signature::build("ls").optional("path", SyntaxType::Pattern) + Signature::build("ls").optional("path", SyntaxShape::Pattern) } fn usage(&self) -> &str { @@ -22,12 +28,11 @@ impl WholeStreamCommand for LS { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - ls(args, registry) + args.process(registry, ls)?.run() + // ls(args, registry) } } -fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result { - let shell_manager = args.shell_manager.clone(); - let args = args.evaluate_once(registry)?; - shell_manager.ls(args) +fn ls(LsArgs { path }: LsArgs, context: RunnableContext) -> Result { + context.shell_manager.ls(path, context.name) } diff --git a/src/commands/mkdir.rs b/src/commands/mkdir.rs index 9dec9a314..8bf8a97d4 100644 --- a/src/commands/mkdir.rs +++ b/src/commands/mkdir.rs @@ -17,7 +17,7 @@ impl PerItemCommand for Mkdir { } fn signature(&self) -> Signature { - Signature::build("mkdir").rest(SyntaxType::Path) + Signature::build("mkdir").rest(SyntaxShape::Path) } fn usage(&self) -> &str { diff --git a/src/commands/mv.rs b/src/commands/mv.rs index 130e5996e..2ace1fa05 100644 --- a/src/commands/mv.rs +++ b/src/commands/mv.rs @@ -1,6 +1,6 @@ use crate::commands::command::RunnablePerItemContext; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::{CommandRegistry, Signature}; use crate::prelude::*; use std::path::PathBuf; @@ -20,9 +20,9 @@ impl PerItemCommand for Move { fn signature(&self) -> Signature { Signature::build("mv") - .required("source", SyntaxType::Path) - .required("destination", SyntaxType::Path) - .named("file", SyntaxType::Any) + .required("source", SyntaxShape::Pattern) + .required("destination", SyntaxShape::Path) + .named("file", SyntaxShape::Any) } fn usage(&self) -> &str { diff --git a/src/commands/nth.rs b/src/commands/nth.rs index 98ab6a10a..bf397e1bc 100644 --- a/src/commands/nth.rs +++ b/src/commands/nth.rs @@ -16,7 +16,7 @@ impl WholeStreamCommand for Nth { } fn signature(&self) -> Signature { - Signature::build("nth").required("amount", SyntaxType::Any) + Signature::build("nth").required("amount", SyntaxShape::Any) } fn usage(&self) -> &str { diff --git a/src/commands/open.rs b/src/commands/open.rs index 32a99c6f1..57f035ac6 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -2,11 +2,10 @@ use crate::commands::UnevaluatedCallInfo; use crate::context::SpanSource; use crate::data::Value; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::Signature; use crate::prelude::*; use std::path::{Path, PathBuf}; -use uuid::Uuid; pub struct Open; impl PerItemCommand for Open { @@ -16,7 +15,7 @@ impl PerItemCommand for Open { fn signature(&self) -> Signature { Signature::build(self.name()) - .required("path", SyntaxType::Path) + .required("path", SyntaxShape::Path) .switch("raw") } @@ -53,7 +52,7 @@ fn run( }; let path_buf = path.as_path()?; 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 registry = registry.clone(); let raw_args = raw_args.clone(); @@ -100,7 +99,7 @@ fn run( }, source: raw_args.call_info.source, 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]), ®istry); @@ -132,7 +131,7 @@ fn run( pub async fn fetch( cwd: &PathBuf, location: &str, - span: Span, + tag: Tag, ) -> Result<(Option, Value, Tag, SpanSource), ShellError> { let mut cwd = cwd.clone(); @@ -144,10 +143,7 @@ pub async fn fetch( cwd.extension() .map(|name| name.to_string_lossy().to_string()), Value::string(s), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), Err(_) => { @@ -163,19 +159,13 @@ pub async fn fetch( cwd.extension() .map(|name| name.to_string_lossy().to_string()), Value::string(s), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), Err(_) => Ok(( None, Value::Binary(bytes), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), } @@ -183,10 +173,7 @@ pub async fn fetch( Ok(( None, Value::Binary(bytes), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )) } @@ -201,19 +188,13 @@ pub async fn fetch( cwd.extension() .map(|name| name.to_string_lossy().to_string()), Value::string(s), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), Err(_) => Ok(( None, Value::Binary(bytes), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), } @@ -221,10 +202,7 @@ pub async fn fetch( Ok(( None, Value::Binary(bytes), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )) } @@ -232,10 +210,7 @@ pub async fn fetch( _ => Ok(( None, Value::Binary(bytes), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::File(cwd.to_string_lossy().to_string()), )), } @@ -245,7 +220,7 @@ pub async fn fetch( return Err(ShellError::labeled_error( "File could not be opened", "file not found", - span, + tag, )); } } @@ -253,7 +228,7 @@ pub async fn fetch( return Err(ShellError::labeled_error( "File could not be opened", "file not found", - span, + tag, )); } } diff --git a/src/commands/pick.rs b/src/commands/pick.rs index bc5f8df40..2fe21dbb4 100644 --- a/src/commands/pick.rs +++ b/src/commands/pick.rs @@ -17,7 +17,7 @@ impl WholeStreamCommand for Pick { } fn signature(&self) -> Signature { - Signature::build("pick").rest(SyntaxType::Any) + Signature::build("pick").rest(SyntaxShape::Any) } fn usage(&self) -> &str { diff --git a/src/commands/post.rs b/src/commands/post.rs index 8790c929a..88717a466 100644 --- a/src/commands/post.rs +++ b/src/commands/post.rs @@ -1,8 +1,8 @@ use crate::commands::UnevaluatedCallInfo; use crate::context::SpanSource; -use crate::errors::ShellError; 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::prelude::*; use base64::encode; @@ -10,7 +10,7 @@ use mime::Mime; use std::path::PathBuf; use std::str::FromStr; use surf::mime; -use uuid::Uuid; + pub struct Post; impl PerItemCommand for Post { @@ -20,10 +20,10 @@ impl PerItemCommand for Post { fn signature(&self) -> Signature { Signature::build(self.name()) - .required("path", SyntaxType::Any) - .required("body", SyntaxType::Any) - .named("user", SyntaxType::Any) - .named("password", SyntaxType::Any) + .required("path", SyntaxShape::Any) + .required("body", SyntaxShape::Any) + .named("user", SyntaxShape::Any) + .named("password", SyntaxShape::Any) .switch("raw") } @@ -63,7 +63,7 @@ fn run( file => file.clone(), }; 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 user = call_info.args.get("user").map(|x| x.as_string().unwrap()); let password = call_info @@ -109,7 +109,7 @@ fn run( }, source: raw_args.call_info.source, 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]), ®istry); @@ -143,7 +143,7 @@ pub async fn post( body: &Tagged, user: Option, password: Option, - span: Span, + tag: Tag, registry: &CommandRegistry, raw_args: &RawCommandArgs, ) -> Result<(Option, Value, Tag, SpanSource), ShellError> { @@ -189,7 +189,7 @@ pub async fn post( }, source: raw_args.call_info.source, 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( @@ -211,7 +211,7 @@ pub async fn post( return Err(ShellError::labeled_error( "Save could not successfully save", "unexpected data during save", - span, + *tag, )); } } @@ -227,7 +227,7 @@ pub async fn post( return Err(ShellError::labeled_error( "Could not automatically convert table", "needs manual conversion", - tag.span, + *tag, )); } } @@ -243,13 +243,10 @@ pub async fn post( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::APPLICATION, mime::JSON) => Ok(( @@ -258,13 +255,10 @@ pub async fn post( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::APPLICATION, mime::OCTET_STREAM) => { @@ -272,16 +266,13 @@ pub async fn post( ShellError::labeled_error( "Could not load binary file", "could not load", - span, + tag, ) })?; Ok(( None, Value::Binary(buf), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } @@ -290,16 +281,13 @@ pub async fn post( ShellError::labeled_error( "Could not load image file", "could not load", - span, + tag, ) })?; Ok(( Some(image_ty.to_string()), Value::Binary(buf), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } @@ -309,13 +297,10 @@ pub async fn post( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), (mime::TEXT, mime::PLAIN) => { @@ -336,13 +321,10 @@ pub async fn post( ShellError::labeled_error( "Could not load text from remote url", "could not load", - span, + tag, ) })?), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )) } @@ -352,10 +334,7 @@ pub async fn post( "Not yet supported MIME type: {} {}", ty, sub_ty )), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), } @@ -363,10 +342,7 @@ pub async fn post( None => Ok(( None, Value::string(format!("No content type found")), - Tag { - span, - origin: Some(Uuid::new_v4()), - }, + tag, SpanSource::Url(location.to_string()), )), }, @@ -374,7 +350,7 @@ pub async fn post( return Err(ShellError::labeled_error( "URL could not be opened", "url not found", - span, + tag, )); } } @@ -382,7 +358,7 @@ pub async fn post( Err(ShellError::labeled_error( "Expected a url", "needs a url", - span, + tag, )) } } diff --git a/src/commands/reject.rs b/src/commands/reject.rs index 49dbc4dd3..ea09bd749 100644 --- a/src/commands/reject.rs +++ b/src/commands/reject.rs @@ -16,7 +16,7 @@ impl WholeStreamCommand for Reject { } fn signature(&self) -> Signature { - Signature::build("reject").rest(SyntaxType::Member) + Signature::build("reject").rest(SyntaxShape::Member) } fn usage(&self) -> &str { diff --git a/src/commands/rm.rs b/src/commands/rm.rs index 60bb5c6e4..ac5aeaae7 100644 --- a/src/commands/rm.rs +++ b/src/commands/rm.rs @@ -1,6 +1,6 @@ use crate::commands::command::RunnablePerItemContext; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry::{CommandRegistry, Signature}; use crate::prelude::*; use std::path::PathBuf; @@ -20,7 +20,7 @@ impl PerItemCommand for Remove { fn signature(&self) -> Signature { Signature::build("rm") - .required("path", SyntaxType::Path) + .required("path", SyntaxShape::Pattern) .switch("recursive") } diff --git a/src/commands/save.rs b/src/commands/save.rs index 26bf8cb16..66d9732d6 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; pub struct Save; macro_rules! process_string { - ($input:ident, $name_span:ident) => {{ + ($input:ident, $name_tag:ident) => {{ let mut result_string = String::new(); for res in $input { match res { @@ -21,7 +21,7 @@ macro_rules! process_string { yield core::task::Poll::Ready(Err(ShellError::labeled_error( "Save could not successfully save", "unexpected data during save", - $name_span, + $name_tag, ))); } } @@ -31,7 +31,7 @@ macro_rules! process_string { } macro_rules! process_string_return_success { - ($result_vec:ident, $name_span:ident) => {{ + ($result_vec:ident, $name_tag:ident) => {{ let mut result_string = String::new(); for res in $result_vec { match res { @@ -45,7 +45,7 @@ macro_rules! process_string_return_success { yield core::task::Poll::Ready(Err(ShellError::labeled_error( "Save could not successfully 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 { - ($result_vec:ident, $name_span:ident) => {{ + ($result_vec:ident, $name_tag:ident) => {{ let mut result_binary: Vec = Vec::new(); for res in $result_vec { match res { @@ -71,7 +71,7 @@ macro_rules! process_binary_return_success { yield core::task::Poll::Ready(Err(ShellError::labeled_error( "Save could not successfully save", "unexpected data during binary save", - $name_span, + $name_tag, ))); } } @@ -93,7 +93,7 @@ impl WholeStreamCommand for Save { fn signature(&self) -> Signature { Signature::build("save") - .optional("path", SyntaxType::Path) + .optional("path", SyntaxShape::Path) .switch("raw") } @@ -127,7 +127,7 @@ fn save( raw_args: RawCommandArgs, ) -> Result { let mut full_path = PathBuf::from(shell_manager.path()); - let name_span = name; + let name_tag = name; let source_map = source_map.clone(); let stream = async_stream_block! { @@ -145,7 +145,7 @@ fn save( yield Err(ShellError::labeled_error( "Save requires a filepath", "needs path", - name_span, + name_tag, )); } }, @@ -153,7 +153,7 @@ fn save( yield Err(ShellError::labeled_error( "Save requires a filepath", "needs path", - name_span, + name_tag, )); } } @@ -161,7 +161,7 @@ fn save( yield Err(ShellError::labeled_error( "Save requires a filepath", "needs path", - name_span, + name_tag, )); } } else { @@ -185,21 +185,21 @@ fn save( }, source: raw_args.call_info.source, 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), ®istry); let result_vec: Vec> = result.drain_vec().await; if converter.is_binary() { - process_binary_return_success!(result_vec, name_span) + process_binary_return_success!(result_vec, name_tag) } else { - process_string_return_success!(result_vec, name_span) + process_string_return_success!(result_vec, name_tag) } } else { - process_string!(input, name_span) + process_string!(input, name_tag) } } else { - process_string!(input, name_span) + process_string!(input, name_tag) } } else { Ok(string_from(&input).into_bytes()) diff --git a/src/commands/shells.rs b/src/commands/shells.rs index 856c23e7b..2aee2c856 100644 --- a/src/commands/shells.rs +++ b/src/commands/shells.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::TaggedDictBuilder; +use crate::errors::ShellError; use crate::prelude::*; pub struct Shells; @@ -29,10 +29,10 @@ impl WholeStreamCommand for Shells { fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result { 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() { - let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span)); + let mut dict = TaggedDictBuilder::new(tag); if index == args.shell_manager.current_shell { dict.insert(" ", "X".to_string()); diff --git a/src/commands/size.rs b/src/commands/size.rs index d8383efcf..51f8d22c1 100644 --- a/src/commands/size.rs +++ b/src/commands/size.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::{TaggedDictBuilder, Value}; +use crate::errors::ShellError; use crate::prelude::*; pub struct Size; @@ -29,7 +29,7 @@ impl WholeStreamCommand for Size { fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result { let input = args.input; - let span = args.call_info.name_span; + let tag = args.call_info.name_tag; Ok(input .values .map(move |v| match v.item { @@ -37,9 +37,9 @@ fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", - span, + tag, "value originates from here", - v.span(), + v.tag(), )), }) .to_output_stream()) @@ -71,7 +71,7 @@ fn count(contents: &str, tag: impl Into) -> Tagged { } 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("lines", Value::int(lines)); dict.insert("words", Value::int(words)); diff --git a/src/commands/skip_while.rs b/src/commands/skip_while.rs index 90ba24b99..041caf300 100644 --- a/src/commands/skip_while.rs +++ b/src/commands/skip_while.rs @@ -16,7 +16,7 @@ impl WholeStreamCommand for SkipWhile { fn signature(&self) -> Signature { Signature::build("skip-while") - .required("condition", SyntaxType::Block) + .required("condition", SyntaxShape::Block) .filter() } diff --git a/src/commands/sort_by.rs b/src/commands/sort_by.rs index edce33b96..8058b7889 100644 --- a/src/commands/sort_by.rs +++ b/src/commands/sort_by.rs @@ -15,7 +15,7 @@ impl WholeStreamCommand for SortBy { } fn signature(&self) -> Signature { - Signature::build("sort-by").rest(SyntaxType::String) + Signature::build("sort-by").rest(SyntaxShape::String) } fn usage(&self) -> &str { diff --git a/src/commands/split_column.rs b/src/commands/split_column.rs index 2df02cac1..00e2609f2 100644 --- a/src/commands/split_column.rs +++ b/src/commands/split_column.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::{Primitive, TaggedDictBuilder, Value}; +use crate::errors::ShellError; use crate::prelude::*; use log::trace; @@ -21,9 +21,9 @@ impl WholeStreamCommand for SplitColumn { fn signature(&self) -> Signature { Signature::build("split-column") - .required("separator", SyntaxType::Any) + .required("separator", SyntaxShape::Any) .switch("collapse-empty") - .rest(SyntaxType::Member) + .rest(SyntaxShape::Member) } fn usage(&self) -> &str { @@ -40,7 +40,11 @@ impl WholeStreamCommand for SplitColumn { } fn split_column( - SplitColumnArgs { separator, rest, collapse_empty}: SplitColumnArgs, + SplitColumnArgs { + separator, + rest, + collapse_empty, + }: SplitColumnArgs, RunnableContext { input, name, .. }: RunnableContext, ) -> Result { Ok(input @@ -92,7 +96,7 @@ fn split_column( "requires string input", name, "value originates from here", - v.span(), + v.tag(), )), }) .to_output_stream()) diff --git a/src/commands/split_row.rs b/src/commands/split_row.rs index d4f3824a8..e70e5cfa8 100644 --- a/src/commands/split_row.rs +++ b/src/commands/split_row.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::{Primitive, Value}; +use crate::errors::ShellError; use crate::prelude::*; use log::trace; @@ -17,8 +17,7 @@ impl WholeStreamCommand for SplitRow { } fn signature(&self) -> Signature { - Signature::build("split-row") - .required("separator", SyntaxType::Any) + Signature::build("split-row").required("separator", SyntaxShape::Any) } fn usage(&self) -> &str { @@ -63,7 +62,7 @@ fn split_row( "requires string input", name, "value originates from here", - v.span(), + v.tag(), ))); result } diff --git a/src/commands/tags.rs b/src/commands/tags.rs index 3f112482c..2b45105c2 100644 --- a/src/commands/tags.rs +++ b/src/commands/tags.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::{TaggedDictBuilder, Value}; +use crate::errors::ShellError; use crate::prelude::*; pub struct Tags; @@ -36,7 +36,7 @@ fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result Result { Ok(Bson::Document(doc)) } -fn shell_encode_document( - writer: &mut Vec, - doc: Document, - span: Span, -) -> Result<(), ShellError> { +fn shell_encode_document(writer: &mut Vec, doc: Document, tag: Tag) -> Result<(), ShellError> { match encode_document(writer, &doc) { Err(e) => Err(ShellError::labeled_error( format!("Failed to encode document due to: {:?}", e), "requires BSON-compatible document", - span, + tag, )), _ => Ok(()), } } -fn bson_value_to_bytes(bson: Bson, span: Span) -> Result, ShellError> { +fn bson_value_to_bytes(bson: Bson, tag: Tag) -> Result, ShellError> { let mut out = Vec::new(); match bson { Bson::Array(a) => { for v in a.into_iter() { 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( format!("All top level values must be Documents, got {:?}", v), "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( format!("All top level values must be Documents, got {:?}", bson), "requires BSON-compatible document", - span, + tag, )) } } @@ -236,7 +232,7 @@ fn bson_value_to_bytes(bson: Bson, span: Span) -> Result, ShellError> { fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let name_span = args.name_span(); + let name_tag = args.name_tag(); let stream = async_stream_block! { let input: Vec> = args.input.values.collect().await; @@ -252,23 +248,23 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result { - match bson_value_to_bytes(bson_value, name_span) { + match bson_value_to_bytes(bson_value, name_tag) { 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( - "Expected a table with BSON-compatible structure.span() from pipeline", + "Expected a table with BSON-compatible structure.tag() from pipeline", "requires BSON-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )), } } _ => yield Err(ShellError::labeled_error( "Expected a table with BSON-compatible structure from pipeline", "requires BSON-compatible input", - name_span)) + name_tag)) } } }; diff --git a/src/commands/to_csv.rs b/src/commands/to_csv.rs index 615e49cbf..fd77fdcb6 100644 --- a/src/commands/to_csv.rs +++ b/src/commands/to_csv.rs @@ -134,7 +134,7 @@ fn to_csv( ToCSVArgs { headerless }: ToCSVArgs, RunnableContext { input, name, .. }: RunnableContext, ) -> Result { - let name_span = name; + let name_tag = name; let stream = async_stream_block! { let input: Vec> = input.values.collect().await; @@ -155,15 +155,15 @@ fn to_csv( } else { 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( - "Expected a table with CSV-compatible structure.span() from pipeline", + "Expected a table with CSV-compatible structure.tag() from pipeline", "requires CSV-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )) } } diff --git a/src/commands/to_json.rs b/src/commands/to_json.rs index 35c03af32..c6b5d9c01 100644 --- a/src/commands/to_json.rs +++ b/src/commands/to_json.rs @@ -80,7 +80,7 @@ fn json_list(input: &Vec>) -> Result, Shell fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let name_span = args.name_span(); + let name_tag = args.name_tag(); let stream = async_stream_block! { let input: Vec> = args.input.values.collect().await; @@ -98,21 +98,21 @@ fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result { match serde_json::to_string(&json_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( - "Expected a table with JSON-compatible structure.span() from pipeline", + "Expected a table with JSON-compatible structure.tag() from pipeline", "requires JSON-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )), } } _ => yield Err(ShellError::labeled_error( "Expected a table with JSON-compatible structure from pipeline", "requires JSON-compatible input", - name_span)) + name_tag)) } } }; diff --git a/src/commands/to_sqlite.rs b/src/commands/to_sqlite.rs index 0fd392f34..580dba96b 100644 --- a/src/commands/to_sqlite.rs +++ b/src/commands/to_sqlite.rs @@ -200,7 +200,7 @@ fn sqlite_input_stream_to_bytes( fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let name_span = args.name_span(); + let name_tag = args.name_tag(); let stream = async_stream_block! { let input: Vec> = args.input.values.collect().await; @@ -208,9 +208,9 @@ fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result yield ReturnSuccess::value(out), _ => { 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", - name_span, + name_tag, )) }, } diff --git a/src/commands/to_toml.rs b/src/commands/to_toml.rs index e18e15236..cf8f2b11f 100644 --- a/src/commands/to_toml.rs +++ b/src/commands/to_toml.rs @@ -75,7 +75,7 @@ fn collect_values(input: &Vec>) -> Result, ShellE fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; - let name_span = args.name_span(); + let name_tag = args.name_tag(); let stream = async_stream_block! { let input: Vec> = args.input.values.collect().await; @@ -93,21 +93,21 @@ fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result { match toml::to_string(&toml_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( - "Expected a table with TOML-compatible structure.span() from pipeline", + "Expected a table with TOML-compatible structure.tag() from pipeline", "requires TOML-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )), } } _ => yield Err(ShellError::labeled_error( "Expected a table with TOML-compatible structure from pipeline", "requires TOML-compatible input", - name_span)) + name_tag)) } } }; diff --git a/src/commands/to_tsv.rs b/src/commands/to_tsv.rs index a0cbf1c1b..7bce174d0 100644 --- a/src/commands/to_tsv.rs +++ b/src/commands/to_tsv.rs @@ -133,7 +133,7 @@ fn to_tsv( ToTSVArgs { headerless }: ToTSVArgs, RunnableContext { input, name, .. }: RunnableContext, ) -> Result { - let name_span = name; + let name_tag = name; let stream = async_stream_block! { let input: Vec> = input.values.collect().await; @@ -154,15 +154,15 @@ fn to_tsv( } else { 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( - "Expected a table with TSV-compatible structure.span() from pipeline", + "Expected a table with TSV-compatible structure.tag() from pipeline", "requires TSV-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )) } } diff --git a/src/commands/to_yaml.rs b/src/commands/to_yaml.rs index 915827252..fc4412da0 100644 --- a/src/commands/to_yaml.rs +++ b/src/commands/to_yaml.rs @@ -76,7 +76,7 @@ pub fn value_to_yaml_value(v: &Tagged) -> Result Result { let args = args.evaluate_once(registry)?; - let name_span = args.name_span(); + let name_tag = args.name_tag(); let stream = async_stream_block! { let input: Vec> = args.input.values.collect().await; @@ -94,21 +94,21 @@ fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result { match serde_yaml::to_string(&yaml_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( - "Expected a table with YAML-compatible structure.span() from pipeline", + "Expected a table with YAML-compatible structure.tag() from pipeline", "requires YAML-compatible input", - name_span, + name_tag, "originates from here".to_string(), - value.span(), + value.tag(), )), } } _ => yield Err(ShellError::labeled_error( "Expected a table with YAML-compatible structure from pipeline", "requires YAML-compatible input", - name_span)) + name_tag)) } } }; diff --git a/src/commands/trim.rs b/src/commands/trim.rs index 865f6b50b..11ed02539 100644 --- a/src/commands/trim.rs +++ b/src/commands/trim.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::data::Value; +use crate::errors::ShellError; use crate::prelude::*; pub struct Trim; @@ -34,7 +34,7 @@ fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result Result { 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(); indexmap.insert( "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)) } diff --git a/src/commands/where_.rs b/src/commands/where_.rs index b09c341b4..673c6dda8 100644 --- a/src/commands/where_.rs +++ b/src/commands/where_.rs @@ -1,6 +1,6 @@ use crate::commands::PerItemCommand; use crate::errors::ShellError; -use crate::parser::hir::SyntaxType; +use crate::parser::hir::SyntaxShape; use crate::parser::registry; use crate::prelude::*; @@ -12,8 +12,7 @@ impl PerItemCommand for Where { } fn signature(&self) -> registry::Signature { - Signature::build("where") - .required("condition", SyntaxType::Block) + Signature::build("where").required("condition", SyntaxShape::Block) } fn usage(&self) -> &str { @@ -43,16 +42,14 @@ impl PerItemCommand for Where { VecDeque::new() } } - Err(e) => { - return Err(e) - } + Err(e) => return Err(e), } } Tagged { tag, .. } => { return Err(ShellError::labeled_error( "Expected a condition", "where needs a condition", - tag.span, + *tag, )) } }; diff --git a/src/commands/which_.rs b/src/commands/which_.rs index 06c93f63f..905515848 100644 --- a/src/commands/which_.rs +++ b/src/commands/which_.rs @@ -1,5 +1,5 @@ -use crate::errors::ShellError; use crate::data::Value; +use crate::errors::ShellError; use crate::prelude::*; use crate::commands::WholeStreamCommand; @@ -13,8 +13,7 @@ impl WholeStreamCommand for Which { } fn signature(&self) -> Signature { - Signature::build("which") - .required("name", SyntaxType::Any) + Signature::build("which").required("name", SyntaxShape::Any) } fn usage(&self) -> &str { @@ -34,7 +33,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result 0 { @@ -53,7 +52,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result Result( &mut self, command: Arc, - name_span: Span, + name_tag: Tag, source_map: SourceMap, args: hir::Call, source: &Text, input: InputStream, ) -> 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()) } @@ -135,13 +135,13 @@ impl Context { args: hir::Call, source: &Text, source_map: SourceMap, - name_span: Span, + name_tag: Tag, ) -> UnevaluatedCallInfo { UnevaluatedCallInfo { args, source: source.clone(), source_map, - name_span, + name_tag, } } @@ -151,12 +151,12 @@ impl Context { input: InputStream, source: &Text, source_map: SourceMap, - name_span: Span, + name_tag: Tag, ) -> CommandArgs { CommandArgs { host: self.host.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, } } diff --git a/src/data/base.rs b/src/data/base.rs index aa491ebdc..fdd5542dc 100644 --- a/src/data/base.rs +++ b/src/data/base.rs @@ -145,7 +145,7 @@ pub struct Operation { pub struct Block { pub(crate) expressions: Vec, pub(crate) source: Text, - pub(crate) span: Span, + pub(crate) tag: Tag, } impl Block { @@ -153,7 +153,7 @@ impl Block { let scope = Scope::new(value.clone()); if self.expressions.len() == 0 { - return Ok(Value::nothing().simple_spanned(self.span)); + return Ok(Value::nothing().tagged(self.tag)); } let mut last = None; @@ -247,7 +247,7 @@ impl std::convert::TryFrom<&Tagged> for Block { Value::Block(block) => Ok(block.clone()), v => Err(ShellError::type_error( "Block", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), } } @@ -263,7 +263,7 @@ impl std::convert::TryFrom<&Tagged> for i64 { } v => Err(ShellError::type_error( "Integer", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), } } @@ -277,7 +277,7 @@ impl std::convert::TryFrom<&Tagged> for String { Value::Primitive(Primitive::String(s)) => Ok(s.clone()), v => Err(ShellError::type_error( "String", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), } } @@ -291,7 +291,7 @@ impl std::convert::TryFrom<&Tagged> for Vec { Value::Binary(b) => Ok(b.clone()), v => Err(ShellError::type_error( "Binary", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), } } @@ -305,7 +305,7 @@ impl<'a> std::convert::TryFrom<&'a Tagged> for &'a crate::data::Dictionar Value::Row(d) => Ok(d), v => Err(ShellError::type_error( "Dictionary", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), } } @@ -327,7 +327,7 @@ impl std::convert::TryFrom>> for Switch { Value::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present), v => Err(ShellError::type_error( "Boolean", - value.copy_span(v.type_name()), + value.copy_tag(v.type_name()), )), }, } @@ -639,7 +639,7 @@ impl Tagged { Value::Primitive(Primitive::Path(path)) => Ok(path.clone()), other => Err(ShellError::type_error( "Path", - other.type_name().tagged(self.span()), + other.type_name().tagged(self.tag()), )), } } diff --git a/src/data/config.rs b/src/data/config.rs index 08296c09a..6b4d1383f 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -50,7 +50,7 @@ pub fn default_path_for(file: &Option) -> Result { } pub fn read( - span: impl Into, + tag: impl Into, at: &Option, ) -> Result>, ShellError> { let filename = default_path()?; @@ -64,15 +64,15 @@ pub fn read( trace!("config file = {}", filename.display()); - let span = span.into(); + let tag = tag.into(); 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)))?; let parsed: toml::Value = toml::from_str(&contents) .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(); match value.item { Value::Row(Dictionary { entries }) => Ok(entries), @@ -83,8 +83,8 @@ pub fn read( } } -pub(crate) fn config(span: impl Into) -> Result>, ShellError> { - read(span, &None) +pub(crate) fn config(tag: impl Into) -> Result>, ShellError> { + read(tag, &None) } pub fn write( diff --git a/src/data/into.rs b/src/data/into.rs index 749ab0601..3d764fa0c 100644 --- a/src/data/into.rs +++ b/src/data/into.rs @@ -15,8 +15,8 @@ impl From for Value { impl> Tagged { pub fn into_tagged_value(self) -> Tagged { - let value_span = self.span(); + let value_tag = self.tag(); let value = self.item.into(); - value.simple_spanned(value_span) + value.tagged(value_tag) } } diff --git a/src/data/meta.rs b/src/data/meta.rs index f1d2b6713..d472a8add 100644 --- a/src/data/meta.rs +++ b/src/data/meta.rs @@ -5,6 +5,7 @@ use derive_new::new; use getset::Getters; use serde::Deserialize; use serde::Serialize; +use std::path::{Path, PathBuf}; use uuid::Uuid; #[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)] @@ -13,9 +14,15 @@ pub struct Tagged { pub item: T, } -impl HasSpan for Tagged { - fn span(&self) -> Span { - self.tag.span +impl HasTag for Tagged { + fn tag(&self) -> Tag { + self.tag + } +} + +impl AsRef for Tagged { + fn as_ref(&self) -> &Path { + self.item.as_ref() } } @@ -24,10 +31,6 @@ pub trait TaggedItem: Sized { Tagged::from_item(self, tag.into()) } - fn simple_spanned(self, span: impl Into) -> Tagged { - 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 // 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. @@ -53,14 +56,8 @@ impl std::ops::Deref for Tagged { } impl Tagged { - pub fn spanned(self, span: impl Into) -> Tagged { - Tagged::from_item( - self.item, - Tag { - span: span.into(), - origin: None, - }, - ) + pub fn with_tag(self, tag: impl Into) -> Tagged { + Tagged::from_item(self.item, tag) } pub fn from_item(item: T, tag: impl Into) -> Tagged { @@ -70,41 +67,26 @@ impl Tagged { } } - pub fn from_simple_spanned_item(item: T, span: impl Into) -> Tagged { - Tagged::from_item( - item, - Tag { - span: span.into(), - origin: None, - }, - ) - } - pub fn map(self, input: impl FnOnce(T) -> U) -> Tagged { let tag = self.tag(); let mapped = input(self.item); - Tagged::from_item(mapped, tag.clone()) + Tagged::from_item(mapped, tag) } - pub(crate) fn copy_span(&self, output: U) -> Tagged { - let span = self.span(); - - Tagged::from_simple_spanned_item(output, span) + pub(crate) fn copy_tag(&self, output: U) -> Tagged { + Tagged::from_item(output, self.tag()) } pub fn source(&self, source: &Text) -> Text { - Text::from(self.span().slice(source)) - } - - pub fn span(&self) -> Span { - self.tag.span + Text::from(self.tag().slice(source)) } pub fn tag(&self) -> Tag { self.tag } + // TODO: This should not be optional pub fn origin(&self) -> Option { self.tag.origin } @@ -126,20 +108,14 @@ impl Tagged { } } -impl From<&Tagged> for Span { - fn from(input: &Tagged) -> Span { - input.span() - } -} - -impl From<&Span> for Span { - fn from(input: &Span) -> Span { +impl From<&Tag> for Tag { + fn from(input: &Tag) -> Tag { *input } } -impl From> for Span { - fn from(input: nom5_locate::LocatedSpan<&str>) -> Span { +impl From> for Span { + fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Span { Span { start: input.offset, end: input.offset + input.fragment.len(), @@ -147,8 +123,18 @@ impl From> for Span { } } -impl From<(nom5_locate::LocatedSpan, nom5_locate::LocatedSpan)> for Span { - fn from(input: (nom5_locate::LocatedSpan, nom5_locate::LocatedSpan)) -> Span { +impl + From<( + nom_locate::LocatedSpanEx, + nom_locate::LocatedSpanEx, + )> for Span +{ + fn from( + input: ( + nom_locate::LocatedSpanEx, + nom_locate::LocatedSpanEx, + ), + ) -> Span { Span { start: input.0.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)> for Tag { + fn from((start, end, origin): (usize, usize, Option)) -> Self { + Tag { + origin, + span: Span { start, end }, + } + } +} + +impl From> 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 for Span { fn from(tag: Tag) -> Self { tag.span @@ -214,12 +230,36 @@ impl Tag { Tag { origin: None, span } } + pub fn unknown_span(origin: Uuid) -> Tag { + Tag { + origin: Some(origin), + span: Span::unknown(), + } + } + pub fn unknown() -> Tag { Tag { origin: None, span: Span::unknown(), } } + + pub fn until(&self, other: impl Into) -> 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)] @@ -284,3 +324,33 @@ impl language_reporting::ReportingSpan for Span { 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 + } +} diff --git a/src/errors.rs b/src/errors.rs index d97435d22..3dfa644d4 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -14,20 +14,22 @@ pub enum Description { impl Description { pub fn from(value: Tagged>) -> Description { - let value_span = value.span(); let value_tag = value.tag(); - match value_span { - Span { start: 0, end: 0 } => Description::Synthetic(value.item.into()), + match value_tag { + 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)), } } } impl Description { - fn into_label(self) -> Result, String> { + fn into_label(self) -> Result, String> { 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), } } @@ -81,7 +83,7 @@ impl ShellError { ) -> ShellError { ProximateShellError::RangeError { kind: expected.into(), - actual_kind: actual.copy_span(format!("{:?}", actual.item)), + actual_kind: actual.copy_tag(format!("{:?}", actual.item)), operation, } .start() @@ -116,9 +118,9 @@ impl ShellError { ProximateShellError::MissingProperty { subpath, expr }.start() } - pub(crate) fn missing_value(span: Option, reason: impl Into) -> ShellError { + pub(crate) fn missing_value(tag: Option, reason: impl Into) -> ShellError { ProximateShellError::MissingValue { - span, + tag, reason: reason.into(), } .start() @@ -127,28 +129,31 @@ impl ShellError { pub(crate) fn argument_error( command: impl Into, kind: ArgumentError, - span: Span, + tag: Tag, ) -> ShellError { ProximateShellError::ArgumentError { command: command.into(), error: kind, - span, + tag, } .start() } - pub(crate) fn invalid_external_word(span: Span) -> ShellError { + pub(crate) fn invalid_external_word(tag: Tag) -> ShellError { ProximateShellError::ArgumentError { command: "Invalid argument to Nu command (did you mean to call an external command?)" .into(), error: ArgumentError::InvalidExternalWord, - span, + tag, } .start() } 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 { use language_reporting::*; @@ -164,34 +169,34 @@ impl ShellError { } nom::Err::Failure(span) | nom::Err::Error(span) => { 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) } } } - pub(crate) fn diagnostic(diagnostic: Diagnostic) -> ShellError { + pub(crate) fn diagnostic(diagnostic: Diagnostic) -> ShellError { ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start() } - pub(crate) fn to_diagnostic(self) -> Diagnostic { + pub(crate) fn to_diagnostic(self) -> Diagnostic { match self.error { ProximateShellError::String(StringError { title, .. }) => { Diagnostic::new(Severity::Error, title) } ProximateShellError::InvalidCommand { 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( Severity::Bug, format!("Internal Error (missing value) :: {}", reason), ); - if let Some(span) = span { - d = d.with_label(Label::new_primary(span)); + if let Some(tag) = tag { + d = d.with_label(Label::new_primary(tag)); } d @@ -199,12 +204,12 @@ impl ShellError { ProximateShellError::ArgumentError { command, error, - span, + tag, } => match error { ArgumentError::InvalidExternalWord => Diagnostic::new( Severity::Error, 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( Severity::Error, format!( @@ -214,7 +219,7 @@ impl ShellError { Color::Black.bold().paint(name) ), ) - .with_label(Label::new_primary(span)), + .with_label(Label::new_primary(tag)), ArgumentError::MissingMandatoryPositional(name) => Diagnostic::new( Severity::Error, format!( @@ -224,7 +229,7 @@ impl ShellError { ), ) .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( Severity::Error, @@ -235,17 +240,17 @@ impl ShellError { Color::Black.bold().paint(name) ), ) - .with_label(Label::new_primary(span)), + .with_label(Label::new_primary(tag)), }, ProximateShellError::TypeError { expected, actual: Tagged { item: Some(actual), - tag: Tag { span, .. }, + tag, }, } => Diagnostic::new(Severity::Error, "Type Error").with_label( - Label::new_primary(span) + Label::new_primary(tag) .with_message(format!("Expected {}, found {}", expected, actual)), ), @@ -254,10 +259,10 @@ impl ShellError { actual: Tagged { item: None, - tag: Tag { span, .. }, + tag }, } => 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 { kind, @@ -265,10 +270,10 @@ impl ShellError { actual_kind: Tagged { item, - tag: Tag { span, .. }, + tag }, } => 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", item, kind.desc(), @@ -279,11 +284,11 @@ impl ShellError { ProximateShellError::SyntaxError { problem: Tagged { - tag: Tag { span, .. }, + tag, .. }, } => 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 } => { let subpath = subpath.into_label(); @@ -306,8 +311,8 @@ impl ShellError { ProximateShellError::Diagnostic(diag) => diag.diagnostic, ProximateShellError::CoerceError { left, right } => { Diagnostic::new(Severity::Error, "Coercion error") - .with_label(Label::new_primary(left.span()).with_message(left.item)) - .with_label(Label::new_secondary(right.span()).with_message(right.item)) + .with_label(Label::new_primary(left.tag()).with_message(left.item)) + .with_label(Label::new_secondary(right.tag()).with_message(right.item)) } } } @@ -315,26 +320,29 @@ impl ShellError { pub fn labeled_error( msg: impl Into, label: impl Into, - span: impl Into, + tag: impl Into, ) -> ShellError { ShellError::diagnostic( 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( msg: impl Into, primary_label: impl Into, - primary_span: Span, + primary_span: impl Into, secondary_label: impl Into, - secondary_span: Span, + secondary_span: impl Into, ) -> ShellError { ShellError::diagnostic( Diagnostic::new_error(msg.into()) - .with_label(Label::new_primary(primary_span).with_message(primary_label.into())) .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, }, MissingValue { - span: Option, + tag: Option, reason: String, }, ArgumentError { command: String, error: ArgumentError, - span: Span, + tag: Tag, }, RangeError { kind: ExpectedRange, @@ -447,7 +455,7 @@ impl ToDebug for ProximateShellError { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ShellDiagnostic { - pub(crate) diagnostic: Diagnostic, + pub(crate) diagnostic: Diagnostic, } impl PartialEq for ShellDiagnostic { diff --git a/src/evaluate/evaluator.rs b/src/evaluate/evaluator.rs index 52edf6981..b9db82b54 100644 --- a/src/evaluate/evaluator.rs +++ b/src/evaluate/evaluator.rs @@ -38,13 +38,13 @@ pub(crate) fn evaluate_baseline_expr( source: &Text, ) -> Result, ShellError> { 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( "Invalid external word", 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::Variable(var) => evaluate_reference(var, 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)?; match left.compare(binary.op(), &*right) { - Ok(result) => Ok(Tagged::from_simple_spanned_item( - Value::boolean(result), - expr.span(), - )), + Ok(result) => Ok(Value::boolean(result).tagged(expr.tag())), Err((left_type, right_type)) => Err(ShellError::coerce_error( - binary.left().copy_span(left_type), - binary.right().copy_span(right_type), + binary.left().copy_tag(left_type), + binary.right().copy_tag(right_type), )), } } @@ -71,12 +68,14 @@ pub(crate) fn evaluate_baseline_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) => { let value = evaluate_baseline_expr(path.head(), registry, scope, source)?; let mut item = value; @@ -92,18 +91,12 @@ pub(crate) fn evaluate_baseline_expr( )) } Some(next) => { - item = Tagged::from_simple_spanned_item( - next.clone().item, - (expr.span().start, name.span().end), - ) + item = next.clone().item.tagged(expr.tag()); } }; } - Ok(Tagged::from_simple_spanned_item( - item.item().clone(), - expr.span(), - )) + Ok(item.item().clone().tagged(expr.tag())) } RawExpression::Boolean(_boolean) => unimplemented!(), } @@ -113,9 +106,9 @@ fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged int.into(), hir::Literal::Size(int, unit) => unit.compute(int), - hir::Literal::String(span) => Value::string(span.slice(source)), - hir::Literal::GlobPattern => Value::pattern(literal.span().slice(source)), - hir::Literal::Bare => Value::string(literal.span().slice(source)), + hir::Literal::String(tag) => Value::string(tag.slice(source)), + hir::Literal::GlobPattern => Value::pattern(literal.tag().slice(source)), + hir::Literal::Bare => Value::string(literal.tag().slice(source)), }; literal.map(|_| result) @@ -127,12 +120,12 @@ fn evaluate_reference( source: &Text, ) -> Result, ShellError> { match name { - hir::Variable::It(span) => Ok(scope.it.item.clone().simple_spanned(span)), - hir::Variable::Other(span) => Ok(scope + hir::Variable::It(tag) => Ok(scope.it.item.clone().tagged(*tag)), + hir::Variable::Other(tag) => Ok(scope .vars - .get(span.slice(source)) + .get(tag.slice(source)) .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, ) -> Result, ShellError> { Err(ShellError::syntax_error( - "Unexpected external command".tagged(external.name()), + "Unexpected external command".tagged(*external.name()), )) } diff --git a/src/format/table.rs b/src/format/table.rs index 717e3c4a2..286be222c 100644 --- a/src/format/table.rs +++ b/src/format/table.rs @@ -204,7 +204,7 @@ impl RenderView for TableView { 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") .map(|s| match s.as_string().unwrap().as_ref() { "light" => TableMode::Light, diff --git a/src/lib.rs b/src/lib.rs index a18343df9..60546e385 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ mod utils; pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue}; pub use crate::context::{SourceMap, SpanSource}; 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::plugin::{serve_plugin, Plugin}; 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::base::{Primitive, Value}; 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 num_traits::cast::ToPrimitive; pub use parser::parse::text::Text; diff --git a/src/parser.rs b/src/parser.rs index 2fd891efb..3b3ac1a13 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -21,10 +21,10 @@ pub(crate) use parse::unit::Unit; pub(crate) use parse_command::parse_command; pub(crate) use registry::CommandRegistry; -pub fn parse(input: &str) -> Result { +pub fn parse(input: &str, origin: uuid::Uuid) -> Result { let _ = pretty_env_logger::try_init(); - match pipeline(nom_input(input)) { + match pipeline(nom_input(input, origin)) { Ok((_rest, val)) => Ok(val), Err(err) => Err(ShellError::parse_error(err)), } diff --git a/src/parser/deserializer.rs b/src/parser/deserializer.rs index d5427766b..f9b9146e5 100644 --- a/src/parser/deserializer.rs +++ b/src/parser/deserializer.rs @@ -37,7 +37,7 @@ impl<'de> ConfigDeserializer<'de> { let value: Option> = if name == "rest" { let positional = self.call.args.slice_from(self.position); self.position += positional.len(); - Some(Value::Table(positional).tagged_unknown()) // TODO: correct span + Some(Value::Table(positional).tagged_unknown()) // TODO: correct tag } else { if self.call.args.has(name) { self.call.args.get(name).map(|x| x.clone()) @@ -52,9 +52,7 @@ impl<'de> ConfigDeserializer<'de> { self.stack.push(DeserializerItem { key_struct_field: Some((name.to_string(), name)), - val: value.unwrap_or_else(|| { - Value::nothing().tagged(Tag::unknown_origin(self.call.name_span)) - }), + val: value.unwrap_or_else(|| Value::nothing().tagged(self.call.name_tag)), }); Ok(()) diff --git a/src/parser/hir.rs b/src/parser/hir.rs index 90bb38796..96eb7272a 100644 --- a/src/parser/hir.rs +++ b/src/parser/hir.rs @@ -25,7 +25,7 @@ pub(crate) use self::external_command::ExternalCommand; pub(crate) use self::named::NamedArguments; 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, tail: Vec>>) -> Path { Path::new( @@ -131,72 +131,57 @@ impl RawExpression { pub type Expression = Tagged; impl Expression { - pub(crate) fn number(i: impl Into, span: impl Into) -> Expression { - Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Number(i.into())), span) + pub(crate) fn number(i: impl Into, tag: impl Into) -> Expression { + RawExpression::Literal(Literal::Number(i.into())).tagged(tag.into()) } pub(crate) fn size( i: impl Into, unit: impl Into, - span: impl Into, + tag: impl Into, ) -> Expression { - Tagged::from_simple_spanned_item( - RawExpression::Literal(Literal::Size(i.into(), unit.into())), - span, - ) + RawExpression::Literal(Literal::Size(i.into(), unit.into())).tagged(tag.into()) } pub(crate) fn synthetic_string(s: impl Into) -> Expression { RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown() } - pub(crate) fn string(inner: impl Into, outer: impl Into) -> Expression { - Tagged::from_simple_spanned_item( - RawExpression::Literal(Literal::String(inner.into())), - outer.into(), - ) + pub(crate) fn string(inner: impl Into, outer: impl Into) -> Expression { + RawExpression::Literal(Literal::String(inner.into())).tagged(outer.into()) } - pub(crate) fn file_path(path: impl Into, outer: impl Into) -> Expression { - Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into()) + pub(crate) fn file_path(path: impl Into, outer: impl Into) -> Expression { + RawExpression::FilePath(path.into()).tagged(outer) } - pub(crate) fn bare(span: impl Into) -> Expression { - Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into()) + pub(crate) fn bare(tag: impl Into) -> Expression { + RawExpression::Literal(Literal::Bare).tagged(tag) } pub(crate) fn pattern(tag: impl Into) -> Expression { RawExpression::Literal(Literal::GlobPattern).tagged(tag.into()) } - pub(crate) fn variable(inner: impl Into, outer: impl Into) -> Expression { - Tagged::from_simple_spanned_item( - RawExpression::Variable(Variable::Other(inner.into())), - outer.into(), - ) + pub(crate) fn variable(inner: impl Into, outer: impl Into) -> Expression { + RawExpression::Variable(Variable::Other(inner.into())).tagged(outer) } - pub(crate) fn external_command(inner: impl Into, outer: impl Into) -> Expression { - Tagged::from_simple_spanned_item( - RawExpression::ExternalCommand(ExternalCommand::new(inner.into())), - outer.into(), - ) + pub(crate) fn external_command(inner: impl Into, outer: impl Into) -> Expression { + RawExpression::ExternalCommand(ExternalCommand::new(inner.into())).tagged(outer) } - pub(crate) fn it_variable(inner: impl Into, outer: impl Into) -> Expression { - Tagged::from_simple_spanned_item( - RawExpression::Variable(Variable::It(inner.into())), - outer.into(), - ) + pub(crate) fn it_variable(inner: impl Into, outer: impl Into) -> Expression { + RawExpression::Variable(Variable::It(inner.into())).tagged(outer) } } impl ToDebug for Expression { fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result { 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::ExternalWord => write!(f, "{}", self.span().slice(source)), + RawExpression::ExternalWord => write!(f, "{}", self.tag().slice(source)), RawExpression::Synthetic(Synthetic::String(s)) => write!(f, "{:?}", s), RawExpression::Variable(Variable::It(_)) => write!(f, "$it"), RawExpression::Variable(Variable::Other(s)) => write!(f, "${}", s.slice(source)), @@ -242,7 +227,7 @@ impl From> for Expression { pub enum Literal { Number(Number), Size(Number, Unit), - String(Span), + String(Tag), GlobPattern, Bare, } @@ -252,9 +237,9 @@ impl ToDebug for Tagged<&Literal> { match self.item() { Literal::Number(number) => write!(f, "{:?}", *number), Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit), - Literal::String(span) => write!(f, "{}", span.slice(source)), - Literal::GlobPattern => write!(f, "{}", self.span().slice(source)), - Literal::Bare => write!(f, "{}", self.span().slice(source)), + Literal::String(tag) => write!(f, "{}", tag.slice(source)), + Literal::GlobPattern => write!(f, "{}", self.tag().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)] pub enum Variable { - It(Span), - Other(Span), + It(Tag), + Other(Tag), } diff --git a/src/parser/hir/baseline_parse.rs b/src/parser/hir/baseline_parse.rs index 5248bde5f..267494f27 100644 --- a/src/parser/hir/baseline_parse.rs +++ b/src/parser/hir/baseline_parse.rs @@ -10,19 +10,19 @@ pub fn baseline_parse_single_token( source: &Text, ) -> Result { 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) => { - 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::Variable(span) if span.slice(source) == "it" => { - hir::Expression::it_variable(span, token.span()) + RawToken::String(tag) => hir::Expression::string(tag, token.tag()), + RawToken::Variable(tag) if tag.slice(source) == "it" => { + hir::Expression::it_variable(tag, token.tag()) } - RawToken::Variable(span) => hir::Expression::variable(span, token.span()), - RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()), - RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())), - RawToken::GlobPattern => hir::Expression::pattern(token.span()), - RawToken::Bare => hir::Expression::bare(token.span()), + RawToken::Variable(tag) => hir::Expression::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::GlobPattern => hir::Expression::pattern(token.tag()), + RawToken::Bare => hir::Expression::bare(token.tag()), }) } @@ -31,24 +31,24 @@ pub fn baseline_parse_token_as_number( source: &Text, ) -> Result { Ok(match *token.item() { - RawToken::Variable(span) if span.slice(source) == "it" => { - hir::Expression::it_variable(span, token.span()) + RawToken::Variable(tag) if tag.slice(source) == "it" => { + hir::Expression::it_variable(tag, 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(number) => hir::Expression::number(number.to_number(source), token.span()), + 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(number) => hir::Expression::number(number.to_number(source), token.tag()), 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 => { return Err(ShellError::type_error( "Number", "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, ) -> Result { Ok(match *token.item() { - RawToken::Variable(span) if span.slice(source) == "it" => { - hir::Expression::it_variable(span, token.span()) + RawToken::Variable(tag) if tag.slice(source) == "it" => { + hir::Expression::it_variable(tag, 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::bare(token.span()), + 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::bare(token.tag()), RawToken::GlobPattern => { return Err(ShellError::type_error( "String", "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, ) -> Result { Ok(match *token.item() { - RawToken::Variable(span) if span.slice(source) == "it" => { - hir::Expression::it_variable(span, token.span()) + RawToken::Variable(tag) if tag.slice(source) == "it" => { + 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 => { return Err(ShellError::type_error( "Path", "glob pattern".tagged(token.tag()), )) } - RawToken::String(span) => { - hir::Expression::file_path(expand_path(span.slice(source), context), token.span()) + RawToken::String(tag) => { + 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, ) -> Result { Ok(match *token.item() { - RawToken::Variable(span) if span.slice(source) == "it" => { - hir::Expression::it_variable(span, token.span()) + RawToken::Variable(tag) if tag.slice(source) == "it" => { + hir::Expression::it_variable(tag, token.tag()) } RawToken::ExternalCommand(_) => { return Err(ShellError::syntax_error( "Invalid external command".to_string().tagged(token.tag()), )) } - 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::GlobPattern => hir::Expression::pattern(token.span()), - RawToken::Bare => hir::Expression::file_path( - expand_path(token.span().slice(source), context), - token.span(), - ), - RawToken::String(span) => { - hir::Expression::file_path(expand_path(span.slice(source), context), token.span()) + 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::GlobPattern => hir::Expression::pattern(token.tag()), + RawToken::Bare => { + hir::Expression::file_path(expand_path(token.tag().slice(source), context), token.tag()) + } + RawToken::String(tag) => { + hir::Expression::file_path(expand_path(tag.slice(source), context), token.tag()) } }) } diff --git a/src/parser/hir/baseline_parse_tokens.rs b/src/parser/hir/baseline_parse_tokens.rs index ac2c703d3..8413bd07e 100644 --- a/src/parser/hir/baseline_parse_tokens.rs +++ b/src/parser/hir/baseline_parse_tokens.rs @@ -8,7 +8,7 @@ use crate::parser::{ }, DelimitedNode, Delimiter, PathNode, RawToken, TokenNode, }; -use crate::{Span, Tag, Tagged, TaggedItem, Text}; +use crate::{Tag, Tagged, TaggedItem, Text}; use derive_new::new; use log::trace; use serde::{Deserialize, Serialize}; @@ -17,7 +17,7 @@ pub fn baseline_parse_tokens( token_nodes: &mut TokensIterator<'_>, context: &Context, source: &Text, - syntax_type: SyntaxType, + syntax_type: SyntaxShape, ) -> Result, ShellError> { let mut exprs: Vec = vec![]; @@ -34,7 +34,7 @@ pub fn baseline_parse_tokens( } #[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub enum SyntaxType { +pub enum SyntaxShape { Any, List, Literal, @@ -49,21 +49,21 @@ pub enum SyntaxType { Boolean, } -impl std::fmt::Display for SyntaxType { +impl std::fmt::Display for SyntaxShape { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - SyntaxType::Any => write!(f, "Any"), - SyntaxType::List => write!(f, "List"), - SyntaxType::Literal => write!(f, "Literal"), - SyntaxType::String => write!(f, "String"), - SyntaxType::Member => write!(f, "Member"), - SyntaxType::Variable => write!(f, "Variable"), - SyntaxType::Number => write!(f, "Number"), - SyntaxType::Path => write!(f, "Path"), - SyntaxType::Pattern => write!(f, "Pattern"), - SyntaxType::Binary => write!(f, "Binary"), - SyntaxType::Block => write!(f, "Block"), - SyntaxType::Boolean => write!(f, "Boolean"), + SyntaxShape::Any => write!(f, "Any"), + SyntaxShape::List => write!(f, "List"), + SyntaxShape::Literal => write!(f, "Literal"), + SyntaxShape::String => write!(f, "String"), + SyntaxShape::Member => write!(f, "Member"), + SyntaxShape::Variable => write!(f, "Variable"), + SyntaxShape::Number => write!(f, "Number"), + SyntaxShape::Path => write!(f, "Path"), + SyntaxShape::Pattern => write!(f, "Pattern"), + SyntaxShape::Binary => write!(f, "Binary"), + SyntaxShape::Block => write!(f, "Block"), + SyntaxShape::Boolean => write!(f, "Boolean"), } } } @@ -72,7 +72,7 @@ pub fn baseline_parse_next_expr( tokens: &mut TokensIterator, context: &Context, source: &Text, - syntax_type: SyntaxType, + syntax_type: SyntaxShape, ) -> Result { let next = tokens .next() @@ -81,69 +81,69 @@ pub fn baseline_parse_next_expr( trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", 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) } - (SyntaxType::Path, token) => { + (SyntaxShape::Path, token) => { return Err(ShellError::type_error( "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) } - (SyntaxType::Pattern, token) => { + (SyntaxShape::Pattern, token) => { return Err(ShellError::type_error( "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); } - (SyntaxType::String, token) => { + (SyntaxShape::String, token) => { return Err(ShellError::type_error( "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)?); } - (SyntaxType::Number, token) => { + (SyntaxShape::Number, token) => { return Err(ShellError::type_error( "Numeric", - token.type_name().simple_spanned(token.span()), + token.type_name().tagged(token.tag()), )) } // TODO: More legit member processing - (SyntaxType::Member, TokenNode::Token(token)) => { + (SyntaxShape::Member, TokenNode::Token(token)) => { return baseline_parse_token_as_string(token, source); } - (SyntaxType::Member, token) => { + (SyntaxShape::Member, token) => { return Err(ShellError::type_error( "member", - token.type_name().simple_spanned(token.span()), + token.type_name().tagged(token.tag()), )) } - (SyntaxType::Any, _) => {} - (SyntaxType::List, _) => {} - (SyntaxType::Literal, _) => {} - (SyntaxType::Variable, _) => {} - (SyntaxType::Binary, _) => {} - (SyntaxType::Block, _) => {} - (SyntaxType::Boolean, _) => {} + (SyntaxShape::Any, _) => {} + (SyntaxShape::List, _) => {} + (SyntaxShape::Literal, _) => {} + (SyntaxShape::Variable, _) => {} + (SyntaxShape::Binary, _) => {} + (SyntaxShape::Block, _) => {} + (SyntaxShape::Boolean, _) => {} }; let first = baseline_parse_semantic_token(next, context, source)?; @@ -162,7 +162,7 @@ pub fn baseline_parse_next_expr( return Err(ShellError::labeled_error( "Expected something after an operator", "operator", - op.span(), + op.tag(), )) } 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 match syntax_type { - SyntaxType::Any => { - let span = (first.span().start, second.span().end); + SyntaxShape::Any => { + let tag = first.tag().until(second.tag()); let binary = hir::Binary::new(first, op, second); let binary = hir::RawExpression::Binary(Box::new(binary)); - let binary = Tagged::from_simple_spanned_item(binary, span); + let binary = binary.tagged(tag); Ok(binary) } - SyntaxType::Block => { - let span = (first.span().start, second.span().end); + SyntaxShape::Block => { + let tag = first.tag().until(second.tag()); let path: Tagged = match first { Tagged { item: hir::RawExpression::Literal(hir::Literal::Bare), - tag: Tag { span, .. }, + tag, } => { - let string = - Tagged::from_simple_spanned_item(span.slice(source).to_string(), span); + let string = tag.slice(source).to_string().tagged(tag); let path = hir::Path::new( - Tagged::from_simple_spanned_item( - // TODO: Deal with synthetic nodes that have no representation at all in source - hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), - (0, 0), - ), + // TODO: Deal with synthetic nodes that have no representation at all in source + hir::RawExpression::Variable(hir::Variable::It(Tag::unknown())) + .tagged(Tag::unknown()), vec![string], ); let path = hir::RawExpression::Path(Box::new(path)); - Tagged::from_simple_spanned_item(path, first.span()) + path.tagged(first.tag()) } Tagged { item: hir::RawExpression::Literal(hir::Literal::String(inner)), - tag: Tag { span, .. }, + tag, } => { - let string = - Tagged::from_simple_spanned_item(inner.slice(source).to_string(), span); + let string = inner.slice(source).to_string().tagged(tag); let path = hir::Path::new( - Tagged::from_simple_spanned_item( - // TODO: Deal with synthetic nodes that have no representation at all in source - hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))), - (0, 0), - ), + // TODO: Deal with synthetic nodes that have no representation at all in source + hir::RawExpression::Variable(hir::Variable::It(Tag::unknown())) + .tagged_unknown(), vec![string], ); let path = hir::RawExpression::Path(Box::new(path)); - Tagged::from_simple_spanned_item(path, first.span()) + path.tagged(first.tag()) } Tagged { item: hir::RawExpression::Variable(..), .. } => first, - Tagged { - tag: Tag { span, .. }, - item, - } => { + Tagged { tag, item } => { return Err(ShellError::labeled_error( "The first part of an un-braced block must be a column name", item.type_name(), - span, + tag, )) } }; let binary = hir::Binary::new(path, op, second); 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 = Tagged::from_simple_spanned_item(block, span); + let block = block.tagged(tag); Ok(block) } @@ -265,11 +256,11 @@ pub fn baseline_parse_semantic_token( "Unexpected operator".tagged(op.tag), )), TokenNode::Flag(flag) => Err(ShellError::syntax_error("Unexpected flag".tagged(flag.tag))), - TokenNode::Member(span) => Err(ShellError::syntax_error( - "BUG: Top-level member".tagged(span), + TokenNode::Member(tag) => Err(ShellError::syntax_error( + "BUG: Top-level member".tagged(*tag), )), - TokenNode::Whitespace(span) => Err(ShellError::syntax_error( - "BUG: Whitespace found during parse".tagged(span), + TokenNode::Whitespace(tag) => Err(ShellError::syntax_error( + "BUG: Whitespace found during parse".tagged(*tag), )), TokenNode::Error(error) => Err(*error.item.clone()), TokenNode::Path(path) => baseline_parse_path(path, context, source), @@ -288,11 +279,11 @@ pub fn baseline_parse_delimited( &mut TokensIterator::new(children), context, source, - SyntaxType::Any, + SyntaxShape::Any, )?; let expr = hir::RawExpression::Block(exprs); - Ok(Tagged::from_simple_spanned_item(expr, token.span())) + Ok(expr.tagged(token.tag())) } Delimiter::Paren => unimplemented!(), Delimiter::Square => { @@ -301,11 +292,11 @@ pub fn baseline_parse_delimited( &mut TokensIterator::new(children), context, source, - SyntaxType::Any, + SyntaxShape::Any, )?; 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() { let string = match part { TokenNode::Token(token) => match token.item() { - RawToken::Bare => token.span().slice(source), - RawToken::String(span) => span.slice(source), + RawToken::Bare => token.tag().slice(source), + RawToken::String(tag) => tag.slice(source), RawToken::Number(_) | RawToken::Size(..) | RawToken::Variable(_) @@ -332,26 +323,26 @@ pub fn baseline_parse_path( | RawToken::ExternalWord => { return Err(ShellError::type_error( "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 other => { 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(); - 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)] diff --git a/src/parser/hir/external_command.rs b/src/parser/hir/external_command.rs index 8511cce1e..28865330d 100644 --- a/src/parser/hir/external_command.rs +++ b/src/parser/hir/external_command.rs @@ -9,7 +9,7 @@ use std::fmt; )] #[get = "pub(crate)"] pub struct ExternalCommand { - name: Span, + name: Tag, } impl ToDebug for ExternalCommand { diff --git a/src/parser/hir/named.rs b/src/parser/hir/named.rs index 96d5132fb..838f643be 100644 --- a/src/parser/hir/named.rs +++ b/src/parser/hir/named.rs @@ -1,7 +1,6 @@ use crate::parser::hir::Expression; use crate::parser::Flag; use crate::prelude::*; -use crate::Span; use derive_new::new; use indexmap::IndexMap; use log::trace; @@ -11,7 +10,7 @@ use std::fmt; #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum NamedValue { AbsentSwitch, - PresentSwitch(Span), + PresentSwitch(Tag), AbsentValue, Value(Expression), } @@ -27,7 +26,7 @@ impl ToDebug for NamedArguments { for (name, value) in &self.named { match value { NamedValue::AbsentSwitch => continue, - NamedValue::PresentSwitch(span) => write!(f, " --{}", span.slice(source))?, + NamedValue::PresentSwitch(tag) => write!(f, " --{}", tag.slice(source))?, NamedValue::AbsentValue => continue, NamedValue::Value(expr) => write!(f, " --{} {}", name, expr.debug(source))?, } diff --git a/src/parser/parse/files.rs b/src/parser/parse/files.rs index 173da54a8..6cedb1e99 100644 --- a/src/parser/parse/files.rs +++ b/src/parser/parse/files.rs @@ -1,6 +1,7 @@ -use crate::Span; +use crate::Tag; use derive_new::new; use language_reporting::{FileName, Location}; +use uuid::Uuid; #[derive(new, Debug, Clone)] pub struct Files { @@ -8,26 +9,30 @@ pub struct Files { } impl language_reporting::ReportingFiles for Files { - type Span = Span; - type FileId = usize; + type Span = Tag; + type FileId = Uuid; fn byte_span( &self, - _file: Self::FileId, + file: Self::FileId, from_index: usize, to_index: usize, ) -> Option { - 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 { FileName::Verbatim(format!("shell")) } + fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option { unimplemented!("byte_index") } + fn location(&self, _file: Self::FileId, byte_index: usize) -> Option { let source = &self.snippet; let mut seen_lines = 0; @@ -51,14 +56,15 @@ impl language_reporting::ReportingFiles for Files { None } } - fn line_span(&self, _file: Self::FileId, lineno: usize) -> Option { + + fn line_span(&self, file: Self::FileId, lineno: usize) -> Option { let source = &self.snippet; let mut seen_lines = 0; let mut seen_bytes = 0; for (pos, _) in source.match_indices('\n') { if seen_lines == lineno { - return Some(Span::from((seen_bytes, pos))); + return Some(Tag::from((seen_bytes, pos, file))); } else { seen_lines += 1; seen_bytes = pos + 1; @@ -66,17 +72,18 @@ impl language_reporting::ReportingFiles for Files { } if seen_lines == 0 { - Some(Span::from((0, self.snippet.len() - 1))) + Some(Tag::from((0, self.snippet.len() - 1, file))) } else { None } } - fn source(&self, span: Self::Span) -> Option { - if span.start > span.end { + + fn source(&self, tag: Self::Span) -> Option { + if tag.span.start > tag.span.end { return None; - } else if span.end >= self.snippet.len() { + } else if tag.span.end >= self.snippet.len() { return None; } - Some(self.snippet[span.start..span.end].to_string()) + Some(tag.slice(&self.snippet).to_string()) } } diff --git a/src/parser/parse/flag.rs b/src/parser/parse/flag.rs index 096d69879..09d1e8633 100644 --- a/src/parser/parse/flag.rs +++ b/src/parser/parse/flag.rs @@ -1,4 +1,4 @@ -use crate::Span; +use crate::Tag; use derive_new::new; use getset::Getters; use serde::{Deserialize, Serialize}; @@ -13,5 +13,5 @@ pub enum FlagKind { #[get = "pub(crate)"] pub struct Flag { kind: FlagKind, - name: Span, + name: Tag, } diff --git a/src/parser/parse/parser.rs b/src/parser/parse/parser.rs index 0be05af06..f30eb2c11 100644 --- a/src/parser/parse/parser.rs +++ b/src/parser/parse/parser.rs @@ -5,7 +5,7 @@ use crate::parser::parse::{ tokens::*, unit::*, }; use crate::prelude::*; -use crate::{Span, Tagged}; +use crate::{Tag, Tagged}; use nom; use nom::branch::*; use nom::bytes::complete::*; @@ -18,15 +18,16 @@ use log::trace; use nom::dbg; use nom::*; use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice}; -use nom5_locate::{position, LocatedSpan}; +use nom_locate::{position, LocatedSpanEx}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; 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<'_> { - LocatedSpan::new(s) +pub fn nom_input(s: &str, origin: Uuid) -> NomSpan<'_> { + LocatedSpanEx::new_extra(s, origin) } macro_rules! operator { @@ -38,7 +39,7 @@ macro_rules! operator { Ok(( 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> { Ok((input, dot)) => input, // 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 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 { let end = input.offset; Ok(( 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 { Ok(( 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 { Ok(( 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 { 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 { let next_char = &input.fragment.chars().nth(0); 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( input, nom::error::ErrorKind::TakeWhile1, @@ -273,7 +277,10 @@ pub fn bare(input: NomSpan) -> IResult { 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 { let (input, _) = take_while1(is_external_word_char)(input)?; 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 { Ok(( 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 { 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 { Ok(( 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 { Ok(( 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> { Ok(( 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 { Ok(( input, - TokenTreeBuilder::spanned_size((number.item, *size), (start, end)), + TokenTreeBuilder::tagged_size((number.item, *size), (start, end, input.extra)), )) } else { let end = input.offset; @@ -401,7 +414,7 @@ pub fn size(input: NomSpan) -> IResult { Ok(( 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![]; 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); for (ws, token) in list { - nodes.push(TokenNode::Whitespace(Span::from(ws))); + nodes.push(TokenNode::Whitespace(Tag::from(ws))); nodes.push(token); } if let Some(sp_right) = sp_right { - nodes.push(TokenNode::Whitespace(Span::from(sp_right))); + nodes.push(TokenNode::Whitespace(Tag::from(sp_right))); } nodes @@ -478,7 +491,10 @@ pub fn whitespace(input: NomSpan) -> IResult { let (input, ws1) = space1(input)?; 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 { Ok(( 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 { Ok(( 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 { Ok(( 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> { let (input, items) = token_list(input)?; 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 { Ok(( 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 { Ok(( input, - TokenTreeBuilder::spanned_pipeline( - (make_call_list(head, items), tail.map(Span::from)), - (start, end), + TokenTreeBuilder::tagged_pipeline( + (make_call_list(head, items), tail.map(Tag::from)), + (start, end, input.extra), ), )) }) @@ -643,17 +665,17 @@ fn make_call_list( let mut out = vec![]; 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); } for (pipe, ws1, call, ws2) in items { let el = PipelineElement::new( - Some(pipe).map(Span::from), - ws1.map(Span::from), + Some(pipe).map(Tag::from), + ws1.map(Tag::from), call, - ws2.map(Span::from), + ws2.map(Tag::from), ); 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 { - is_start_bare_char(c) || c == '*' + is_start_bare_char(c) || is_glob_specific_char(c) } 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 { @@ -779,7 +806,7 @@ mod tests { macro_rules! equal_tokens { ($source:tt -> $tokens:expr) => { 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 { let debug_result = format!("{}", result.debug($source)); @@ -818,12 +845,12 @@ mod tests { fn test_integer() { assert_leaf! { parsers [ size ] - "123" -> 0..3 { Number(RawNumber::int((0, 3)).item) } + "123" -> 0..3 { Number(RawNumber::int((0, 3, test_uuid())).item) } } assert_leaf! { 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() { assert_leaf! { 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! { 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() { assert_leaf! { parsers [ string dq_string ] - r#""hello world""# -> 0..13 { String(span(1, 12)) } + r#""hello world""# -> 0..13 { String(tag(1, 12)) } } assert_leaf! { 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() { assert_leaf! { parsers [ var ] - "$it" -> 0..3 { Variable(span(1, 3)) } + "$it" -> 0..3 { Variable(tag(1, 3)) } } assert_leaf! { 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() { assert_leaf! { parsers [ external ] - "^ls" -> 0..3 { ExternalCommand(span(1, 3)) } + "^ls" -> 0..3 { ExternalCommand(tag(1, 3)) } } } @@ -1260,7 +1287,7 @@ mod tests { desc: &str, string: &str, ) -> T { - match f(NomSpan::new(string)) { + match f(NomSpan::new_extra(string, uuid::Uuid::nil())) { Ok(v) => v.1, Err(other) => { println!("{:?}", other); @@ -1270,44 +1297,46 @@ mod tests { } } - fn span(left: usize, right: usize) -> Span { - Span::from((left, right)) + fn tag(left: usize, right: usize) -> Tag { + Tag::from((left, right, uuid::Uuid::nil())) } fn delimited( - delimiter: Delimiter, + delimiter: Tagged, children: Vec, left: usize, right: usize, ) -> TokenNode { - let node = DelimitedNode::new(delimiter, children); - let spanned = Tagged::from_simple_spanned_item(node, (left, right)); + let node = DelimitedNode::new(*delimiter, children); + let spanned = node.tagged((left, right, delimiter.tag.origin)); TokenNode::Delimited(spanned) } fn path(head: TokenNode, tail: Vec, left: usize, right: usize) -> TokenNode { + let tag = head.tag(); + let node = PathNode::new( Box::new(head), 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) } - 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 { - TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right))) + TokenNode::Token(token.tagged((left, right, uuid::Uuid::nil()))) } fn build(block: CurriedNode) -> T { - let mut builder = TokenTreeBuilder::new(); + let mut builder = TokenTreeBuilder::new(uuid::Uuid::nil()); block(&mut builder) } 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() } } diff --git a/src/parser/parse/pipeline.rs b/src/parser/parse/pipeline.rs index 64a899c17..42bbe23a1 100644 --- a/src/parser/parse/pipeline.rs +++ b/src/parser/parse/pipeline.rs @@ -1,6 +1,6 @@ use crate::parser::CallNode; use crate::traits::ToDebug; -use crate::{Span, Tagged}; +use crate::{Tag, Tagged}; use derive_new::new; use getset::Getters; use std::fmt; @@ -8,7 +8,7 @@ use std::fmt; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)] pub struct Pipeline { pub(crate) parts: Vec, - pub(crate) post_ws: Option, + pub(crate) post_ws: Option, } impl ToDebug for Pipeline { @@ -27,11 +27,11 @@ impl ToDebug for Pipeline { #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)] pub struct PipelineElement { - pub pipe: Option, - pub pre_ws: Option, + pub pipe: Option, + pub pre_ws: Option, #[get = "pub(crate)"] call: Tagged, - pub post_ws: Option, + pub post_ws: Option, } impl ToDebug for PipelineElement { diff --git a/src/parser/parse/token_tree.rs b/src/parser/parse/token_tree.rs index f69c176e9..e0072360e 100644 --- a/src/parser/parse/token_tree.rs +++ b/src/parser/parse/token_tree.rs @@ -1,7 +1,7 @@ use crate::errors::ShellError; use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*}; use crate::traits::ToDebug; -use crate::{Span, Tagged, Text}; +use crate::{Tag, Tagged, Text}; use derive_new::new; use enum_utils::FromStr; use getset::Getters; @@ -16,8 +16,8 @@ pub enum TokenNode { Pipeline(Tagged), Operator(Tagged), Flag(Tagged), - Member(Span), - Whitespace(Span), + Member(Tag), + Whitespace(Tag), Error(Tagged>), Path(Tagged), @@ -78,31 +78,31 @@ impl fmt::Debug for DebugTokenNode<'_> { ) } TokenNode::Pipeline(pipeline) => write!(f, "{}", pipeline.debug(self.source)), - TokenNode::Error(s) => write!(f, " for {:?}", s.span().slice(self.source)), - rest => write!(f, "{}", rest.span().slice(self.source)), + TokenNode::Error(s) => write!(f, " for {:?}", s.tag().slice(self.source)), + rest => write!(f, "{}", rest.tag().slice(self.source)), } } } -impl From<&TokenNode> for Span { - fn from(token: &TokenNode) -> Span { - token.span() +impl From<&TokenNode> for Tag { + fn from(token: &TokenNode) -> Tag { + token.tag() } } impl TokenNode { - pub fn span(&self) -> Span { + pub fn tag(&self) -> Tag { match self { - TokenNode::Token(t) => t.span(), - TokenNode::Call(s) => s.span(), - TokenNode::Delimited(s) => s.span(), - TokenNode::Pipeline(s) => s.span(), - TokenNode::Operator(s) => s.span(), - TokenNode::Flag(s) => s.span(), + TokenNode::Token(t) => t.tag(), + TokenNode::Call(s) => s.tag(), + TokenNode::Delimited(s) => s.tag(), + TokenNode::Pipeline(s) => s.tag(), + TokenNode::Operator(s) => s.tag(), + TokenNode::Flag(s) => s.tag(), TokenNode::Member(s) => *s, TokenNode::Whitespace(s) => *s, - TokenNode::Error(s) => s.span(), - TokenNode::Path(s) => s.span(), + TokenNode::Error(s) => s.tag(), + TokenNode::Path(s) => s.tag(), } } @@ -127,11 +127,11 @@ impl TokenNode { } 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 { - self.span().slice(source) + self.tag().slice(source) } 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 { TokenNode::Token(Tagged { - item: RawToken::ExternalCommand(span), + item: RawToken::ExternalCommand(tag), .. - }) => *span, + }) => *tag, _ => panic!("Only call expect_external if you checked is_external first"), } } diff --git a/src/parser/parse/token_tree_builder.rs b/src/parser/parse/token_tree_builder.rs index ae1b344c4..1ed8383f4 100644 --- a/src/parser/parse/token_tree_builder.rs +++ b/src/parser/parse/token_tree_builder.rs @@ -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::unit::Unit; use crate::parser::CallNode; -use crate::Span; use derive_new::new; +use uuid::Uuid; #[derive(new)] pub struct TokenTreeBuilder { @@ -17,14 +17,16 @@ pub struct TokenTreeBuilder { #[new(default)] output: String, + + origin: Uuid, } pub type CurriedToken = Box TokenNode + 'static>; pub type CurriedCall = Box Tagged + 'static>; impl TokenTreeBuilder { - pub fn build(block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) { - let mut builder = TokenTreeBuilder::new(); + pub fn build(origin: Uuid, block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) { + let mut builder = TokenTreeBuilder::new(origin); let node = block(&mut builder); (node, builder.output) } @@ -52,50 +54,37 @@ impl TokenTreeBuilder { .expect("A pipeline must contain at least one element"); 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 post_span = post.map(|post| b.consume(&post)); + let post_tag = post.map(|post| b.consume_tag(&post)); - out.push(PipelineElement::new( - pipe, - pre_span.map(Span::from), - call, - post_span.map(Span::from), - )); + out.push(PipelineElement::new(pipe, pre_tag, call, post_tag)); loop { match input.next() { None => break, Some((pre, call, post)) => { - let pipe = Some(Span::from(b.consume("|"))); - let pre_span = pre.map(|pre| b.consume(&pre)); + let pipe = Some(b.consume_tag("|")); + let pre_span = pre.map(|pre| b.consume_tag(&pre)); 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( - pipe, - pre_span.map(Span::from), - call, - post_span.map(Span::from), - )); + out.push(PipelineElement::new(pipe, pre_span, call, post_span)); } } } let end = b.pos; - TokenTreeBuilder::spanned_pipeline((out, None), (start, end)) + TokenTreeBuilder::tagged_pipeline((out, None), (start, end, b.origin)) }) } - pub fn spanned_pipeline( - input: (Vec, Option), - span: impl Into, + pub fn tagged_pipeline( + input: (Vec, Option), + tag: impl Into, ) -> TokenNode { - TokenNode::Pipeline(Tagged::from_simple_spanned_item( - Pipeline::new(input.0, input.1.into()), - span, - )) + TokenNode::Pipeline(Pipeline::new(input.0, input.1.into()).tagged(tag.into())) } pub fn op(input: impl Into) -> CurriedToken { @@ -106,12 +95,12 @@ impl TokenTreeBuilder { b.pos = end; - TokenTreeBuilder::spanned_op(input, (start, end)) + TokenTreeBuilder::tagged_op(input, (start, end, b.origin)) }) } - pub fn spanned_op(input: impl Into, span: impl Into) -> TokenNode { - TokenNode::Operator(Tagged::from_simple_spanned_item(input.into(), span.into())) + pub fn tagged_op(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Operator(input.into().tagged(tag.into())) } pub fn string(input: impl Into) -> CurriedToken { @@ -123,15 +112,15 @@ impl TokenTreeBuilder { let (_, end) = b.consume("\""); 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: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::String(input.into()), - span.into(), - )) + pub fn tagged_string(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Token(RawToken::String(input.into()).tagged(tag.into())) } pub fn bare(input: impl Into) -> CurriedToken { @@ -141,15 +130,12 @@ impl TokenTreeBuilder { let (start, end) = b.consume(&input); b.pos = end; - TokenTreeBuilder::spanned_bare((start, end)) + TokenTreeBuilder::tagged_bare((start, end, b.origin)) }) } - pub fn spanned_bare(input: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::Bare, - input.into(), - )) + pub fn tagged_bare(tag: impl Into) -> TokenNode { + TokenNode::Token(RawToken::Bare.tagged(tag.into())) } pub fn pattern(input: impl Into) -> CurriedToken { @@ -159,15 +145,12 @@ impl TokenTreeBuilder { let (start, end) = b.consume(&input); b.pos = end; - TokenTreeBuilder::spanned_pattern((start, end)) + TokenTreeBuilder::tagged_pattern((start, end, b.origin)) }) } - pub fn spanned_pattern(input: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::Bare, - input.into(), - )) + pub fn tagged_pattern(input: impl Into) -> TokenNode { + TokenNode::Token(RawToken::GlobPattern.tagged(input.into())) } pub fn external_word(input: impl Into) -> CurriedToken { @@ -177,22 +160,16 @@ impl TokenTreeBuilder { let (start, end) = b.consume(&input); 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) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::ExternalWord, - input.into(), - )) + pub fn tagged_external_word(input: impl Into) -> TokenNode { + TokenNode::Token(RawToken::ExternalWord.tagged(input.into())) } - pub fn spanned_external(input: impl Into, span: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::ExternalCommand(input.into()), - span.into(), - )) + pub fn tagged_external(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Token(RawToken::ExternalCommand(input.into()).tagged(tag.into())) } pub fn int(input: impl Into) -> CurriedToken { @@ -202,7 +179,10 @@ impl TokenTreeBuilder { let (start, end) = b.consume(&int.to_string()); 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()); 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, span: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::Number(input.into()), - span.into(), - )) + pub fn tagged_number(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Token(RawToken::Number(input.into()).tagged(tag.into())) } pub fn size(int: impl Into, unit: impl Into) -> CurriedToken { @@ -233,23 +213,20 @@ impl TokenTreeBuilder { let (_, end_unit) = b.consume(unit.as_str()); b.pos = end_unit; - TokenTreeBuilder::spanned_size( - (RawNumber::Int((start_int, end_int).into()), unit), - (start_int, end_unit), + TokenTreeBuilder::tagged_size( + (RawNumber::Int((start_int, end_int, b.origin).into()), unit), + (start_int, end_unit, b.origin), ) }) } - pub fn spanned_size( + pub fn tagged_size( input: (impl Into, impl Into), - span: impl Into, + tag: impl Into, ) -> TokenNode { let (int, unit) = (input.0.into(), input.1.into()); - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::Size(int, unit), - span, - )) + TokenNode::Token(RawToken::Size(int, unit).tagged(tag.into())) } pub fn path(head: CurriedToken, tail: Vec) -> CurriedToken { @@ -267,15 +244,12 @@ impl TokenTreeBuilder { 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), span: impl Into) -> TokenNode { - TokenNode::Path(Tagged::from_simple_spanned_item( - PathNode::new(Box::new(input.0), input.1), - span, - )) + pub fn tagged_path(input: (TokenNode, Vec), tag: impl Into) -> TokenNode { + TokenNode::Path(PathNode::new(Box::new(input.0), input.1).tagged(tag.into())) } pub fn var(input: impl Into) -> CurriedToken { @@ -285,15 +259,12 @@ impl TokenTreeBuilder { let (start, _) = b.consume("$"); 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: impl Into) -> TokenNode { - TokenNode::Token(Tagged::from_simple_spanned_item( - RawToken::Variable(input.into()), - span.into(), - )) + pub fn tagged_var(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Token(RawToken::Variable(input.into()).tagged(tag.into())) } pub fn flag(input: impl Into) -> CurriedToken { @@ -303,15 +274,12 @@ impl TokenTreeBuilder { let (start, _) = b.consume("--"); 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: impl Into) -> TokenNode { - TokenNode::Flag(Tagged::from_simple_spanned_item( - Flag::new(FlagKind::Longhand, input.into()), - span.into(), - )) + pub fn tagged_flag(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Flag(Flag::new(FlagKind::Longhand, input.into()).tagged(tag.into())) } pub fn shorthand(input: impl Into) -> CurriedToken { @@ -321,15 +289,12 @@ impl TokenTreeBuilder { let (start, _) = b.consume("-"); 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: impl Into) -> TokenNode { - TokenNode::Flag(Tagged::from_simple_spanned_item( - Flag::new(FlagKind::Shorthand, input.into()), - span.into(), - )) + pub fn tagged_shorthand(input: impl Into, tag: impl Into) -> TokenNode { + TokenNode::Flag(Flag::new(FlagKind::Shorthand, input.into()).tagged(tag.into())) } pub fn member(input: impl Into) -> CurriedToken { @@ -337,12 +302,12 @@ impl TokenTreeBuilder { Box::new(move |b| { 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) -> TokenNode { - TokenNode::Member(span.into()) + pub fn tagged_member(tag: impl Into) -> TokenNode { + TokenNode::Member(tag.into()) } pub fn call(head: CurriedToken, input: Vec) -> CurriedCall { @@ -358,11 +323,11 @@ impl TokenTreeBuilder { let end = b.pos; - TokenTreeBuilder::spanned_call(nodes, (start, end)) + TokenTreeBuilder::tagged_call(nodes, (start, end, b.origin)) }) } - pub fn spanned_call(input: Vec, span: impl Into) -> Tagged { + pub fn tagged_call(input: Vec, tag: impl Into) -> Tagged { if input.len() == 0 { panic!("BUG: spanned call (TODO)") } @@ -372,7 +337,7 @@ impl TokenTreeBuilder { let head = input.next().unwrap(); 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 { @@ -385,15 +350,12 @@ impl TokenTreeBuilder { 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>, span: impl Into) -> TokenNode { - TokenNode::Delimited(Tagged::from_simple_spanned_item( - DelimitedNode::new(Delimiter::Paren, input.into()), - span, - )) + pub fn tagged_parens(input: impl Into>, tag: impl Into) -> TokenNode { + TokenNode::Delimited(DelimitedNode::new(Delimiter::Paren, input.into()).tagged(tag.into())) } pub fn square(input: Vec) -> CurriedToken { @@ -406,15 +368,12 @@ impl TokenTreeBuilder { 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>, span: impl Into) -> TokenNode { - TokenNode::Delimited(Tagged::from_simple_spanned_item( - DelimitedNode::new(Delimiter::Square, input.into()), - span, - )) + pub fn tagged_square(input: impl Into>, tag: impl Into) -> TokenNode { + TokenNode::Delimited(DelimitedNode::new(Delimiter::Square, input.into()).tagged(tag.into())) } pub fn braced(input: Vec) -> CurriedToken { @@ -427,21 +386,18 @@ impl TokenTreeBuilder { 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>, span: impl Into) -> TokenNode { - TokenNode::Delimited(Tagged::from_simple_spanned_item( - DelimitedNode::new(Delimiter::Brace, input.into()), - span, - )) + pub fn tagged_brace(input: impl Into>, tag: impl Into) -> TokenNode { + TokenNode::Delimited(DelimitedNode::new(Delimiter::Brace, input.into()).tagged(tag.into())) } pub fn sp() -> CurriedToken { Box::new(|b| { 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| { 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) -> TokenNode { - let span = span.into(); - - TokenNode::Whitespace(span.into()) + pub fn tagged_ws(tag: impl Into) -> TokenNode { + TokenNode::Whitespace(tag.into()) } fn consume(&mut self, input: &str) -> (usize, usize) { @@ -466,4 +420,11 @@ impl TokenTreeBuilder { self.output.push_str(input); (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() + } } diff --git a/src/parser/parse/tokens.rs b/src/parser/parse/tokens.rs index b59985249..d796a8fcb 100644 --- a/src/parser/parse/tokens.rs +++ b/src/parser/parse/tokens.rs @@ -1,6 +1,6 @@ use crate::parser::parse::unit::*; use crate::prelude::*; -use crate::{Span, Tagged, Text}; +use crate::{Tagged, Text}; use std::fmt; use std::str::FromStr; @@ -8,9 +8,9 @@ use std::str::FromStr; pub enum RawToken { Number(RawNumber), Size(RawNumber, Unit), - String(Span), - Variable(Span), - ExternalCommand(Span), + String(Tag), + Variable(Tag), + ExternalCommand(Tag), ExternalWord, GlobPattern, Bare, @@ -18,28 +18,28 @@ pub enum RawToken { #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum RawNumber { - Int(Span), - Decimal(Span), + Int(Tag), + Decimal(Tag), } impl RawNumber { - pub fn int(span: impl Into) -> Tagged { - let span = span.into(); + pub fn int(tag: impl Into) -> Tagged { + let tag = tag.into(); - RawNumber::Int(span).tagged(span) + RawNumber::Int(tag).tagged(tag) } - pub fn decimal(span: impl Into) -> Tagged { - let span = span.into(); + pub fn decimal(tag: impl Into) -> Tagged { + let tag = tag.into(); - RawNumber::Decimal(span).tagged(span) + RawNumber::Decimal(tag).tagged(tag) } pub(crate) fn to_number(self, source: &Text) -> Number { match self { - RawNumber::Int(span) => Number::Int(BigInt::from_str(span.slice(source)).unwrap()), - RawNumber::Decimal(span) => { - Number::Decimal(BigDecimal::from_str(span.slice(source)).unwrap()) + RawNumber::Int(tag) => Number::Int(BigInt::from_str(tag.slice(source)).unwrap()), + RawNumber::Decimal(tag) => { + Number::Decimal(BigDecimal::from_str(tag.slice(source)).unwrap()) } } } @@ -78,6 +78,6 @@ pub struct DebugToken<'a> { impl fmt::Debug for DebugToken<'_> { 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)) } } diff --git a/src/parser/parse_command.rs b/src/parser/parse_command.rs index e0fc9d86f..36ba82f8e 100644 --- a/src/parser/parse_command.rs +++ b/src/parser/parse_command.rs @@ -7,7 +7,7 @@ use crate::parser::{ Flag, RawToken, TokenNode, }; use crate::traits::ToDebug; -use crate::{Span, Tag, Tagged, Text}; +use crate::{Tag, Tagged, TaggedItem, Text}; use log::trace; pub fn parse_command( @@ -33,7 +33,7 @@ pub fn parse_command( .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)), Some((positional, named)) => Ok(hir::Call::new(Box::new(head), positional, named)), } @@ -49,12 +49,9 @@ fn parse_command_head(head: &TokenNode) -> Result { ) => Ok(spanned.map(|_| hir::RawExpression::Literal(hir::Literal::Bare))), TokenNode::Token(Tagged { - item: RawToken::String(inner_span), - tag: Tag { span, origin: None }, - }) => Ok(Tagged::from_simple_spanned_item( - hir::RawExpression::Literal(hir::Literal::String(*inner_span)), - *span, - )), + item: RawToken::String(inner_tag), + tag, + }) => Ok(hir::RawExpression::Literal(hir::Literal::String(*inner_tag)).tagged(*tag)), other => Err(ShellError::unexpected(&format!( "command head -> {:?}", @@ -68,7 +65,7 @@ fn parse_command_tail( context: &Context, tail: Option>, source: &Text, - command_span: Span, + command_tag: Tag, ) -> Result>, Option)>, ShellError> { let tail = &mut match &tail { None => hir::TokensIterator::new(&[]), @@ -89,7 +86,7 @@ fn parse_command_tail( named.insert_switch(name, flag); } 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 Ok((pos, flag)) => { tail.move_to(pos); @@ -98,7 +95,7 @@ fn parse_command_tail( return Err(ShellError::argument_error( config.name.clone(), ArgumentError::MissingValueForName(name.to_string()), - flag.span(), + flag.tag(), )); } @@ -119,7 +116,7 @@ fn parse_command_tail( return Err(ShellError::argument_error( config.name.clone(), ArgumentError::MissingValueForName(name.to_string()), - flag.span(), + flag.tag(), )); } @@ -150,7 +147,7 @@ fn parse_command_tail( return Err(ShellError::argument_error( config.name.clone(), ArgumentError::MissingMandatoryPositional(arg.name().to_string()), - command_span, + command_tag, )); } } @@ -208,7 +205,7 @@ fn extract_mandatory( name: &str, tokens: &mut hir::TokensIterator<'_>, source: &Text, - span: Span, + tag: Tag, ) -> Result<(usize, Tagged), ShellError> { let flag = tokens.extract(|t| t.as_flag(name, source)); @@ -216,7 +213,7 @@ fn extract_mandatory( None => Err(ShellError::argument_error( config.name.clone(), ArgumentError::MissingMandatoryFlag(name.to_string()), - span, + tag, )), Some((pos, flag)) => { diff --git a/src/parser/registry.rs b/src/parser/registry.rs index 7112d9111..e199be192 100644 --- a/src/parser/registry.rs +++ b/src/parser/registry.rs @@ -1,7 +1,7 @@ // TODO: Temporary redirect pub(crate) use crate::context::CommandRegistry; 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 derive_new::new; use indexmap::IndexMap; @@ -12,35 +12,35 @@ use std::fmt; #[derive(Debug, Serialize, Deserialize, Clone)] pub enum NamedType { Switch, - Mandatory(SyntaxType), - Optional(SyntaxType), + Mandatory(SyntaxShape), + Optional(SyntaxShape), } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum PositionalType { - Mandatory(String, SyntaxType), - Optional(String, SyntaxType), + Mandatory(String, SyntaxShape), + Optional(String, SyntaxShape), } impl PositionalType { - pub fn mandatory(name: &str, ty: SyntaxType) -> PositionalType { + pub fn mandatory(name: &str, ty: SyntaxShape) -> PositionalType { PositionalType::Mandatory(name.to_string(), ty) } 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 { - 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) } 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 { @@ -50,7 +50,7 @@ impl PositionalType { } } - pub(crate) fn syntax_type(&self) -> SyntaxType { + pub(crate) fn syntax_type(&self) -> SyntaxShape { match *self { PositionalType::Mandatory(_, t) => t, PositionalType::Optional(_, t) => t, @@ -66,7 +66,7 @@ pub struct Signature { #[new(default)] pub positional: Vec, #[new(value = "None")] - pub rest_positional: Option, + pub rest_positional: Option, #[new(default)] pub named: IndexMap, #[new(value = "false")] @@ -83,21 +83,21 @@ impl Signature { self } - pub fn required(mut self, name: impl Into, ty: impl Into) -> Signature { + pub fn required(mut self, name: impl Into, ty: impl Into) -> Signature { self.positional .push(PositionalType::Mandatory(name.into(), ty.into())); self } - pub fn optional(mut self, name: impl Into, ty: impl Into) -> Signature { + pub fn optional(mut self, name: impl Into, ty: impl Into) -> Signature { self.positional .push(PositionalType::Optional(name.into(), ty.into())); self } - pub fn named(mut self, name: impl Into, ty: impl Into) -> Signature { + pub fn named(mut self, name: impl Into, ty: impl Into) -> Signature { self.named .insert(name.into(), NamedType::Optional(ty.into())); @@ -107,7 +107,7 @@ impl Signature { pub fn required_named( mut self, name: impl Into, - ty: impl Into, + ty: impl Into, ) -> Signature { self.named .insert(name.into(), NamedType::Mandatory(ty.into())); @@ -126,7 +126,7 @@ impl Signature { self } - pub fn rest(mut self, ty: SyntaxType) -> Signature { + pub fn rest(mut self, ty: SyntaxShape) -> Signature { self.rest_positional = Some(ty); self } @@ -312,10 +312,10 @@ pub(crate) fn evaluate_args( for (name, value) in n.named.iter() { match value { - hir::named::NamedValue::PresentSwitch(span) => { + hir::named::NamedValue::PresentSwitch(tag) => { results.insert( name.clone(), - Tagged::from_simple_spanned_item(Value::boolean(true), *span), + Value::boolean(true).tagged(*tag), ); } hir::named::NamedValue::Value(expr) => { diff --git a/src/plugins/add.rs b/src/plugins/add.rs index 744003cd7..03e1d4282 100644 --- a/src/plugins/add.rs +++ b/src/plugins/add.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxType, Tagged, Value, + SyntaxShape, Tagged, Value, }; struct Add { @@ -44,9 +44,9 @@ impl Plugin for Add { fn config(&mut self) -> Result { Ok(Signature::build("add") .desc("Add a new field to the table.") - .required("Field", SyntaxType::String) - .required("Value", SyntaxType::String) - .rest(SyntaxType::String) + .required("Field", SyntaxShape::String) + .required("Value", SyntaxShape::String) + .rest(SyntaxShape::String) .filter()) } diff --git a/src/plugins/edit.rs b/src/plugins/edit.rs index aeda4ba09..db116fedf 100644 --- a/src/plugins/edit.rs +++ b/src/plugins/edit.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxType, Tagged, Value, + SyntaxShape, Tagged, Value, }; struct Edit { @@ -43,8 +43,8 @@ impl Plugin for Edit { fn config(&mut self) -> Result { Ok(Signature::build("edit") .desc("Edit an existing column to have a new value.") - .required("Field", SyntaxType::String) - .required("Value", SyntaxType::String) + .required("Field", SyntaxShape::String) + .required("Value", SyntaxShape::String) .filter()) } diff --git a/src/plugins/embed.rs b/src/plugins/embed.rs index 95140aa60..646db8091 100644 --- a/src/plugins/embed.rs +++ b/src/plugins/embed.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxType, Tag, Tagged, TaggedDictBuilder, Value, + SyntaxShape, Tag, Tagged, TaggedDictBuilder, Value, }; struct Embed { @@ -37,8 +37,8 @@ impl Plugin for Embed { fn config(&mut self) -> Result { Ok(Signature::build("embed") .desc("Embeds a new field to the table.") - .required("Field", SyntaxType::String) - .rest(SyntaxType::String) + .required("Field", SyntaxShape::String) + .rest(SyntaxShape::String) .filter()) } diff --git a/src/plugins/inc.rs b/src/plugins/inc.rs index d75da4142..4422195be 100644 --- a/src/plugins/inc.rs +++ b/src/plugins/inc.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxType, Tagged, TaggedItem, Value, + SyntaxShape, Tagged, TaggedItem, Value, }; enum Action { @@ -120,7 +120,7 @@ impl Plugin for Inc { .switch("major") .switch("minor") .switch("patch") - .rest(SyntaxType::String) + .rest(SyntaxShape::String) .filter()) } @@ -181,18 +181,20 @@ mod tests { use super::{Inc, SemVerAction}; use indexmap::IndexMap; use nu::{ - CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, - TaggedDictBuilder, TaggedItem, Value, + CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Tag, Tagged, TaggedDictBuilder, + TaggedItem, Value, }; struct CallStub { + origin: uuid::Uuid, positionals: Vec>, flags: IndexMap>, } impl CallStub { - fn new() -> CallStub { + fn new(origin: uuid::Uuid) -> CallStub { CallStub { + origin, positionals: vec![], flags: indexmap::IndexMap::new(), } @@ -201,14 +203,14 @@ mod tests { fn with_long_flag(&mut self, name: &str) -> &mut Self { self.flags.insert( name.to_string(), - Value::boolean(true).simple_spanned(Span::unknown()), + Value::boolean(true).tagged(Tag::unknown()), ); self } fn with_parameter(&mut self, name: &str) -> &mut Self { 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 } @@ -216,7 +218,7 @@ mod tests { CallInfo { args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())), 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(); assert!(plugin - .begin_filter(CallStub::new().with_long_flag("major").create()) + .begin_filter(CallStub::new(test_uuid()).with_long_flag("major").create()) .is_ok()); assert!(plugin.action.is_some()); } @@ -253,7 +255,7 @@ mod tests { let mut plugin = Inc::new(); assert!(plugin - .begin_filter(CallStub::new().with_long_flag("minor").create()) + .begin_filter(CallStub::new(test_uuid()).with_long_flag("minor").create()) .is_ok()); assert!(plugin.action.is_some()); } @@ -263,7 +265,7 @@ mod tests { let mut plugin = Inc::new(); assert!(plugin - .begin_filter(CallStub::new().with_long_flag("patch").create()) + .begin_filter(CallStub::new(test_uuid()).with_long_flag("patch").create()) .is_ok()); assert!(plugin.action.is_some()); } @@ -274,7 +276,7 @@ mod tests { assert!(plugin .begin_filter( - CallStub::new() + CallStub::new(test_uuid()) .with_long_flag("major") .with_long_flag("minor") .create(), @@ -288,7 +290,11 @@ mod tests { let mut plugin = Inc::new(); assert!(plugin - .begin_filter(CallStub::new().with_parameter("package.version").create()) + .begin_filter( + CallStub::new(test_uuid()) + .with_parameter("package.version") + .create() + ) .is_ok()); assert_eq!(plugin.field, Some("package.version".to_string())); @@ -321,7 +327,7 @@ mod tests { assert!(plugin .begin_filter( - CallStub::new() + CallStub::new(test_uuid()) .with_long_flag("major") .with_parameter("version") .create() @@ -349,7 +355,7 @@ mod tests { assert!(plugin .begin_filter( - CallStub::new() + CallStub::new(test_uuid()) .with_long_flag("minor") .with_parameter("version") .create() @@ -378,7 +384,7 @@ mod tests { assert!(plugin .begin_filter( - CallStub::new() + CallStub::new(test_uuid()) .with_long_flag("patch") .with_parameter(&field) .create() @@ -399,4 +405,8 @@ mod tests { _ => {} } } + + fn test_uuid() -> uuid::Uuid { + uuid::Uuid::nil() + } } diff --git a/src/plugins/ps.rs b/src/plugins/ps.rs index 0f06167bd..342bd5eb3 100644 --- a/src/plugins/ps.rs +++ b/src/plugins/ps.rs @@ -40,7 +40,7 @@ async fn ps(tag: Tag) -> Vec> { let mut output = vec![]; while let Some(res) = processes.next().await { 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())); if let Ok(name) = process.name().await { dict.insert("name", Value::string(name)); @@ -64,7 +64,7 @@ impl Plugin for Ps { } fn begin_filter(&mut self, callinfo: CallInfo) -> Result, ShellError> { - Ok(block_on(ps(Tag::unknown_origin(callinfo.name_span))) + Ok(block_on(ps(Tag::unknown_origin(callinfo.name_tag))) .into_iter() .map(ReturnSuccess::value) .collect()) diff --git a/src/plugins/skip.rs b/src/plugins/skip.rs index cb259e99b..efd323152 100644 --- a/src/plugins/skip.rs +++ b/src/plugins/skip.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - Signature, SyntaxType, Tagged, TaggedItem, Value, + Signature, SyntaxShape, Tagged, TaggedItem, Value, }; struct Skip { @@ -15,9 +15,9 @@ impl Skip { impl Plugin for Skip { fn config(&mut self) -> Result { - Ok(Signature::build("skip") + Ok(Signature::build("skip") .desc("Skip a number of rows") - .rest(SyntaxType::Number) + .rest(SyntaxShape::Number) .filter()) } fn begin_filter(&mut self, call_info: CallInfo) -> Result, ShellError> { @@ -34,7 +34,7 @@ impl Plugin for Skip { return Err(ShellError::labeled_error( "Unrecognized type in params", "expected an integer", - arg.span(), + arg.tag(), )) } } diff --git a/src/plugins/str.rs b/src/plugins/str.rs index 99700449b..c9e82ab15 100644 --- a/src/plugins/str.rs +++ b/src/plugins/str.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - SyntaxType, Tagged, Value, + SyntaxShape, Tagged, Value, }; use regex::Regex; @@ -174,7 +174,7 @@ impl Plugin for Str { .switch("to-int") .switch("replace") .switch("find-replace") - .rest(SyntaxType::Member) + .rest(SyntaxShape::Member) .filter()) } @@ -261,7 +261,7 @@ mod tests { use super::{Action, ReplaceAction, Str}; use indexmap::IndexMap; use nu::{ - CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Span, Tag, Tagged, + CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Tag, Tagged, TaggedDictBuilder, TaggedItem, Value, }; use num_bigint::BigInt; @@ -277,6 +277,7 @@ mod tests { } struct CallStub { + origin: uuid::Uuid, positionals: Vec>, flags: IndexMap>, } @@ -284,6 +285,7 @@ mod tests { impl CallStub { fn new() -> CallStub { CallStub { + origin: uuid::Uuid::nil(), positionals: vec![], flags: indexmap::IndexMap::new(), } @@ -292,14 +294,14 @@ mod tests { fn with_long_flag(&mut self, name: &str) -> &mut Self { self.flags.insert( name.to_string(), - Value::boolean(true).simple_spanned(Span::unknown()), + Value::boolean(true).tagged(Tag::unknown()), ); self } fn with_parameter(&mut self, name: &str) -> &mut Self { self.positionals - .push(Value::string(name.to_string()).simple_spanned(Span::unknown())); + .push(Value::string(name.to_string()).tagged(Tag::unknown())); self } @@ -307,7 +309,7 @@ mod tests { CallInfo { args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())), source_map: SourceMap::new(), - name_span: Span::unknown(), + name_tag: Tag::unknown_span(self.origin), } } } diff --git a/src/plugins/sum.rs b/src/plugins/sum.rs index 32ecd7a9c..ffb39cb90 100644 --- a/src/plugins/sum.rs +++ b/src/plugins/sum.rs @@ -1,6 +1,6 @@ use nu::{ serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, - Tag, Tagged, Value, + Tagged, TaggedItem, Value, }; struct Sum { @@ -18,11 +18,10 @@ impl Sum { match &self.total { Some(Tagged { item: Value::Primitive(Primitive::Int(j)), - tag: Tag { span, .. }, + tag, }) => { //TODO: handle overflow - self.total = - Some(Tagged::from_simple_spanned_item(Value::int(i + j), span)); + self.total = Some(Value::int(i + j).tagged(*tag)); Ok(()) } None => { @@ -38,11 +37,10 @@ impl Sum { match self.total { Some(Tagged { item: Value::Primitive(Primitive::Bytes(j)), - tag: Tag { span, .. }, + tag, }) => { //TODO: handle overflow - self.total = - Some(Tagged::from_simple_spanned_item(Value::bytes(b + j), span)); + self.total = Some(Value::bytes(b + j).tagged(tag)); Ok(()) } None => { diff --git a/src/plugins/sys.rs b/src/plugins/sys.rs index db7de6e62..8030a86b8 100644 --- a/src/plugins/sys.rs +++ b/src/plugins/sys.rs @@ -315,7 +315,7 @@ impl Plugin for Sys { } fn begin_filter(&mut self, callinfo: CallInfo) -> Result, ShellError> { - Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span))) + Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_tag))) .into_iter() .map(ReturnSuccess::value) .collect()) diff --git a/src/prelude.rs b/src/prelude.rs index a491aff5d..d58e7989a 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -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; 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::registry::Signature; 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::value_shell::ValueShell; pub(crate) use crate::stream::{InputStream, OutputStream}; -pub(crate) use crate::traits::{HasSpan, ToDebug}; -pub(crate) use crate::Span; +pub(crate) use crate::traits::{HasTag, ToDebug}; pub(crate) use crate::Text; pub(crate) use bigdecimal::BigDecimal; pub(crate) use futures::stream::BoxStream; diff --git a/src/shell/filesystem_shell.rs b/src/shell/filesystem_shell.rs index 16cbf513f..1d26fa163 100644 --- a/src/shell/filesystem_shell.rs +++ b/src/shell/filesystem_shell.rs @@ -81,23 +81,27 @@ impl Shell for FilesystemShell { dirs::home_dir() } - fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result { + fn ls( + &self, + pattern: Option>, + command_tag: Tag, + ) -> Result { let cwd = self.path(); let mut full_path = PathBuf::from(self.path()); - match &args.nth(0) { - Some(value) => full_path.push(Path::new(&value.as_path()?)), + match &pattern { + Some(value) => full_path.push((*value).as_ref()), _ => {} } let entries: Vec<_> = match glob::glob(&full_path.to_string_lossy()) { Ok(files) => files.collect(), Err(_) => { - if let Some(source) = args.nth(0) { + if let Some(source) = pattern { return Err(ShellError::labeled_error( "Invalid pattern", "Invalid pattern", - source.span(), + source.tag(), )); } else { return Err(ShellError::string("Invalid pattern.")); @@ -114,17 +118,17 @@ impl Shell for FilesystemShell { let entries = std::fs::read_dir(&entry); let entries = match entries { Err(e) => { - if let Some(s) = args.nth(0) { + if let Some(s) = pattern { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - s.span(), + s.tag(), )); } else { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - args.name_span(), + command_tag, )); } } @@ -138,11 +142,7 @@ impl Shell for FilesystemShell { } else { Path::new(&filepath) }; - let value = dir_entry_dict( - filename, - &entry.metadata()?, - Tag::unknown_origin(args.call_info.name_span), - )?; + let value = dir_entry_dict(filename, &entry.metadata()?, command_tag)?; shell_entries.push_back(ReturnSuccess::value(value)) } return Ok(shell_entries.to_output_stream()); @@ -159,11 +159,7 @@ impl Shell for FilesystemShell { Path::new(&entry) }; let metadata = std::fs::metadata(&entry)?; - let value = dir_entry_dict( - filename, - &metadata, - Tag::unknown_origin(args.call_info.name_span), - )?; + let value = dir_entry_dict(filename, &metadata, command_tag)?; shell_entries.push_back(ReturnSuccess::value(value)) } } @@ -179,7 +175,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( "Can not change to home directory", "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( "Can not change to directory", "directory not found", - v.span().clone(), + v.tag().clone(), )) } } @@ -207,8 +203,7 @@ impl Shell for FilesystemShell { let mut stream = VecDeque::new(); - stream.push_back( - ReturnSuccess::change_cwd( + stream.push_back(ReturnSuccess::change_cwd( path.to_string_lossy().to_string(), )); @@ -222,10 +217,10 @@ impl Shell for FilesystemShell { dst, recursive, }: CopyArgs, - name: Span, + name: Tag, path: &str, ) -> Result { - let name_span = name; + let name_tag = name; let mut source = PathBuf::from(path); let mut destination = PathBuf::from(path); @@ -280,7 +275,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -296,7 +291,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -332,7 +327,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -346,7 +341,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -360,7 +355,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( "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( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -406,7 +401,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -420,7 +415,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( e.to_string(), e.to_string(), - name_span, + name_tag, )); } Ok(o) => o, @@ -453,7 +448,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( "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( "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( 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( &self, MkdirArgs { rest: directories }: MkdirArgs, - name: Span, + name: Tag, path: &str, ) -> Result { let full_path = PathBuf::from(path); @@ -525,7 +520,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( reason.to_string(), reason.to_string(), - dir.span(), + dir.tag(), )) } Ok(_) => {} @@ -538,10 +533,10 @@ impl Shell for FilesystemShell { fn mv( &self, MoveArgs { src, dst }: MoveArgs, - name: Span, + name: Tag, path: &str, ) -> Result { - let name_span = name; + let name_tag = name; let mut source = PathBuf::from(path); let mut destination = PathBuf::from(path); @@ -567,7 +562,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( "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( "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( 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, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -640,7 +635,7 @@ impl Shell for FilesystemShell { destination_file_name, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -662,7 +657,7 @@ impl Shell for FilesystemShell { destination_file_name, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -715,7 +710,7 @@ impl Shell for FilesystemShell { destination_file_name, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -739,7 +734,7 @@ impl Shell for FilesystemShell { destination_file_name, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -762,7 +757,7 @@ impl Shell for FilesystemShell { destination_file_name, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -794,7 +789,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( "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, e.to_string(), ), - name_span, + name_tag, )); } Ok(o) => o, @@ -830,7 +825,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( 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( &self, RemoveArgs { target, recursive }: RemoveArgs, - name: Span, + name: Tag, path: &str, ) -> Result { - let name_span = name; + let name_tag = name; if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") { return Err(ShellError::labeled_error( "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( 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( "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\".", path_file_name ), - target.span(), + target.tag(), )); } @@ -933,7 +928,7 @@ impl Shell for FilesystemShell { return Err(ShellError::labeled_error( 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( "unable to show current directory", "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(); stream.push_back(ReturnSuccess::value( 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()) diff --git a/src/shell/help_shell.rs b/src/shell/help_shell.rs index 35c939d7d..25f1b9c42 100644 --- a/src/shell/help_shell.rs +++ b/src/shell/help_shell.rs @@ -126,7 +126,11 @@ impl Shell for HelpShell { self.path = path.clone(); } - fn ls(&self, _args: EvaluatedWholeStreamCommandArgs) -> Result { + fn ls( + &self, + _pattern: Option>, + _command_tag: Tag, + ) -> Result { Ok(self .commands() .map(|x| ReturnSuccess::value(x)) @@ -161,24 +165,19 @@ impl Shell for HelpShell { Ok(stream.into()) } - fn cp(&self, _args: CopyArgs, _name: Span, _path: &str) -> Result { + fn cp(&self, _args: CopyArgs, _name: Tag, _path: &str) -> Result { Ok(OutputStream::empty()) } - fn mv(&self, _args: MoveArgs, _name: Span, _path: &str) -> Result { + fn mv(&self, _args: MoveArgs, _name: Tag, _path: &str) -> Result { Ok(OutputStream::empty()) } - fn mkdir( - &self, - _args: MkdirArgs, - _name: Span, - _path: &str, - ) -> Result { + fn mkdir(&self, _args: MkdirArgs, _name: Tag, _path: &str) -> Result { Ok(OutputStream::empty()) } - fn rm(&self, _args: RemoveArgs, _name: Span, _path: &str) -> Result { + fn rm(&self, _args: RemoveArgs, _name: Tag, _path: &str) -> Result { Ok(OutputStream::empty()) } diff --git a/src/shell/helper.rs b/src/shell/helper.rs index 16802657d..6fb454435 100644 --- a/src/shell/helper.rs +++ b/src/shell/helper.rs @@ -66,7 +66,7 @@ impl Highlighter for Helper { } 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 { Err(_) => Cow::Borrowed(line), @@ -106,47 +106,47 @@ impl Highlighter for Helper { fn paint_token_node(token_node: &TokenNode, line: &str) -> String { let styled = match token_node { - TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)), - TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)), - TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)), - TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.span().slice(line)), - TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)), - TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)), - TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)), - TokenNode::Operator(..) => Color::White.normal().paint(token_node.span().slice(line)), - TokenNode::Pipeline(..) => Color::Blue.normal().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.tag().slice(line)), + TokenNode::Flag(..) => Color::Black.bold().paint(token_node.tag().slice(line)), + TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.tag().slice(line)), + TokenNode::Path(..) => Color::Green.bold().paint(token_node.tag().slice(line)), + TokenNode::Error(..) => Color::Red.bold().paint(token_node.tag().slice(line)), + TokenNode::Delimited(..) => Color::White.paint(token_node.tag().slice(line)), + TokenNode::Operator(..) => Color::White.normal().paint(token_node.tag().slice(line)), + TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::Number(..), .. - }) => Color::Purple.bold().paint(token_node.span().slice(line)), + }) => Color::Purple.bold().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::Size(..), .. - }) => Color::Purple.bold().paint(token_node.span().slice(line)), + }) => Color::Purple.bold().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::GlobPattern, .. - }) => Color::Cyan.normal().paint(token_node.span().slice(line)), + }) => Color::Cyan.normal().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::String(..), .. - }) => Color::Green.normal().paint(token_node.span().slice(line)), + }) => Color::Green.normal().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::Variable(..), .. - }) => Color::Yellow.bold().paint(token_node.span().slice(line)), + }) => Color::Yellow.bold().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::Bare, .. - }) => Color::Green.normal().paint(token_node.span().slice(line)), + }) => Color::Green.normal().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::ExternalCommand(..), .. - }) => Color::Cyan.bold().paint(token_node.span().slice(line)), + }) => Color::Cyan.bold().paint(token_node.tag().slice(line)), TokenNode::Token(Tagged { item: RawToken::ExternalWord, .. - }) => Color::Black.bold().paint(token_node.span().slice(line)), + }) => Color::Black.bold().paint(token_node.tag().slice(line)), }; styled.to_string() @@ -166,7 +166,7 @@ fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> Str styled.push_str( &Color::Cyan .bold() - .paint(pipeline_element.call().head().span().slice(line)) + .paint(pipeline_element.call().head().tag().slice(line)) .to_string(), ); diff --git a/src/shell/shell.rs b/src/shell/shell.rs index 549aa79d2..c567e474a 100644 --- a/src/shell/shell.rs +++ b/src/shell/shell.rs @@ -13,12 +13,16 @@ pub trait Shell: std::fmt::Debug { fn name(&self, source_map: &SourceMap) -> String; fn homedir(&self) -> Option; - fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result; + fn ls( + &self, + pattern: Option>, + command_tag: Tag, + ) -> Result; fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result; - fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result; - fn mkdir(&self, args: MkdirArgs, name: Span, path: &str) -> Result; - fn mv(&self, args: MoveArgs, name: Span, path: &str) -> Result; - fn rm(&self, args: RemoveArgs, name: Span, path: &str) -> Result; + fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result; + fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result; + fn mv(&self, args: MoveArgs, name: Tag, path: &str) -> Result; + fn rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result; fn path(&self) -> String; fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result; fn set_path(&mut self, path: String); diff --git a/src/shell/shell_manager.rs b/src/shell/shell_manager.rs index 53984c950..c4c42367e 100644 --- a/src/shell/shell_manager.rs +++ b/src/shell/shell_manager.rs @@ -115,10 +115,14 @@ impl ShellManager { env[self.current_shell].homedir() } - pub fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result { + pub fn ls( + &self, + path: Option>, + command_tag: Tag, + ) -> Result { 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 { diff --git a/src/shell/value_shell.rs b/src/shell/value_shell.rs index 010c7ae08..175e232e7 100644 --- a/src/shell/value_shell.rs +++ b/src/shell/value_shell.rs @@ -87,13 +87,15 @@ impl Shell for ValueShell { Some(PathBuf::from("/")) } - fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result { + fn ls( + &self, + target: Option>, + command_name: Tag, + ) -> Result { let mut full_path = PathBuf::from(self.path()); - let target = args.nth(0); - - match target { - Some(value) => full_path.push(Path::new(&value.as_path()?)), + match &target { + Some(value) => full_path.push(value.as_ref()), _ => {} } @@ -101,18 +103,18 @@ impl Shell for ValueShell { value_system.walk_decorate(&self.value)?; if !value_system.exists(&full_path) { - if let Some(target) = target { + if let Some(target) = &target { return Err(ShellError::labeled_error( "Can not list entries inside", "No such path exists", - target.span(), + target.tag(), )); } return Err(ShellError::labeled_error( "Can not list entries inside", "No such path exists", - args.call_info.name_span, + command_name, )); } @@ -157,14 +159,14 @@ impl Shell for ValueShell { return Err(ShellError::labeled_error( "Can not change to path inside", "No such path exists", - destination.span(), + destination.tag(), )); } return Err(ShellError::labeled_error( "Can not change to path inside", "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()) } - fn cp(&self, _args: CopyArgs, name: Span, _path: &str) -> Result { + fn cp(&self, _args: CopyArgs, name: Tag, _path: &str) -> Result { Err(ShellError::labeled_error( "cp not currently supported on values", "not currently supported", @@ -181,7 +183,7 @@ impl Shell for ValueShell { )) } - fn mv(&self, _args: MoveArgs, name: Span, _path: &str) -> Result { + fn mv(&self, _args: MoveArgs, name: Tag, _path: &str) -> Result { Err(ShellError::labeled_error( "mv not currently supported on values", "not currently supported", @@ -189,7 +191,7 @@ impl Shell for ValueShell { )) } - fn mkdir(&self, _args: MkdirArgs, name: Span, _path: &str) -> Result { + fn mkdir(&self, _args: MkdirArgs, name: Tag, _path: &str) -> Result { Err(ShellError::labeled_error( "mkdir not currently supported on values", "not currently supported", @@ -197,7 +199,7 @@ impl Shell for ValueShell { )) } - fn rm(&self, _args: RemoveArgs, name: Span, _path: &str) -> Result { + fn rm(&self, _args: RemoveArgs, name: Tag, _path: &str) -> Result { Err(ShellError::labeled_error( "rm not currently supported on values", "not currently supported", @@ -213,7 +215,7 @@ impl Shell for ValueShell { let mut stream = VecDeque::new(); stream.push_back(ReturnSuccess::value(Tagged::from_item( Value::string(self.path()), - args.call_info.name_span, + args.call_info.name_tag, ))); Ok(stream.into()) } diff --git a/src/traits.rs b/src/traits.rs index 5b022c444..677d019ad 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -12,8 +12,8 @@ impl fmt::Display for Debuggable<'_, T> { } } -pub trait HasSpan { - fn span(&self) -> Span; +pub trait HasTag { + fn tag(&self) -> Tag; } pub trait ToDebug: Sized {