mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Merge pull request #643 from nushell/improve-external-words
Migrate most uses of the Span concept to Tag
This commit is contained in:
commit
4c2796f11c
97 changed files with 1174 additions and 1255 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -1474,8 +1474,8 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom5_locate"
|
name = "nom_locate"
|
||||||
version = "0.1.1"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1531,7 +1531,7 @@ dependencies = [
|
||||||
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3129,7 +3129,7 @@ dependencies = [
|
||||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||||
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||||
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
||||||
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d"
|
"checksum nom_locate 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f932834fd8e391fc7710e2ba17e8f9f8645d846b55aa63207e17e110a1e1ce35"
|
||||||
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
|
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
|
||||||
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
||||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||||
|
|
|
@ -53,7 +53,7 @@ ctrlc = "3.1.3"
|
||||||
surf = "1.0.2"
|
surf = "1.0.2"
|
||||||
url = "2.1.0"
|
url = "2.1.0"
|
||||||
roxmltree = "0.7.0"
|
roxmltree = "0.7.0"
|
||||||
nom5_locate = "0.1.1"
|
nom_locate = "1.0.0"
|
||||||
enum-utils = "0.1.1"
|
enum-utils = "0.1.1"
|
||||||
unicode-xid = "0.2.0"
|
unicode-xid = "0.2.0"
|
||||||
serde_ini = "0.2.0"
|
serde_ini = "0.2.0"
|
||||||
|
|
25
src/cli.rs
25
src/cli.rs
|
@ -266,7 +266,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
context.shell_manager.clone(),
|
context.shell_manager.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let edit_mode = crate::data::config::config(Span::unknown())?
|
let edit_mode = crate::data::config::config(Tag::unknown())?
|
||||||
.get("edit_mode")
|
.get("edit_mode")
|
||||||
.map(|s| match s.as_string().unwrap().as_ref() {
|
.map(|s| match s.as_string().unwrap().as_ref() {
|
||||||
"vi" => EditMode::Vi,
|
"vi" => EditMode::Vi,
|
||||||
|
@ -344,7 +344,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||||
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
||||||
|
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
let result = match crate::parser::parse(&line) {
|
let result = match crate::parser::parse(&line, uuid::Uuid::nil()) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return LineResult::Error(line.clone(), err);
|
return LineResult::Error(line.clone(), err);
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||||
.commands
|
.commands
|
||||||
.push(ClassifiedCommand::Internal(InternalCommand {
|
.push(ClassifiedCommand::Internal(InternalCommand {
|
||||||
command: whole_stream_command(autoview::Autoview),
|
command: whole_stream_command(autoview::Autoview),
|
||||||
name_span: Span::unknown(),
|
name_tag: Tag::unknown(),
|
||||||
args: hir::Call::new(
|
args: hir::Call::new(
|
||||||
Box::new(hir::Expression::synthetic_string("autoview")),
|
Box::new(hir::Expression::synthetic_string("autoview")),
|
||||||
None,
|
None,
|
||||||
|
@ -486,10 +486,10 @@ fn classify_command(
|
||||||
match call {
|
match call {
|
||||||
// If the command starts with `^`, treat it as an external command no matter what
|
// If the command starts with `^`, treat it as an external command no matter what
|
||||||
call if call.head().is_external() => {
|
call if call.head().is_external() => {
|
||||||
let name_span = call.head().expect_external();
|
let name_tag = call.head().expect_external();
|
||||||
let name = name_span.slice(source);
|
let name = name_tag.slice(source);
|
||||||
|
|
||||||
Ok(external_command(call, source, name.tagged(name_span)))
|
Ok(external_command(call, source, name.tagged(name_tag)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, if the command is a bare word, we'll need to triage it
|
// Otherwise, if the command is a bare word, we'll need to triage it
|
||||||
|
@ -511,19 +511,19 @@ fn classify_command(
|
||||||
|
|
||||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||||
command,
|
command,
|
||||||
name_span: head.span().clone(),
|
name_tag: head.tag(),
|
||||||
args,
|
args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, it's an external command
|
// otherwise, it's an external command
|
||||||
false => Ok(external_command(call, source, name.tagged(head.span()))),
|
false => Ok(external_command(call, source, name.tagged(head.tag()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the command is something else (like a number or a variable), that is currently unsupported.
|
// If the command is something else (like a number or a variable), that is currently unsupported.
|
||||||
// We might support `$somevar` as a curried command in the future.
|
// We might support `$somevar` as a curried command in the future.
|
||||||
call => Err(ShellError::invalid_command(call.head().span())),
|
call => Err(ShellError::invalid_command(call.head().tag())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,10 +540,7 @@ fn external_command(
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|i| match i {
|
.filter_map(|i| match i {
|
||||||
TokenNode::Whitespace(_) => None,
|
TokenNode::Whitespace(_) => None,
|
||||||
other => Some(Tagged::from_simple_spanned_item(
|
other => Some(other.as_external_arg(source).tagged(other.tag())),
|
||||||
other.as_external_arg(source),
|
|
||||||
other.span(),
|
|
||||||
)),
|
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
None => vec![],
|
None => vec![],
|
||||||
|
@ -553,7 +550,7 @@ fn external_command(
|
||||||
|
|
||||||
ClassifiedCommand::External(ExternalCommand {
|
ClassifiedCommand::External(ExternalCommand {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
name_span: tag.span,
|
name_tag: tag,
|
||||||
args: arg_list_strings,
|
args: arg_list_strings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,7 @@ impl WholeStreamCommand for CD {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("cd")
|
Signature::build("cd").optional("directory", SyntaxShape::Path)
|
||||||
.optional("directory", SyntaxType::Path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub(crate) enum ClassifiedCommand {
|
||||||
|
|
||||||
pub(crate) struct InternalCommand {
|
pub(crate) struct InternalCommand {
|
||||||
pub(crate) command: Arc<Command>,
|
pub(crate) command: Arc<Command>,
|
||||||
pub(crate) name_span: Span,
|
pub(crate) name_tag: Tag,
|
||||||
pub(crate) args: hir::Call,
|
pub(crate) args: hir::Call,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ impl InternalCommand {
|
||||||
|
|
||||||
let result = context.run_command(
|
let result = context.run_command(
|
||||||
self.command,
|
self.command,
|
||||||
self.name_span.clone(),
|
self.name_tag.clone(),
|
||||||
context.source_map.clone(),
|
context.source_map.clone(),
|
||||||
self.args,
|
self.args,
|
||||||
&source,
|
&source,
|
||||||
|
@ -133,21 +133,18 @@ impl InternalCommand {
|
||||||
match value {
|
match value {
|
||||||
Tagged {
|
Tagged {
|
||||||
item: Value::Primitive(Primitive::String(cmd)),
|
item: Value::Primitive(Primitive::String(cmd)),
|
||||||
..
|
tag,
|
||||||
} => {
|
} => {
|
||||||
context.shell_manager.insert_at_current(Box::new(
|
context.shell_manager.insert_at_current(Box::new(
|
||||||
HelpShell::for_command(
|
HelpShell::for_command(
|
||||||
Tagged::from_simple_spanned_item(
|
Value::string(cmd).tagged(tag),
|
||||||
Value::string(cmd),
|
&context.registry(),
|
||||||
Span::unknown(),
|
|
||||||
),
|
|
||||||
&context.registry().clone(),
|
|
||||||
)?,
|
)?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
context.shell_manager.insert_at_current(Box::new(
|
context.shell_manager.insert_at_current(Box::new(
|
||||||
HelpShell::index(&context.registry().clone())?,
|
HelpShell::index(&context.registry())?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +186,7 @@ impl InternalCommand {
|
||||||
pub(crate) struct ExternalCommand {
|
pub(crate) struct ExternalCommand {
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
|
|
||||||
pub(crate) name_span: Span,
|
pub(crate) name_tag: Tag,
|
||||||
pub(crate) args: Vec<Tagged<String>>,
|
pub(crate) args: Vec<Tagged<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +205,7 @@ impl ExternalCommand {
|
||||||
) -> Result<ClassifiedInputStream, ShellError> {
|
) -> Result<ClassifiedInputStream, ShellError> {
|
||||||
let stdin = input.stdin;
|
let stdin = input.stdin;
|
||||||
let inputs: Vec<Tagged<Value>> = input.objects.into_vec().await;
|
let inputs: Vec<Tagged<Value>> = input.objects.into_vec().await;
|
||||||
let name_span = self.name_span.clone();
|
let name_tag = self.name_tag.clone();
|
||||||
|
|
||||||
trace!(target: "nu::run::external", "-> {}", self.name);
|
trace!(target: "nu::run::external", "-> {}", self.name);
|
||||||
trace!(target: "nu::run::external", "inputs = {:?}", inputs);
|
trace!(target: "nu::run::external", "inputs = {:?}", inputs);
|
||||||
|
@ -227,17 +224,17 @@ impl ExternalCommand {
|
||||||
|
|
||||||
for i in &inputs {
|
for i in &inputs {
|
||||||
if i.as_string().is_err() {
|
if i.as_string().is_err() {
|
||||||
let mut span = None;
|
let mut tag = None;
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.item.contains("$it") {
|
if arg.item.contains("$it") {
|
||||||
span = Some(arg.span());
|
tag = Some(arg.tag());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(span) = span {
|
if let Some(tag) = tag {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"External $it needs string data",
|
"External $it needs string data",
|
||||||
"given row instead of string data",
|
"given row instead of string data",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::string("Error: $it needs string data"));
|
return Err(ShellError::string("Error: $it needs string data"));
|
||||||
|
@ -314,9 +311,7 @@ impl ExternalCommand {
|
||||||
let stdout = popen.stdout.take().unwrap();
|
let stdout = popen.stdout.take().unwrap();
|
||||||
let file = futures::io::AllowStdIo::new(stdout);
|
let file = futures::io::AllowStdIo::new(stdout);
|
||||||
let stream = Framed::new(file, LinesCodec {});
|
let stream = Framed::new(file, LinesCodec {});
|
||||||
let stream = stream.map(move |line| {
|
let stream = stream.map(move |line| Value::string(line.unwrap()).tagged(name_tag));
|
||||||
Tagged::from_simple_spanned_item(Value::string(line.unwrap()), name_span)
|
|
||||||
});
|
|
||||||
Ok(ClassifiedInputStream::from_input_stream(
|
Ok(ClassifiedInputStream::from_input_stream(
|
||||||
stream.boxed() as BoxStream<'static, Tagged<Value>>
|
stream.boxed() as BoxStream<'static, Tagged<Value>>
|
||||||
))
|
))
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub mod clipboard {
|
||||||
Ok(OutputStream::from(stream))
|
Ok(OutputStream::from(stream))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_clip(input: Vec<Tagged<Value>>, name: Span) -> OutputStream {
|
async fn inner_clip(input: Vec<Tagged<Value>>, name: Tag) -> OutputStream {
|
||||||
let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap();
|
let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap();
|
||||||
let mut new_copy_data = String::new();
|
let mut new_copy_data = String::new();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub struct UnevaluatedCallInfo {
|
||||||
pub args: hir::Call,
|
pub args: hir::Call,
|
||||||
pub source: Text,
|
pub source: Text,
|
||||||
pub source_map: SourceMap,
|
pub source_map: SourceMap,
|
||||||
pub name_span: Span,
|
pub name_tag: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for UnevaluatedCallInfo {
|
impl ToDebug for UnevaluatedCallInfo {
|
||||||
|
@ -38,7 +38,7 @@ impl UnevaluatedCallInfo {
|
||||||
Ok(CallInfo {
|
Ok(CallInfo {
|
||||||
args,
|
args,
|
||||||
source_map: self.source_map,
|
source_map: self.source_map,
|
||||||
name_span: self.name_span,
|
name_tag: self.name_tag,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ impl UnevaluatedCallInfo {
|
||||||
pub struct CallInfo {
|
pub struct CallInfo {
|
||||||
pub args: registry::EvaluatedArgs,
|
pub args: registry::EvaluatedArgs,
|
||||||
pub source_map: SourceMap,
|
pub source_map: SourceMap,
|
||||||
pub name_span: Span,
|
pub name_tag: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallInfo {
|
impl CallInfo {
|
||||||
|
@ -89,7 +89,7 @@ impl CallInfo {
|
||||||
args: T::deserialize(&mut deserializer)?,
|
args: T::deserialize(&mut deserializer)?,
|
||||||
context: RunnablePerItemContext {
|
context: RunnablePerItemContext {
|
||||||
shell_manager: shell_manager.clone(),
|
shell_manager: shell_manager.clone(),
|
||||||
name: self.name_span,
|
name: self.name_tag,
|
||||||
},
|
},
|
||||||
callback,
|
callback,
|
||||||
})
|
})
|
||||||
|
@ -158,7 +158,7 @@ impl CommandArgs {
|
||||||
let host = self.host.clone();
|
let host = self.host.clone();
|
||||||
let args = self.evaluate_once(registry)?;
|
let args = self.evaluate_once(registry)?;
|
||||||
let (input, args) = args.split();
|
let (input, args) = args.split();
|
||||||
let name_span = args.call_info.name_span;
|
let name_tag = args.call_info.name_tag;
|
||||||
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
|
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
|
||||||
|
|
||||||
Ok(RunnableArgs {
|
Ok(RunnableArgs {
|
||||||
|
@ -167,7 +167,7 @@ impl CommandArgs {
|
||||||
input,
|
input,
|
||||||
commands: registry.clone(),
|
commands: registry.clone(),
|
||||||
shell_manager,
|
shell_manager,
|
||||||
name: name_span,
|
name: name_tag,
|
||||||
source_map,
|
source_map,
|
||||||
host,
|
host,
|
||||||
},
|
},
|
||||||
|
@ -191,7 +191,7 @@ impl CommandArgs {
|
||||||
let host = self.host.clone();
|
let host = self.host.clone();
|
||||||
let args = self.evaluate_once(registry)?;
|
let args = self.evaluate_once(registry)?;
|
||||||
let (input, args) = args.split();
|
let (input, args) = args.split();
|
||||||
let name_span = args.call_info.name_span;
|
let name_tag = args.call_info.name_tag;
|
||||||
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
|
let mut deserializer = ConfigDeserializer::from_call_info(args.call_info);
|
||||||
|
|
||||||
Ok(RunnableRawArgs {
|
Ok(RunnableRawArgs {
|
||||||
|
@ -200,7 +200,7 @@ impl CommandArgs {
|
||||||
input,
|
input,
|
||||||
commands: registry.clone(),
|
commands: registry.clone(),
|
||||||
shell_manager,
|
shell_manager,
|
||||||
name: name_span,
|
name: name_tag,
|
||||||
source_map,
|
source_map,
|
||||||
host,
|
host,
|
||||||
},
|
},
|
||||||
|
@ -212,7 +212,7 @@ impl CommandArgs {
|
||||||
|
|
||||||
pub struct RunnablePerItemContext {
|
pub struct RunnablePerItemContext {
|
||||||
pub shell_manager: ShellManager,
|
pub shell_manager: ShellManager,
|
||||||
pub name: Span,
|
pub name: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunnablePerItemContext {
|
impl RunnablePerItemContext {
|
||||||
|
@ -227,7 +227,7 @@ pub struct RunnableContext {
|
||||||
pub host: Arc<Mutex<dyn Host>>,
|
pub host: Arc<Mutex<dyn Host>>,
|
||||||
pub commands: CommandRegistry,
|
pub commands: CommandRegistry,
|
||||||
pub source_map: SourceMap,
|
pub source_map: SourceMap,
|
||||||
pub name: Span,
|
pub name: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunnableContext {
|
impl RunnableContext {
|
||||||
|
@ -311,8 +311,8 @@ impl EvaluatedWholeStreamCommandArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_span(&self) -> Span {
|
pub fn name_tag(&self) -> Tag {
|
||||||
self.args.call_info.name_span
|
self.args.call_info.name_tag
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) {
|
pub fn parts(self) -> (InputStream, registry::EvaluatedArgs) {
|
||||||
|
@ -471,12 +471,6 @@ impl ReturnSuccess {
|
||||||
pub fn action(input: CommandAction) -> ReturnValue {
|
pub fn action(input: CommandAction) -> ReturnValue {
|
||||||
Ok(ReturnSuccess::Action(input))
|
Ok(ReturnSuccess::Action(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
|
||||||
Ok(ReturnSuccess::Value(Tagged::from_simple_spanned_item(
|
|
||||||
input, span,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WholeStreamCommand: Send + Sync {
|
pub trait WholeStreamCommand: Send + Sync {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::data::{config, Value};
|
use crate::data::{config, Value};
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::{self};
|
use crate::parser::registry::{self};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
@ -26,10 +26,10 @@ impl WholeStreamCommand for Config {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("config")
|
Signature::build("config")
|
||||||
.named("load", SyntaxType::Path)
|
.named("load", SyntaxShape::Path)
|
||||||
.named("set", SyntaxType::Any)
|
.named("set", SyntaxShape::Any)
|
||||||
.named("get", SyntaxType::Any)
|
.named("get", SyntaxShape::Any)
|
||||||
.named("remove", SyntaxType::Any)
|
.named("remove", SyntaxShape::Any)
|
||||||
.switch("clear")
|
.switch("clear")
|
||||||
.switch("path")
|
.switch("path")
|
||||||
}
|
}
|
||||||
|
@ -96,41 +96,21 @@ pub fn config(
|
||||||
|
|
||||||
config::write(&result, &configuration)?;
|
config::write(&result, &configuration)?;
|
||||||
|
|
||||||
return Ok(stream![Tagged::from_simple_spanned_item(
|
return Ok(stream![Value::Row(result.into()).tagged(value.tag())].from_input_stream());
|
||||||
Value::Row(result.into()),
|
|
||||||
value.span()
|
|
||||||
)]
|
|
||||||
.from_input_stream());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Tagged {
|
if let Tagged { item: true, tag } = clear {
|
||||||
item: true,
|
|
||||||
tag: Tag { span, .. },
|
|
||||||
} = clear
|
|
||||||
{
|
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
config::write(&result, &configuration)?;
|
config::write(&result, &configuration)?;
|
||||||
|
|
||||||
return Ok(stream![Tagged::from_simple_spanned_item(
|
return Ok(stream![Value::Row(result.into()).tagged(tag)].from_input_stream());
|
||||||
Value::Row(result.into()),
|
|
||||||
span
|
|
||||||
)]
|
|
||||||
.from_input_stream());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Tagged {
|
if let Tagged { item: true, tag } = path {
|
||||||
item: true,
|
|
||||||
tag: Tag { span, .. },
|
|
||||||
} = path
|
|
||||||
{
|
|
||||||
let path = config::default_path_for(&configuration)?;
|
let path = config::default_path_for(&configuration)?;
|
||||||
|
|
||||||
return Ok(stream![Tagged::from_simple_spanned_item(
|
return Ok(stream![Value::Primitive(Primitive::Path(path)).tagged(tag)].from_input_stream());
|
||||||
Value::Primitive(Primitive::Path(path)),
|
|
||||||
span
|
|
||||||
)]
|
|
||||||
.from_input_stream());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = remove {
|
if let Some(v) = remove {
|
||||||
|
@ -146,9 +126,9 @@ pub fn config(
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let obj = VecDeque::from_iter(vec![Value::Row(result.into()).simple_spanned(v.span())]);
|
let obj = VecDeque::from_iter(vec![Value::Row(result.into()).tagged(v.tag())]);
|
||||||
return Ok(obj.from_input_stream());
|
return Ok(obj.from_input_stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(vec![Value::Row(result.into()).simple_spanned(name)].into());
|
return Ok(vec![Value::Row(result.into()).tagged(name)].into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::command::RunnablePerItemContext;
|
use crate::commands::command::RunnablePerItemContext;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::{CommandRegistry, Signature};
|
use crate::parser::registry::{CommandRegistry, Signature};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -21,9 +21,9 @@ impl PerItemCommand for Cpy {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("cp")
|
Signature::build("cp")
|
||||||
.required("src", SyntaxType::Pattern)
|
.required("src", SyntaxShape::Pattern)
|
||||||
.required("dst", SyntaxType::Path)
|
.required("dst", SyntaxShape::Path)
|
||||||
.named("file", SyntaxType::Any)
|
.named("file", SyntaxShape::Any)
|
||||||
.switch("recursive")
|
.switch("recursive")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{Dictionary, Value};
|
use crate::data::{Dictionary, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use chrono::{DateTime, Local, Utc};
|
use chrono::{DateTime, Local, Utc};
|
||||||
|
|
||||||
|
@ -33,58 +33,40 @@ impl WholeStreamCommand for Date {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, span: Span) -> Tagged<Value>
|
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag) -> Tagged<Value>
|
||||||
where
|
where
|
||||||
T::Offset: Display,
|
T::Offset: Display,
|
||||||
{
|
{
|
||||||
let mut indexmap = IndexMap::new();
|
let mut indexmap = IndexMap::new();
|
||||||
|
|
||||||
indexmap.insert(
|
indexmap.insert("year".to_string(), Value::int(dt.year()).tagged(tag));
|
||||||
"year".to_string(),
|
indexmap.insert("month".to_string(), Value::int(dt.month()).tagged(tag));
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.year()), span),
|
indexmap.insert("day".to_string(), Value::int(dt.day()).tagged(tag));
|
||||||
);
|
indexmap.insert("hour".to_string(), Value::int(dt.hour()).tagged(tag));
|
||||||
indexmap.insert(
|
indexmap.insert("minute".to_string(), Value::int(dt.minute()).tagged(tag));
|
||||||
"month".to_string(),
|
indexmap.insert("second".to_string(), Value::int(dt.second()).tagged(tag));
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.month()), span),
|
|
||||||
);
|
|
||||||
indexmap.insert(
|
|
||||||
"day".to_string(),
|
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.day()), span),
|
|
||||||
);
|
|
||||||
indexmap.insert(
|
|
||||||
"hour".to_string(),
|
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.hour()), span),
|
|
||||||
);
|
|
||||||
indexmap.insert(
|
|
||||||
"minute".to_string(),
|
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.minute()), span),
|
|
||||||
);
|
|
||||||
indexmap.insert(
|
|
||||||
"second".to_string(),
|
|
||||||
Tagged::from_simple_spanned_item(Value::int(dt.second()), span),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tz = dt.offset();
|
let tz = dt.offset();
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"timezone".to_string(),
|
"timezone".to_string(),
|
||||||
Tagged::from_simple_spanned_item(Value::string(format!("{}", tz)), span),
|
Value::string(format!("{}", tz)).tagged(tag),
|
||||||
);
|
);
|
||||||
|
|
||||||
Tagged::from_simple_spanned_item(Value::Row(Dictionary::from(indexmap)), span)
|
Value::Row(Dictionary::from(indexmap)).tagged(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
|
|
||||||
let mut date_out = VecDeque::new();
|
let mut date_out = VecDeque::new();
|
||||||
let span = args.call_info.name_span;
|
let tag = args.call_info.name_tag;
|
||||||
|
|
||||||
let value = if args.has("utc") {
|
let value = if args.has("utc") {
|
||||||
let utc: DateTime<Utc> = Utc::now();
|
let utc: DateTime<Utc> = Utc::now();
|
||||||
date_to_value(utc, span)
|
date_to_value(utc, tag)
|
||||||
} else {
|
} else {
|
||||||
let local: DateTime<Local> = Local::now();
|
let local: DateTime<Local> = Local::now();
|
||||||
date_to_value(local, span)
|
date_to_value(local, tag)
|
||||||
};
|
};
|
||||||
|
|
||||||
date_out.push_back(value);
|
date_out.push_back(value);
|
||||||
|
|
|
@ -12,7 +12,7 @@ impl PerItemCommand for Echo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("echo").rest(SyntaxType::Any)
|
Signature::build("echo").rest(SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -35,7 +35,7 @@ fn run(
|
||||||
_registry: &CommandRegistry,
|
_registry: &CommandRegistry,
|
||||||
_raw_args: &RawCommandArgs,
|
_raw_args: &RawCommandArgs,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name = call_info.name_span;
|
let name = call_info.name_tag;
|
||||||
|
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ fn run(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expect a string from pipeline",
|
"Expect a string from pipeline",
|
||||||
"not a string-compatible value",
|
"not a string-compatible value",
|
||||||
i.span(),
|
i.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ fn run(
|
||||||
}
|
}
|
||||||
|
|
||||||
let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value(
|
let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value(
|
||||||
Value::string(output).simple_spanned(name),
|
Value::string(output).tagged(name),
|
||||||
))]);
|
))]);
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
Ok(stream.to_output_stream())
|
||||||
|
|
|
@ -14,7 +14,7 @@ impl PerItemCommand for Enter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> registry::Signature {
|
fn signature(&self) -> registry::Signature {
|
||||||
Signature::build("enter").required("location", SyntaxType::Block)
|
Signature::build("enter").required("location", SyntaxShape::Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -70,7 +70,7 @@ impl PerItemCommand for Enter {
|
||||||
crate::commands::open::fetch(
|
crate::commands::open::fetch(
|
||||||
&full_path,
|
&full_path,
|
||||||
&location_clone,
|
&location_clone,
|
||||||
Span::unknown(),
|
Tag::unknown(),
|
||||||
)
|
)
|
||||||
.await.unwrap();
|
.await.unwrap();
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ impl PerItemCommand for Enter {
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut result = converter.run(
|
let mut result = converter.run(
|
||||||
|
|
|
@ -2,14 +2,13 @@ use crate::commands::UnevaluatedCallInfo;
|
||||||
use crate::context::SpanSource;
|
use crate::context::SpanSource;
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::Signature;
|
use crate::parser::registry::Signature;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use surf::mime;
|
use surf::mime;
|
||||||
use uuid::Uuid;
|
|
||||||
pub struct Fetch;
|
pub struct Fetch;
|
||||||
|
|
||||||
impl PerItemCommand for Fetch {
|
impl PerItemCommand for Fetch {
|
||||||
|
@ -19,7 +18,7 @@ impl PerItemCommand for Fetch {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.required("path", SyntaxType::Path)
|
.required("path", SyntaxShape::Path)
|
||||||
.switch("raw")
|
.switch("raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,14 +51,14 @@ fn run(
|
||||||
};
|
};
|
||||||
let path_buf = path.as_path()?;
|
let path_buf = path.as_path()?;
|
||||||
let path_str = path_buf.display().to_string();
|
let path_str = path_buf.display().to_string();
|
||||||
let path_span = path.span();
|
let path_tag = path.tag();
|
||||||
let has_raw = call_info.args.has("raw");
|
let has_raw = call_info.args.has("raw");
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let raw_args = raw_args.clone();
|
let raw_args = raw_args.clone();
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
|
||||||
let result = fetch(&path_str, path_span).await;
|
let result = fetch(&path_str, path_tag).await;
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
yield Err(e);
|
yield Err(e);
|
||||||
|
@ -99,7 +98,7 @@ fn run(
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
||||||
|
@ -130,13 +129,13 @@ fn run(
|
||||||
|
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
location: &str,
|
location: &str,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
||||||
if let Err(_) = url::Url::parse(location) {
|
if let Err(_) = url::Url::parse(location) {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Incomplete or incorrect url",
|
"Incomplete or incorrect url",
|
||||||
"expected a full url",
|
"expected a full url",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +151,10 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::JSON) => Ok((
|
(mime::APPLICATION, mime::JSON) => Ok((
|
||||||
|
@ -167,13 +163,10 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
||||||
|
@ -181,16 +174,13 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load binary file",
|
"Could not load binary file",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((
|
Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -200,13 +190,10 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load svg from remote url",
|
"Could not load svg from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::IMAGE, image_ty) => {
|
(mime::IMAGE, image_ty) => {
|
||||||
|
@ -214,16 +201,13 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load image file",
|
"Could not load image file",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((
|
Ok((
|
||||||
Some(image_ty.to_string()),
|
Some(image_ty.to_string()),
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -233,13 +217,10 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::TEXT, mime::PLAIN) => {
|
(mime::TEXT, mime::PLAIN) => {
|
||||||
|
@ -260,23 +241,17 @@ pub async fn fetch(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
(ty, sub_ty) => Ok((
|
(ty, sub_ty) => Ok((
|
||||||
None,
|
None,
|
||||||
Value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)),
|
Value::string(format!("Not yet supported MIME type: {} {}", ty, sub_ty)),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -284,10 +259,7 @@ pub async fn fetch(
|
||||||
None => Ok((
|
None => Ok((
|
||||||
None,
|
None,
|
||||||
Value::string(format!("No content type found")),
|
Value::string(format!("No content type found")),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
@ -295,7 +267,7 @@ pub async fn fetch(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"URL could not be opened",
|
"URL could not be opened",
|
||||||
"url not found",
|
"url not found",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl WholeStreamCommand for First {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("first")
|
Signature::build("first")
|
||||||
.required("amount", SyntaxType::Literal)
|
.required("amount", SyntaxShape::Literal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ExpectedRange;
|
|
||||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||||
|
use crate::errors::ExpectedRange;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bson::{decode_document, spec::BinarySubtype, Bson};
|
use bson::{decode_document, spec::BinarySubtype, Bson};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -198,7 +198,7 @@ pub fn from_bson_bytes_to_value(
|
||||||
|
|
||||||
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -208,24 +208,24 @@ fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
let value_tag = value.tag();
|
let value_tag = value.tag();
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Binary(vb) =>
|
Value::Binary(vb) =>
|
||||||
match from_bson_bytes_to_value(vb, span) {
|
match from_bson_bytes_to_value(vb, tag) {
|
||||||
Ok(x) => yield ReturnSuccess::value(x),
|
Ok(x) => yield ReturnSuccess::value(x),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as BSON",
|
"Could not parse as BSON",
|
||||||
"input cannot be parsed as BSON",
|
"input cannot be parsed as BSON",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn from_csv(
|
||||||
}: FromCSVArgs,
|
}: FromCSVArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
@ -105,15 +105,15 @@ fn from_csv(
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_csv_string_to_value(concat_string, skip_headers, name_span) {
|
match from_csv_string_to_value(concat_string, skip_headers, name_tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -126,9 +126,9 @@ fn from_csv(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as CSV",
|
"Could not parse as CSV",
|
||||||
"input cannot be parsed as CSV",
|
"input cannot be parsed as CSV",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub fn from_ini_string_to_value(
|
||||||
|
|
||||||
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -84,15 +84,15 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_ini_string_to_value(concat_string, span) {
|
match from_ini_string_to_value(concat_string, tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -105,9 +105,9 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as INI",
|
"Could not parse as INI",
|
||||||
"input cannot be parsed as INI",
|
"input cannot be parsed as INI",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ fn from_json(
|
||||||
FromJSONArgs { objects }: FromJSONArgs,
|
FromJSONArgs { objects }: FromJSONArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
@ -91,9 +91,9 @@ fn from_json(
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ fn from_json(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_json_string_to_value(json_str.to_string(), name_span) {
|
match from_json_string_to_value(json_str.to_string(), name_tag) {
|
||||||
Ok(x) =>
|
Ok(x) =>
|
||||||
yield ReturnSuccess::value(x),
|
yield ReturnSuccess::value(x),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -114,15 +114,15 @@ fn from_json(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could nnot parse as JSON",
|
"Could nnot parse as JSON",
|
||||||
"input cannot be parsed as JSON",
|
"input cannot be parsed as JSON",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span))
|
last_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match from_json_string_to_value(concat_string, name_span) {
|
match from_json_string_to_value(concat_string, name_tag) {
|
||||||
Ok(x) =>
|
Ok(x) =>
|
||||||
match x {
|
match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
|
@ -137,9 +137,9 @@ fn from_json(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as JSON",
|
"Could not parse as JSON",
|
||||||
"input cannot be parsed as JSON",
|
"input cannot be parsed as JSON",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span))
|
last_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub fn from_sqlite_bytes_to_value(
|
||||||
|
|
||||||
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -138,7 +138,7 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
|
||||||
let value_tag = value.tag();
|
let value_tag = value.tag();
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Binary(vb) =>
|
Value::Binary(vb) =>
|
||||||
match from_sqlite_bytes_to_value(vb, span) {
|
match from_sqlite_bytes_to_value(vb, tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -151,18 +151,18 @@ fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as SQLite",
|
"Could not parse as SQLite",
|
||||||
"input cannot be parsed as SQLite",
|
"input cannot be parsed as SQLite",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub fn from_toml(
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -88,15 +88,15 @@ pub fn from_toml(
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_toml_string_to_value(concat_string, span) {
|
match from_toml_string_to_value(concat_string, tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -109,9 +109,9 @@ pub fn from_toml(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as TOML",
|
"Could not parse as TOML",
|
||||||
"input cannot be parsed as TOML",
|
"input cannot be parsed as TOML",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn from_tsv(
|
||||||
}: FromTSVArgs,
|
}: FromTSVArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
@ -106,15 +106,15 @@ fn from_tsv(
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_tsv_string_to_value(concat_string, skip_headers, name_span) {
|
match from_tsv_string_to_value(concat_string, skip_headers, name_tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -127,9 +127,9 @@ fn from_tsv(
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as TSV",
|
"Could not parse as TSV",
|
||||||
"input cannot be parsed as TSV",
|
"input cannot be parsed as TSV",
|
||||||
name_span,
|
name_tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub fn from_xml_string_to_value(
|
||||||
|
|
||||||
fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -103,15 +103,15 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_xml_string_to_value(concat_string, span) {
|
match from_xml_string_to_value(concat_string, tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -124,9 +124,9 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as XML",
|
"Could not parse as XML",
|
||||||
"input cannot be parsed as XML",
|
"input cannot be parsed as XML",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ pub fn from_yaml_string_to_value(
|
||||||
|
|
||||||
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -117,15 +117,15 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
value_tag.span,
|
value_tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match from_yaml_string_to_value(concat_string, span) {
|
match from_yaml_string_to_value(concat_string, tag) {
|
||||||
Ok(x) => match x {
|
Ok(x) => match x {
|
||||||
Tagged { item: Value::Table(list), .. } => {
|
Tagged { item: Value::Table(list), .. } => {
|
||||||
for l in list {
|
for l in list {
|
||||||
|
@ -138,9 +138,9 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as YAML",
|
"Could not parse as YAML",
|
||||||
"input cannot be parsed as YAML",
|
"input cannot be parsed as YAML",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
last_tag.span,
|
last_tag,
|
||||||
))
|
))
|
||||||
} ,
|
} ,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Get;
|
pub struct Get;
|
||||||
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for Get {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("get").rest(SyntaxType::Member)
|
Signature::build("get").rest(SyntaxShape::Member)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -47,7 +47,7 @@ fn get_member(path: &Tagged<String>, obj: &Tagged<Value>) -> Result<Tagged<Value
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Unknown column",
|
"Unknown column",
|
||||||
"table missing column",
|
"table missing column",
|
||||||
path.span(),
|
path.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::commands::command::CommandAction;
|
use crate::commands::command::CommandAction;
|
||||||
use crate::commands::PerItemCommand;
|
use crate::commands::PerItemCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{command_dict, TaggedDictBuilder};
|
use crate::data::{command_dict, TaggedDictBuilder};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::parser::registry;
|
use crate::parser::registry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ impl PerItemCommand for Help {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> registry::Signature {
|
fn signature(&self) -> registry::Signature {
|
||||||
Signature::build("help").rest(SyntaxType::Any)
|
Signature::build("help").rest(SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -27,11 +27,11 @@ impl PerItemCommand for Help {
|
||||||
_raw_args: &RawCommandArgs,
|
_raw_args: &RawCommandArgs,
|
||||||
_input: Tagged<Value>,
|
_input: Tagged<Value>,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let span = call_info.name_span;
|
let tag = call_info.name_tag;
|
||||||
|
|
||||||
if call_info.args.len() == 0 {
|
if call_info.args.len() == 0 {
|
||||||
return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
|
||||||
Tagged::from_simple_spanned_item(Value::nothing(), span),
|
Value::nothing().tagged(tag),
|
||||||
)))]
|
)))]
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for Last {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("last").required("amount", SyntaxType::Number)
|
Signature::build("last").required("amount", SyntaxShape::Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{Primitive, Value};
|
use crate::data::{Primitive, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ impl WholeStreamCommand for Lines {
|
||||||
|
|
||||||
fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.name_span();
|
let tag = args.name_tag();
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let input: InputStream = trace_stream!(target: "nu::trace_stream::lines", "input" = input);
|
let input: InputStream = trace_stream!(target: "nu::trace_stream::lines", "input" = input);
|
||||||
|
@ -58,9 +58,9 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||||
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.span(),
|
v.tag(),
|
||||||
)));
|
)));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub struct LS;
|
pub struct LS;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct LsArgs {
|
||||||
|
path: Option<Tagged<PathBuf>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WholeStreamCommand for LS {
|
impl WholeStreamCommand for LS {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"ls"
|
"ls"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("ls").optional("path", SyntaxType::Pattern)
|
Signature::build("ls").optional("path", SyntaxShape::Pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -22,12 +28,11 @@ impl WholeStreamCommand for LS {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
ls(args, registry)
|
args.process(registry, ls)?.run()
|
||||||
|
// ls(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn ls(LsArgs { path }: LsArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
||||||
let shell_manager = args.shell_manager.clone();
|
context.shell_manager.ls(path, context.name)
|
||||||
let args = args.evaluate_once(registry)?;
|
|
||||||
shell_manager.ls(args)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl PerItemCommand for Mkdir {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("mkdir").rest(SyntaxType::Path)
|
Signature::build("mkdir").rest(SyntaxShape::Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::command::RunnablePerItemContext;
|
use crate::commands::command::RunnablePerItemContext;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::{CommandRegistry, Signature};
|
use crate::parser::registry::{CommandRegistry, Signature};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -20,9 +20,9 @@ impl PerItemCommand for Move {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("mv")
|
Signature::build("mv")
|
||||||
.required("source", SyntaxType::Path)
|
.required("source", SyntaxShape::Pattern)
|
||||||
.required("destination", SyntaxType::Path)
|
.required("destination", SyntaxShape::Path)
|
||||||
.named("file", SyntaxType::Any)
|
.named("file", SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for Nth {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("nth").required("amount", SyntaxType::Any)
|
Signature::build("nth").required("amount", SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -2,11 +2,10 @@ use crate::commands::UnevaluatedCallInfo;
|
||||||
use crate::context::SpanSource;
|
use crate::context::SpanSource;
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::Signature;
|
use crate::parser::registry::Signature;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use uuid::Uuid;
|
|
||||||
pub struct Open;
|
pub struct Open;
|
||||||
|
|
||||||
impl PerItemCommand for Open {
|
impl PerItemCommand for Open {
|
||||||
|
@ -16,7 +15,7 @@ impl PerItemCommand for Open {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.required("path", SyntaxType::Path)
|
.required("path", SyntaxShape::Path)
|
||||||
.switch("raw")
|
.switch("raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ fn run(
|
||||||
};
|
};
|
||||||
let path_buf = path.as_path()?;
|
let path_buf = path.as_path()?;
|
||||||
let path_str = path_buf.display().to_string();
|
let path_str = path_buf.display().to_string();
|
||||||
let path_span = path.span();
|
let path_span = path.tag();
|
||||||
let has_raw = call_info.args.has("raw");
|
let has_raw = call_info.args.has("raw");
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let raw_args = raw_args.clone();
|
let raw_args = raw_args.clone();
|
||||||
|
@ -100,7 +99,7 @@ fn run(
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
||||||
|
@ -132,7 +131,7 @@ fn run(
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
cwd: &PathBuf,
|
cwd: &PathBuf,
|
||||||
location: &str,
|
location: &str,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
||||||
let mut cwd = cwd.clone();
|
let mut cwd = cwd.clone();
|
||||||
|
|
||||||
|
@ -144,10 +143,7 @@ pub async fn fetch(
|
||||||
cwd.extension()
|
cwd.extension()
|
||||||
.map(|name| name.to_string_lossy().to_string()),
|
.map(|name| name.to_string_lossy().to_string()),
|
||||||
Value::string(s),
|
Value::string(s),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -163,19 +159,13 @@ pub async fn fetch(
|
||||||
cwd.extension()
|
cwd.extension()
|
||||||
.map(|name| name.to_string_lossy().to_string()),
|
.map(|name| name.to_string_lossy().to_string()),
|
||||||
Value::string(s),
|
Value::string(s),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
Err(_) => Ok((
|
Err(_) => Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -183,10 +173,7 @@ pub async fn fetch(
|
||||||
Ok((
|
Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -201,19 +188,13 @@ pub async fn fetch(
|
||||||
cwd.extension()
|
cwd.extension()
|
||||||
.map(|name| name.to_string_lossy().to_string()),
|
.map(|name| name.to_string_lossy().to_string()),
|
||||||
Value::string(s),
|
Value::string(s),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
Err(_) => Ok((
|
Err(_) => Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -221,10 +202,7 @@ pub async fn fetch(
|
||||||
Ok((
|
Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -232,10 +210,7 @@ pub async fn fetch(
|
||||||
_ => Ok((
|
_ => Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -245,7 +220,7 @@ pub async fn fetch(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"File could not be opened",
|
"File could not be opened",
|
||||||
"file not found",
|
"file not found",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +228,7 @@ pub async fn fetch(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"File could not be opened",
|
"File could not be opened",
|
||||||
"file not found",
|
"file not found",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl WholeStreamCommand for Pick {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("pick").rest(SyntaxType::Any)
|
Signature::build("pick").rest(SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::commands::UnevaluatedCallInfo;
|
use crate::commands::UnevaluatedCallInfo;
|
||||||
use crate::context::SpanSource;
|
use crate::context::SpanSource;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::errors::ShellError;
|
||||||
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::Signature;
|
use crate::parser::registry::Signature;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use base64::encode;
|
use base64::encode;
|
||||||
|
@ -10,7 +10,7 @@ use mime::Mime;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use surf::mime;
|
use surf::mime;
|
||||||
use uuid::Uuid;
|
|
||||||
pub struct Post;
|
pub struct Post;
|
||||||
|
|
||||||
impl PerItemCommand for Post {
|
impl PerItemCommand for Post {
|
||||||
|
@ -20,10 +20,10 @@ impl PerItemCommand for Post {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.required("path", SyntaxType::Any)
|
.required("path", SyntaxShape::Any)
|
||||||
.required("body", SyntaxType::Any)
|
.required("body", SyntaxShape::Any)
|
||||||
.named("user", SyntaxType::Any)
|
.named("user", SyntaxShape::Any)
|
||||||
.named("password", SyntaxType::Any)
|
.named("password", SyntaxShape::Any)
|
||||||
.switch("raw")
|
.switch("raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ fn run(
|
||||||
file => file.clone(),
|
file => file.clone(),
|
||||||
};
|
};
|
||||||
let path_str = path.as_string()?;
|
let path_str = path.as_string()?;
|
||||||
let path_span = path.span();
|
let path_span = path.tag();
|
||||||
let has_raw = call_info.args.has("raw");
|
let has_raw = call_info.args.has("raw");
|
||||||
let user = call_info.args.get("user").map(|x| x.as_string().unwrap());
|
let user = call_info.args.get("user").map(|x| x.as_string().unwrap());
|
||||||
let password = call_info
|
let password = call_info
|
||||||
|
@ -109,7 +109,7 @@ fn run(
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry);
|
||||||
|
@ -143,7 +143,7 @@ pub async fn post(
|
||||||
body: &Tagged<Value>,
|
body: &Tagged<Value>,
|
||||||
user: Option<String>,
|
user: Option<String>,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
raw_args: &RawCommandArgs,
|
raw_args: &RawCommandArgs,
|
||||||
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
||||||
|
@ -189,7 +189,7 @@ pub async fn post(
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut result = converter.run(
|
let mut result = converter.run(
|
||||||
|
@ -211,7 +211,7 @@ pub async fn post(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Save could not successfully save",
|
"Save could not successfully save",
|
||||||
"unexpected data during save",
|
"unexpected data during save",
|
||||||
span,
|
*tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ pub async fn post(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Could not automatically convert table",
|
"Could not automatically convert table",
|
||||||
"needs manual conversion",
|
"needs manual conversion",
|
||||||
tag.span,
|
*tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,13 +243,10 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::JSON) => Ok((
|
(mime::APPLICATION, mime::JSON) => Ok((
|
||||||
|
@ -258,13 +255,10 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
||||||
|
@ -272,16 +266,13 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load binary file",
|
"Could not load binary file",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((
|
Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -290,16 +281,13 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load image file",
|
"Could not load image file",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((
|
Ok((
|
||||||
Some(image_ty.to_string()),
|
Some(image_ty.to_string()),
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -309,13 +297,10 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::TEXT, mime::PLAIN) => {
|
(mime::TEXT, mime::PLAIN) => {
|
||||||
|
@ -336,13 +321,10 @@ pub async fn post(
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not load text from remote url",
|
"Could not load text from remote url",
|
||||||
"could not load",
|
"could not load",
|
||||||
span,
|
tag,
|
||||||
)
|
)
|
||||||
})?),
|
})?),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -352,10 +334,7 @@ pub async fn post(
|
||||||
"Not yet supported MIME type: {} {}",
|
"Not yet supported MIME type: {} {}",
|
||||||
ty, sub_ty
|
ty, sub_ty
|
||||||
)),
|
)),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -363,10 +342,7 @@ pub async fn post(
|
||||||
None => Ok((
|
None => Ok((
|
||||||
None,
|
None,
|
||||||
Value::string(format!("No content type found")),
|
Value::string(format!("No content type found")),
|
||||||
Tag {
|
tag,
|
||||||
span,
|
|
||||||
origin: Some(Uuid::new_v4()),
|
|
||||||
},
|
|
||||||
SpanSource::Url(location.to_string()),
|
SpanSource::Url(location.to_string()),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
@ -374,7 +350,7 @@ pub async fn post(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"URL could not be opened",
|
"URL could not be opened",
|
||||||
"url not found",
|
"url not found",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,7 +358,7 @@ pub async fn post(
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"Expected a url",
|
"Expected a url",
|
||||||
"needs a url",
|
"needs a url",
|
||||||
span,
|
tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for Reject {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("reject").rest(SyntaxType::Member)
|
Signature::build("reject").rest(SyntaxShape::Member)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::command::RunnablePerItemContext;
|
use crate::commands::command::RunnablePerItemContext;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry::{CommandRegistry, Signature};
|
use crate::parser::registry::{CommandRegistry, Signature};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -20,7 +20,7 @@ impl PerItemCommand for Remove {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("rm")
|
Signature::build("rm")
|
||||||
.required("path", SyntaxType::Path)
|
.required("path", SyntaxShape::Pattern)
|
||||||
.switch("recursive")
|
.switch("recursive")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
||||||
pub struct Save;
|
pub struct Save;
|
||||||
|
|
||||||
macro_rules! process_string {
|
macro_rules! process_string {
|
||||||
($input:ident, $name_span:ident) => {{
|
($input:ident, $name_tag:ident) => {{
|
||||||
let mut result_string = String::new();
|
let mut result_string = String::new();
|
||||||
for res in $input {
|
for res in $input {
|
||||||
match res {
|
match res {
|
||||||
|
@ -21,7 +21,7 @@ macro_rules! process_string {
|
||||||
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
||||||
"Save could not successfully save",
|
"Save could not successfully save",
|
||||||
"unexpected data during save",
|
"unexpected data during save",
|
||||||
$name_span,
|
$name_tag,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ macro_rules! process_string {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! process_string_return_success {
|
macro_rules! process_string_return_success {
|
||||||
($result_vec:ident, $name_span:ident) => {{
|
($result_vec:ident, $name_tag:ident) => {{
|
||||||
let mut result_string = String::new();
|
let mut result_string = String::new();
|
||||||
for res in $result_vec {
|
for res in $result_vec {
|
||||||
match res {
|
match res {
|
||||||
|
@ -45,7 +45,7 @@ macro_rules! process_string_return_success {
|
||||||
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
||||||
"Save could not successfully save",
|
"Save could not successfully save",
|
||||||
"unexpected data during text save",
|
"unexpected data during text save",
|
||||||
$name_span,
|
$name_tag,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ macro_rules! process_string_return_success {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! process_binary_return_success {
|
macro_rules! process_binary_return_success {
|
||||||
($result_vec:ident, $name_span:ident) => {{
|
($result_vec:ident, $name_tag:ident) => {{
|
||||||
let mut result_binary: Vec<u8> = Vec::new();
|
let mut result_binary: Vec<u8> = Vec::new();
|
||||||
for res in $result_vec {
|
for res in $result_vec {
|
||||||
match res {
|
match res {
|
||||||
|
@ -71,7 +71,7 @@ macro_rules! process_binary_return_success {
|
||||||
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
yield core::task::Poll::Ready(Err(ShellError::labeled_error(
|
||||||
"Save could not successfully save",
|
"Save could not successfully save",
|
||||||
"unexpected data during binary save",
|
"unexpected data during binary save",
|
||||||
$name_span,
|
$name_tag,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ impl WholeStreamCommand for Save {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("save")
|
Signature::build("save")
|
||||||
.optional("path", SyntaxType::Path)
|
.optional("path", SyntaxShape::Path)
|
||||||
.switch("raw")
|
.switch("raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ fn save(
|
||||||
raw_args: RawCommandArgs,
|
raw_args: RawCommandArgs,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let mut full_path = PathBuf::from(shell_manager.path());
|
let mut full_path = PathBuf::from(shell_manager.path());
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let source_map = source_map.clone();
|
let source_map = source_map.clone();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
|
@ -145,7 +145,7 @@ fn save(
|
||||||
yield Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -153,7 +153,7 @@ fn save(
|
||||||
yield Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ fn save(
|
||||||
yield Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -185,21 +185,21 @@ fn save(
|
||||||
},
|
},
|
||||||
source: raw_args.call_info.source,
|
source: raw_args.call_info.source,
|
||||||
source_map: raw_args.call_info.source_map,
|
source_map: raw_args.call_info.source_map,
|
||||||
name_span: raw_args.call_info.name_span,
|
name_tag: raw_args.call_info.name_tag,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut result = converter.run(new_args.with_input(input), ®istry);
|
let mut result = converter.run(new_args.with_input(input), ®istry);
|
||||||
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await;
|
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await;
|
||||||
if converter.is_binary() {
|
if converter.is_binary() {
|
||||||
process_binary_return_success!(result_vec, name_span)
|
process_binary_return_success!(result_vec, name_tag)
|
||||||
} else {
|
} else {
|
||||||
process_string_return_success!(result_vec, name_span)
|
process_string_return_success!(result_vec, name_tag)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
process_string!(input, name_span)
|
process_string!(input, name_tag)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
process_string!(input, name_span)
|
process_string!(input, name_tag)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(string_from(&input).into_bytes())
|
Ok(string_from(&input).into_bytes())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::TaggedDictBuilder;
|
use crate::data::TaggedDictBuilder;
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Shells;
|
pub struct Shells;
|
||||||
|
@ -29,10 +29,10 @@ impl WholeStreamCommand for Shells {
|
||||||
|
|
||||||
fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let mut shells_out = VecDeque::new();
|
let mut shells_out = VecDeque::new();
|
||||||
let span = args.call_info.name_span;
|
let tag = args.call_info.name_tag;
|
||||||
|
|
||||||
for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() {
|
for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() {
|
||||||
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span));
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
if index == args.shell_manager.current_shell {
|
if index == args.shell_manager.current_shell {
|
||||||
dict.insert(" ", "X".to_string());
|
dict.insert(" ", "X".to_string());
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{TaggedDictBuilder, Value};
|
use crate::data::{TaggedDictBuilder, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Size;
|
pub struct Size;
|
||||||
|
@ -29,7 +29,7 @@ impl WholeStreamCommand for Size {
|
||||||
|
|
||||||
fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
let span = args.call_info.name_span;
|
let tag = args.call_info.name_tag;
|
||||||
Ok(input
|
Ok(input
|
||||||
.values
|
.values
|
||||||
.map(move |v| match v.item {
|
.map(move |v| match v.item {
|
||||||
|
@ -37,9 +37,9 @@ fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||||
_ => Err(ShellError::labeled_error_with_secondary(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a string from pipeline",
|
"Expected a string from pipeline",
|
||||||
"requires string input",
|
"requires string input",
|
||||||
span,
|
tag,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.span(),
|
v.tag(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
@ -71,7 +71,7 @@ fn count(contents: &str, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dict = TaggedDictBuilder::new(tag);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
//TODO: add back in name when we have it in the span
|
//TODO: add back in name when we have it in the tag
|
||||||
//dict.insert("name", Value::string(name));
|
//dict.insert("name", Value::string(name));
|
||||||
dict.insert("lines", Value::int(lines));
|
dict.insert("lines", Value::int(lines));
|
||||||
dict.insert("words", Value::int(words));
|
dict.insert("words", Value::int(words));
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for SkipWhile {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("skip-while")
|
Signature::build("skip-while")
|
||||||
.required("condition", SyntaxType::Block)
|
.required("condition", SyntaxShape::Block)
|
||||||
.filter()
|
.filter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl WholeStreamCommand for SortBy {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("sort-by").rest(SyntaxType::String)
|
Signature::build("sort-by").rest(SyntaxShape::String)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
use crate::data::{Primitive, TaggedDictBuilder, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ impl WholeStreamCommand for SplitColumn {
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("split-column")
|
Signature::build("split-column")
|
||||||
.required("separator", SyntaxType::Any)
|
.required("separator", SyntaxShape::Any)
|
||||||
.switch("collapse-empty")
|
.switch("collapse-empty")
|
||||||
.rest(SyntaxType::Member)
|
.rest(SyntaxShape::Member)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -40,7 +40,11 @@ impl WholeStreamCommand for SplitColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_column(
|
fn split_column(
|
||||||
SplitColumnArgs { separator, rest, collapse_empty}: SplitColumnArgs,
|
SplitColumnArgs {
|
||||||
|
separator,
|
||||||
|
rest,
|
||||||
|
collapse_empty,
|
||||||
|
}: SplitColumnArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(input
|
Ok(input
|
||||||
|
@ -92,7 +96,7 @@ fn split_column(
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name,
|
name,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.span(),
|
v.tag(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{Primitive, Value};
|
use crate::data::{Primitive, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
|
@ -17,8 +17,7 @@ impl WholeStreamCommand for SplitRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("split-row")
|
Signature::build("split-row").required("separator", SyntaxShape::Any)
|
||||||
.required("separator", SyntaxType::Any)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -63,7 +62,7 @@ fn split_row(
|
||||||
"requires string input",
|
"requires string input",
|
||||||
name,
|
name,
|
||||||
"value originates from here",
|
"value originates from here",
|
||||||
v.span(),
|
v.tag(),
|
||||||
)));
|
)));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{TaggedDictBuilder, Value};
|
use crate::data::{TaggedDictBuilder, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Tags;
|
pub struct Tags;
|
||||||
|
@ -36,7 +36,7 @@ fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||||
let mut tags = TaggedDictBuilder::new(v.tag());
|
let mut tags = TaggedDictBuilder::new(v.tag());
|
||||||
{
|
{
|
||||||
let origin = v.origin();
|
let origin = v.origin();
|
||||||
let span = v.span();
|
let span = v.tag().span;
|
||||||
let mut dict = TaggedDictBuilder::new(v.tag());
|
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||||
dict.insert("start", Value::int(span.start as i64));
|
dict.insert("start", Value::int(span.start as i64));
|
||||||
dict.insert("end", Value::int(span.end as i64));
|
dict.insert("end", Value::int(span.end as i64));
|
||||||
|
|
|
@ -190,44 +190,40 @@ fn generic_object_value_to_bson(o: &Dictionary) -> Result<Bson, ShellError> {
|
||||||
Ok(Bson::Document(doc))
|
Ok(Bson::Document(doc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shell_encode_document(
|
fn shell_encode_document(writer: &mut Vec<u8>, doc: Document, tag: Tag) -> Result<(), ShellError> {
|
||||||
writer: &mut Vec<u8>,
|
|
||||||
doc: Document,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<(), ShellError> {
|
|
||||||
match encode_document(writer, &doc) {
|
match encode_document(writer, &doc) {
|
||||||
Err(e) => Err(ShellError::labeled_error(
|
Err(e) => Err(ShellError::labeled_error(
|
||||||
format!("Failed to encode document due to: {:?}", e),
|
format!("Failed to encode document due to: {:?}", e),
|
||||||
"requires BSON-compatible document",
|
"requires BSON-compatible document",
|
||||||
span,
|
tag,
|
||||||
)),
|
)),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bson_value_to_bytes(bson: Bson, span: Span) -> Result<Vec<u8>, ShellError> {
|
fn bson_value_to_bytes(bson: Bson, tag: Tag) -> Result<Vec<u8>, ShellError> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
match bson {
|
match bson {
|
||||||
Bson::Array(a) => {
|
Bson::Array(a) => {
|
||||||
for v in a.into_iter() {
|
for v in a.into_iter() {
|
||||||
match v {
|
match v {
|
||||||
Bson::Document(d) => shell_encode_document(&mut out, d, span)?,
|
Bson::Document(d) => shell_encode_document(&mut out, d, tag)?,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("All top level values must be Documents, got {:?}", v),
|
format!("All top level values must be Documents, got {:?}", v),
|
||||||
"requires BSON-compatible document",
|
"requires BSON-compatible document",
|
||||||
span,
|
tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bson::Document(d) => shell_encode_document(&mut out, d, span)?,
|
Bson::Document(d) => shell_encode_document(&mut out, d, tag)?,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("All top level values must be Documents, got {:?}", bson),
|
format!("All top level values must be Documents, got {:?}", bson),
|
||||||
"requires BSON-compatible document",
|
"requires BSON-compatible document",
|
||||||
span,
|
tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +232,7 @@ fn bson_value_to_bytes(bson: Bson, span: Span) -> Result<Vec<u8>, ShellError> {
|
||||||
|
|
||||||
fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let name_span = args.name_span();
|
let name_tag = args.name_tag();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
||||||
|
|
||||||
|
@ -252,23 +248,23 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||||
for value in to_process_input {
|
for value in to_process_input {
|
||||||
match value_to_bson_value(&value) {
|
match value_to_bson_value(&value) {
|
||||||
Ok(bson_value) => {
|
Ok(bson_value) => {
|
||||||
match bson_value_to_bytes(bson_value, name_span) {
|
match bson_value_to_bytes(bson_value, name_tag) {
|
||||||
Ok(x) => yield ReturnSuccess::value(
|
Ok(x) => yield ReturnSuccess::value(
|
||||||
Value::Binary(x).simple_spanned(name_span),
|
Value::Binary(x).tagged(name_tag),
|
||||||
),
|
),
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with BSON-compatible structure.span() from pipeline",
|
"Expected a table with BSON-compatible structure.tag() from pipeline",
|
||||||
"requires BSON-compatible input",
|
"requires BSON-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Expected a table with BSON-compatible structure from pipeline",
|
"Expected a table with BSON-compatible structure from pipeline",
|
||||||
"requires BSON-compatible input",
|
"requires BSON-compatible input",
|
||||||
name_span))
|
name_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -134,7 +134,7 @@ fn to_csv(
|
||||||
ToCSVArgs { headerless }: ToCSVArgs,
|
ToCSVArgs { headerless }: ToCSVArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
|
||||||
|
@ -155,15 +155,15 @@ fn to_csv(
|
||||||
} else {
|
} else {
|
||||||
x
|
x
|
||||||
};
|
};
|
||||||
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).simple_spanned(name_span))
|
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).tagged(name_tag))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with CSV-compatible structure.span() from pipeline",
|
"Expected a table with CSV-compatible structure.tag() from pipeline",
|
||||||
"requires CSV-compatible input",
|
"requires CSV-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ fn json_list(input: &Vec<Tagged<Value>>) -> Result<Vec<serde_json::Value>, Shell
|
||||||
|
|
||||||
fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let name_span = args.name_span();
|
let name_tag = args.name_tag();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
||||||
|
|
||||||
|
@ -98,21 +98,21 @@ fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||||
Ok(json_value) => {
|
Ok(json_value) => {
|
||||||
match serde_json::to_string(&json_value) {
|
match serde_json::to_string(&json_value) {
|
||||||
Ok(x) => yield ReturnSuccess::value(
|
Ok(x) => yield ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
Value::Primitive(Primitive::String(x)).tagged(name_tag),
|
||||||
),
|
),
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with JSON-compatible structure.span() from pipeline",
|
"Expected a table with JSON-compatible structure.tag() from pipeline",
|
||||||
"requires JSON-compatible input",
|
"requires JSON-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Expected a table with JSON-compatible structure from pipeline",
|
"Expected a table with JSON-compatible structure from pipeline",
|
||||||
"requires JSON-compatible input",
|
"requires JSON-compatible input",
|
||||||
name_span))
|
name_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,7 +200,7 @@ fn sqlite_input_stream_to_bytes(
|
||||||
|
|
||||||
fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let name_span = args.name_span();
|
let name_tag = args.name_tag();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
||||||
|
|
||||||
|
@ -208,9 +208,9 @@ fn to_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
Ok(out) => yield ReturnSuccess::value(out),
|
Ok(out) => yield ReturnSuccess::value(out),
|
||||||
_ => {
|
_ => {
|
||||||
yield Err(ShellError::labeled_error(
|
yield Err(ShellError::labeled_error(
|
||||||
"Expected a table with SQLite-compatible structure.span() from pipeline",
|
"Expected a table with SQLite-compatible structure.tag() from pipeline",
|
||||||
"requires SQLite-compatible input",
|
"requires SQLite-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ fn collect_values(input: &Vec<Tagged<Value>>) -> Result<Vec<toml::Value>, ShellE
|
||||||
|
|
||||||
fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let name_span = args.name_span();
|
let name_tag = args.name_tag();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
||||||
|
|
||||||
|
@ -93,21 +93,21 @@ fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||||
Ok(toml_value) => {
|
Ok(toml_value) => {
|
||||||
match toml::to_string(&toml_value) {
|
match toml::to_string(&toml_value) {
|
||||||
Ok(x) => yield ReturnSuccess::value(
|
Ok(x) => yield ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
Value::Primitive(Primitive::String(x)).tagged(name_tag),
|
||||||
),
|
),
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with TOML-compatible structure.span() from pipeline",
|
"Expected a table with TOML-compatible structure.tag() from pipeline",
|
||||||
"requires TOML-compatible input",
|
"requires TOML-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Expected a table with TOML-compatible structure from pipeline",
|
"Expected a table with TOML-compatible structure from pipeline",
|
||||||
"requires TOML-compatible input",
|
"requires TOML-compatible input",
|
||||||
name_span))
|
name_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -133,7 +133,7 @@ fn to_tsv(
|
||||||
ToTSVArgs { headerless }: ToTSVArgs,
|
ToTSVArgs { headerless }: ToTSVArgs,
|
||||||
RunnableContext { input, name, .. }: RunnableContext,
|
RunnableContext { input, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||||
|
|
||||||
|
@ -154,15 +154,15 @@ fn to_tsv(
|
||||||
} else {
|
} else {
|
||||||
x
|
x
|
||||||
};
|
};
|
||||||
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).simple_spanned(name_span))
|
yield ReturnSuccess::value(Value::Primitive(Primitive::String(converted)).tagged(name_tag))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
yield Err(ShellError::labeled_error_with_secondary(
|
yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with TSV-compatible structure.span() from pipeline",
|
"Expected a table with TSV-compatible structure.tag() from pipeline",
|
||||||
"requires TSV-compatible input",
|
"requires TSV-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub fn value_to_yaml_value(v: &Tagged<Value>) -> Result<serde_yaml::Value, Shell
|
||||||
|
|
||||||
fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let name_span = args.name_span();
|
let name_tag = args.name_tag();
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
let input: Vec<Tagged<Value>> = args.input.values.collect().await;
|
||||||
|
|
||||||
|
@ -94,21 +94,21 @@ fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||||
Ok(yaml_value) => {
|
Ok(yaml_value) => {
|
||||||
match serde_yaml::to_string(&yaml_value) {
|
match serde_yaml::to_string(&yaml_value) {
|
||||||
Ok(x) => yield ReturnSuccess::value(
|
Ok(x) => yield ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
Value::Primitive(Primitive::String(x)).tagged(name_tag),
|
||||||
),
|
),
|
||||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected a table with YAML-compatible structure.span() from pipeline",
|
"Expected a table with YAML-compatible structure.tag() from pipeline",
|
||||||
"requires YAML-compatible input",
|
"requires YAML-compatible input",
|
||||||
name_span,
|
name_tag,
|
||||||
"originates from here".to_string(),
|
"originates from here".to_string(),
|
||||||
value.span(),
|
value.tag(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => yield Err(ShellError::labeled_error(
|
_ => yield Err(ShellError::labeled_error(
|
||||||
"Expected a table with YAML-compatible structure from pipeline",
|
"Expected a table with YAML-compatible structure from pipeline",
|
||||||
"requires YAML-compatible input",
|
"requires YAML-compatible input",
|
||||||
name_span))
|
name_tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub struct Trim;
|
pub struct Trim;
|
||||||
|
@ -34,7 +34,7 @@ fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
||||||
.values
|
.values
|
||||||
.map(move |v| {
|
.map(move |v| {
|
||||||
let string = String::extract(&v)?;
|
let string = String::extract(&v)?;
|
||||||
ReturnSuccess::value(Value::string(string.trim()).simple_spanned(v.span()))
|
ReturnSuccess::value(Value::string(string.trim()).tagged(v.tag()))
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::{Dictionary, Value};
|
use crate::data::{Dictionary, Value};
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::parser::registry::Signature;
|
use crate::parser::registry::Signature;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -31,14 +31,14 @@ impl WholeStreamCommand for Version {
|
||||||
|
|
||||||
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
let span = args.call_info.name_span;
|
let tag = args.call_info.name_tag;
|
||||||
|
|
||||||
let mut indexmap = IndexMap::new();
|
let mut indexmap = IndexMap::new();
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"version".to_string(),
|
"version".to_string(),
|
||||||
Tagged::from_simple_spanned_item(Value::string(clap::crate_version!()), span),
|
Value::string(clap::crate_version!()).tagged(tag),
|
||||||
);
|
);
|
||||||
|
|
||||||
let value = Tagged::from_simple_spanned_item(Value::Row(Dictionary::from(indexmap)), span);
|
let value = Value::Row(Dictionary::from(indexmap)).tagged(tag);
|
||||||
Ok(OutputStream::one(value))
|
Ok(OutputStream::one(value))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::commands::PerItemCommand;
|
use crate::commands::PerItemCommand;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxShape;
|
||||||
use crate::parser::registry;
|
use crate::parser::registry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ impl PerItemCommand for Where {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> registry::Signature {
|
fn signature(&self) -> registry::Signature {
|
||||||
Signature::build("where")
|
Signature::build("where").required("condition", SyntaxShape::Block)
|
||||||
.required("condition", SyntaxType::Block)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -43,16 +42,14 @@ impl PerItemCommand for Where {
|
||||||
VecDeque::new()
|
VecDeque::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => return Err(e),
|
||||||
return Err(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tagged { tag, .. } => {
|
Tagged { tag, .. } => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected a condition",
|
"Expected a condition",
|
||||||
"where needs a condition",
|
"where needs a condition",
|
||||||
tag.span,
|
*tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::errors::ShellError;
|
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
|
@ -13,8 +13,7 @@ impl WholeStreamCommand for Which {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("which")
|
Signature::build("which").required("name", SyntaxShape::Any)
|
||||||
.required("name", SyntaxType::Any)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -34,7 +33,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
let args = args.evaluate_once(registry)?;
|
let args = args.evaluate_once(registry)?;
|
||||||
|
|
||||||
let mut which_out = VecDeque::new();
|
let mut which_out = VecDeque::new();
|
||||||
let span = args.call_info.name_span;
|
let tag = args.call_info.name_tag;
|
||||||
|
|
||||||
if let Some(v) = &args.call_info.args.positional {
|
if let Some(v) = &args.call_info.args.positional {
|
||||||
if v.len() > 0 {
|
if v.len() > 0 {
|
||||||
|
@ -53,7 +52,7 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected a filename to find",
|
"Expected a filename to find",
|
||||||
"needs a filename",
|
"needs a filename",
|
||||||
tag.span,
|
*tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +60,14 @@ pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected a binary to find",
|
"Expected a binary to find",
|
||||||
"needs application name",
|
"needs application name",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected a binary to find",
|
"Expected a binary to find",
|
||||||
"needs application name",
|
"needs application name",
|
||||||
span,
|
tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,13 +120,13 @@ impl Context {
|
||||||
pub(crate) fn run_command<'a>(
|
pub(crate) fn run_command<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<Command>,
|
command: Arc<Command>,
|
||||||
name_span: Span,
|
name_tag: Tag,
|
||||||
source_map: SourceMap,
|
source_map: SourceMap,
|
||||||
args: hir::Call,
|
args: hir::Call,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
) -> OutputStream {
|
) -> OutputStream {
|
||||||
let command_args = self.command_args(args, input, source, source_map, name_span);
|
let command_args = self.command_args(args, input, source, source_map, name_tag);
|
||||||
command.run(command_args, self.registry())
|
command.run(command_args, self.registry())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +135,13 @@ impl Context {
|
||||||
args: hir::Call,
|
args: hir::Call,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
source_map: SourceMap,
|
source_map: SourceMap,
|
||||||
name_span: Span,
|
name_tag: Tag,
|
||||||
) -> UnevaluatedCallInfo {
|
) -> UnevaluatedCallInfo {
|
||||||
UnevaluatedCallInfo {
|
UnevaluatedCallInfo {
|
||||||
args,
|
args,
|
||||||
source: source.clone(),
|
source: source.clone(),
|
||||||
source_map,
|
source_map,
|
||||||
name_span,
|
name_tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,12 +151,12 @@ impl Context {
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
source_map: SourceMap,
|
source_map: SourceMap,
|
||||||
name_span: Span,
|
name_tag: Tag,
|
||||||
) -> CommandArgs {
|
) -> CommandArgs {
|
||||||
CommandArgs {
|
CommandArgs {
|
||||||
host: self.host.clone(),
|
host: self.host.clone(),
|
||||||
shell_manager: self.shell_manager.clone(),
|
shell_manager: self.shell_manager.clone(),
|
||||||
call_info: self.call_info(args, source, source_map, name_span),
|
call_info: self.call_info(args, source, source_map, name_tag),
|
||||||
input,
|
input,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ pub struct Operation {
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub(crate) expressions: Vec<hir::Expression>,
|
pub(crate) expressions: Vec<hir::Expression>,
|
||||||
pub(crate) source: Text,
|
pub(crate) source: Text,
|
||||||
pub(crate) span: Span,
|
pub(crate) tag: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
|
@ -153,7 +153,7 @@ impl Block {
|
||||||
let scope = Scope::new(value.clone());
|
let scope = Scope::new(value.clone());
|
||||||
|
|
||||||
if self.expressions.len() == 0 {
|
if self.expressions.len() == 0 {
|
||||||
return Ok(Value::nothing().simple_spanned(self.span));
|
return Ok(Value::nothing().tagged(self.tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
|
@ -247,7 +247,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for Block {
|
||||||
Value::Block(block) => Ok(block.clone()),
|
Value::Block(block) => Ok(block.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Block",
|
"Block",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for i64 {
|
||||||
}
|
}
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Integer",
|
"Integer",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for String {
|
||||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"String",
|
"String",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ impl std::convert::TryFrom<&Tagged<Value>> for Vec<u8> {
|
||||||
Value::Binary(b) => Ok(b.clone()),
|
Value::Binary(b) => Ok(b.clone()),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Binary",
|
"Binary",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ impl<'a> std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::data::Dictionar
|
||||||
Value::Row(d) => Ok(d),
|
Value::Row(d) => Ok(d),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Dictionary",
|
"Dictionary",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ impl std::convert::TryFrom<Option<&Tagged<Value>>> for Switch {
|
||||||
Value::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present),
|
Value::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present),
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Boolean",
|
"Boolean",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_tag(v.type_name()),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -639,7 +639,7 @@ impl Tagged<Value> {
|
||||||
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
||||||
other => Err(ShellError::type_error(
|
other => Err(ShellError::type_error(
|
||||||
"Path",
|
"Path",
|
||||||
other.type_name().tagged(self.span()),
|
other.type_name().tagged(self.tag()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub fn default_path_for(file: &Option<PathBuf>) -> Result<PathBuf, ShellError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(
|
pub fn read(
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
at: &Option<PathBuf>,
|
at: &Option<PathBuf>,
|
||||||
) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
||||||
let filename = default_path()?;
|
let filename = default_path()?;
|
||||||
|
@ -64,15 +64,15 @@ pub fn read(
|
||||||
|
|
||||||
trace!("config file = {}", filename.display());
|
trace!("config file = {}", filename.display());
|
||||||
|
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
let contents = fs::read_to_string(filename)
|
let contents = fs::read_to_string(filename)
|
||||||
.map(|v| v.simple_spanned(span))
|
.map(|v| v.tagged(tag))
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
||||||
|
|
||||||
let parsed: toml::Value = toml::from_str(&contents)
|
let parsed: toml::Value = toml::from_str(&contents)
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
|
||||||
|
|
||||||
let value = convert_toml_value_to_nu_value(&parsed, Tag::unknown_origin(span));
|
let value = convert_toml_value_to_nu_value(&parsed, tag);
|
||||||
let tag = value.tag();
|
let tag = value.tag();
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Row(Dictionary { entries }) => Ok(entries),
|
Value::Row(Dictionary { entries }) => Ok(entries),
|
||||||
|
@ -83,8 +83,8 @@ pub fn read(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
pub(crate) fn config(tag: impl Into<Tag>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
||||||
read(span, &None)
|
read(tag, &None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(
|
pub fn write(
|
||||||
|
|
|
@ -15,8 +15,8 @@ impl From<String> for Value {
|
||||||
|
|
||||||
impl<T: Into<Value>> Tagged<T> {
|
impl<T: Into<Value>> Tagged<T> {
|
||||||
pub fn into_tagged_value(self) -> Tagged<Value> {
|
pub fn into_tagged_value(self) -> Tagged<Value> {
|
||||||
let value_span = self.span();
|
let value_tag = self.tag();
|
||||||
let value = self.item.into();
|
let value = self.item.into();
|
||||||
value.simple_spanned(value_span)
|
value.tagged(value_tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
164
src/data/meta.rs
164
src/data/meta.rs
|
@ -5,6 +5,7 @@ use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
|
@ -13,9 +14,15 @@ pub struct Tagged<T> {
|
||||||
pub item: T,
|
pub item: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> HasSpan for Tagged<T> {
|
impl<T> HasTag for Tagged<T> {
|
||||||
fn span(&self) -> Span {
|
fn tag(&self) -> Tag {
|
||||||
self.tag.span
|
self.tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<Path> for Tagged<PathBuf> {
|
||||||
|
fn as_ref(&self) -> &Path {
|
||||||
|
self.item.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,10 +31,6 @@ pub trait TaggedItem: Sized {
|
||||||
Tagged::from_item(self, tag.into())
|
Tagged::from_item(self, tag.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_spanned(self, span: impl Into<Span>) -> Tagged<Self> {
|
|
||||||
Tagged::from_simple_spanned_item(self, span.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
// For now, this is a temporary facility. In many cases, there are other useful spans that we
|
// For now, this is a temporary facility. In many cases, there are other useful spans that we
|
||||||
// could be using, such as the original source spans of JSON or Toml files, but we don't yet
|
// could be using, such as the original source spans of JSON or Toml files, but we don't yet
|
||||||
// have the infrastructure to make that work.
|
// have the infrastructure to make that work.
|
||||||
|
@ -53,14 +56,8 @@ impl<T> std::ops::Deref for Tagged<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tagged<T> {
|
impl<T> Tagged<T> {
|
||||||
pub fn spanned(self, span: impl Into<Span>) -> Tagged<T> {
|
pub fn with_tag(self, tag: impl Into<Tag>) -> Tagged<T> {
|
||||||
Tagged::from_item(
|
Tagged::from_item(self.item, tag)
|
||||||
self.item,
|
|
||||||
Tag {
|
|
||||||
span: span.into(),
|
|
||||||
origin: None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
|
pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
|
||||||
|
@ -70,41 +67,26 @@ impl<T> Tagged<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_simple_spanned_item(item: T, span: impl Into<Span>) -> Tagged<T> {
|
|
||||||
Tagged::from_item(
|
|
||||||
item,
|
|
||||||
Tag {
|
|
||||||
span: span.into(),
|
|
||||||
origin: None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
|
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
|
||||||
let tag = self.tag();
|
let tag = self.tag();
|
||||||
|
|
||||||
let mapped = input(self.item);
|
let mapped = input(self.item);
|
||||||
Tagged::from_item(mapped, tag.clone())
|
Tagged::from_item(mapped, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
pub(crate) fn copy_tag<U>(&self, output: U) -> Tagged<U> {
|
||||||
let span = self.span();
|
Tagged::from_item(output, self.tag())
|
||||||
|
|
||||||
Tagged::from_simple_spanned_item(output, span)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(&self, source: &Text) -> Text {
|
pub fn source(&self, source: &Text) -> Text {
|
||||||
Text::from(self.span().slice(source))
|
Text::from(self.tag().slice(source))
|
||||||
}
|
|
||||||
|
|
||||||
pub fn span(&self) -> Span {
|
|
||||||
self.tag.span
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tag(&self) -> Tag {
|
pub fn tag(&self) -> Tag {
|
||||||
self.tag
|
self.tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This should not be optional
|
||||||
pub fn origin(&self) -> Option<uuid::Uuid> {
|
pub fn origin(&self) -> Option<uuid::Uuid> {
|
||||||
self.tag.origin
|
self.tag.origin
|
||||||
}
|
}
|
||||||
|
@ -126,20 +108,14 @@ impl<T> Tagged<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<&Tagged<T>> for Span {
|
impl From<&Tag> for Tag {
|
||||||
fn from(input: &Tagged<T>) -> Span {
|
fn from(input: &Tag) -> Tag {
|
||||||
input.span()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Span> for Span {
|
|
||||||
fn from(input: &Span) -> Span {
|
|
||||||
*input
|
*input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nom5_locate::LocatedSpan<&str>> for Span {
|
impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Span {
|
||||||
fn from(input: nom5_locate::LocatedSpan<&str>) -> Span {
|
fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Span {
|
||||||
Span {
|
Span {
|
||||||
start: input.offset,
|
start: input.offset,
|
||||||
end: input.offset + input.fragment.len(),
|
end: input.offset + input.fragment.len(),
|
||||||
|
@ -147,8 +123,18 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Span {
|
impl<T>
|
||||||
fn from(input: (nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)) -> Span {
|
From<(
|
||||||
|
nom_locate::LocatedSpanEx<T, Uuid>,
|
||||||
|
nom_locate::LocatedSpanEx<T, Uuid>,
|
||||||
|
)> for Span
|
||||||
|
{
|
||||||
|
fn from(
|
||||||
|
input: (
|
||||||
|
nom_locate::LocatedSpanEx<T, Uuid>,
|
||||||
|
nom_locate::LocatedSpanEx<T, Uuid>,
|
||||||
|
),
|
||||||
|
) -> Span {
|
||||||
Span {
|
Span {
|
||||||
start: input.0.offset,
|
start: input.0.offset,
|
||||||
end: input.1.offset,
|
end: input.1.offset,
|
||||||
|
@ -197,6 +183,36 @@ impl From<&Span> for Tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<(usize, usize, Uuid)> for Tag {
|
||||||
|
fn from((start, end, origin): (usize, usize, Uuid)) -> Self {
|
||||||
|
Tag {
|
||||||
|
origin: Some(origin),
|
||||||
|
span: Span { start, end },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(usize, usize, Option<Uuid>)> for Tag {
|
||||||
|
fn from((start, end, origin): (usize, usize, Option<Uuid>)) -> Self {
|
||||||
|
Tag {
|
||||||
|
origin,
|
||||||
|
span: Span { start, end },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Tag {
|
||||||
|
fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Tag {
|
||||||
|
Tag {
|
||||||
|
origin: Some(input.extra),
|
||||||
|
span: Span {
|
||||||
|
start: input.offset,
|
||||||
|
end: input.offset + input.fragment.len(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Tag> for Span {
|
impl From<Tag> for Span {
|
||||||
fn from(tag: Tag) -> Self {
|
fn from(tag: Tag) -> Self {
|
||||||
tag.span
|
tag.span
|
||||||
|
@ -214,12 +230,36 @@ impl Tag {
|
||||||
Tag { origin: None, span }
|
Tag { origin: None, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unknown_span(origin: Uuid) -> Tag {
|
||||||
|
Tag {
|
||||||
|
origin: Some(origin),
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unknown() -> Tag {
|
pub fn unknown() -> Tag {
|
||||||
Tag {
|
Tag {
|
||||||
origin: None,
|
origin: None,
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn until(&self, other: impl Into<Tag>) -> Tag {
|
||||||
|
let other = other.into();
|
||||||
|
debug_assert!(self.origin == other.origin, "Can only merge two tags with the same origin");
|
||||||
|
|
||||||
|
Tag {
|
||||||
|
span: Span {
|
||||||
|
start: self.span.start,
|
||||||
|
end: other.span.end
|
||||||
|
},
|
||||||
|
origin: self.origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
|
||||||
|
self.span.slice(source)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
|
@ -284,3 +324,33 @@ impl language_reporting::ReportingSpan for Span {
|
||||||
self.end
|
self.end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl language_reporting::ReportingSpan for Tag {
|
||||||
|
fn with_start(&self, start: usize) -> Self {
|
||||||
|
Tag {
|
||||||
|
span: Span {
|
||||||
|
start,
|
||||||
|
end: self.span.end,
|
||||||
|
},
|
||||||
|
origin: self.origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_end(&self, end: usize) -> Self {
|
||||||
|
Tag {
|
||||||
|
span: Span {
|
||||||
|
start: self.span.start,
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
origin: self.origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(&self) -> usize {
|
||||||
|
self.span.start
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(&self) -> usize {
|
||||||
|
self.span.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,20 +14,22 @@ pub enum Description {
|
||||||
|
|
||||||
impl Description {
|
impl Description {
|
||||||
pub fn from(value: Tagged<impl Into<String>>) -> Description {
|
pub fn from(value: Tagged<impl Into<String>>) -> Description {
|
||||||
let value_span = value.span();
|
|
||||||
let value_tag = value.tag();
|
let value_tag = value.tag();
|
||||||
|
|
||||||
match value_span {
|
match value_tag {
|
||||||
Span { start: 0, end: 0 } => Description::Synthetic(value.item.into()),
|
Tag {
|
||||||
|
span: crate::data::meta::Span { start: 0, end: 0 },
|
||||||
|
..
|
||||||
|
} => Description::Synthetic(value.item.into()),
|
||||||
_ => Description::Source(Tagged::from_item(value.item.into(), value_tag)),
|
_ => Description::Source(Tagged::from_item(value.item.into(), value_tag)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Description {
|
impl Description {
|
||||||
fn into_label(self) -> Result<Label<Span>, String> {
|
fn into_label(self) -> Result<Label<Tag>, String> {
|
||||||
match self {
|
match self {
|
||||||
Description::Source(s) => Ok(Label::new_primary(s.span()).with_message(s.item)),
|
Description::Source(s) => Ok(Label::new_primary(s.tag()).with_message(s.item)),
|
||||||
Description::Synthetic(s) => Err(s),
|
Description::Synthetic(s) => Err(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +83,7 @@ impl ShellError {
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ProximateShellError::RangeError {
|
ProximateShellError::RangeError {
|
||||||
kind: expected.into(),
|
kind: expected.into(),
|
||||||
actual_kind: actual.copy_span(format!("{:?}", actual.item)),
|
actual_kind: actual.copy_tag(format!("{:?}", actual.item)),
|
||||||
operation,
|
operation,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
|
@ -116,9 +118,9 @@ impl ShellError {
|
||||||
ProximateShellError::MissingProperty { subpath, expr }.start()
|
ProximateShellError::MissingProperty { subpath, expr }.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError {
|
pub(crate) fn missing_value(tag: Option<Tag>, reason: impl Into<String>) -> ShellError {
|
||||||
ProximateShellError::MissingValue {
|
ProximateShellError::MissingValue {
|
||||||
span,
|
tag,
|
||||||
reason: reason.into(),
|
reason: reason.into(),
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
|
@ -127,28 +129,31 @@ impl ShellError {
|
||||||
pub(crate) fn argument_error(
|
pub(crate) fn argument_error(
|
||||||
command: impl Into<String>,
|
command: impl Into<String>,
|
||||||
kind: ArgumentError,
|
kind: ArgumentError,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ProximateShellError::ArgumentError {
|
ProximateShellError::ArgumentError {
|
||||||
command: command.into(),
|
command: command.into(),
|
||||||
error: kind,
|
error: kind,
|
||||||
span,
|
tag,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn invalid_external_word(span: Span) -> ShellError {
|
pub(crate) fn invalid_external_word(tag: Tag) -> ShellError {
|
||||||
ProximateShellError::ArgumentError {
|
ProximateShellError::ArgumentError {
|
||||||
command: "Invalid argument to Nu command (did you mean to call an external command?)"
|
command: "Invalid argument to Nu command (did you mean to call an external command?)"
|
||||||
.into(),
|
.into(),
|
||||||
error: ArgumentError::InvalidExternalWord,
|
error: ArgumentError::InvalidExternalWord,
|
||||||
span,
|
tag,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_error(
|
pub(crate) fn parse_error(
|
||||||
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
|
error: nom::Err<(
|
||||||
|
nom_locate::LocatedSpanEx<&str, uuid::Uuid>,
|
||||||
|
nom::error::ErrorKind,
|
||||||
|
)>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
use language_reporting::*;
|
use language_reporting::*;
|
||||||
|
|
||||||
|
@ -164,34 +169,34 @@ impl ShellError {
|
||||||
}
|
}
|
||||||
nom::Err::Failure(span) | nom::Err::Error(span) => {
|
nom::Err::Failure(span) | nom::Err::Error(span) => {
|
||||||
let diagnostic = Diagnostic::new(Severity::Error, format!("Parse Error"))
|
let diagnostic = Diagnostic::new(Severity::Error, format!("Parse Error"))
|
||||||
.with_label(Label::new_primary(Span::from(span.0)));
|
.with_label(Label::new_primary(Tag::from(span.0)));
|
||||||
|
|
||||||
ShellError::diagnostic(diagnostic)
|
ShellError::diagnostic(diagnostic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
pub(crate) fn diagnostic(diagnostic: Diagnostic<Tag>) -> ShellError {
|
||||||
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_diagnostic(self) -> Diagnostic<Span> {
|
pub(crate) fn to_diagnostic(self) -> Diagnostic<Tag> {
|
||||||
match self.error {
|
match self.error {
|
||||||
ProximateShellError::String(StringError { title, .. }) => {
|
ProximateShellError::String(StringError { title, .. }) => {
|
||||||
Diagnostic::new(Severity::Error, title)
|
Diagnostic::new(Severity::Error, title)
|
||||||
}
|
}
|
||||||
ProximateShellError::InvalidCommand { command } => {
|
ProximateShellError::InvalidCommand { command } => {
|
||||||
Diagnostic::new(Severity::Error, "Invalid command")
|
Diagnostic::new(Severity::Error, "Invalid command")
|
||||||
.with_label(Label::new_primary(command.span))
|
.with_label(Label::new_primary(command))
|
||||||
}
|
}
|
||||||
ProximateShellError::MissingValue { span, reason } => {
|
ProximateShellError::MissingValue { tag, reason } => {
|
||||||
let mut d = Diagnostic::new(
|
let mut d = Diagnostic::new(
|
||||||
Severity::Bug,
|
Severity::Bug,
|
||||||
format!("Internal Error (missing value) :: {}", reason),
|
format!("Internal Error (missing value) :: {}", reason),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(span) = span {
|
if let Some(tag) = tag {
|
||||||
d = d.with_label(Label::new_primary(span));
|
d = d.with_label(Label::new_primary(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
d
|
d
|
||||||
|
@ -199,12 +204,12 @@ impl ShellError {
|
||||||
ProximateShellError::ArgumentError {
|
ProximateShellError::ArgumentError {
|
||||||
command,
|
command,
|
||||||
error,
|
error,
|
||||||
span,
|
tag,
|
||||||
} => match error {
|
} => match error {
|
||||||
ArgumentError::InvalidExternalWord => Diagnostic::new(
|
ArgumentError::InvalidExternalWord => Diagnostic::new(
|
||||||
Severity::Error,
|
Severity::Error,
|
||||||
format!("Invalid bare word for Nu command (did you intend to invoke an external command?)"))
|
format!("Invalid bare word for Nu command (did you intend to invoke an external command?)"))
|
||||||
.with_label(Label::new_primary(span)),
|
.with_label(Label::new_primary(tag)),
|
||||||
ArgumentError::MissingMandatoryFlag(name) => Diagnostic::new(
|
ArgumentError::MissingMandatoryFlag(name) => Diagnostic::new(
|
||||||
Severity::Error,
|
Severity::Error,
|
||||||
format!(
|
format!(
|
||||||
|
@ -214,7 +219,7 @@ impl ShellError {
|
||||||
Color::Black.bold().paint(name)
|
Color::Black.bold().paint(name)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.with_label(Label::new_primary(span)),
|
.with_label(Label::new_primary(tag)),
|
||||||
ArgumentError::MissingMandatoryPositional(name) => Diagnostic::new(
|
ArgumentError::MissingMandatoryPositional(name) => Diagnostic::new(
|
||||||
Severity::Error,
|
Severity::Error,
|
||||||
format!(
|
format!(
|
||||||
|
@ -224,7 +229,7 @@ impl ShellError {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new_primary(span).with_message(format!("requires {} parameter", name)),
|
Label::new_primary(tag).with_message(format!("requires {} parameter", name)),
|
||||||
),
|
),
|
||||||
ArgumentError::MissingValueForName(name) => Diagnostic::new(
|
ArgumentError::MissingValueForName(name) => Diagnostic::new(
|
||||||
Severity::Error,
|
Severity::Error,
|
||||||
|
@ -235,17 +240,17 @@ impl ShellError {
|
||||||
Color::Black.bold().paint(name)
|
Color::Black.bold().paint(name)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.with_label(Label::new_primary(span)),
|
.with_label(Label::new_primary(tag)),
|
||||||
},
|
},
|
||||||
ProximateShellError::TypeError {
|
ProximateShellError::TypeError {
|
||||||
expected,
|
expected,
|
||||||
actual:
|
actual:
|
||||||
Tagged {
|
Tagged {
|
||||||
item: Some(actual),
|
item: Some(actual),
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Type Error").with_label(
|
} => Diagnostic::new(Severity::Error, "Type Error").with_label(
|
||||||
Label::new_primary(span)
|
Label::new_primary(tag)
|
||||||
.with_message(format!("Expected {}, found {}", expected, actual)),
|
.with_message(format!("Expected {}, found {}", expected, actual)),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -254,10 +259,10 @@ impl ShellError {
|
||||||
actual:
|
actual:
|
||||||
Tagged {
|
Tagged {
|
||||||
item: None,
|
item: None,
|
||||||
tag: Tag { span, .. },
|
tag
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Type Error")
|
} => Diagnostic::new(Severity::Error, "Type Error")
|
||||||
.with_label(Label::new_primary(span).with_message(expected)),
|
.with_label(Label::new_primary(tag).with_message(expected)),
|
||||||
|
|
||||||
ProximateShellError::RangeError {
|
ProximateShellError::RangeError {
|
||||||
kind,
|
kind,
|
||||||
|
@ -265,10 +270,10 @@ impl ShellError {
|
||||||
actual_kind:
|
actual_kind:
|
||||||
Tagged {
|
Tagged {
|
||||||
item,
|
item,
|
||||||
tag: Tag { span, .. },
|
tag
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Range Error").with_label(
|
} => Diagnostic::new(Severity::Error, "Range Error").with_label(
|
||||||
Label::new_primary(span).with_message(format!(
|
Label::new_primary(tag).with_message(format!(
|
||||||
"Expected to convert {} to {} while {}, but it was out of range",
|
"Expected to convert {} to {} while {}, but it was out of range",
|
||||||
item,
|
item,
|
||||||
kind.desc(),
|
kind.desc(),
|
||||||
|
@ -279,11 +284,11 @@ impl ShellError {
|
||||||
ProximateShellError::SyntaxError {
|
ProximateShellError::SyntaxError {
|
||||||
problem:
|
problem:
|
||||||
Tagged {
|
Tagged {
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Syntax Error")
|
} => Diagnostic::new(Severity::Error, "Syntax Error")
|
||||||
.with_label(Label::new_primary(span).with_message("Unexpected external command")),
|
.with_label(Label::new_primary(tag).with_message("Unexpected external command")),
|
||||||
|
|
||||||
ProximateShellError::MissingProperty { subpath, expr } => {
|
ProximateShellError::MissingProperty { subpath, expr } => {
|
||||||
let subpath = subpath.into_label();
|
let subpath = subpath.into_label();
|
||||||
|
@ -306,8 +311,8 @@ impl ShellError {
|
||||||
ProximateShellError::Diagnostic(diag) => diag.diagnostic,
|
ProximateShellError::Diagnostic(diag) => diag.diagnostic,
|
||||||
ProximateShellError::CoerceError { left, right } => {
|
ProximateShellError::CoerceError { left, right } => {
|
||||||
Diagnostic::new(Severity::Error, "Coercion error")
|
Diagnostic::new(Severity::Error, "Coercion error")
|
||||||
.with_label(Label::new_primary(left.span()).with_message(left.item))
|
.with_label(Label::new_primary(left.tag()).with_message(left.item))
|
||||||
.with_label(Label::new_secondary(right.span()).with_message(right.item))
|
.with_label(Label::new_secondary(right.tag()).with_message(right.item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,26 +320,29 @@ impl ShellError {
|
||||||
pub fn labeled_error(
|
pub fn labeled_error(
|
||||||
msg: impl Into<String>,
|
msg: impl Into<String>,
|
||||||
label: impl Into<String>,
|
label: impl Into<String>,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ShellError::diagnostic(
|
ShellError::diagnostic(
|
||||||
Diagnostic::new(Severity::Error, msg.into())
|
Diagnostic::new(Severity::Error, msg.into())
|
||||||
.with_label(Label::new_primary(span.into()).with_message(label.into())),
|
.with_label(Label::new_primary(tag.into()).with_message(label.into())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn labeled_error_with_secondary(
|
pub fn labeled_error_with_secondary(
|
||||||
msg: impl Into<String>,
|
msg: impl Into<String>,
|
||||||
primary_label: impl Into<String>,
|
primary_label: impl Into<String>,
|
||||||
primary_span: Span,
|
primary_span: impl Into<Tag>,
|
||||||
secondary_label: impl Into<String>,
|
secondary_label: impl Into<String>,
|
||||||
secondary_span: Span,
|
secondary_span: impl Into<Tag>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ShellError::diagnostic(
|
ShellError::diagnostic(
|
||||||
Diagnostic::new_error(msg.into())
|
Diagnostic::new_error(msg.into())
|
||||||
.with_label(Label::new_primary(primary_span).with_message(primary_label.into()))
|
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new_secondary(secondary_span).with_message(secondary_label.into()),
|
Label::new_primary(primary_span.into()).with_message(primary_label.into()),
|
||||||
|
)
|
||||||
|
.with_label(
|
||||||
|
Label::new_secondary(secondary_span.into())
|
||||||
|
.with_message(secondary_label.into()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -409,13 +417,13 @@ pub enum ProximateShellError {
|
||||||
expr: Description,
|
expr: Description,
|
||||||
},
|
},
|
||||||
MissingValue {
|
MissingValue {
|
||||||
span: Option<Span>,
|
tag: Option<Tag>,
|
||||||
reason: String,
|
reason: String,
|
||||||
},
|
},
|
||||||
ArgumentError {
|
ArgumentError {
|
||||||
command: String,
|
command: String,
|
||||||
error: ArgumentError,
|
error: ArgumentError,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
},
|
},
|
||||||
RangeError {
|
RangeError {
|
||||||
kind: ExpectedRange,
|
kind: ExpectedRange,
|
||||||
|
@ -447,7 +455,7 @@ impl ToDebug for ProximateShellError {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ShellDiagnostic {
|
pub struct ShellDiagnostic {
|
||||||
pub(crate) diagnostic: Diagnostic<Span>,
|
pub(crate) diagnostic: Diagnostic<Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for ShellDiagnostic {
|
impl PartialEq for ShellDiagnostic {
|
||||||
|
|
|
@ -38,13 +38,13 @@ pub(crate) fn evaluate_baseline_expr(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match &expr.item {
|
match &expr.item {
|
||||||
RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_span(literal), source)),
|
RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_tag(literal), source)),
|
||||||
RawExpression::ExternalWord => Err(ShellError::argument_error(
|
RawExpression::ExternalWord => Err(ShellError::argument_error(
|
||||||
"Invalid external word",
|
"Invalid external word",
|
||||||
ArgumentError::InvalidExternalWord,
|
ArgumentError::InvalidExternalWord,
|
||||||
expr.span(),
|
expr.tag(),
|
||||||
)),
|
)),
|
||||||
RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.span())),
|
RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.tag())),
|
||||||
RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()),
|
RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()),
|
||||||
RawExpression::Variable(var) => evaluate_reference(var, scope, source),
|
RawExpression::Variable(var) => evaluate_reference(var, scope, source),
|
||||||
RawExpression::ExternalCommand(external) => evaluate_external(external, scope, source),
|
RawExpression::ExternalCommand(external) => evaluate_external(external, scope, source),
|
||||||
|
@ -53,13 +53,10 @@ pub(crate) fn evaluate_baseline_expr(
|
||||||
let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?;
|
let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?;
|
||||||
|
|
||||||
match left.compare(binary.op(), &*right) {
|
match left.compare(binary.op(), &*right) {
|
||||||
Ok(result) => Ok(Tagged::from_simple_spanned_item(
|
Ok(result) => Ok(Value::boolean(result).tagged(expr.tag())),
|
||||||
Value::boolean(result),
|
|
||||||
expr.span(),
|
|
||||||
)),
|
|
||||||
Err((left_type, right_type)) => Err(ShellError::coerce_error(
|
Err((left_type, right_type)) => Err(ShellError::coerce_error(
|
||||||
binary.left().copy_span(left_type),
|
binary.left().copy_tag(left_type),
|
||||||
binary.right().copy_span(right_type),
|
binary.right().copy_tag(right_type),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,12 +68,14 @@ pub(crate) fn evaluate_baseline_expr(
|
||||||
exprs.push(expr);
|
exprs.push(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Table(exprs).tagged(Tag::unknown_origin(expr.span())))
|
Ok(Value::Table(exprs).tagged(expr.tag()))
|
||||||
|
}
|
||||||
|
RawExpression::Block(block) => {
|
||||||
|
Ok(
|
||||||
|
Value::Block(Block::new(block.clone(), source.clone(), expr.tag()))
|
||||||
|
.tagged(expr.tag()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
RawExpression::Block(block) => Ok(Tagged::from_simple_spanned_item(
|
|
||||||
Value::Block(Block::new(block.clone(), source.clone(), expr.span())),
|
|
||||||
expr.span(),
|
|
||||||
)),
|
|
||||||
RawExpression::Path(path) => {
|
RawExpression::Path(path) => {
|
||||||
let value = evaluate_baseline_expr(path.head(), registry, scope, source)?;
|
let value = evaluate_baseline_expr(path.head(), registry, scope, source)?;
|
||||||
let mut item = value;
|
let mut item = value;
|
||||||
|
@ -92,18 +91,12 @@ pub(crate) fn evaluate_baseline_expr(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
item = Tagged::from_simple_spanned_item(
|
item = next.clone().item.tagged(expr.tag());
|
||||||
next.clone().item,
|
|
||||||
(expr.span().start, name.span().end),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Tagged::from_simple_spanned_item(
|
Ok(item.item().clone().tagged(expr.tag()))
|
||||||
item.item().clone(),
|
|
||||||
expr.span(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
RawExpression::Boolean(_boolean) => unimplemented!(),
|
RawExpression::Boolean(_boolean) => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -113,9 +106,9 @@ fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged<Val
|
||||||
let result = match literal.item {
|
let result = match literal.item {
|
||||||
hir::Literal::Number(int) => int.into(),
|
hir::Literal::Number(int) => int.into(),
|
||||||
hir::Literal::Size(int, unit) => unit.compute(int),
|
hir::Literal::Size(int, unit) => unit.compute(int),
|
||||||
hir::Literal::String(span) => Value::string(span.slice(source)),
|
hir::Literal::String(tag) => Value::string(tag.slice(source)),
|
||||||
hir::Literal::GlobPattern => Value::pattern(literal.span().slice(source)),
|
hir::Literal::GlobPattern => Value::pattern(literal.tag().slice(source)),
|
||||||
hir::Literal::Bare => Value::string(literal.span().slice(source)),
|
hir::Literal::Bare => Value::string(literal.tag().slice(source)),
|
||||||
};
|
};
|
||||||
|
|
||||||
literal.map(|_| result)
|
literal.map(|_| result)
|
||||||
|
@ -127,12 +120,12 @@ fn evaluate_reference(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
hir::Variable::It(span) => Ok(scope.it.item.clone().simple_spanned(span)),
|
hir::Variable::It(tag) => Ok(scope.it.item.clone().tagged(*tag)),
|
||||||
hir::Variable::Other(span) => Ok(scope
|
hir::Variable::Other(tag) => Ok(scope
|
||||||
.vars
|
.vars
|
||||||
.get(span.slice(source))
|
.get(tag.slice(source))
|
||||||
.map(|v| v.clone())
|
.map(|v| v.clone())
|
||||||
.unwrap_or_else(|| Value::nothing().simple_spanned(span))),
|
.unwrap_or_else(|| Value::nothing().tagged(*tag))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +135,6 @@ fn evaluate_external(
|
||||||
_source: &Text,
|
_source: &Text,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
Err(ShellError::syntax_error(
|
Err(ShellError::syntax_error(
|
||||||
"Unexpected external command".tagged(external.name()),
|
"Unexpected external command".tagged(*external.name()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl RenderView for TableView {
|
||||||
|
|
||||||
let mut table = Table::new();
|
let mut table = Table::new();
|
||||||
|
|
||||||
let table_mode = crate::data::config::config(Span::unknown())?
|
let table_mode = crate::data::config::config(Tag::unknown())?
|
||||||
.get("table_mode")
|
.get("table_mode")
|
||||||
.map(|s| match s.as_string().unwrap().as_ref() {
|
.map(|s| match s.as_string().unwrap().as_ref() {
|
||||||
"light" => TableMode::Light,
|
"light" => TableMode::Light,
|
||||||
|
|
|
@ -23,7 +23,7 @@ mod utils;
|
||||||
pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue};
|
pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue};
|
||||||
pub use crate::context::{SourceMap, SpanSource};
|
pub use crate::context::{SourceMap, SpanSource};
|
||||||
pub use crate::env::host::BasicHost;
|
pub use crate::env::host::BasicHost;
|
||||||
pub use crate::parser::hir::SyntaxType;
|
pub use crate::parser::hir::SyntaxShape;
|
||||||
pub use crate::parser::parse::token_tree_builder::TokenTreeBuilder;
|
pub use crate::parser::parse::token_tree_builder::TokenTreeBuilder;
|
||||||
pub use crate::plugin::{serve_plugin, Plugin};
|
pub use crate::plugin::{serve_plugin, Plugin};
|
||||||
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
|
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
|
||||||
|
@ -31,7 +31,7 @@ pub use cli::cli;
|
||||||
pub use data::config::{APP_INFO, config_path};
|
pub use data::config::{APP_INFO, config_path};
|
||||||
pub use data::base::{Primitive, Value};
|
pub use data::base::{Primitive, Value};
|
||||||
pub use data::dict::{Dictionary, TaggedDictBuilder};
|
pub use data::dict::{Dictionary, TaggedDictBuilder};
|
||||||
pub use data::meta::{Span, Tag, Tagged, TaggedItem};
|
pub use data::meta::{Tag, Tagged, TaggedItem};
|
||||||
pub use errors::{CoerceInto, ShellError};
|
pub use errors::{CoerceInto, ShellError};
|
||||||
pub use num_traits::cast::ToPrimitive;
|
pub use num_traits::cast::ToPrimitive;
|
||||||
pub use parser::parse::text::Text;
|
pub use parser::parse::text::Text;
|
||||||
|
|
|
@ -21,10 +21,10 @@ pub(crate) use parse::unit::Unit;
|
||||||
pub(crate) use parse_command::parse_command;
|
pub(crate) use parse_command::parse_command;
|
||||||
pub(crate) use registry::CommandRegistry;
|
pub(crate) use registry::CommandRegistry;
|
||||||
|
|
||||||
pub fn parse(input: &str) -> Result<TokenNode, ShellError> {
|
pub fn parse(input: &str, origin: uuid::Uuid) -> Result<TokenNode, ShellError> {
|
||||||
let _ = pretty_env_logger::try_init();
|
let _ = pretty_env_logger::try_init();
|
||||||
|
|
||||||
match pipeline(nom_input(input)) {
|
match pipeline(nom_input(input, origin)) {
|
||||||
Ok((_rest, val)) => Ok(val),
|
Ok((_rest, val)) => Ok(val),
|
||||||
Err(err) => Err(ShellError::parse_error(err)),
|
Err(err) => Err(ShellError::parse_error(err)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl<'de> ConfigDeserializer<'de> {
|
||||||
let value: Option<Tagged<Value>> = if name == "rest" {
|
let value: Option<Tagged<Value>> = if name == "rest" {
|
||||||
let positional = self.call.args.slice_from(self.position);
|
let positional = self.call.args.slice_from(self.position);
|
||||||
self.position += positional.len();
|
self.position += positional.len();
|
||||||
Some(Value::Table(positional).tagged_unknown()) // TODO: correct span
|
Some(Value::Table(positional).tagged_unknown()) // TODO: correct tag
|
||||||
} else {
|
} else {
|
||||||
if self.call.args.has(name) {
|
if self.call.args.has(name) {
|
||||||
self.call.args.get(name).map(|x| x.clone())
|
self.call.args.get(name).map(|x| x.clone())
|
||||||
|
@ -52,9 +52,7 @@ impl<'de> ConfigDeserializer<'de> {
|
||||||
|
|
||||||
self.stack.push(DeserializerItem {
|
self.stack.push(DeserializerItem {
|
||||||
key_struct_field: Some((name.to_string(), name)),
|
key_struct_field: Some((name.to_string(), name)),
|
||||||
val: value.unwrap_or_else(|| {
|
val: value.unwrap_or_else(|| Value::nothing().tagged(self.call.name_tag)),
|
||||||
Value::nothing().tagged(Tag::unknown_origin(self.call.name_span))
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) use self::external_command::ExternalCommand;
|
||||||
pub(crate) use self::named::NamedArguments;
|
pub(crate) use self::named::NamedArguments;
|
||||||
pub(crate) use self::path::Path;
|
pub(crate) use self::path::Path;
|
||||||
|
|
||||||
pub use self::baseline_parse_tokens::SyntaxType;
|
pub use self::baseline_parse_tokens::SyntaxShape;
|
||||||
|
|
||||||
pub fn path(head: impl Into<Expression>, tail: Vec<Tagged<impl Into<String>>>) -> Path {
|
pub fn path(head: impl Into<Expression>, tail: Vec<Tagged<impl Into<String>>>) -> Path {
|
||||||
Path::new(
|
Path::new(
|
||||||
|
@ -131,72 +131,57 @@ impl RawExpression {
|
||||||
pub type Expression = Tagged<RawExpression>;
|
pub type Expression = Tagged<RawExpression>;
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub(crate) fn number(i: impl Into<Number>, span: impl Into<Span>) -> Expression {
|
pub(crate) fn number(i: impl Into<Number>, tag: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Number(i.into())), span)
|
RawExpression::Literal(Literal::Number(i.into())).tagged(tag.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn size(
|
pub(crate) fn size(
|
||||||
i: impl Into<Number>,
|
i: impl Into<Number>,
|
||||||
unit: impl Into<Unit>,
|
unit: impl Into<Unit>,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Expression {
|
) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
RawExpression::Literal(Literal::Size(i.into(), unit.into())).tagged(tag.into())
|
||||||
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
|
||||||
span,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression {
|
pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression {
|
||||||
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
|
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn string(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
RawExpression::Literal(Literal::String(inner.into())).tagged(outer.into())
|
||||||
RawExpression::Literal(Literal::String(inner.into())),
|
|
||||||
outer.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into())
|
RawExpression::FilePath(path.into()).tagged(outer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bare(span: impl Into<Span>) -> Expression {
|
pub(crate) fn bare(tag: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
|
RawExpression::Literal(Literal::Bare).tagged(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pattern(tag: impl Into<Tag>) -> Expression {
|
pub(crate) fn pattern(tag: impl Into<Tag>) -> Expression {
|
||||||
RawExpression::Literal(Literal::GlobPattern).tagged(tag.into())
|
RawExpression::Literal(Literal::GlobPattern).tagged(tag.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn variable(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
RawExpression::Variable(Variable::Other(inner.into())).tagged(outer)
|
||||||
RawExpression::Variable(Variable::Other(inner.into())),
|
|
||||||
outer.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn external_command(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())).tagged(outer)
|
||||||
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())),
|
|
||||||
outer.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn it_variable(inner: impl Into<Tag>, outer: impl Into<Tag>) -> Expression {
|
||||||
Tagged::from_simple_spanned_item(
|
RawExpression::Variable(Variable::It(inner.into())).tagged(outer)
|
||||||
RawExpression::Variable(Variable::It(inner.into())),
|
|
||||||
outer.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for Expression {
|
impl ToDebug for Expression {
|
||||||
fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result {
|
fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result {
|
||||||
match self.item() {
|
match self.item() {
|
||||||
RawExpression::Literal(l) => l.tagged(self.span()).fmt_debug(f, source),
|
RawExpression::Literal(l) => l.tagged(self.tag()).fmt_debug(f, source),
|
||||||
RawExpression::FilePath(p) => write!(f, "{}", p.display()),
|
RawExpression::FilePath(p) => write!(f, "{}", p.display()),
|
||||||
RawExpression::ExternalWord => write!(f, "{}", self.span().slice(source)),
|
RawExpression::ExternalWord => write!(f, "{}", self.tag().slice(source)),
|
||||||
RawExpression::Synthetic(Synthetic::String(s)) => write!(f, "{:?}", s),
|
RawExpression::Synthetic(Synthetic::String(s)) => write!(f, "{:?}", s),
|
||||||
RawExpression::Variable(Variable::It(_)) => write!(f, "$it"),
|
RawExpression::Variable(Variable::It(_)) => write!(f, "$it"),
|
||||||
RawExpression::Variable(Variable::Other(s)) => write!(f, "${}", s.slice(source)),
|
RawExpression::Variable(Variable::Other(s)) => write!(f, "${}", s.slice(source)),
|
||||||
|
@ -242,7 +227,7 @@ impl From<Tagged<Path>> for Expression {
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
Number(Number),
|
Number(Number),
|
||||||
Size(Number, Unit),
|
Size(Number, Unit),
|
||||||
String(Span),
|
String(Tag),
|
||||||
GlobPattern,
|
GlobPattern,
|
||||||
Bare,
|
Bare,
|
||||||
}
|
}
|
||||||
|
@ -252,9 +237,9 @@ impl ToDebug for Tagged<&Literal> {
|
||||||
match self.item() {
|
match self.item() {
|
||||||
Literal::Number(number) => write!(f, "{:?}", *number),
|
Literal::Number(number) => write!(f, "{:?}", *number),
|
||||||
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
|
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
|
||||||
Literal::String(span) => write!(f, "{}", span.slice(source)),
|
Literal::String(tag) => write!(f, "{}", tag.slice(source)),
|
||||||
Literal::GlobPattern => write!(f, "{}", self.span().slice(source)),
|
Literal::GlobPattern => write!(f, "{}", self.tag().slice(source)),
|
||||||
Literal::Bare => write!(f, "{}", self.span().slice(source)),
|
Literal::Bare => write!(f, "{}", self.tag().slice(source)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,6 +258,6 @@ impl Literal {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||||
pub enum Variable {
|
pub enum Variable {
|
||||||
It(Span),
|
It(Tag),
|
||||||
Other(Span),
|
Other(Tag),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,19 @@ pub fn baseline_parse_single_token(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
Ok(match *token.item() {
|
Ok(match *token.item() {
|
||||||
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()),
|
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.tag()),
|
||||||
RawToken::Size(int, unit) => {
|
RawToken::Size(int, unit) => {
|
||||||
hir::Expression::size(int.to_number(source), unit, token.span())
|
hir::Expression::size(int.to_number(source), unit, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(tag) if tag.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(tag, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
|
||||||
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()),
|
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
|
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
|
||||||
RawToken::GlobPattern => hir::Expression::pattern(token.span()),
|
RawToken::GlobPattern => hir::Expression::pattern(token.tag()),
|
||||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
RawToken::Bare => hir::Expression::bare(token.tag()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,24 +31,24 @@ pub fn baseline_parse_token_as_number(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
Ok(match *token.item() {
|
Ok(match *token.item() {
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(tag) if tag.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(tag, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()),
|
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
|
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
|
||||||
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()),
|
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.tag()),
|
||||||
RawToken::Size(number, unit) => {
|
RawToken::Size(number, unit) => {
|
||||||
hir::Expression::size(number.to_number(source), unit, token.span())
|
hir::Expression::size(number.to_number(source), unit, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
RawToken::Bare => hir::Expression::bare(token.tag()),
|
||||||
RawToken::GlobPattern => {
|
RawToken::GlobPattern => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Number",
|
"Number",
|
||||||
"glob pattern".to_string().tagged(token.tag()),
|
"glob pattern".to_string().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,22 +57,22 @@ pub fn baseline_parse_token_as_string(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
Ok(match *token.item() {
|
Ok(match *token.item() {
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(tag) if tag.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(tag, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()),
|
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
|
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
|
||||||
RawToken::Number(_) => hir::Expression::bare(token.span()),
|
RawToken::Number(_) => hir::Expression::bare(token.tag()),
|
||||||
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
|
RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
|
||||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
RawToken::Bare => hir::Expression::bare(token.tag()),
|
||||||
RawToken::GlobPattern => {
|
RawToken::GlobPattern => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"String",
|
"String",
|
||||||
"glob pattern".tagged(token.tag()),
|
"glob pattern".tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
RawToken::String(tag) => hir::Expression::string(tag, token.tag()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,26 +82,25 @@ pub fn baseline_parse_token_as_path(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
Ok(match *token.item() {
|
Ok(match *token.item() {
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(tag) if tag.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(tag, token.tag())
|
||||||
|
}
|
||||||
|
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token.tag()),
|
||||||
|
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
|
||||||
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
|
||||||
|
RawToken::Number(_) => hir::Expression::bare(token.tag()),
|
||||||
|
RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
|
||||||
|
RawToken::Bare => {
|
||||||
|
hir::Expression::file_path(expand_path(token.tag().slice(source), context), token.tag())
|
||||||
}
|
}
|
||||||
RawToken::ExternalCommand(span) => hir::Expression::external_command(span, token.span()),
|
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
|
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
|
||||||
RawToken::Number(_) => hir::Expression::bare(token.span()),
|
|
||||||
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
|
|
||||||
RawToken::Bare => hir::Expression::file_path(
|
|
||||||
expand_path(token.span().slice(source), context),
|
|
||||||
token.span(),
|
|
||||||
),
|
|
||||||
RawToken::GlobPattern => {
|
RawToken::GlobPattern => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Path",
|
"Path",
|
||||||
"glob pattern".tagged(token.tag()),
|
"glob pattern".tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
RawToken::String(span) => {
|
RawToken::String(tag) => {
|
||||||
hir::Expression::file_path(expand_path(span.slice(source), context), token.span())
|
hir::Expression::file_path(expand_path(tag.slice(source), context), token.tag())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -112,25 +111,24 @@ pub fn baseline_parse_token_as_pattern(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
Ok(match *token.item() {
|
Ok(match *token.item() {
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(tag) if tag.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(tag, token.tag())
|
||||||
}
|
}
|
||||||
RawToken::ExternalCommand(_) => {
|
RawToken::ExternalCommand(_) => {
|
||||||
return Err(ShellError::syntax_error(
|
return Err(ShellError::syntax_error(
|
||||||
"Invalid external command".to_string().tagged(token.tag()),
|
"Invalid external command".to_string().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.span())),
|
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token.tag())),
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token.tag()),
|
||||||
RawToken::Number(_) => hir::Expression::bare(token.span()),
|
RawToken::Number(_) => hir::Expression::bare(token.tag()),
|
||||||
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
|
RawToken::Size(_, _) => hir::Expression::bare(token.tag()),
|
||||||
RawToken::GlobPattern => hir::Expression::pattern(token.span()),
|
RawToken::GlobPattern => hir::Expression::pattern(token.tag()),
|
||||||
RawToken::Bare => hir::Expression::file_path(
|
RawToken::Bare => {
|
||||||
expand_path(token.span().slice(source), context),
|
hir::Expression::file_path(expand_path(token.tag().slice(source), context), token.tag())
|
||||||
token.span(),
|
}
|
||||||
),
|
RawToken::String(tag) => {
|
||||||
RawToken::String(span) => {
|
hir::Expression::file_path(expand_path(tag.slice(source), context), token.tag())
|
||||||
hir::Expression::file_path(expand_path(span.slice(source), context), token.span())
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::parser::{
|
||||||
},
|
},
|
||||||
DelimitedNode, Delimiter, PathNode, RawToken, TokenNode,
|
DelimitedNode, Delimiter, PathNode, RawToken, TokenNode,
|
||||||
};
|
};
|
||||||
use crate::{Span, Tag, Tagged, TaggedItem, Text};
|
use crate::{Tag, Tagged, TaggedItem, Text};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -17,7 +17,7 @@ pub fn baseline_parse_tokens(
|
||||||
token_nodes: &mut TokensIterator<'_>,
|
token_nodes: &mut TokensIterator<'_>,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
syntax_type: SyntaxType,
|
syntax_type: SyntaxShape,
|
||||||
) -> Result<Vec<hir::Expression>, ShellError> {
|
) -> Result<Vec<hir::Expression>, ShellError> {
|
||||||
let mut exprs: Vec<hir::Expression> = vec![];
|
let mut exprs: Vec<hir::Expression> = vec![];
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ pub fn baseline_parse_tokens(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum SyntaxType {
|
pub enum SyntaxShape {
|
||||||
Any,
|
Any,
|
||||||
List,
|
List,
|
||||||
Literal,
|
Literal,
|
||||||
|
@ -49,21 +49,21 @@ pub enum SyntaxType {
|
||||||
Boolean,
|
Boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for SyntaxType {
|
impl std::fmt::Display for SyntaxShape {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
SyntaxType::Any => write!(f, "Any"),
|
SyntaxShape::Any => write!(f, "Any"),
|
||||||
SyntaxType::List => write!(f, "List"),
|
SyntaxShape::List => write!(f, "List"),
|
||||||
SyntaxType::Literal => write!(f, "Literal"),
|
SyntaxShape::Literal => write!(f, "Literal"),
|
||||||
SyntaxType::String => write!(f, "String"),
|
SyntaxShape::String => write!(f, "String"),
|
||||||
SyntaxType::Member => write!(f, "Member"),
|
SyntaxShape::Member => write!(f, "Member"),
|
||||||
SyntaxType::Variable => write!(f, "Variable"),
|
SyntaxShape::Variable => write!(f, "Variable"),
|
||||||
SyntaxType::Number => write!(f, "Number"),
|
SyntaxShape::Number => write!(f, "Number"),
|
||||||
SyntaxType::Path => write!(f, "Path"),
|
SyntaxShape::Path => write!(f, "Path"),
|
||||||
SyntaxType::Pattern => write!(f, "Pattern"),
|
SyntaxShape::Pattern => write!(f, "Pattern"),
|
||||||
SyntaxType::Binary => write!(f, "Binary"),
|
SyntaxShape::Binary => write!(f, "Binary"),
|
||||||
SyntaxType::Block => write!(f, "Block"),
|
SyntaxShape::Block => write!(f, "Block"),
|
||||||
SyntaxType::Boolean => write!(f, "Boolean"),
|
SyntaxShape::Boolean => write!(f, "Boolean"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ pub fn baseline_parse_next_expr(
|
||||||
tokens: &mut TokensIterator,
|
tokens: &mut TokensIterator,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
syntax_type: SyntaxType,
|
syntax_type: SyntaxShape,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
let next = tokens
|
let next = tokens
|
||||||
.next()
|
.next()
|
||||||
|
@ -81,69 +81,69 @@ pub fn baseline_parse_next_expr(
|
||||||
trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", syntax_type, next);
|
trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", syntax_type, next);
|
||||||
|
|
||||||
match (syntax_type, next) {
|
match (syntax_type, next) {
|
||||||
(SyntaxType::Path, TokenNode::Token(token)) => {
|
(SyntaxShape::Path, TokenNode::Token(token)) => {
|
||||||
return baseline_parse_token_as_path(token, context, source)
|
return baseline_parse_token_as_path(token, context, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Path, token) => {
|
(SyntaxShape::Path, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Path",
|
"Path",
|
||||||
token.type_name().simple_spanned(token.span()),
|
token.type_name().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Pattern, TokenNode::Token(token)) => {
|
(SyntaxShape::Pattern, TokenNode::Token(token)) => {
|
||||||
return baseline_parse_token_as_pattern(token, context, source)
|
return baseline_parse_token_as_pattern(token, context, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Pattern, token) => {
|
(SyntaxShape::Pattern, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Path",
|
"Path",
|
||||||
token.type_name().simple_spanned(token.span()),
|
token.type_name().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::String, TokenNode::Token(token)) => {
|
(SyntaxShape::String, TokenNode::Token(token)) => {
|
||||||
return baseline_parse_token_as_string(token, source);
|
return baseline_parse_token_as_string(token, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::String, token) => {
|
(SyntaxShape::String, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"String",
|
"String",
|
||||||
token.type_name().simple_spanned(token.span()),
|
token.type_name().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Number, TokenNode::Token(token)) => {
|
(SyntaxShape::Number, TokenNode::Token(token)) => {
|
||||||
return Ok(baseline_parse_token_as_number(token, source)?);
|
return Ok(baseline_parse_token_as_number(token, source)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Number, token) => {
|
(SyntaxShape::Number, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Numeric",
|
"Numeric",
|
||||||
token.type_name().simple_spanned(token.span()),
|
token.type_name().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: More legit member processing
|
// TODO: More legit member processing
|
||||||
(SyntaxType::Member, TokenNode::Token(token)) => {
|
(SyntaxShape::Member, TokenNode::Token(token)) => {
|
||||||
return baseline_parse_token_as_string(token, source);
|
return baseline_parse_token_as_string(token, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Member, token) => {
|
(SyntaxShape::Member, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"member",
|
"member",
|
||||||
token.type_name().simple_spanned(token.span()),
|
token.type_name().tagged(token.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
(SyntaxType::Any, _) => {}
|
(SyntaxShape::Any, _) => {}
|
||||||
(SyntaxType::List, _) => {}
|
(SyntaxShape::List, _) => {}
|
||||||
(SyntaxType::Literal, _) => {}
|
(SyntaxShape::Literal, _) => {}
|
||||||
(SyntaxType::Variable, _) => {}
|
(SyntaxShape::Variable, _) => {}
|
||||||
(SyntaxType::Binary, _) => {}
|
(SyntaxShape::Binary, _) => {}
|
||||||
(SyntaxType::Block, _) => {}
|
(SyntaxShape::Block, _) => {}
|
||||||
(SyntaxType::Boolean, _) => {}
|
(SyntaxShape::Boolean, _) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let first = baseline_parse_semantic_token(next, context, source)?;
|
let first = baseline_parse_semantic_token(next, context, source)?;
|
||||||
|
@ -162,7 +162,7 @@ pub fn baseline_parse_next_expr(
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected something after an operator",
|
"Expected something after an operator",
|
||||||
"operator",
|
"operator",
|
||||||
op.span(),
|
op.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(token) => baseline_parse_semantic_token(token, context, source)?,
|
Some(token) => baseline_parse_semantic_token(token, context, source)?,
|
||||||
|
@ -171,75 +171,66 @@ pub fn baseline_parse_next_expr(
|
||||||
// We definitely have a binary expression here -- let's see if we should coerce it into a block
|
// We definitely have a binary expression here -- let's see if we should coerce it into a block
|
||||||
|
|
||||||
match syntax_type {
|
match syntax_type {
|
||||||
SyntaxType::Any => {
|
SyntaxShape::Any => {
|
||||||
let span = (first.span().start, second.span().end);
|
let tag = first.tag().until(second.tag());
|
||||||
let binary = hir::Binary::new(first, op, second);
|
let binary = hir::Binary::new(first, op, second);
|
||||||
let binary = hir::RawExpression::Binary(Box::new(binary));
|
let binary = hir::RawExpression::Binary(Box::new(binary));
|
||||||
let binary = Tagged::from_simple_spanned_item(binary, span);
|
let binary = binary.tagged(tag);
|
||||||
|
|
||||||
Ok(binary)
|
Ok(binary)
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxType::Block => {
|
SyntaxShape::Block => {
|
||||||
let span = (first.span().start, second.span().end);
|
let tag = first.tag().until(second.tag());
|
||||||
|
|
||||||
let path: Tagged<hir::RawExpression> = match first {
|
let path: Tagged<hir::RawExpression> = match first {
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
} => {
|
} => {
|
||||||
let string =
|
let string = tag.slice(source).to_string().tagged(tag);
|
||||||
Tagged::from_simple_spanned_item(span.slice(source).to_string(), span);
|
|
||||||
let path = hir::Path::new(
|
let path = hir::Path::new(
|
||||||
Tagged::from_simple_spanned_item(
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
hir::RawExpression::Variable(hir::Variable::It(Tag::unknown()))
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
.tagged(Tag::unknown()),
|
||||||
(0, 0),
|
|
||||||
),
|
|
||||||
vec![string],
|
vec![string],
|
||||||
);
|
);
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
Tagged::from_simple_spanned_item(path, first.span())
|
path.tagged(first.tag())
|
||||||
}
|
}
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
} => {
|
} => {
|
||||||
let string =
|
let string = inner.slice(source).to_string().tagged(tag);
|
||||||
Tagged::from_simple_spanned_item(inner.slice(source).to_string(), span);
|
|
||||||
let path = hir::Path::new(
|
let path = hir::Path::new(
|
||||||
Tagged::from_simple_spanned_item(
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
hir::RawExpression::Variable(hir::Variable::It(Tag::unknown()))
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
.tagged_unknown(),
|
||||||
(0, 0),
|
|
||||||
),
|
|
||||||
vec![string],
|
vec![string],
|
||||||
);
|
);
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
Tagged::from_simple_spanned_item(path, first.span())
|
path.tagged(first.tag())
|
||||||
}
|
}
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Variable(..),
|
item: hir::RawExpression::Variable(..),
|
||||||
..
|
..
|
||||||
} => first,
|
} => first,
|
||||||
Tagged {
|
Tagged { tag, item } => {
|
||||||
tag: Tag { span, .. },
|
|
||||||
item,
|
|
||||||
} => {
|
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"The first part of an un-braced block must be a column name",
|
"The first part of an un-braced block must be a column name",
|
||||||
item.type_name(),
|
item.type_name(),
|
||||||
span,
|
tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let binary = hir::Binary::new(path, op, second);
|
let binary = hir::Binary::new(path, op, second);
|
||||||
let binary = hir::RawExpression::Binary(Box::new(binary));
|
let binary = hir::RawExpression::Binary(Box::new(binary));
|
||||||
let binary = Tagged::from_simple_spanned_item(binary, span);
|
let binary = binary.tagged(tag);
|
||||||
|
|
||||||
let block = hir::RawExpression::Block(vec![binary]);
|
let block = hir::RawExpression::Block(vec![binary]);
|
||||||
let block = Tagged::from_simple_spanned_item(block, span);
|
let block = block.tagged(tag);
|
||||||
|
|
||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
@ -265,11 +256,11 @@ pub fn baseline_parse_semantic_token(
|
||||||
"Unexpected operator".tagged(op.tag),
|
"Unexpected operator".tagged(op.tag),
|
||||||
)),
|
)),
|
||||||
TokenNode::Flag(flag) => Err(ShellError::syntax_error("Unexpected flag".tagged(flag.tag))),
|
TokenNode::Flag(flag) => Err(ShellError::syntax_error("Unexpected flag".tagged(flag.tag))),
|
||||||
TokenNode::Member(span) => Err(ShellError::syntax_error(
|
TokenNode::Member(tag) => Err(ShellError::syntax_error(
|
||||||
"BUG: Top-level member".tagged(span),
|
"BUG: Top-level member".tagged(*tag),
|
||||||
)),
|
)),
|
||||||
TokenNode::Whitespace(span) => Err(ShellError::syntax_error(
|
TokenNode::Whitespace(tag) => Err(ShellError::syntax_error(
|
||||||
"BUG: Whitespace found during parse".tagged(span),
|
"BUG: Whitespace found during parse".tagged(*tag),
|
||||||
)),
|
)),
|
||||||
TokenNode::Error(error) => Err(*error.item.clone()),
|
TokenNode::Error(error) => Err(*error.item.clone()),
|
||||||
TokenNode::Path(path) => baseline_parse_path(path, context, source),
|
TokenNode::Path(path) => baseline_parse_path(path, context, source),
|
||||||
|
@ -288,11 +279,11 @@ pub fn baseline_parse_delimited(
|
||||||
&mut TokensIterator::new(children),
|
&mut TokensIterator::new(children),
|
||||||
context,
|
context,
|
||||||
source,
|
source,
|
||||||
SyntaxType::Any,
|
SyntaxShape::Any,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let expr = hir::RawExpression::Block(exprs);
|
let expr = hir::RawExpression::Block(exprs);
|
||||||
Ok(Tagged::from_simple_spanned_item(expr, token.span()))
|
Ok(expr.tagged(token.tag()))
|
||||||
}
|
}
|
||||||
Delimiter::Paren => unimplemented!(),
|
Delimiter::Paren => unimplemented!(),
|
||||||
Delimiter::Square => {
|
Delimiter::Square => {
|
||||||
|
@ -301,11 +292,11 @@ pub fn baseline_parse_delimited(
|
||||||
&mut TokensIterator::new(children),
|
&mut TokensIterator::new(children),
|
||||||
context,
|
context,
|
||||||
source,
|
source,
|
||||||
SyntaxType::Any,
|
SyntaxShape::Any,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let expr = hir::RawExpression::List(exprs);
|
let expr = hir::RawExpression::List(exprs);
|
||||||
Ok(expr.tagged(Tag::unknown_origin(token.span())))
|
Ok(expr.tagged(token.tag()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,8 +313,8 @@ pub fn baseline_parse_path(
|
||||||
for part in token.tail() {
|
for part in token.tail() {
|
||||||
let string = match part {
|
let string = match part {
|
||||||
TokenNode::Token(token) => match token.item() {
|
TokenNode::Token(token) => match token.item() {
|
||||||
RawToken::Bare => token.span().slice(source),
|
RawToken::Bare => token.tag().slice(source),
|
||||||
RawToken::String(span) => span.slice(source),
|
RawToken::String(tag) => tag.slice(source),
|
||||||
RawToken::Number(_)
|
RawToken::Number(_)
|
||||||
| RawToken::Size(..)
|
| RawToken::Size(..)
|
||||||
| RawToken::Variable(_)
|
| RawToken::Variable(_)
|
||||||
|
@ -332,26 +323,26 @@ pub fn baseline_parse_path(
|
||||||
| RawToken::ExternalWord => {
|
| RawToken::ExternalWord => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"String",
|
"String",
|
||||||
token.type_name().simple_spanned(part),
|
token.type_name().tagged(part.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
TokenNode::Member(span) => span.slice(source),
|
TokenNode::Member(tag) => tag.slice(source),
|
||||||
|
|
||||||
// TODO: Make this impossible
|
// TODO: Make this impossible
|
||||||
other => {
|
other => {
|
||||||
return Err(ShellError::syntax_error(
|
return Err(ShellError::syntax_error(
|
||||||
format!("{} in path", other.type_name()).tagged(other.span()),
|
format!("{} in path", other.type_name()).tagged(other.tag()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
tail.push(string.simple_spanned(part));
|
tail.push(string.tagged(part.tag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(hir::path(head, tail).simple_spanned(token).into())
|
Ok(hir::path(head, tail).tagged(token.tag()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, new)]
|
#[derive(Debug, new)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::fmt;
|
||||||
)]
|
)]
|
||||||
#[get = "pub(crate)"]
|
#[get = "pub(crate)"]
|
||||||
pub struct ExternalCommand {
|
pub struct ExternalCommand {
|
||||||
name: Span,
|
name: Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for ExternalCommand {
|
impl ToDebug for ExternalCommand {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::parser::hir::Expression;
|
use crate::parser::hir::Expression;
|
||||||
use crate::parser::Flag;
|
use crate::parser::Flag;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::Span;
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
@ -11,7 +10,7 @@ use std::fmt;
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum NamedValue {
|
pub enum NamedValue {
|
||||||
AbsentSwitch,
|
AbsentSwitch,
|
||||||
PresentSwitch(Span),
|
PresentSwitch(Tag),
|
||||||
AbsentValue,
|
AbsentValue,
|
||||||
Value(Expression),
|
Value(Expression),
|
||||||
}
|
}
|
||||||
|
@ -27,7 +26,7 @@ impl ToDebug for NamedArguments {
|
||||||
for (name, value) in &self.named {
|
for (name, value) in &self.named {
|
||||||
match value {
|
match value {
|
||||||
NamedValue::AbsentSwitch => continue,
|
NamedValue::AbsentSwitch => continue,
|
||||||
NamedValue::PresentSwitch(span) => write!(f, " --{}", span.slice(source))?,
|
NamedValue::PresentSwitch(tag) => write!(f, " --{}", tag.slice(source))?,
|
||||||
NamedValue::AbsentValue => continue,
|
NamedValue::AbsentValue => continue,
|
||||||
NamedValue::Value(expr) => write!(f, " --{} {}", name, expr.debug(source))?,
|
NamedValue::Value(expr) => write!(f, " --{} {}", name, expr.debug(source))?,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::Span;
|
use crate::Tag;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use language_reporting::{FileName, Location};
|
use language_reporting::{FileName, Location};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(new, Debug, Clone)]
|
#[derive(new, Debug, Clone)]
|
||||||
pub struct Files {
|
pub struct Files {
|
||||||
|
@ -8,26 +9,30 @@ pub struct Files {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl language_reporting::ReportingFiles for Files {
|
impl language_reporting::ReportingFiles for Files {
|
||||||
type Span = Span;
|
type Span = Tag;
|
||||||
type FileId = usize;
|
type FileId = Uuid;
|
||||||
|
|
||||||
fn byte_span(
|
fn byte_span(
|
||||||
&self,
|
&self,
|
||||||
_file: Self::FileId,
|
file: Self::FileId,
|
||||||
from_index: usize,
|
from_index: usize,
|
||||||
to_index: usize,
|
to_index: usize,
|
||||||
) -> Option<Self::Span> {
|
) -> Option<Self::Span> {
|
||||||
Some(Span::from((from_index, to_index)))
|
Some(Tag::from((from_index, to_index, file)))
|
||||||
}
|
}
|
||||||
fn file_id(&self, _span: Self::Span) -> Self::FileId {
|
|
||||||
0
|
fn file_id(&self, tag: Self::Span) -> Self::FileId {
|
||||||
|
tag.origin.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_name(&self, _file: Self::FileId) -> FileName {
|
fn file_name(&self, _file: Self::FileId) -> FileName {
|
||||||
FileName::Verbatim(format!("shell"))
|
FileName::Verbatim(format!("shell"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option<usize> {
|
fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option<usize> {
|
||||||
unimplemented!("byte_index")
|
unimplemented!("byte_index")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn location(&self, _file: Self::FileId, byte_index: usize) -> Option<Location> {
|
fn location(&self, _file: Self::FileId, byte_index: usize) -> Option<Location> {
|
||||||
let source = &self.snippet;
|
let source = &self.snippet;
|
||||||
let mut seen_lines = 0;
|
let mut seen_lines = 0;
|
||||||
|
@ -51,14 +56,15 @@ impl language_reporting::ReportingFiles for Files {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn line_span(&self, _file: Self::FileId, lineno: usize) -> Option<Self::Span> {
|
|
||||||
|
fn line_span(&self, file: Self::FileId, lineno: usize) -> Option<Self::Span> {
|
||||||
let source = &self.snippet;
|
let source = &self.snippet;
|
||||||
let mut seen_lines = 0;
|
let mut seen_lines = 0;
|
||||||
let mut seen_bytes = 0;
|
let mut seen_bytes = 0;
|
||||||
|
|
||||||
for (pos, _) in source.match_indices('\n') {
|
for (pos, _) in source.match_indices('\n') {
|
||||||
if seen_lines == lineno {
|
if seen_lines == lineno {
|
||||||
return Some(Span::from((seen_bytes, pos)));
|
return Some(Tag::from((seen_bytes, pos, file)));
|
||||||
} else {
|
} else {
|
||||||
seen_lines += 1;
|
seen_lines += 1;
|
||||||
seen_bytes = pos + 1;
|
seen_bytes = pos + 1;
|
||||||
|
@ -66,17 +72,18 @@ impl language_reporting::ReportingFiles for Files {
|
||||||
}
|
}
|
||||||
|
|
||||||
if seen_lines == 0 {
|
if seen_lines == 0 {
|
||||||
Some(Span::from((0, self.snippet.len() - 1)))
|
Some(Tag::from((0, self.snippet.len() - 1, file)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn source(&self, span: Self::Span) -> Option<String> {
|
|
||||||
if span.start > span.end {
|
fn source(&self, tag: Self::Span) -> Option<String> {
|
||||||
|
if tag.span.start > tag.span.end {
|
||||||
return None;
|
return None;
|
||||||
} else if span.end >= self.snippet.len() {
|
} else if tag.span.end >= self.snippet.len() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(self.snippet[span.start..span.end].to_string())
|
Some(tag.slice(&self.snippet).to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::Span;
|
use crate::Tag;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -13,5 +13,5 @@ pub enum FlagKind {
|
||||||
#[get = "pub(crate)"]
|
#[get = "pub(crate)"]
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
kind: FlagKind,
|
kind: FlagKind,
|
||||||
name: Span,
|
name: Tag,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::parser::parse::{
|
||||||
tokens::*, unit::*,
|
tokens::*, unit::*,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{Span, Tagged};
|
use crate::{Tag, Tagged};
|
||||||
use nom;
|
use nom;
|
||||||
use nom::branch::*;
|
use nom::branch::*;
|
||||||
use nom::bytes::complete::*;
|
use nom::bytes::complete::*;
|
||||||
|
@ -18,15 +18,16 @@ use log::trace;
|
||||||
use nom::dbg;
|
use nom::dbg;
|
||||||
use nom::*;
|
use nom::*;
|
||||||
use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice};
|
use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice};
|
||||||
use nom5_locate::{position, LocatedSpan};
|
use nom_locate::{position, LocatedSpanEx};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub type NomSpan<'a> = LocatedSpan<&'a str>;
|
pub type NomSpan<'a> = LocatedSpanEx<&'a str, Uuid>;
|
||||||
|
|
||||||
pub fn nom_input(s: &str) -> NomSpan<'_> {
|
pub fn nom_input(s: &str, origin: Uuid) -> NomSpan<'_> {
|
||||||
LocatedSpan::new(s)
|
LocatedSpanEx::new_extra(s, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! operator {
|
macro_rules! operator {
|
||||||
|
@ -38,7 +39,7 @@ macro_rules! operator {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_op(tag.fragment, (start, end)),
|
TokenTreeBuilder::tagged_op(tag.fragment, (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -159,14 +160,14 @@ pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<RawNumber>> {
|
||||||
Ok((input, dot)) => input,
|
Ok((input, dot)) => input,
|
||||||
|
|
||||||
// it's just an integer
|
// it's just an integer
|
||||||
Err(_) => return Ok((input, RawNumber::int((start, input.offset)))),
|
Err(_) => return Ok((input, RawNumber::int((start, input.offset, input.extra)))),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (input, tail) = digit1(input)?;
|
let (input, tail) = digit1(input)?;
|
||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, RawNumber::decimal((start, end))))
|
Ok((input, RawNumber::decimal((start, end, input.extra))))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +190,7 @@ pub fn dq_string(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_string((start1, end1), (start, end)),
|
TokenTreeBuilder::tagged_string((start1, end1, input.extra), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -206,7 +207,7 @@ pub fn sq_string(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_string((start1, end1), (start, end)),
|
TokenTreeBuilder::tagged_string((start1, end1, input.extra), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -226,7 +227,7 @@ pub fn external(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_external(bare, (start, end)),
|
TokenTreeBuilder::tagged_external(bare, (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -250,7 +251,10 @@ pub fn pattern(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_pattern((start, end))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_pattern((start, end, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +267,7 @@ pub fn bare(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
let next_char = &input.fragment.chars().nth(0);
|
let next_char = &input.fragment.chars().nth(0);
|
||||||
|
|
||||||
if let Some(next_char) = next_char {
|
if let Some(next_char) = next_char {
|
||||||
if is_external_word_char(*next_char) || *next_char == '*' {
|
if is_external_word_char(*next_char) || is_glob_specific_char(*next_char) {
|
||||||
return Err(nom::Err::Error(nom::error::make_error(
|
return Err(nom::Err::Error(nom::error::make_error(
|
||||||
input,
|
input,
|
||||||
nom::error::ErrorKind::TakeWhile1,
|
nom::error::ErrorKind::TakeWhile1,
|
||||||
|
@ -273,7 +277,10 @@ pub fn bare(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_bare((start, end))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_bare((start, end, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +290,10 @@ pub fn external_word(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
let (input, _) = take_while1(is_external_word_char)(input)?;
|
let (input, _) = take_while1(is_external_word_char)(input)?;
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_external_word((start, end))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_external_word((start, end, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +306,7 @@ pub fn var(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_var(bare.span(), (start, end)),
|
TokenTreeBuilder::tagged_var(bare.tag(), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -309,7 +319,10 @@ pub fn member(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_member((start, end))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_member((start, end, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +335,7 @@ pub fn flag(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_flag(bare.span(), (start, end)),
|
TokenTreeBuilder::tagged_flag(bare.tag(), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -336,7 +349,7 @@ pub fn shorthand(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_shorthand(bare.span(), (start, end)),
|
TokenTreeBuilder::tagged_shorthand(bare.tag(), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -369,7 +382,7 @@ pub fn raw_unit(input: NomSpan) -> IResult<NomSpan, Tagged<Unit>> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Tagged::from_simple_spanned_item(Unit::from(unit.fragment), (start, end)),
|
Unit::from(unit.fragment).tagged((start, end, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -389,7 +402,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_size((number.item, *size), (start, end)),
|
TokenTreeBuilder::tagged_size((number.item, *size), (start, end, input.extra)),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
@ -401,7 +414,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_number(number.item, number.tag),
|
TokenTreeBuilder::tagged_number(number.item, number.tag),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -455,18 +468,18 @@ fn make_token_list(
|
||||||
let mut nodes = vec![];
|
let mut nodes = vec![];
|
||||||
|
|
||||||
if let Some(sp_left) = sp_left {
|
if let Some(sp_left) = sp_left {
|
||||||
nodes.push(TokenNode::Whitespace(Span::from(sp_left)));
|
nodes.push(TokenNode::Whitespace(Tag::from(sp_left)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.push(first);
|
nodes.push(first);
|
||||||
|
|
||||||
for (ws, token) in list {
|
for (ws, token) in list {
|
||||||
nodes.push(TokenNode::Whitespace(Span::from(ws)));
|
nodes.push(TokenNode::Whitespace(Tag::from(ws)));
|
||||||
nodes.push(token);
|
nodes.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sp_right) = sp_right {
|
if let Some(sp_right) = sp_right {
|
||||||
nodes.push(TokenNode::Whitespace(Span::from(sp_right)));
|
nodes.push(TokenNode::Whitespace(Tag::from(sp_right)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes
|
nodes
|
||||||
|
@ -478,7 +491,10 @@ pub fn whitespace(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
let (input, ws1) = space1(input)?;
|
let (input, ws1) = space1(input)?;
|
||||||
let right = input.offset;
|
let right = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_ws((left, right))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_ws((left, right, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,7 +524,7 @@ pub fn delimited_paren(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_parens(items, (left, right)),
|
TokenTreeBuilder::tagged_parens(items, (left, right, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -539,7 +555,7 @@ pub fn delimited_square(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_square(items, (left, right)),
|
TokenTreeBuilder::tagged_square(items, (left, right, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -556,7 +572,10 @@ pub fn delimited_brace(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_brace(items.unwrap_or_else(|| vec![]), (left, right)),
|
TokenTreeBuilder::tagged_brace(
|
||||||
|
items.unwrap_or_else(|| vec![]),
|
||||||
|
(left, right, input.extra),
|
||||||
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -567,7 +586,10 @@ pub fn raw_call(input: NomSpan) -> IResult<NomSpan, Tagged<CallNode>> {
|
||||||
let (input, items) = token_list(input)?;
|
let (input, items) = token_list(input)?;
|
||||||
let right = input.offset;
|
let right = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_call(items, (left, right))))
|
Ok((
|
||||||
|
input,
|
||||||
|
TokenTreeBuilder::tagged_call(items, (left, right, input.extra)),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +603,7 @@ pub fn path(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_path((head, tail), (left, right)),
|
TokenTreeBuilder::tagged_path((head, tail), (left, right, input.extra)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -628,9 +650,9 @@ pub fn pipeline(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
TokenTreeBuilder::spanned_pipeline(
|
TokenTreeBuilder::tagged_pipeline(
|
||||||
(make_call_list(head, items), tail.map(Span::from)),
|
(make_call_list(head, items), tail.map(Tag::from)),
|
||||||
(start, end),
|
(start, end, input.extra),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -643,17 +665,17 @@ fn make_call_list(
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
|
|
||||||
if let Some(head) = head {
|
if let Some(head) = head {
|
||||||
let el = PipelineElement::new(None, head.0.map(Span::from), head.1, head.2.map(Span::from));
|
let el = PipelineElement::new(None, head.0.map(Tag::from), head.1, head.2.map(Tag::from));
|
||||||
|
|
||||||
out.push(el);
|
out.push(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pipe, ws1, call, ws2) in items {
|
for (pipe, ws1, call, ws2) in items {
|
||||||
let el = PipelineElement::new(
|
let el = PipelineElement::new(
|
||||||
Some(pipe).map(Span::from),
|
Some(pipe).map(Tag::from),
|
||||||
ws1.map(Span::from),
|
ws1.map(Tag::from),
|
||||||
call,
|
call,
|
||||||
ws2.map(Span::from),
|
ws2.map(Tag::from),
|
||||||
);
|
);
|
||||||
|
|
||||||
out.push(el);
|
out.push(el);
|
||||||
|
@ -679,12 +701,17 @@ fn is_external_word_char(c: char) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// These characters appear in globs and not bare words
|
||||||
|
fn is_glob_specific_char(c: char) -> bool {
|
||||||
|
c == '*' || c == '?'
|
||||||
|
}
|
||||||
|
|
||||||
fn is_start_glob_char(c: char) -> bool {
|
fn is_start_glob_char(c: char) -> bool {
|
||||||
is_start_bare_char(c) || c == '*'
|
is_start_bare_char(c) || is_glob_specific_char(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_glob_char(c: char) -> bool {
|
fn is_glob_char(c: char) -> bool {
|
||||||
is_bare_char(c) || c == '*'
|
is_bare_char(c) || is_glob_specific_char(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_start_bare_char(c: char) -> bool {
|
fn is_start_bare_char(c: char) -> bool {
|
||||||
|
@ -779,7 +806,7 @@ mod tests {
|
||||||
macro_rules! equal_tokens {
|
macro_rules! equal_tokens {
|
||||||
($source:tt -> $tokens:expr) => {
|
($source:tt -> $tokens:expr) => {
|
||||||
let result = apply(pipeline, "pipeline", $source);
|
let result = apply(pipeline, "pipeline", $source);
|
||||||
let (expected_tree, expected_source) = TokenTreeBuilder::build($tokens);
|
let (expected_tree, expected_source) = TokenTreeBuilder::build(uuid::Uuid::nil(), $tokens);
|
||||||
|
|
||||||
if result != expected_tree {
|
if result != expected_tree {
|
||||||
let debug_result = format!("{}", result.debug($source));
|
let debug_result = format!("{}", result.debug($source));
|
||||||
|
@ -818,12 +845,12 @@ mod tests {
|
||||||
fn test_integer() {
|
fn test_integer() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"123" -> 0..3 { Number(RawNumber::int((0, 3)).item) }
|
"123" -> 0..3 { Number(RawNumber::int((0, 3, test_uuid())).item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"-123" -> 0..4 { Number(RawNumber::int((0, 4)).item) }
|
"-123" -> 0..4 { Number(RawNumber::int((0, 4, test_uuid())).item) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,12 +858,12 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"123MB" -> 0..5 { Size(RawNumber::int((0, 3)).item, Unit::MB) }
|
"123MB" -> 0..5 { Size(RawNumber::int((0, 3, test_uuid())).item, Unit::MB) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"10GB" -> 0..4 { Size(RawNumber::int((0, 2)).item, Unit::GB) }
|
"10GB" -> 0..4 { Size(RawNumber::int((0, 2, test_uuid())).item, Unit::GB) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,12 +901,12 @@ mod tests {
|
||||||
fn test_string() {
|
fn test_string() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ string dq_string ]
|
parsers [ string dq_string ]
|
||||||
r#""hello world""# -> 0..13 { String(span(1, 12)) }
|
r#""hello world""# -> 0..13 { String(tag(1, 12)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ string sq_string ]
|
parsers [ string sq_string ]
|
||||||
r"'hello world'" -> 0..13 { String(span(1, 12)) }
|
r"'hello world'" -> 0..13 { String(tag(1, 12)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,12 +958,12 @@ mod tests {
|
||||||
fn test_variable() {
|
fn test_variable() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ var ]
|
parsers [ var ]
|
||||||
"$it" -> 0..3 { Variable(span(1, 3)) }
|
"$it" -> 0..3 { Variable(tag(1, 3)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ var ]
|
parsers [ var ]
|
||||||
"$name" -> 0..5 { Variable(span(1, 5)) }
|
"$name" -> 0..5 { Variable(tag(1, 5)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +971,7 @@ mod tests {
|
||||||
fn test_external() {
|
fn test_external() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ external ]
|
parsers [ external ]
|
||||||
"^ls" -> 0..3 { ExternalCommand(span(1, 3)) }
|
"^ls" -> 0..3 { ExternalCommand(tag(1, 3)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,7 +1287,7 @@ mod tests {
|
||||||
desc: &str,
|
desc: &str,
|
||||||
string: &str,
|
string: &str,
|
||||||
) -> T {
|
) -> T {
|
||||||
match f(NomSpan::new(string)) {
|
match f(NomSpan::new_extra(string, uuid::Uuid::nil())) {
|
||||||
Ok(v) => v.1,
|
Ok(v) => v.1,
|
||||||
Err(other) => {
|
Err(other) => {
|
||||||
println!("{:?}", other);
|
println!("{:?}", other);
|
||||||
|
@ -1270,44 +1297,46 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(left: usize, right: usize) -> Span {
|
fn tag(left: usize, right: usize) -> Tag {
|
||||||
Span::from((left, right))
|
Tag::from((left, right, uuid::Uuid::nil()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delimited(
|
fn delimited(
|
||||||
delimiter: Delimiter,
|
delimiter: Tagged<Delimiter>,
|
||||||
children: Vec<TokenNode>,
|
children: Vec<TokenNode>,
|
||||||
left: usize,
|
left: usize,
|
||||||
right: usize,
|
right: usize,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
let node = DelimitedNode::new(delimiter, children);
|
let node = DelimitedNode::new(*delimiter, children);
|
||||||
let spanned = Tagged::from_simple_spanned_item(node, (left, right));
|
let spanned = node.tagged((left, right, delimiter.tag.origin));
|
||||||
TokenNode::Delimited(spanned)
|
TokenNode::Delimited(spanned)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(head: TokenNode, tail: Vec<Token>, left: usize, right: usize) -> TokenNode {
|
fn path(head: TokenNode, tail: Vec<Token>, left: usize, right: usize) -> TokenNode {
|
||||||
|
let tag = head.tag();
|
||||||
|
|
||||||
let node = PathNode::new(
|
let node = PathNode::new(
|
||||||
Box::new(head),
|
Box::new(head),
|
||||||
tail.into_iter().map(TokenNode::Token).collect(),
|
tail.into_iter().map(TokenNode::Token).collect(),
|
||||||
);
|
);
|
||||||
let spanned = Tagged::from_simple_spanned_item(node, (left, right));
|
let spanned = node.tagged((left, right, tag.origin));
|
||||||
TokenNode::Path(spanned)
|
TokenNode::Path(spanned)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
fn token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
|
TokenNode::Token(token.tagged((left, right, uuid::Uuid::nil())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build<T>(block: CurriedNode<T>) -> T {
|
fn build<T>(block: CurriedNode<T>) -> T {
|
||||||
let mut builder = TokenTreeBuilder::new();
|
let mut builder = TokenTreeBuilder::new(uuid::Uuid::nil());
|
||||||
block(&mut builder)
|
block(&mut builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_token(block: CurriedToken) -> TokenNode {
|
fn build_token(block: CurriedToken) -> TokenNode {
|
||||||
TokenTreeBuilder::build(block).0
|
TokenTreeBuilder::build(uuid::Uuid::nil(), block).0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_uuid() -> uuid::Uuid {
|
||||||
|
uuid::Uuid::nil()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::parser::CallNode;
|
use crate::parser::CallNode;
|
||||||
use crate::traits::ToDebug;
|
use crate::traits::ToDebug;
|
||||||
use crate::{Span, Tagged};
|
use crate::{Tag, Tagged};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -8,7 +8,7 @@ use std::fmt;
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
pub(crate) parts: Vec<PipelineElement>,
|
pub(crate) parts: Vec<PipelineElement>,
|
||||||
pub(crate) post_ws: Option<Span>,
|
pub(crate) post_ws: Option<Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for Pipeline {
|
impl ToDebug for Pipeline {
|
||||||
|
@ -27,11 +27,11 @@ impl ToDebug for Pipeline {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
||||||
pub struct PipelineElement {
|
pub struct PipelineElement {
|
||||||
pub pipe: Option<Span>,
|
pub pipe: Option<Tag>,
|
||||||
pub pre_ws: Option<Span>,
|
pub pre_ws: Option<Tag>,
|
||||||
#[get = "pub(crate)"]
|
#[get = "pub(crate)"]
|
||||||
call: Tagged<CallNode>,
|
call: Tagged<CallNode>,
|
||||||
pub post_ws: Option<Span>,
|
pub post_ws: Option<Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToDebug for PipelineElement {
|
impl ToDebug for PipelineElement {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*};
|
use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*};
|
||||||
use crate::traits::ToDebug;
|
use crate::traits::ToDebug;
|
||||||
use crate::{Span, Tagged, Text};
|
use crate::{Tag, Tagged, Text};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use enum_utils::FromStr;
|
use enum_utils::FromStr;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
|
@ -16,8 +16,8 @@ pub enum TokenNode {
|
||||||
Pipeline(Tagged<Pipeline>),
|
Pipeline(Tagged<Pipeline>),
|
||||||
Operator(Tagged<Operator>),
|
Operator(Tagged<Operator>),
|
||||||
Flag(Tagged<Flag>),
|
Flag(Tagged<Flag>),
|
||||||
Member(Span),
|
Member(Tag),
|
||||||
Whitespace(Span),
|
Whitespace(Tag),
|
||||||
|
|
||||||
Error(Tagged<Box<ShellError>>),
|
Error(Tagged<Box<ShellError>>),
|
||||||
Path(Tagged<PathNode>),
|
Path(Tagged<PathNode>),
|
||||||
|
@ -78,31 +78,31 @@ impl fmt::Debug for DebugTokenNode<'_> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
TokenNode::Pipeline(pipeline) => write!(f, "{}", pipeline.debug(self.source)),
|
TokenNode::Pipeline(pipeline) => write!(f, "{}", pipeline.debug(self.source)),
|
||||||
TokenNode::Error(s) => write!(f, "<error> for {:?}", s.span().slice(self.source)),
|
TokenNode::Error(s) => write!(f, "<error> for {:?}", s.tag().slice(self.source)),
|
||||||
rest => write!(f, "{}", rest.span().slice(self.source)),
|
rest => write!(f, "{}", rest.tag().slice(self.source)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&TokenNode> for Span {
|
impl From<&TokenNode> for Tag {
|
||||||
fn from(token: &TokenNode) -> Span {
|
fn from(token: &TokenNode) -> Tag {
|
||||||
token.span()
|
token.tag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenNode {
|
impl TokenNode {
|
||||||
pub fn span(&self) -> Span {
|
pub fn tag(&self) -> Tag {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Token(t) => t.span(),
|
TokenNode::Token(t) => t.tag(),
|
||||||
TokenNode::Call(s) => s.span(),
|
TokenNode::Call(s) => s.tag(),
|
||||||
TokenNode::Delimited(s) => s.span(),
|
TokenNode::Delimited(s) => s.tag(),
|
||||||
TokenNode::Pipeline(s) => s.span(),
|
TokenNode::Pipeline(s) => s.tag(),
|
||||||
TokenNode::Operator(s) => s.span(),
|
TokenNode::Operator(s) => s.tag(),
|
||||||
TokenNode::Flag(s) => s.span(),
|
TokenNode::Flag(s) => s.tag(),
|
||||||
TokenNode::Member(s) => *s,
|
TokenNode::Member(s) => *s,
|
||||||
TokenNode::Whitespace(s) => *s,
|
TokenNode::Whitespace(s) => *s,
|
||||||
TokenNode::Error(s) => s.span(),
|
TokenNode::Error(s) => s.tag(),
|
||||||
TokenNode::Path(s) => s.span(),
|
TokenNode::Path(s) => s.tag(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,11 +127,11 @@ impl TokenNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_external_arg(&self, source: &Text) -> String {
|
pub fn as_external_arg(&self, source: &Text) -> String {
|
||||||
self.span().slice(source).to_string()
|
self.tag().slice(source).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source<'a>(&self, source: &'a Text) -> &'a str {
|
pub fn source<'a>(&self, source: &'a Text) -> &'a str {
|
||||||
self.span().slice(source)
|
self.tag().slice(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_bare(&self) -> bool {
|
pub fn is_bare(&self) -> bool {
|
||||||
|
@ -154,12 +154,12 @@ impl TokenNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_external(&self) -> Span {
|
pub fn expect_external(&self) -> Tag {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::ExternalCommand(span),
|
item: RawToken::ExternalCommand(tag),
|
||||||
..
|
..
|
||||||
}) => *span,
|
}) => *tag,
|
||||||
_ => panic!("Only call expect_external if you checked is_external first"),
|
_ => panic!("Only call expect_external if you checked is_external first"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, Token
|
||||||
use crate::parser::parse::tokens::{RawNumber, RawToken};
|
use crate::parser::parse::tokens::{RawNumber, RawToken};
|
||||||
use crate::parser::parse::unit::Unit;
|
use crate::parser::parse::unit::Unit;
|
||||||
use crate::parser::CallNode;
|
use crate::parser::CallNode;
|
||||||
use crate::Span;
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
pub struct TokenTreeBuilder {
|
pub struct TokenTreeBuilder {
|
||||||
|
@ -17,14 +17,16 @@ pub struct TokenTreeBuilder {
|
||||||
|
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
output: String,
|
output: String,
|
||||||
|
|
||||||
|
origin: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CurriedToken = Box<dyn FnOnce(&mut TokenTreeBuilder) -> TokenNode + 'static>;
|
pub type CurriedToken = Box<dyn FnOnce(&mut TokenTreeBuilder) -> TokenNode + 'static>;
|
||||||
pub type CurriedCall = Box<dyn FnOnce(&mut TokenTreeBuilder) -> Tagged<CallNode> + 'static>;
|
pub type CurriedCall = Box<dyn FnOnce(&mut TokenTreeBuilder) -> Tagged<CallNode> + 'static>;
|
||||||
|
|
||||||
impl TokenTreeBuilder {
|
impl TokenTreeBuilder {
|
||||||
pub fn build(block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) {
|
pub fn build(origin: Uuid, block: impl FnOnce(&mut Self) -> TokenNode) -> (TokenNode, String) {
|
||||||
let mut builder = TokenTreeBuilder::new();
|
let mut builder = TokenTreeBuilder::new(origin);
|
||||||
let node = block(&mut builder);
|
let node = block(&mut builder);
|
||||||
(node, builder.output)
|
(node, builder.output)
|
||||||
}
|
}
|
||||||
|
@ -52,50 +54,37 @@ impl TokenTreeBuilder {
|
||||||
.expect("A pipeline must contain at least one element");
|
.expect("A pipeline must contain at least one element");
|
||||||
|
|
||||||
let pipe = None;
|
let pipe = None;
|
||||||
let pre_span = pre.map(|pre| b.consume(&pre));
|
let pre_tag = pre.map(|pre| b.consume_tag(&pre));
|
||||||
let call = call(b);
|
let call = call(b);
|
||||||
let post_span = post.map(|post| b.consume(&post));
|
let post_tag = post.map(|post| b.consume_tag(&post));
|
||||||
|
|
||||||
out.push(PipelineElement::new(
|
out.push(PipelineElement::new(pipe, pre_tag, call, post_tag));
|
||||||
pipe,
|
|
||||||
pre_span.map(Span::from),
|
|
||||||
call,
|
|
||||||
post_span.map(Span::from),
|
|
||||||
));
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
None => break,
|
None => break,
|
||||||
Some((pre, call, post)) => {
|
Some((pre, call, post)) => {
|
||||||
let pipe = Some(Span::from(b.consume("|")));
|
let pipe = Some(b.consume_tag("|"));
|
||||||
let pre_span = pre.map(|pre| b.consume(&pre));
|
let pre_span = pre.map(|pre| b.consume_tag(&pre));
|
||||||
let call = call(b);
|
let call = call(b);
|
||||||
let post_span = post.map(|post| b.consume(&post));
|
let post_span = post.map(|post| b.consume_tag(&post));
|
||||||
|
|
||||||
out.push(PipelineElement::new(
|
out.push(PipelineElement::new(pipe, pre_span, call, post_span));
|
||||||
pipe,
|
|
||||||
pre_span.map(Span::from),
|
|
||||||
call,
|
|
||||||
post_span.map(Span::from),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = b.pos;
|
let end = b.pos;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_pipeline((out, None), (start, end))
|
TokenTreeBuilder::tagged_pipeline((out, None), (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_pipeline(
|
pub fn tagged_pipeline(
|
||||||
input: (Vec<PipelineElement>, Option<Span>),
|
input: (Vec<PipelineElement>, Option<Tag>),
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
TokenNode::Pipeline(Tagged::from_simple_spanned_item(
|
TokenNode::Pipeline(Pipeline::new(input.0, input.1.into()).tagged(tag.into()))
|
||||||
Pipeline::new(input.0, input.1.into()),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn op(input: impl Into<Operator>) -> CurriedToken {
|
pub fn op(input: impl Into<Operator>) -> CurriedToken {
|
||||||
|
@ -106,12 +95,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_op(input, (start, end))
|
TokenTreeBuilder::tagged_op(input, (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_op(input: impl Into<Operator>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Operator(Tagged::from_simple_spanned_item(input.into(), span.into()))
|
TokenNode::Operator(input.into().tagged(tag.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string(input: impl Into<String>) -> CurriedToken {
|
pub fn string(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -123,15 +112,15 @@ impl TokenTreeBuilder {
|
||||||
let (_, end) = b.consume("\"");
|
let (_, end) = b.consume("\"");
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_string((inner_start, inner_end), (start, end))
|
TokenTreeBuilder::tagged_string(
|
||||||
|
(inner_start, inner_end, b.origin),
|
||||||
|
(start, end, b.origin),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_string(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::String(input.into()).tagged(tag.into()))
|
||||||
RawToken::String(input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bare(input: impl Into<String>) -> CurriedToken {
|
pub fn bare(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -141,15 +130,12 @@ impl TokenTreeBuilder {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_bare((start, end))
|
TokenTreeBuilder::tagged_bare((start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_bare(input: impl Into<Span>) -> TokenNode {
|
pub fn tagged_bare(tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::Bare.tagged(tag.into()))
|
||||||
RawToken::Bare,
|
|
||||||
input.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pattern(input: impl Into<String>) -> CurriedToken {
|
pub fn pattern(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -159,15 +145,12 @@ impl TokenTreeBuilder {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_pattern((start, end))
|
TokenTreeBuilder::tagged_pattern((start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_pattern(input: impl Into<Span>) -> TokenNode {
|
pub fn tagged_pattern(input: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::GlobPattern.tagged(input.into()))
|
||||||
RawToken::Bare,
|
|
||||||
input.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn external_word(input: impl Into<String>) -> CurriedToken {
|
pub fn external_word(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -177,22 +160,16 @@ impl TokenTreeBuilder {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_external_word((start, end))
|
TokenTreeBuilder::tagged_external_word((start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_external_word(input: impl Into<Span>) -> TokenNode {
|
pub fn tagged_external_word(input: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::ExternalWord.tagged(input.into()))
|
||||||
RawToken::ExternalWord,
|
|
||||||
input.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_external(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_external(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::ExternalCommand(input.into()).tagged(tag.into()))
|
||||||
RawToken::ExternalCommand(input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int(input: impl Into<BigInt>) -> CurriedToken {
|
pub fn int(input: impl Into<BigInt>) -> CurriedToken {
|
||||||
|
@ -202,7 +179,10 @@ impl TokenTreeBuilder {
|
||||||
let (start, end) = b.consume(&int.to_string());
|
let (start, end) = b.consume(&int.to_string());
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_number(RawNumber::Int((start, end).into()), (start, end))
|
TokenTreeBuilder::tagged_number(
|
||||||
|
RawNumber::Int((start, end, b.origin).into()),
|
||||||
|
(start, end, b.origin),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,15 +193,15 @@ impl TokenTreeBuilder {
|
||||||
let (start, end) = b.consume(&decimal.to_string());
|
let (start, end) = b.consume(&decimal.to_string());
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_number(RawNumber::Decimal((start, end).into()), (start, end))
|
TokenTreeBuilder::tagged_number(
|
||||||
|
RawNumber::Decimal((start, end, b.origin).into()),
|
||||||
|
(start, end, b.origin),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_number(input: impl Into<RawNumber>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_number(input: impl Into<RawNumber>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::Number(input.into()).tagged(tag.into()))
|
||||||
RawToken::Number(input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
|
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
|
||||||
|
@ -233,23 +213,20 @@ impl TokenTreeBuilder {
|
||||||
let (_, end_unit) = b.consume(unit.as_str());
|
let (_, end_unit) = b.consume(unit.as_str());
|
||||||
b.pos = end_unit;
|
b.pos = end_unit;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_size(
|
TokenTreeBuilder::tagged_size(
|
||||||
(RawNumber::Int((start_int, end_int).into()), unit),
|
(RawNumber::Int((start_int, end_int, b.origin).into()), unit),
|
||||||
(start_int, end_unit),
|
(start_int, end_unit, b.origin),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_size(
|
pub fn tagged_size(
|
||||||
input: (impl Into<RawNumber>, impl Into<Unit>),
|
input: (impl Into<RawNumber>, impl Into<Unit>),
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
let (int, unit) = (input.0.into(), input.1.into());
|
let (int, unit) = (input.0.into(), input.1.into());
|
||||||
|
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::Size(int, unit).tagged(tag.into()))
|
||||||
RawToken::Size(int, unit),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
|
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -267,15 +244,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
let end = b.pos;
|
let end = b.pos;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_path((head, output), (start, end))
|
TokenTreeBuilder::tagged_path((head, output), (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_path(input: (TokenNode, Vec<TokenNode>), tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Path(Tagged::from_simple_spanned_item(
|
TokenNode::Path(PathNode::new(Box::new(input.0), input.1).tagged(tag.into()))
|
||||||
PathNode::new(Box::new(input.0), input.1),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn var(input: impl Into<String>) -> CurriedToken {
|
pub fn var(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -285,15 +259,12 @@ impl TokenTreeBuilder {
|
||||||
let (start, _) = b.consume("$");
|
let (start, _) = b.consume("$");
|
||||||
let (inner_start, end) = b.consume(&input);
|
let (inner_start, end) = b.consume(&input);
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_var((inner_start, end), (start, end))
|
TokenTreeBuilder::tagged_var((inner_start, end, b.origin), (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_var(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_simple_spanned_item(
|
TokenNode::Token(RawToken::Variable(input.into()).tagged(tag.into()))
|
||||||
RawToken::Variable(input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flag(input: impl Into<String>) -> CurriedToken {
|
pub fn flag(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -303,15 +274,12 @@ impl TokenTreeBuilder {
|
||||||
let (start, _) = b.consume("--");
|
let (start, _) = b.consume("--");
|
||||||
let (inner_start, end) = b.consume(&input);
|
let (inner_start, end) = b.consume(&input);
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_flag((inner_start, end), (start, end))
|
TokenTreeBuilder::tagged_flag((inner_start, end, b.origin), (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_flag(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Flag(Tagged::from_simple_spanned_item(
|
TokenNode::Flag(Flag::new(FlagKind::Longhand, input.into()).tagged(tag.into()))
|
||||||
Flag::new(FlagKind::Longhand, input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shorthand(input: impl Into<String>) -> CurriedToken {
|
pub fn shorthand(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -321,15 +289,12 @@ impl TokenTreeBuilder {
|
||||||
let (start, _) = b.consume("-");
|
let (start, _) = b.consume("-");
|
||||||
let (inner_start, end) = b.consume(&input);
|
let (inner_start, end) = b.consume(&input);
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_shorthand((inner_start, end), (start, end))
|
TokenTreeBuilder::tagged_shorthand((inner_start, end, b.origin), (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_shorthand(input: impl Into<Tag>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Flag(Tagged::from_simple_spanned_item(
|
TokenNode::Flag(Flag::new(FlagKind::Shorthand, input.into()).tagged(tag.into()))
|
||||||
Flag::new(FlagKind::Shorthand, input.into()),
|
|
||||||
span.into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn member(input: impl Into<String>) -> CurriedToken {
|
pub fn member(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -337,12 +302,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
Box::new(move |b| {
|
Box::new(move |b| {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
TokenTreeBuilder::spanned_member((start, end))
|
TokenTreeBuilder::tagged_member((start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_member(span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_member(tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Member(span.into())
|
TokenNode::Member(tag.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall {
|
pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall {
|
||||||
|
@ -358,11 +323,11 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
let end = b.pos;
|
let end = b.pos;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_call(nodes, (start, end))
|
TokenTreeBuilder::tagged_call(nodes, (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_call(input: Vec<TokenNode>, span: impl Into<Span>) -> Tagged<CallNode> {
|
pub fn tagged_call(input: Vec<TokenNode>, tag: impl Into<Tag>) -> Tagged<CallNode> {
|
||||||
if input.len() == 0 {
|
if input.len() == 0 {
|
||||||
panic!("BUG: spanned call (TODO)")
|
panic!("BUG: spanned call (TODO)")
|
||||||
}
|
}
|
||||||
|
@ -372,7 +337,7 @@ impl TokenTreeBuilder {
|
||||||
let head = input.next().unwrap();
|
let head = input.next().unwrap();
|
||||||
let tail = input.collect();
|
let tail = input.collect();
|
||||||
|
|
||||||
Tagged::from_simple_spanned_item(CallNode::new(Box::new(head), tail), span)
|
CallNode::new(Box::new(head), tail).tagged(tag.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
|
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -385,15 +350,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
let (_, end) = b.consume(")");
|
let (_, end) = b.consume(")");
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_parens(output, (start, end))
|
TokenTreeBuilder::tagged_parens(output, (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_parens(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
TokenNode::Delimited(DelimitedNode::new(Delimiter::Paren, input.into()).tagged(tag.into()))
|
||||||
DelimitedNode::new(Delimiter::Paren, input.into()),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn square(input: Vec<CurriedToken>) -> CurriedToken {
|
pub fn square(input: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -406,15 +368,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
let (_, end) = b.consume("]");
|
let (_, end) = b.consume("]");
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_square(output, (start, end))
|
TokenTreeBuilder::tagged_square(output, (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_square(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
TokenNode::Delimited(DelimitedNode::new(Delimiter::Square, input.into()).tagged(tag.into()))
|
||||||
DelimitedNode::new(Delimiter::Square, input.into()),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn braced(input: Vec<CurriedToken>) -> CurriedToken {
|
pub fn braced(input: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -427,21 +386,18 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
let (_, end) = b.consume(" }");
|
let (_, end) = b.consume(" }");
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_brace(output, (start, end))
|
TokenTreeBuilder::tagged_brace(output, (start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_brace(input: impl Into<Vec<TokenNode>>, tag: impl Into<Tag>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
TokenNode::Delimited(DelimitedNode::new(Delimiter::Brace, input.into()).tagged(tag.into()))
|
||||||
DelimitedNode::new(Delimiter::Brace, input.into()),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sp() -> CurriedToken {
|
pub fn sp() -> CurriedToken {
|
||||||
Box::new(|b| {
|
Box::new(|b| {
|
||||||
let (start, end) = b.consume(" ");
|
let (start, end) = b.consume(" ");
|
||||||
TokenNode::Whitespace(Span::from((start, end)))
|
TokenNode::Whitespace(Tag::from((start, end, b.origin)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,14 +406,12 @@ impl TokenTreeBuilder {
|
||||||
|
|
||||||
Box::new(move |b| {
|
Box::new(move |b| {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
TokenTreeBuilder::spanned_ws((start, end))
|
TokenTreeBuilder::tagged_ws((start, end, b.origin))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_ws(span: impl Into<Span>) -> TokenNode {
|
pub fn tagged_ws(tag: impl Into<Tag>) -> TokenNode {
|
||||||
let span = span.into();
|
TokenNode::Whitespace(tag.into())
|
||||||
|
|
||||||
TokenNode::Whitespace(span.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume(&mut self, input: &str) -> (usize, usize) {
|
fn consume(&mut self, input: &str) -> (usize, usize) {
|
||||||
|
@ -466,4 +420,11 @@ impl TokenTreeBuilder {
|
||||||
self.output.push_str(input);
|
self.output.push_str(input);
|
||||||
(start, self.pos)
|
(start, self.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn consume_tag(&mut self, input: &str) -> Tag {
|
||||||
|
let start = self.pos;
|
||||||
|
self.pos += input.len();
|
||||||
|
self.output.push_str(input);
|
||||||
|
(start, self.pos, self.origin).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::parser::parse::unit::*;
|
use crate::parser::parse::unit::*;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{Span, Tagged, Text};
|
use crate::{Tagged, Text};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ use std::str::FromStr;
|
||||||
pub enum RawToken {
|
pub enum RawToken {
|
||||||
Number(RawNumber),
|
Number(RawNumber),
|
||||||
Size(RawNumber, Unit),
|
Size(RawNumber, Unit),
|
||||||
String(Span),
|
String(Tag),
|
||||||
Variable(Span),
|
Variable(Tag),
|
||||||
ExternalCommand(Span),
|
ExternalCommand(Tag),
|
||||||
ExternalWord,
|
ExternalWord,
|
||||||
GlobPattern,
|
GlobPattern,
|
||||||
Bare,
|
Bare,
|
||||||
|
@ -18,28 +18,28 @@ pub enum RawToken {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub enum RawNumber {
|
pub enum RawNumber {
|
||||||
Int(Span),
|
Int(Tag),
|
||||||
Decimal(Span),
|
Decimal(Tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawNumber {
|
impl RawNumber {
|
||||||
pub fn int(span: impl Into<Span>) -> Tagged<RawNumber> {
|
pub fn int(tag: impl Into<Tag>) -> Tagged<RawNumber> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
RawNumber::Int(span).tagged(span)
|
RawNumber::Int(tag).tagged(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decimal(span: impl Into<Span>) -> Tagged<RawNumber> {
|
pub fn decimal(tag: impl Into<Tag>) -> Tagged<RawNumber> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
RawNumber::Decimal(span).tagged(span)
|
RawNumber::Decimal(tag).tagged(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_number(self, source: &Text) -> Number {
|
pub(crate) fn to_number(self, source: &Text) -> Number {
|
||||||
match self {
|
match self {
|
||||||
RawNumber::Int(span) => Number::Int(BigInt::from_str(span.slice(source)).unwrap()),
|
RawNumber::Int(tag) => Number::Int(BigInt::from_str(tag.slice(source)).unwrap()),
|
||||||
RawNumber::Decimal(span) => {
|
RawNumber::Decimal(tag) => {
|
||||||
Number::Decimal(BigDecimal::from_str(span.slice(source)).unwrap())
|
Number::Decimal(BigDecimal::from_str(tag.slice(source)).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,6 @@ pub struct DebugToken<'a> {
|
||||||
|
|
||||||
impl fmt::Debug for DebugToken<'_> {
|
impl fmt::Debug for DebugToken<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.node.span().slice(self.source))
|
write!(f, "{}", self.node.tag().slice(self.source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::parser::{
|
||||||
Flag, RawToken, TokenNode,
|
Flag, RawToken, TokenNode,
|
||||||
};
|
};
|
||||||
use crate::traits::ToDebug;
|
use crate::traits::ToDebug;
|
||||||
use crate::{Span, Tag, Tagged, Text};
|
use crate::{Tag, Tagged, TaggedItem, Text};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
pub fn parse_command(
|
pub fn parse_command(
|
||||||
|
@ -33,7 +33,7 @@ pub fn parse_command(
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
match parse_command_tail(&config, context, children, source, call.span())? {
|
match parse_command_tail(&config, context, children, source, call.tag())? {
|
||||||
None => Ok(hir::Call::new(Box::new(head), None, None)),
|
None => Ok(hir::Call::new(Box::new(head), None, None)),
|
||||||
Some((positional, named)) => Ok(hir::Call::new(Box::new(head), positional, named)),
|
Some((positional, named)) => Ok(hir::Call::new(Box::new(head), positional, named)),
|
||||||
}
|
}
|
||||||
|
@ -49,12 +49,9 @@ fn parse_command_head(head: &TokenNode) -> Result<hir::Expression, ShellError> {
|
||||||
) => Ok(spanned.map(|_| hir::RawExpression::Literal(hir::Literal::Bare))),
|
) => Ok(spanned.map(|_| hir::RawExpression::Literal(hir::Literal::Bare))),
|
||||||
|
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::String(inner_span),
|
item: RawToken::String(inner_tag),
|
||||||
tag: Tag { span, origin: None },
|
tag,
|
||||||
}) => Ok(Tagged::from_simple_spanned_item(
|
}) => Ok(hir::RawExpression::Literal(hir::Literal::String(*inner_tag)).tagged(*tag)),
|
||||||
hir::RawExpression::Literal(hir::Literal::String(*inner_span)),
|
|
||||||
*span,
|
|
||||||
)),
|
|
||||||
|
|
||||||
other => Err(ShellError::unexpected(&format!(
|
other => Err(ShellError::unexpected(&format!(
|
||||||
"command head -> {:?}",
|
"command head -> {:?}",
|
||||||
|
@ -68,7 +65,7 @@ fn parse_command_tail(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
tail: Option<Vec<TokenNode>>,
|
tail: Option<Vec<TokenNode>>,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
command_span: Span,
|
command_tag: Tag,
|
||||||
) -> Result<Option<(Option<Vec<hir::Expression>>, Option<NamedArguments>)>, ShellError> {
|
) -> Result<Option<(Option<Vec<hir::Expression>>, Option<NamedArguments>)>, ShellError> {
|
||||||
let tail = &mut match &tail {
|
let tail = &mut match &tail {
|
||||||
None => hir::TokensIterator::new(&[]),
|
None => hir::TokensIterator::new(&[]),
|
||||||
|
@ -89,7 +86,7 @@ fn parse_command_tail(
|
||||||
named.insert_switch(name, flag);
|
named.insert_switch(name, flag);
|
||||||
}
|
}
|
||||||
NamedType::Mandatory(syntax_type) => {
|
NamedType::Mandatory(syntax_type) => {
|
||||||
match extract_mandatory(config, name, tail, source, command_span) {
|
match extract_mandatory(config, name, tail, source, command_tag) {
|
||||||
Err(err) => return Err(err), // produce a correct diagnostic
|
Err(err) => return Err(err), // produce a correct diagnostic
|
||||||
Ok((pos, flag)) => {
|
Ok((pos, flag)) => {
|
||||||
tail.move_to(pos);
|
tail.move_to(pos);
|
||||||
|
@ -98,7 +95,7 @@ fn parse_command_tail(
|
||||||
return Err(ShellError::argument_error(
|
return Err(ShellError::argument_error(
|
||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
ArgumentError::MissingValueForName(name.to_string()),
|
ArgumentError::MissingValueForName(name.to_string()),
|
||||||
flag.span(),
|
flag.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +116,7 @@ fn parse_command_tail(
|
||||||
return Err(ShellError::argument_error(
|
return Err(ShellError::argument_error(
|
||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
ArgumentError::MissingValueForName(name.to_string()),
|
ArgumentError::MissingValueForName(name.to_string()),
|
||||||
flag.span(),
|
flag.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +147,7 @@ fn parse_command_tail(
|
||||||
return Err(ShellError::argument_error(
|
return Err(ShellError::argument_error(
|
||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
ArgumentError::MissingMandatoryPositional(arg.name().to_string()),
|
ArgumentError::MissingMandatoryPositional(arg.name().to_string()),
|
||||||
command_span,
|
command_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +205,7 @@ fn extract_mandatory(
|
||||||
name: &str,
|
name: &str,
|
||||||
tokens: &mut hir::TokensIterator<'_>,
|
tokens: &mut hir::TokensIterator<'_>,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
) -> Result<(usize, Tagged<Flag>), ShellError> {
|
) -> Result<(usize, Tagged<Flag>), ShellError> {
|
||||||
let flag = tokens.extract(|t| t.as_flag(name, source));
|
let flag = tokens.extract(|t| t.as_flag(name, source));
|
||||||
|
|
||||||
|
@ -216,7 +213,7 @@ fn extract_mandatory(
|
||||||
None => Err(ShellError::argument_error(
|
None => Err(ShellError::argument_error(
|
||||||
config.name.clone(),
|
config.name.clone(),
|
||||||
ArgumentError::MissingMandatoryFlag(name.to_string()),
|
ArgumentError::MissingMandatoryFlag(name.to_string()),
|
||||||
span,
|
tag,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
Some((pos, flag)) => {
|
Some((pos, flag)) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// TODO: Temporary redirect
|
// TODO: Temporary redirect
|
||||||
pub(crate) use crate::context::CommandRegistry;
|
pub(crate) use crate::context::CommandRegistry;
|
||||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||||
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode};
|
use crate::parser::{hir, hir::SyntaxShape, parse_command, CallNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -12,35 +12,35 @@ use std::fmt;
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub enum NamedType {
|
pub enum NamedType {
|
||||||
Switch,
|
Switch,
|
||||||
Mandatory(SyntaxType),
|
Mandatory(SyntaxShape),
|
||||||
Optional(SyntaxType),
|
Optional(SyntaxShape),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum PositionalType {
|
pub enum PositionalType {
|
||||||
Mandatory(String, SyntaxType),
|
Mandatory(String, SyntaxShape),
|
||||||
Optional(String, SyntaxType),
|
Optional(String, SyntaxShape),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionalType {
|
impl PositionalType {
|
||||||
pub fn mandatory(name: &str, ty: SyntaxType) -> PositionalType {
|
pub fn mandatory(name: &str, ty: SyntaxShape) -> PositionalType {
|
||||||
PositionalType::Mandatory(name.to_string(), ty)
|
PositionalType::Mandatory(name.to_string(), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mandatory_any(name: &str) -> PositionalType {
|
pub fn mandatory_any(name: &str) -> PositionalType {
|
||||||
PositionalType::Mandatory(name.to_string(), SyntaxType::Any)
|
PositionalType::Mandatory(name.to_string(), SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mandatory_block(name: &str) -> PositionalType {
|
pub fn mandatory_block(name: &str) -> PositionalType {
|
||||||
PositionalType::Mandatory(name.to_string(), SyntaxType::Block)
|
PositionalType::Mandatory(name.to_string(), SyntaxShape::Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn optional(name: &str, ty: SyntaxType) -> PositionalType {
|
pub fn optional(name: &str, ty: SyntaxShape) -> PositionalType {
|
||||||
PositionalType::Optional(name.to_string(), ty)
|
PositionalType::Optional(name.to_string(), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn optional_any(name: &str) -> PositionalType {
|
pub fn optional_any(name: &str) -> PositionalType {
|
||||||
PositionalType::Optional(name.to_string(), SyntaxType::Any)
|
PositionalType::Optional(name.to_string(), SyntaxShape::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn name(&self) -> &str {
|
pub(crate) fn name(&self) -> &str {
|
||||||
|
@ -50,7 +50,7 @@ impl PositionalType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn syntax_type(&self) -> SyntaxType {
|
pub(crate) fn syntax_type(&self) -> SyntaxShape {
|
||||||
match *self {
|
match *self {
|
||||||
PositionalType::Mandatory(_, t) => t,
|
PositionalType::Mandatory(_, t) => t,
|
||||||
PositionalType::Optional(_, t) => t,
|
PositionalType::Optional(_, t) => t,
|
||||||
|
@ -66,7 +66,7 @@ pub struct Signature {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub positional: Vec<PositionalType>,
|
pub positional: Vec<PositionalType>,
|
||||||
#[new(value = "None")]
|
#[new(value = "None")]
|
||||||
pub rest_positional: Option<SyntaxType>,
|
pub rest_positional: Option<SyntaxShape>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub named: IndexMap<String, NamedType>,
|
pub named: IndexMap<String, NamedType>,
|
||||||
#[new(value = "false")]
|
#[new(value = "false")]
|
||||||
|
@ -83,21 +83,21 @@ impl Signature {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
|
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
|
||||||
self.positional
|
self.positional
|
||||||
.push(PositionalType::Mandatory(name.into(), ty.into()));
|
.push(PositionalType::Mandatory(name.into(), ty.into()));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
|
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
|
||||||
self.positional
|
self.positional
|
||||||
.push(PositionalType::Optional(name.into(), ty.into()));
|
.push(PositionalType::Optional(name.into(), ty.into()));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
|
pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxShape>) -> Signature {
|
||||||
self.named
|
self.named
|
||||||
.insert(name.into(), NamedType::Optional(ty.into()));
|
.insert(name.into(), NamedType::Optional(ty.into()));
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl Signature {
|
||||||
pub fn required_named(
|
pub fn required_named(
|
||||||
mut self,
|
mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
ty: impl Into<SyntaxType>,
|
ty: impl Into<SyntaxShape>,
|
||||||
) -> Signature {
|
) -> Signature {
|
||||||
self.named
|
self.named
|
||||||
.insert(name.into(), NamedType::Mandatory(ty.into()));
|
.insert(name.into(), NamedType::Mandatory(ty.into()));
|
||||||
|
@ -126,7 +126,7 @@ impl Signature {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rest(mut self, ty: SyntaxType) -> Signature {
|
pub fn rest(mut self, ty: SyntaxShape) -> Signature {
|
||||||
self.rest_positional = Some(ty);
|
self.rest_positional = Some(ty);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -312,10 +312,10 @@ pub(crate) fn evaluate_args(
|
||||||
|
|
||||||
for (name, value) in n.named.iter() {
|
for (name, value) in n.named.iter() {
|
||||||
match value {
|
match value {
|
||||||
hir::named::NamedValue::PresentSwitch(span) => {
|
hir::named::NamedValue::PresentSwitch(tag) => {
|
||||||
results.insert(
|
results.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Tagged::from_simple_spanned_item(Value::boolean(true), *span),
|
Value::boolean(true).tagged(*tag),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
hir::named::NamedValue::Value(expr) => {
|
hir::named::NamedValue::Value(expr) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
SyntaxType, Tagged, Value,
|
SyntaxShape, Tagged, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Add {
|
struct Add {
|
||||||
|
@ -44,9 +44,9 @@ impl Plugin for Add {
|
||||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||||
Ok(Signature::build("add")
|
Ok(Signature::build("add")
|
||||||
.desc("Add a new field to the table.")
|
.desc("Add a new field to the table.")
|
||||||
.required("Field", SyntaxType::String)
|
.required("Field", SyntaxShape::String)
|
||||||
.required("Value", SyntaxType::String)
|
.required("Value", SyntaxShape::String)
|
||||||
.rest(SyntaxType::String)
|
.rest(SyntaxShape::String)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
SyntaxType, Tagged, Value,
|
SyntaxShape, Tagged, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Edit {
|
struct Edit {
|
||||||
|
@ -43,8 +43,8 @@ impl Plugin for Edit {
|
||||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||||
Ok(Signature::build("edit")
|
Ok(Signature::build("edit")
|
||||||
.desc("Edit an existing column to have a new value.")
|
.desc("Edit an existing column to have a new value.")
|
||||||
.required("Field", SyntaxType::String)
|
.required("Field", SyntaxShape::String)
|
||||||
.required("Value", SyntaxType::String)
|
.required("Value", SyntaxShape::String)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
SyntaxType, Tag, Tagged, TaggedDictBuilder, Value,
|
SyntaxShape, Tag, Tagged, TaggedDictBuilder, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Embed {
|
struct Embed {
|
||||||
|
@ -37,8 +37,8 @@ impl Plugin for Embed {
|
||||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||||
Ok(Signature::build("embed")
|
Ok(Signature::build("embed")
|
||||||
.desc("Embeds a new field to the table.")
|
.desc("Embeds a new field to the table.")
|
||||||
.required("Field", SyntaxType::String)
|
.required("Field", SyntaxShape::String)
|
||||||
.rest(SyntaxType::String)
|
.rest(SyntaxShape::String)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
SyntaxType, Tagged, TaggedItem, Value,
|
SyntaxShape, Tagged, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Action {
|
enum Action {
|
||||||
|
@ -120,7 +120,7 @@ impl Plugin for Inc {
|
||||||
.switch("major")
|
.switch("major")
|
||||||
.switch("minor")
|
.switch("minor")
|
||||||
.switch("patch")
|
.switch("patch")
|
||||||
.rest(SyntaxType::String)
|
.rest(SyntaxShape::String)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,18 +181,20 @@ mod tests {
|
||||||
use super::{Inc, SemVerAction};
|
use super::{Inc, SemVerAction};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged,
|
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Tag, Tagged, TaggedDictBuilder,
|
||||||
TaggedDictBuilder, TaggedItem, Value,
|
TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallStub {
|
struct CallStub {
|
||||||
|
origin: uuid::Uuid,
|
||||||
positionals: Vec<Tagged<Value>>,
|
positionals: Vec<Tagged<Value>>,
|
||||||
flags: IndexMap<String, Tagged<Value>>,
|
flags: IndexMap<String, Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallStub {
|
impl CallStub {
|
||||||
fn new() -> CallStub {
|
fn new(origin: uuid::Uuid) -> CallStub {
|
||||||
CallStub {
|
CallStub {
|
||||||
|
origin,
|
||||||
positionals: vec![],
|
positionals: vec![],
|
||||||
flags: indexmap::IndexMap::new(),
|
flags: indexmap::IndexMap::new(),
|
||||||
}
|
}
|
||||||
|
@ -201,14 +203,14 @@ mod tests {
|
||||||
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
||||||
self.flags.insert(
|
self.flags.insert(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
Value::boolean(true).simple_spanned(Span::unknown()),
|
Value::boolean(true).tagged(Tag::unknown()),
|
||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
||||||
self.positionals
|
self.positionals
|
||||||
.push(Value::string(name.to_string()).simple_spanned(Span::unknown()));
|
.push(Value::string(name.to_string()).tagged(Tag::unknown_span(self.origin)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +218,7 @@ mod tests {
|
||||||
CallInfo {
|
CallInfo {
|
||||||
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
||||||
source_map: SourceMap::new(),
|
source_map: SourceMap::new(),
|
||||||
name_span: Span::unknown(),
|
name_tag: Tag::unknown_span(self.origin),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +245,7 @@ mod tests {
|
||||||
let mut plugin = Inc::new();
|
let mut plugin = Inc::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("major").create())
|
.begin_filter(CallStub::new(test_uuid()).with_long_flag("major").create())
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -253,7 +255,7 @@ mod tests {
|
||||||
let mut plugin = Inc::new();
|
let mut plugin = Inc::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("minor").create())
|
.begin_filter(CallStub::new(test_uuid()).with_long_flag("minor").create())
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -263,7 +265,7 @@ mod tests {
|
||||||
let mut plugin = Inc::new();
|
let mut plugin = Inc::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("patch").create())
|
.begin_filter(CallStub::new(test_uuid()).with_long_flag("patch").create())
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -274,7 +276,7 @@ mod tests {
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(
|
.begin_filter(
|
||||||
CallStub::new()
|
CallStub::new(test_uuid())
|
||||||
.with_long_flag("major")
|
.with_long_flag("major")
|
||||||
.with_long_flag("minor")
|
.with_long_flag("minor")
|
||||||
.create(),
|
.create(),
|
||||||
|
@ -288,7 +290,11 @@ mod tests {
|
||||||
let mut plugin = Inc::new();
|
let mut plugin = Inc::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_parameter("package.version").create())
|
.begin_filter(
|
||||||
|
CallStub::new(test_uuid())
|
||||||
|
.with_parameter("package.version")
|
||||||
|
.create()
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
assert_eq!(plugin.field, Some("package.version".to_string()));
|
assert_eq!(plugin.field, Some("package.version".to_string()));
|
||||||
|
@ -321,7 +327,7 @@ mod tests {
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(
|
.begin_filter(
|
||||||
CallStub::new()
|
CallStub::new(test_uuid())
|
||||||
.with_long_flag("major")
|
.with_long_flag("major")
|
||||||
.with_parameter("version")
|
.with_parameter("version")
|
||||||
.create()
|
.create()
|
||||||
|
@ -349,7 +355,7 @@ mod tests {
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(
|
.begin_filter(
|
||||||
CallStub::new()
|
CallStub::new(test_uuid())
|
||||||
.with_long_flag("minor")
|
.with_long_flag("minor")
|
||||||
.with_parameter("version")
|
.with_parameter("version")
|
||||||
.create()
|
.create()
|
||||||
|
@ -378,7 +384,7 @@ mod tests {
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(
|
.begin_filter(
|
||||||
CallStub::new()
|
CallStub::new(test_uuid())
|
||||||
.with_long_flag("patch")
|
.with_long_flag("patch")
|
||||||
.with_parameter(&field)
|
.with_parameter(&field)
|
||||||
.create()
|
.create()
|
||||||
|
@ -399,4 +405,8 @@ mod tests {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_uuid() -> uuid::Uuid {
|
||||||
|
uuid::Uuid::nil()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ async fn ps(tag: Tag) -> Vec<Tagged<Value>> {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
while let Some(res) = processes.next().await {
|
while let Some(res) = processes.next().await {
|
||||||
if let Ok((process, usage)) = res {
|
if let Ok((process, usage)) = res {
|
||||||
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(tag.span));
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
dict.insert("pid", Value::int(process.pid()));
|
dict.insert("pid", Value::int(process.pid()));
|
||||||
if let Ok(name) = process.name().await {
|
if let Ok(name) = process.name().await {
|
||||||
dict.insert("name", Value::string(name));
|
dict.insert("name", Value::string(name));
|
||||||
|
@ -64,7 +64,7 @@ impl Plugin for Ps {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
Ok(block_on(ps(Tag::unknown_origin(callinfo.name_span)))
|
Ok(block_on(ps(Tag::unknown_origin(callinfo.name_tag)))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(ReturnSuccess::value)
|
.map(ReturnSuccess::value)
|
||||||
.collect())
|
.collect())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||||
Signature, SyntaxType, Tagged, TaggedItem, Value,
|
Signature, SyntaxShape, Tagged, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Skip {
|
struct Skip {
|
||||||
|
@ -15,9 +15,9 @@ impl Skip {
|
||||||
|
|
||||||
impl Plugin for Skip {
|
impl Plugin for Skip {
|
||||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||||
Ok(Signature::build("skip")
|
Ok(Signature::build("skip")
|
||||||
.desc("Skip a number of rows")
|
.desc("Skip a number of rows")
|
||||||
.rest(SyntaxType::Number)
|
.rest(SyntaxShape::Number)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
|
@ -34,7 +34,7 @@ impl Plugin for Skip {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Unrecognized type in params",
|
"Unrecognized type in params",
|
||||||
"expected an integer",
|
"expected an integer",
|
||||||
arg.span(),
|
arg.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
SyntaxType, Tagged, Value,
|
SyntaxShape, Tagged, Value,
|
||||||
};
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ impl Plugin for Str {
|
||||||
.switch("to-int")
|
.switch("to-int")
|
||||||
.switch("replace")
|
.switch("replace")
|
||||||
.switch("find-replace")
|
.switch("find-replace")
|
||||||
.rest(SyntaxType::Member)
|
.rest(SyntaxShape::Member)
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ mod tests {
|
||||||
use super::{Action, ReplaceAction, Str};
|
use super::{Action, ReplaceAction, Str};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Span, Tag, Tagged,
|
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Tag, Tagged,
|
||||||
TaggedDictBuilder, TaggedItem, Value,
|
TaggedDictBuilder, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
@ -277,6 +277,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CallStub {
|
struct CallStub {
|
||||||
|
origin: uuid::Uuid,
|
||||||
positionals: Vec<Tagged<Value>>,
|
positionals: Vec<Tagged<Value>>,
|
||||||
flags: IndexMap<String, Tagged<Value>>,
|
flags: IndexMap<String, Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
@ -284,6 +285,7 @@ mod tests {
|
||||||
impl CallStub {
|
impl CallStub {
|
||||||
fn new() -> CallStub {
|
fn new() -> CallStub {
|
||||||
CallStub {
|
CallStub {
|
||||||
|
origin: uuid::Uuid::nil(),
|
||||||
positionals: vec![],
|
positionals: vec![],
|
||||||
flags: indexmap::IndexMap::new(),
|
flags: indexmap::IndexMap::new(),
|
||||||
}
|
}
|
||||||
|
@ -292,14 +294,14 @@ mod tests {
|
||||||
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
||||||
self.flags.insert(
|
self.flags.insert(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
Value::boolean(true).simple_spanned(Span::unknown()),
|
Value::boolean(true).tagged(Tag::unknown()),
|
||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
||||||
self.positionals
|
self.positionals
|
||||||
.push(Value::string(name.to_string()).simple_spanned(Span::unknown()));
|
.push(Value::string(name.to_string()).tagged(Tag::unknown()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +309,7 @@ mod tests {
|
||||||
CallInfo {
|
CallInfo {
|
||||||
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
args: EvaluatedArgs::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
||||||
source_map: SourceMap::new(),
|
source_map: SourceMap::new(),
|
||||||
name_span: Span::unknown(),
|
name_tag: Tag::unknown_span(self.origin),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||||
Tag, Tagged, Value,
|
Tagged, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sum {
|
struct Sum {
|
||||||
|
@ -18,11 +18,10 @@ impl Sum {
|
||||||
match &self.total {
|
match &self.total {
|
||||||
Some(Tagged {
|
Some(Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(j)),
|
item: Value::Primitive(Primitive::Int(j)),
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
}) => {
|
}) => {
|
||||||
//TODO: handle overflow
|
//TODO: handle overflow
|
||||||
self.total =
|
self.total = Some(Value::int(i + j).tagged(*tag));
|
||||||
Some(Tagged::from_simple_spanned_item(Value::int(i + j), span));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -38,11 +37,10 @@ impl Sum {
|
||||||
match self.total {
|
match self.total {
|
||||||
Some(Tagged {
|
Some(Tagged {
|
||||||
item: Value::Primitive(Primitive::Bytes(j)),
|
item: Value::Primitive(Primitive::Bytes(j)),
|
||||||
tag: Tag { span, .. },
|
tag,
|
||||||
}) => {
|
}) => {
|
||||||
//TODO: handle overflow
|
//TODO: handle overflow
|
||||||
self.total =
|
self.total = Some(Value::bytes(b + j).tagged(tag));
|
||||||
Some(Tagged::from_simple_spanned_item(Value::bytes(b + j), span));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -315,7 +315,7 @@ impl Plugin for Sys {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
|
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_tag)))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(ReturnSuccess::value)
|
.map(ReturnSuccess::value)
|
||||||
.collect())
|
.collect())
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) use crate::data::{Primitive, Value};
|
||||||
pub(crate) use crate::env::host::handle_unexpected;
|
pub(crate) use crate::env::host::handle_unexpected;
|
||||||
pub(crate) use crate::env::Host;
|
pub(crate) use crate::env::Host;
|
||||||
pub(crate) use crate::errors::{CoerceInto, ShellError};
|
pub(crate) use crate::errors::{CoerceInto, ShellError};
|
||||||
pub(crate) use crate::parser::hir::SyntaxType;
|
pub(crate) use crate::parser::hir::SyntaxShape;
|
||||||
pub(crate) use crate::parser::parse::parser::Number;
|
pub(crate) use crate::parser::parse::parser::Number;
|
||||||
pub(crate) use crate::parser::registry::Signature;
|
pub(crate) use crate::parser::registry::Signature;
|
||||||
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
||||||
|
@ -70,8 +70,7 @@ pub(crate) use crate::shell::help_shell::HelpShell;
|
||||||
pub(crate) use crate::shell::shell_manager::ShellManager;
|
pub(crate) use crate::shell::shell_manager::ShellManager;
|
||||||
pub(crate) use crate::shell::value_shell::ValueShell;
|
pub(crate) use crate::shell::value_shell::ValueShell;
|
||||||
pub(crate) use crate::stream::{InputStream, OutputStream};
|
pub(crate) use crate::stream::{InputStream, OutputStream};
|
||||||
pub(crate) use crate::traits::{HasSpan, ToDebug};
|
pub(crate) use crate::traits::{HasTag, ToDebug};
|
||||||
pub(crate) use crate::Span;
|
|
||||||
pub(crate) use crate::Text;
|
pub(crate) use crate::Text;
|
||||||
pub(crate) use bigdecimal::BigDecimal;
|
pub(crate) use bigdecimal::BigDecimal;
|
||||||
pub(crate) use futures::stream::BoxStream;
|
pub(crate) use futures::stream::BoxStream;
|
||||||
|
|
|
@ -81,23 +81,27 @@ impl Shell for FilesystemShell {
|
||||||
dirs::home_dir()
|
dirs::home_dir()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
fn ls(
|
||||||
|
&self,
|
||||||
|
pattern: Option<Tagged<PathBuf>>,
|
||||||
|
command_tag: Tag,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let cwd = self.path();
|
let cwd = self.path();
|
||||||
let mut full_path = PathBuf::from(self.path());
|
let mut full_path = PathBuf::from(self.path());
|
||||||
|
|
||||||
match &args.nth(0) {
|
match &pattern {
|
||||||
Some(value) => full_path.push(Path::new(&value.as_path()?)),
|
Some(value) => full_path.push((*value).as_ref()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries: Vec<_> = match glob::glob(&full_path.to_string_lossy()) {
|
let entries: Vec<_> = match glob::glob(&full_path.to_string_lossy()) {
|
||||||
Ok(files) => files.collect(),
|
Ok(files) => files.collect(),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
if let Some(source) = args.nth(0) {
|
if let Some(source) = pattern {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Invalid pattern",
|
"Invalid pattern",
|
||||||
"Invalid pattern",
|
"Invalid pattern",
|
||||||
source.span(),
|
source.tag(),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::string("Invalid pattern."));
|
return Err(ShellError::string("Invalid pattern."));
|
||||||
|
@ -114,17 +118,17 @@ impl Shell for FilesystemShell {
|
||||||
let entries = std::fs::read_dir(&entry);
|
let entries = std::fs::read_dir(&entry);
|
||||||
let entries = match entries {
|
let entries = match entries {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(s) = args.nth(0) {
|
if let Some(s) = pattern {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
s.span(),
|
s.tag(),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
args.name_span(),
|
command_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,11 +142,7 @@ impl Shell for FilesystemShell {
|
||||||
} else {
|
} else {
|
||||||
Path::new(&filepath)
|
Path::new(&filepath)
|
||||||
};
|
};
|
||||||
let value = dir_entry_dict(
|
let value = dir_entry_dict(filename, &entry.metadata()?, command_tag)?;
|
||||||
filename,
|
|
||||||
&entry.metadata()?,
|
|
||||||
Tag::unknown_origin(args.call_info.name_span),
|
|
||||||
)?;
|
|
||||||
shell_entries.push_back(ReturnSuccess::value(value))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
return Ok(shell_entries.to_output_stream());
|
return Ok(shell_entries.to_output_stream());
|
||||||
|
@ -159,11 +159,7 @@ impl Shell for FilesystemShell {
|
||||||
Path::new(&entry)
|
Path::new(&entry)
|
||||||
};
|
};
|
||||||
let metadata = std::fs::metadata(&entry)?;
|
let metadata = std::fs::metadata(&entry)?;
|
||||||
let value = dir_entry_dict(
|
let value = dir_entry_dict(filename, &metadata, command_tag)?;
|
||||||
filename,
|
|
||||||
&metadata,
|
|
||||||
Tag::unknown_origin(args.call_info.name_span),
|
|
||||||
)?;
|
|
||||||
shell_entries.push_back(ReturnSuccess::value(value))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +175,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not change to home directory",
|
"Can not change to home directory",
|
||||||
"can not go to home",
|
"can not go to home",
|
||||||
args.call_info.name_span,
|
args.call_info.name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -197,7 +193,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not change to directory",
|
"Can not change to directory",
|
||||||
"directory not found",
|
"directory not found",
|
||||||
v.span().clone(),
|
v.tag().clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,8 +203,7 @@ impl Shell for FilesystemShell {
|
||||||
|
|
||||||
let mut stream = VecDeque::new();
|
let mut stream = VecDeque::new();
|
||||||
|
|
||||||
stream.push_back(
|
stream.push_back(ReturnSuccess::change_cwd(
|
||||||
ReturnSuccess::change_cwd(
|
|
||||||
path.to_string_lossy().to_string(),
|
path.to_string_lossy().to_string(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -222,10 +217,10 @@ impl Shell for FilesystemShell {
|
||||||
dst,
|
dst,
|
||||||
recursive,
|
recursive,
|
||||||
}: CopyArgs,
|
}: CopyArgs,
|
||||||
name: Span,
|
name: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let mut source = PathBuf::from(path);
|
let mut source = PathBuf::from(path);
|
||||||
let mut destination = PathBuf::from(path);
|
let mut destination = PathBuf::from(path);
|
||||||
|
@ -280,7 +275,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -296,7 +291,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -332,7 +327,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -346,7 +341,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -360,7 +355,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Copy aborted. Not a valid path",
|
"Copy aborted. Not a valid path",
|
||||||
"Copy aborted. Not a valid path",
|
"Copy aborted. Not a valid path",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +365,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -406,7 +401,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -420,7 +415,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -453,7 +448,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Copy aborted. Not a valid path",
|
"Copy aborted. Not a valid path",
|
||||||
"Copy aborted. Not a valid path",
|
"Copy aborted. Not a valid path",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,7 +475,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Copy aborted. Not a valid destination",
|
"Copy aborted. Not a valid destination",
|
||||||
"Copy aborted. Not a valid destination",
|
"Copy aborted. Not a valid destination",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +484,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
||||||
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
||||||
&dst.span(),
|
dst.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +495,7 @@ impl Shell for FilesystemShell {
|
||||||
fn mkdir(
|
fn mkdir(
|
||||||
&self,
|
&self,
|
||||||
MkdirArgs { rest: directories }: MkdirArgs,
|
MkdirArgs { rest: directories }: MkdirArgs,
|
||||||
name: Span,
|
name: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let full_path = PathBuf::from(path);
|
let full_path = PathBuf::from(path);
|
||||||
|
@ -525,7 +520,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
reason.to_string(),
|
reason.to_string(),
|
||||||
reason.to_string(),
|
reason.to_string(),
|
||||||
dir.span(),
|
dir.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -538,10 +533,10 @@ impl Shell for FilesystemShell {
|
||||||
fn mv(
|
fn mv(
|
||||||
&self,
|
&self,
|
||||||
MoveArgs { src, dst }: MoveArgs,
|
MoveArgs { src, dst }: MoveArgs,
|
||||||
name: Span,
|
name: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
let mut source = PathBuf::from(path);
|
let mut source = PathBuf::from(path);
|
||||||
let mut destination = PathBuf::from(path);
|
let mut destination = PathBuf::from(path);
|
||||||
|
@ -567,7 +562,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Rename aborted. Not a valid destination",
|
"Rename aborted. Not a valid destination",
|
||||||
"Rename aborted. Not a valid destination",
|
"Rename aborted. Not a valid destination",
|
||||||
dst.span(),
|
dst.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,7 +576,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Rename aborted. Not a valid entry name",
|
"Rename aborted. Not a valid entry name",
|
||||||
"Rename aborted. Not a valid entry name",
|
"Rename aborted. Not a valid entry name",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -593,7 +588,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("Rename aborted. {:}", e.to_string()),
|
format!("Rename aborted. {:}", e.to_string()),
|
||||||
format!("Rename aborted. {:}", e.to_string()),
|
format!("Rename aborted. {:}", e.to_string()),
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -617,7 +612,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -640,7 +635,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -662,7 +657,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -715,7 +710,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -739,7 +734,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -762,7 +757,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -794,7 +789,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Rename aborted. Not a valid entry name",
|
"Rename aborted. Not a valid entry name",
|
||||||
"Rename aborted. Not a valid entry name",
|
"Rename aborted. Not a valid entry name",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -818,7 +813,7 @@ impl Shell for FilesystemShell {
|
||||||
destination_file_name,
|
destination_file_name,
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
),
|
),
|
||||||
name_span,
|
name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
|
@ -830,7 +825,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||||
dst.span(),
|
dst.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,16 +836,16 @@ impl Shell for FilesystemShell {
|
||||||
fn rm(
|
fn rm(
|
||||||
&self,
|
&self,
|
||||||
RemoveArgs { target, recursive }: RemoveArgs,
|
RemoveArgs { target, recursive }: RemoveArgs,
|
||||||
name: Span,
|
name: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = name;
|
let name_tag = name;
|
||||||
|
|
||||||
if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") {
|
if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Remove aborted. \".\" or \"..\" may not be removed.",
|
"Remove aborted. \".\" or \"..\" may not be removed.",
|
||||||
"Remove aborted. \".\" or \"..\" may not be removed.",
|
"Remove aborted. \".\" or \"..\" may not be removed.",
|
||||||
target.span(),
|
target.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,7 +877,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
||||||
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
||||||
target.span(),
|
target.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -899,7 +894,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Remove aborted. Not a valid path",
|
"Remove aborted. Not a valid path",
|
||||||
"Remove aborted. Not a valid path",
|
"Remove aborted. Not a valid path",
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,7 +914,7 @@ impl Shell for FilesystemShell {
|
||||||
"Directory {:?} found somewhere inside. Try using \"--recursive\".",
|
"Directory {:?} found somewhere inside. Try using \"--recursive\".",
|
||||||
path_file_name
|
path_file_name
|
||||||
),
|
),
|
||||||
target.span(),
|
target.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,7 +928,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
format!("Remove aborted. {:}", e.to_string()),
|
format!("Remove aborted. {:}", e.to_string()),
|
||||||
format!("Remove aborted. {:}", e.to_string()),
|
format!("Remove aborted. {:}", e.to_string()),
|
||||||
name_span,
|
name_tag,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -954,7 +949,7 @@ impl Shell for FilesystemShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"unable to show current directory",
|
"unable to show current directory",
|
||||||
"pwd command failed",
|
"pwd command failed",
|
||||||
args.call_info.name_span,
|
args.call_info.name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -962,7 +957,7 @@ impl Shell for FilesystemShell {
|
||||||
let mut stream = VecDeque::new();
|
let mut stream = VecDeque::new();
|
||||||
stream.push_back(ReturnSuccess::value(
|
stream.push_back(ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(p.to_string_lossy().to_string()))
|
Value::Primitive(Primitive::String(p.to_string_lossy().to_string()))
|
||||||
.simple_spanned(args.call_info.name_span),
|
.tagged(args.call_info.name_tag),
|
||||||
));
|
));
|
||||||
|
|
||||||
Ok(stream.into())
|
Ok(stream.into())
|
||||||
|
|
|
@ -126,7 +126,11 @@ impl Shell for HelpShell {
|
||||||
self.path = path.clone();
|
self.path = path.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls(&self, _args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
fn ls(
|
||||||
|
&self,
|
||||||
|
_pattern: Option<Tagged<PathBuf>>,
|
||||||
|
_command_tag: Tag,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.commands()
|
.commands()
|
||||||
.map(|x| ReturnSuccess::value(x))
|
.map(|x| ReturnSuccess::value(x))
|
||||||
|
@ -161,24 +165,19 @@ impl Shell for HelpShell {
|
||||||
Ok(stream.into())
|
Ok(stream.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cp(&self, _args: CopyArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn cp(&self, _args: CopyArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Ok(OutputStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mv(&self, _args: MoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn mv(&self, _args: MoveArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Ok(OutputStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkdir(
|
fn mkdir(&self, _args: MkdirArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
&self,
|
|
||||||
_args: MkdirArgs,
|
|
||||||
_name: Span,
|
|
||||||
_path: &str,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
Ok(OutputStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rm(&self, _args: RemoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn rm(&self, _args: RemoveArgs, _name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Ok(OutputStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl Highlighter for Helper {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
|
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
|
||||||
let tokens = crate::parser::pipeline(nom_input(line));
|
let tokens = crate::parser::pipeline(nom_input(line, uuid::Uuid::nil()));
|
||||||
|
|
||||||
match tokens {
|
match tokens {
|
||||||
Err(_) => Cow::Borrowed(line),
|
Err(_) => Cow::Borrowed(line),
|
||||||
|
@ -106,47 +106,47 @@ impl Highlighter for Helper {
|
||||||
|
|
||||||
fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
||||||
let styled = match token_node {
|
let styled = match token_node {
|
||||||
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)),
|
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)),
|
TokenNode::Path(..) => Color::Green.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)),
|
TokenNode::Error(..) => Color::Red.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)),
|
TokenNode::Delimited(..) => Color::White.paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Operator(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
TokenNode::Operator(..) => Color::White.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.span().slice(line)),
|
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::Number(..),
|
item: RawToken::Number(..),
|
||||||
..
|
..
|
||||||
}) => Color::Purple.bold().paint(token_node.span().slice(line)),
|
}) => Color::Purple.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::Size(..),
|
item: RawToken::Size(..),
|
||||||
..
|
..
|
||||||
}) => Color::Purple.bold().paint(token_node.span().slice(line)),
|
}) => Color::Purple.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::GlobPattern,
|
item: RawToken::GlobPattern,
|
||||||
..
|
..
|
||||||
}) => Color::Cyan.normal().paint(token_node.span().slice(line)),
|
}) => Color::Cyan.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::String(..),
|
item: RawToken::String(..),
|
||||||
..
|
..
|
||||||
}) => Color::Green.normal().paint(token_node.span().slice(line)),
|
}) => Color::Green.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::Variable(..),
|
item: RawToken::Variable(..),
|
||||||
..
|
..
|
||||||
}) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
}) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::Bare,
|
item: RawToken::Bare,
|
||||||
..
|
..
|
||||||
}) => Color::Green.normal().paint(token_node.span().slice(line)),
|
}) => Color::Green.normal().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::ExternalCommand(..),
|
item: RawToken::ExternalCommand(..),
|
||||||
..
|
..
|
||||||
}) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
}) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::ExternalWord,
|
item: RawToken::ExternalWord,
|
||||||
..
|
..
|
||||||
}) => Color::Black.bold().paint(token_node.span().slice(line)),
|
}) => Color::Black.bold().paint(token_node.tag().slice(line)),
|
||||||
};
|
};
|
||||||
|
|
||||||
styled.to_string()
|
styled.to_string()
|
||||||
|
@ -166,7 +166,7 @@ fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> Str
|
||||||
styled.push_str(
|
styled.push_str(
|
||||||
&Color::Cyan
|
&Color::Cyan
|
||||||
.bold()
|
.bold()
|
||||||
.paint(pipeline_element.call().head().span().slice(line))
|
.paint(pipeline_element.call().head().tag().slice(line))
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,16 @@ pub trait Shell: std::fmt::Debug {
|
||||||
fn name(&self, source_map: &SourceMap) -> String;
|
fn name(&self, source_map: &SourceMap) -> String;
|
||||||
fn homedir(&self) -> Option<PathBuf>;
|
fn homedir(&self) -> Option<PathBuf>;
|
||||||
|
|
||||||
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
fn ls(
|
||||||
|
&self,
|
||||||
|
pattern: Option<Tagged<PathBuf>>,
|
||||||
|
command_tag: Tag,
|
||||||
|
) -> Result<OutputStream, ShellError>;
|
||||||
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
||||||
fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
|
fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||||
fn mkdir(&self, args: MkdirArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
|
fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||||
fn mv(&self, args: MoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
|
fn mv(&self, args: MoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||||
fn rm(&self, args: RemoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
|
fn rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;
|
||||||
fn path(&self) -> String;
|
fn path(&self) -> String;
|
||||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
||||||
fn set_path(&mut self, path: String);
|
fn set_path(&mut self, path: String);
|
||||||
|
|
|
@ -115,10 +115,14 @@ impl ShellManager {
|
||||||
env[self.current_shell].homedir()
|
env[self.current_shell].homedir()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn ls(
|
||||||
|
&self,
|
||||||
|
path: Option<Tagged<PathBuf>>,
|
||||||
|
command_tag: Tag,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let env = self.shells.lock().unwrap();
|
let env = self.shells.lock().unwrap();
|
||||||
|
|
||||||
env[self.current_shell].ls(args)
|
env[self.current_shell].ls(path, command_tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
|
|
@ -87,13 +87,15 @@ impl Shell for ValueShell {
|
||||||
Some(PathBuf::from("/"))
|
Some(PathBuf::from("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
fn ls(
|
||||||
|
&self,
|
||||||
|
target: Option<Tagged<PathBuf>>,
|
||||||
|
command_name: Tag,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let mut full_path = PathBuf::from(self.path());
|
let mut full_path = PathBuf::from(self.path());
|
||||||
|
|
||||||
let target = args.nth(0);
|
match &target {
|
||||||
|
Some(value) => full_path.push(value.as_ref()),
|
||||||
match target {
|
|
||||||
Some(value) => full_path.push(Path::new(&value.as_path()?)),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,18 +103,18 @@ impl Shell for ValueShell {
|
||||||
value_system.walk_decorate(&self.value)?;
|
value_system.walk_decorate(&self.value)?;
|
||||||
|
|
||||||
if !value_system.exists(&full_path) {
|
if !value_system.exists(&full_path) {
|
||||||
if let Some(target) = target {
|
if let Some(target) = &target {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not list entries inside",
|
"Can not list entries inside",
|
||||||
"No such path exists",
|
"No such path exists",
|
||||||
target.span(),
|
target.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not list entries inside",
|
"Can not list entries inside",
|
||||||
"No such path exists",
|
"No such path exists",
|
||||||
args.call_info.name_span,
|
command_name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,14 +159,14 @@ impl Shell for ValueShell {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not change to path inside",
|
"Can not change to path inside",
|
||||||
"No such path exists",
|
"No such path exists",
|
||||||
destination.span(),
|
destination.tag(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not change to path inside",
|
"Can not change to path inside",
|
||||||
"No such path exists",
|
"No such path exists",
|
||||||
args.call_info.name_span,
|
args.call_info.name_tag,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +175,7 @@ impl Shell for ValueShell {
|
||||||
Ok(stream.into())
|
Ok(stream.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cp(&self, _args: CopyArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn cp(&self, _args: CopyArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"cp not currently supported on values",
|
"cp not currently supported on values",
|
||||||
"not currently supported",
|
"not currently supported",
|
||||||
|
@ -181,7 +183,7 @@ impl Shell for ValueShell {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mv(&self, _args: MoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn mv(&self, _args: MoveArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"mv not currently supported on values",
|
"mv not currently supported on values",
|
||||||
"not currently supported",
|
"not currently supported",
|
||||||
|
@ -189,7 +191,7 @@ impl Shell for ValueShell {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkdir(&self, _args: MkdirArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn mkdir(&self, _args: MkdirArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"mkdir not currently supported on values",
|
"mkdir not currently supported on values",
|
||||||
"not currently supported",
|
"not currently supported",
|
||||||
|
@ -197,7 +199,7 @@ impl Shell for ValueShell {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rm(&self, _args: RemoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
|
fn rm(&self, _args: RemoveArgs, name: Tag, _path: &str) -> Result<OutputStream, ShellError> {
|
||||||
Err(ShellError::labeled_error(
|
Err(ShellError::labeled_error(
|
||||||
"rm not currently supported on values",
|
"rm not currently supported on values",
|
||||||
"not currently supported",
|
"not currently supported",
|
||||||
|
@ -213,7 +215,7 @@ impl Shell for ValueShell {
|
||||||
let mut stream = VecDeque::new();
|
let mut stream = VecDeque::new();
|
||||||
stream.push_back(ReturnSuccess::value(Tagged::from_item(
|
stream.push_back(ReturnSuccess::value(Tagged::from_item(
|
||||||
Value::string(self.path()),
|
Value::string(self.path()),
|
||||||
args.call_info.name_span,
|
args.call_info.name_tag,
|
||||||
)));
|
)));
|
||||||
Ok(stream.into())
|
Ok(stream.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ impl<T: ToDebug> fmt::Display for Debuggable<'_, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasSpan {
|
pub trait HasTag {
|
||||||
fn span(&self) -> Span;
|
fn tag(&self) -> Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToDebug: Sized {
|
pub trait ToDebug: Sized {
|
||||||
|
|
Loading…
Reference in a new issue