forked from extern/nushell
Merge pull request #181 from nushell/string-arg
Make signatures a little more general
This commit is contained in:
commit
60f4436849
@ -3,7 +3,8 @@ use crate::prelude::*;
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::config;
|
use crate::object::config;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
use crate::parser::registry::{CommandConfig, NamedType, NamedValue};
|
use crate::parser::hir::SyntaxType;
|
||||||
|
use crate::parser::registry::{CommandConfig, NamedType};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
@ -20,14 +21,11 @@ impl Command for Config {
|
|||||||
|
|
||||||
fn config(&self) -> CommandConfig {
|
fn config(&self) -> CommandConfig {
|
||||||
let mut named: IndexMap<String, NamedType> = IndexMap::new();
|
let mut named: IndexMap<String, NamedType> = IndexMap::new();
|
||||||
named.insert("set".to_string(), NamedType::Optional(NamedValue::Single));
|
named.insert("set".to_string(), NamedType::Optional(SyntaxType::Any));
|
||||||
named.insert("get".to_string(), NamedType::Optional(NamedValue::Single));
|
named.insert("get".to_string(), NamedType::Optional(SyntaxType::Any));
|
||||||
named.insert("clear".to_string(), NamedType::Switch);
|
named.insert("clear".to_string(), NamedType::Switch);
|
||||||
|
|
||||||
named.insert(
|
named.insert("remove".to_string(), NamedType::Optional(SyntaxType::Any));
|
||||||
"remove".to_string(),
|
|
||||||
NamedType::Optional(NamedValue::Single),
|
|
||||||
);
|
|
||||||
|
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: self.name().to_string(),
|
name: self.name().to_string(),
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! named_type {
|
||||||
|
($name:ident) => {
|
||||||
|
$crate::parser::registry::NamedType::$($name)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! command {
|
macro_rules! command {
|
||||||
(
|
(
|
||||||
@ -11,7 +18,7 @@ macro_rules! command {
|
|||||||
rest_positional: $rest_positional:tt,
|
rest_positional: $rest_positional:tt,
|
||||||
named: {
|
named: {
|
||||||
$(
|
$(
|
||||||
($named_param:tt : $named_type:tt)
|
($named_param:tt : $named_type:ty : $named_kind:tt)
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +42,7 @@ macro_rules! command {
|
|||||||
Ok(output.boxed().to_output_stream())
|
Ok(output.boxed().to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
let tuple = ( $($extract),*, );
|
let tuple = ( $($extract ,)* );
|
||||||
command( $args, tuple )
|
command( $args, tuple )
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +65,7 @@ macro_rules! command {
|
|||||||
let mut named: indexmap::IndexMap<String, NamedType> = indexmap::IndexMap::new();
|
let mut named: indexmap::IndexMap<String, NamedType> = indexmap::IndexMap::new();
|
||||||
|
|
||||||
$(
|
$(
|
||||||
named.insert(stringify!($named_param).to_string(), NamedType::$named_type);
|
named.insert(stringify!($named_param).to_string(), $crate::parser::registry::NamedType::$named_kind);
|
||||||
)*
|
)*
|
||||||
|
|
||||||
named
|
named
|
||||||
@ -72,7 +79,7 @@ macro_rules! command {
|
|||||||
(
|
(
|
||||||
Named { $export:tt $args:ident $body:block }
|
Named { $export:tt $args:ident $body:block }
|
||||||
Positional { $($positional_count:tt)* }
|
Positional { $($positional_count:tt)* }
|
||||||
Rest { , -- $param_name:ident : Switch $($rest:tt)* }
|
Rest { -- $param_name:ident : Switch , $($rest:tt)* }
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name:tt,
|
name: $config_name:tt,
|
||||||
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
||||||
@ -100,7 +107,7 @@ macro_rules! command {
|
|||||||
rest_positional: $rest_positional,
|
rest_positional: $rest_positional,
|
||||||
named: {
|
named: {
|
||||||
$($config_named)*
|
$($config_named)*
|
||||||
($param_name : Switch)
|
($param_name : Switch : Switch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,11 +116,11 @@ macro_rules! command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Extract {
|
Extract {
|
||||||
($($extract)* {
|
$($extract)* {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
$args.get(stringify!($param_name)).clone().try_into()?
|
$args.get(stringify!($param_name)).clone().try_into()?
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -122,7 +129,7 @@ macro_rules! command {
|
|||||||
(
|
(
|
||||||
Named { $export:tt $args:ident $body:block }
|
Named { $export:tt $args:ident $body:block }
|
||||||
Positional { $($positional_count:tt)* }
|
Positional { $($positional_count:tt)* }
|
||||||
Rest { , -- $param_name:ident : $param_kind:tt $($rest:tt)* }
|
Rest { -- $param_name:ident : $param_kind:ty , $($rest:tt)* }
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name:tt,
|
name: $config_name:tt,
|
||||||
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
||||||
@ -159,11 +166,11 @@ macro_rules! command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Extract {
|
Extract {
|
||||||
($($extract)* {
|
$($extract)* {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
$args.get(stringify!($param_name)).clone().try_into()?
|
$args.get(stringify!($param_name)).clone().try_into()?
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -172,7 +179,7 @@ macro_rules! command {
|
|||||||
(
|
(
|
||||||
Named { $export:tt $args:ident $body:block }
|
Named { $export:tt $args:ident $body:block }
|
||||||
Positional { $($positional_count:tt)* }
|
Positional { $($positional_count:tt)* }
|
||||||
Rest { , -- $param_name:ident ? : $param_kind:tt $($rest:tt)* }
|
Rest { -- $param_name:ident ? : $param_kind:ty , $($rest:tt)* }
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name:tt,
|
name: $config_name:tt,
|
||||||
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
||||||
@ -209,11 +216,11 @@ macro_rules! command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Extract {
|
Extract {
|
||||||
($($extract)* {
|
$($extract)* {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
$args.get(stringify!($param_name)).clone().try_into()?
|
$args.get(stringify!($param_name)).clone().try_into()?
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -222,7 +229,7 @@ macro_rules! command {
|
|||||||
(
|
(
|
||||||
Named { $export:ident $args:ident $body:block }
|
Named { $export:ident $args:ident $body:block }
|
||||||
Positional { $($positional_count:tt)* }
|
Positional { $($positional_count:tt)* }
|
||||||
Rest { , $param_name:ident : Block $($rest:tt)* }
|
Rest { $param_name:ident : Block , $($rest:tt)* }
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name:tt,
|
name: $config_name:tt,
|
||||||
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
||||||
@ -277,7 +284,7 @@ macro_rules! command {
|
|||||||
(
|
(
|
||||||
Named { $export:ident $args:ident $body:block }
|
Named { $export:ident $args:ident $body:block }
|
||||||
Positional { $($positional_count:tt)* }
|
Positional { $($positional_count:tt)* }
|
||||||
Rest { , $param_name:ident : $param_kind:tt $($rest:tt)* }
|
Rest { $param_name:ident : $param_kind:ty , $($rest:tt)* }
|
||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name:tt,
|
name: $config_name:tt,
|
||||||
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
|
||||||
@ -304,7 +311,7 @@ macro_rules! command {
|
|||||||
CommandConfig {
|
CommandConfig {
|
||||||
name: $config_name,
|
name: $config_name,
|
||||||
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory(
|
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory(
|
||||||
stringify!($param_name)
|
stringify!($param_name), <$param_kind>::syntax_type()
|
||||||
), ],
|
), ],
|
||||||
optional_positional: vec![ $($optional_positional)* ],
|
optional_positional: vec![ $($optional_positional)* ],
|
||||||
rest_positional: $rest_positional,
|
rest_positional: $rest_positional,
|
||||||
@ -321,14 +328,13 @@ macro_rules! command {
|
|||||||
$($extract:tt)* {
|
$($extract:tt)* {
|
||||||
use $crate::object::types::ExtractType;
|
use $crate::object::types::ExtractType;
|
||||||
let value = $args.expect_nth($($positional_count)*)?;
|
let value = $args.expect_nth($($positional_count)*)?;
|
||||||
// let value = $param_kind.check(value)?;
|
<$param_kind>::extract(&value)?
|
||||||
$param_kind::extract(value)?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
($export:ident as $config_name:tt ( $args:ident $($command_rest:tt)* ) $body:block) => {
|
($export:ident as $config_name:tt ( $args:ident , $($command_rest:tt)* ) $body:block) => {
|
||||||
command!(
|
command!(
|
||||||
Named { $export $args $body }
|
Named { $export $args $body }
|
||||||
Positional { 0 }
|
Positional { 0 }
|
||||||
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
command! {
|
command! {
|
||||||
Open as open(args, --raw: Switch) {
|
Open as open(args, path: Spanned<PathBuf>, --raw: Switch,) {
|
||||||
let span = args.name_span;
|
let span = args.name_span;
|
||||||
|
|
||||||
let cwd = args
|
let cwd = args
|
||||||
@ -21,16 +21,19 @@ command! {
|
|||||||
|
|
||||||
let full_path = PathBuf::from(cwd);
|
let full_path = PathBuf::from(cwd);
|
||||||
|
|
||||||
let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
|
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".spanned(path.span)))?;
|
||||||
Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
|
|
||||||
_ => {
|
let (file_extension, contents, contents_span) = fetch(&full_path, path_str, path.span)?;
|
||||||
return Err(ShellError::labeled_error(
|
// let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
|
||||||
"Expected string value for filename",
|
// Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
|
||||||
"expected filename",
|
// _ => {
|
||||||
args.expect_nth(0)?.span,
|
// return Err(ShellError::labeled_error(
|
||||||
));
|
// "Expected string value for filename",
|
||||||
}
|
// "expected filename",
|
||||||
};
|
// args.expect_nth(0)?.span,
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
let mut stream = VecDeque::new();
|
let mut stream = VecDeque::new();
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
|||||||
}
|
}
|
||||||
Value::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
Value::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
||||||
Value::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
||||||
|
Value::Primitive(Primitive::Path(s)) => serde_json::Value::String(s.display().to_string()),
|
||||||
|
|
||||||
Value::Filesystem => serde_json::Value::Null,
|
Value::Filesystem => serde_json::Value::Null,
|
||||||
Value::List(l) => {
|
Value::List(l) => {
|
||||||
|
@ -13,6 +13,7 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
|||||||
Value::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i),
|
Value::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i),
|
||||||
Value::Primitive(Primitive::Nothing) => toml::Value::String("<Nothing>".to_string()),
|
Value::Primitive(Primitive::Nothing) => toml::Value::String("<Nothing>".to_string()),
|
||||||
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||||
|
Value::Primitive(Primitive::Path(s)) => toml::Value::String(s.display().to_string()),
|
||||||
|
|
||||||
Value::Filesystem => toml::Value::String("<Filesystem>".to_string()),
|
Value::Filesystem => toml::Value::String("<Filesystem>".to_string()),
|
||||||
Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()),
|
Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()),
|
||||||
|
@ -5,7 +5,7 @@ use futures::future::ready;
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
command! {
|
command! {
|
||||||
Where as where(args, condition: Block) {
|
Where as where(args, condition: Block,) {
|
||||||
let input: InputStream = trace_stream!(target: "nu::trace_stream::where", "where input" = args.input);
|
let input: InputStream = trace_stream!(target: "nu::trace_stream::where", "where input" = args.input);
|
||||||
|
|
||||||
input.values.filter_map(move |item| {
|
input.values.filter_map(move |item| {
|
||||||
|
@ -11,6 +11,7 @@ use derive_new::new;
|
|||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
||||||
@ -40,6 +41,7 @@ pub enum Primitive {
|
|||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Date(DateTime<Utc>),
|
Date(DateTime<Utc>),
|
||||||
|
Path(PathBuf),
|
||||||
|
|
||||||
EndOfStream,
|
EndOfStream,
|
||||||
}
|
}
|
||||||
@ -51,6 +53,7 @@ impl Primitive {
|
|||||||
match self {
|
match self {
|
||||||
Nothing => "nothing",
|
Nothing => "nothing",
|
||||||
EndOfStream => "end-of-stream",
|
EndOfStream => "end-of-stream",
|
||||||
|
Path(_) => "path",
|
||||||
Int(_) => "int",
|
Int(_) => "int",
|
||||||
Float(_) => "float",
|
Float(_) => "float",
|
||||||
Bytes(_) => "bytes",
|
Bytes(_) => "bytes",
|
||||||
@ -68,6 +71,7 @@ impl Primitive {
|
|||||||
Nothing => write!(f, "Nothing"),
|
Nothing => write!(f, "Nothing"),
|
||||||
EndOfStream => write!(f, "EndOfStream"),
|
EndOfStream => write!(f, "EndOfStream"),
|
||||||
Int(int) => write!(f, "{}", int),
|
Int(int) => write!(f, "{}", int),
|
||||||
|
Path(path) => write!(f, "{}", path.display()),
|
||||||
Float(float) => write!(f, "{:?}", float),
|
Float(float) => write!(f, "{:?}", float),
|
||||||
Bytes(bytes) => write!(f, "{}", bytes),
|
Bytes(bytes) => write!(f, "{}", bytes),
|
||||||
String(string) => write!(f, "{:?}", string),
|
String(string) => write!(f, "{:?}", string),
|
||||||
@ -80,6 +84,7 @@ impl Primitive {
|
|||||||
match self {
|
match self {
|
||||||
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
|
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
|
||||||
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")),
|
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")),
|
||||||
|
Primitive::Path(p) => format!("{}", p.display()),
|
||||||
Primitive::Bytes(b) => {
|
Primitive::Bytes(b) => {
|
||||||
let byte = byte_unit::Byte::from_bytes(*b as u128);
|
let byte = byte_unit::Byte::from_bytes(*b as u128);
|
||||||
|
|
||||||
|
@ -3,19 +3,34 @@ use crate::parser::hir;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub trait Type: std::fmt::Debug + Send {
|
pub trait Type: std::fmt::Debug + Send {
|
||||||
type Extractor: ExtractType;
|
type Extractor: ExtractType;
|
||||||
|
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn coerce(&self) -> Option<hir::ExpressionKindHint> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExtractType: Sized {
|
pub trait ExtractType: Sized {
|
||||||
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError>;
|
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError>;
|
||||||
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
|
||||||
|
fn syntax_type() -> hir::SyntaxType {
|
||||||
|
hir::SyntaxType::Any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ExtractType> ExtractType for Spanned<T> {
|
||||||
|
fn extract(value: &Spanned<Value>) -> Result<Spanned<T>, ShellError> {
|
||||||
|
Ok(T::extract(value)?.spanned(value.span))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
|
T::check(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn syntax_type() -> hir::SyntaxType {
|
||||||
|
T::syntax_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
||||||
@ -39,6 +54,35 @@ impl ExtractType for Spanned<Value> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FilePath;
|
||||||
|
|
||||||
|
impl ExtractType for std::path::PathBuf {
|
||||||
|
fn syntax_type() -> hir::SyntaxType {
|
||||||
|
hir::SyntaxType::Path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract(value: &'a Spanned<Value>) -> Result<std::path::PathBuf, ShellError> {
|
||||||
|
match &value {
|
||||||
|
Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(p)),
|
||||||
|
span,
|
||||||
|
} => Ok(PathBuf::from(p)),
|
||||||
|
other => Err(ShellError::type_error("Path", other.spanned_type_name())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||||
|
match &value {
|
||||||
|
v @ Spanned {
|
||||||
|
item: Value::Primitive(Primitive::Path(_)),
|
||||||
|
..
|
||||||
|
} => Ok(v),
|
||||||
|
other => Err(ShellError::type_error("Path", other.spanned_type_name())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
||||||
pub struct Integer;
|
pub struct Integer;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ use crate::parser::{Span, Spanned, Unit};
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
|
|
||||||
crate use baseline_parse::baseline_parse_single_token;
|
crate use baseline_parse::{baseline_parse_single_token, baseline_parse_token_as_string};
|
||||||
crate use baseline_parse_tokens::{baseline_parse_next_expr, ExpressionKindHint, TokensIterator};
|
crate use baseline_parse_tokens::{baseline_parse_next_expr, SyntaxType, TokensIterator};
|
||||||
crate use binary::Binary;
|
crate use binary::Binary;
|
||||||
crate use named::NamedArguments;
|
crate use named::NamedArguments;
|
||||||
crate use path::Path;
|
crate use path::Path;
|
||||||
|
@ -13,3 +13,16 @@ pub fn baseline_parse_single_token(token: &Token, source: &Text) -> hir::Express
|
|||||||
RawToken::Bare => hir::Expression::bare(token.span),
|
RawToken::Bare => hir::Expression::bare(token.span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn baseline_parse_token_as_string(token: &Token, source: &Text) -> hir::Expression {
|
||||||
|
match *token.item() {
|
||||||
|
RawToken::Variable(span) if span.slice(source) == "it" => {
|
||||||
|
hir::Expression::it_variable(span, token.span)
|
||||||
|
}
|
||||||
|
RawToken::Variable(span) => hir::Expression::variable(span, token.span),
|
||||||
|
RawToken::Integer(_) => hir::Expression::bare(token.span),
|
||||||
|
RawToken::Size(int, unit) => hir::Expression::bare(token.span),
|
||||||
|
RawToken::Bare => hir::Expression::bare(token.span),
|
||||||
|
RawToken::String(span) => hir::Expression::string(span, token.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::registry::CommandRegistry;
|
use crate::parser::registry::CommandRegistry;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
hir, hir::baseline_parse_single_token, DelimitedNode, Delimiter, PathNode, RawToken, Span,
|
hir,
|
||||||
Spanned, TokenNode,
|
hir::{baseline_parse_single_token, baseline_parse_token_as_string},
|
||||||
|
DelimitedNode, Delimiter, PathNode, RawToken, Span, Spanned, TokenNode,
|
||||||
};
|
};
|
||||||
use crate::{SpannedItem, Text};
|
use crate::{SpannedItem, Text};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
use log::trace;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub fn baseline_parse_tokens(
|
pub fn baseline_parse_tokens(
|
||||||
token_nodes: &mut TokensIterator<'_>,
|
token_nodes: &mut TokensIterator<'_>,
|
||||||
@ -19,7 +22,7 @@ pub fn baseline_parse_tokens(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = baseline_parse_next_expr(token_nodes, registry, source, None)?;
|
let expr = baseline_parse_next_expr(token_nodes, registry, source, SyntaxType::Any)?;
|
||||||
exprs.push(expr);
|
exprs.push(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,10 +30,12 @@ pub fn baseline_parse_tokens(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum ExpressionKindHint {
|
pub enum SyntaxType {
|
||||||
|
Any,
|
||||||
Literal,
|
Literal,
|
||||||
Variable,
|
Variable,
|
||||||
|
Path,
|
||||||
Binary,
|
Binary,
|
||||||
Block,
|
Block,
|
||||||
Boolean,
|
Boolean,
|
||||||
@ -40,13 +45,31 @@ pub fn baseline_parse_next_expr(
|
|||||||
tokens: &mut TokensIterator,
|
tokens: &mut TokensIterator,
|
||||||
registry: &dyn CommandRegistry,
|
registry: &dyn CommandRegistry,
|
||||||
source: &Text,
|
source: &Text,
|
||||||
coerce_hint: Option<ExpressionKindHint>,
|
syntax_type: SyntaxType,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
let first = match tokens.next() {
|
let next = tokens
|
||||||
None => return Err(ShellError::string("Expected token, found none")),
|
.next()
|
||||||
Some(token) => baseline_parse_semantic_token(token, registry, source)?,
|
.ok_or_else(|| ShellError::string("Expected token, found none"))?;
|
||||||
|
|
||||||
|
trace!(target: "nu::parser::parse_one_expr", "syntax_type={:?}, token={:?}", syntax_type, next);
|
||||||
|
|
||||||
|
match (syntax_type, next) {
|
||||||
|
(SyntaxType::Path, TokenNode::Token(token)) => {
|
||||||
|
return Ok(baseline_parse_token_as_string(token, source))
|
||||||
|
}
|
||||||
|
|
||||||
|
(SyntaxType::Path, token) => {
|
||||||
|
return Err(ShellError::type_error(
|
||||||
|
"Path",
|
||||||
|
token.type_name().spanned(token.span()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let first = baseline_parse_semantic_token(next, registry, source)?;
|
||||||
|
|
||||||
let possible_op = tokens.peek();
|
let possible_op = tokens.peek();
|
||||||
|
|
||||||
let op = match possible_op {
|
let op = match possible_op {
|
||||||
@ -69,8 +92,8 @@ 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 coerce_hint {
|
match syntax_type {
|
||||||
None => {
|
SyntaxType::Any => {
|
||||||
let span = (first.span.start, second.span.end);
|
let span = (first.span.start, second.span.end);
|
||||||
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));
|
||||||
@ -79,74 +102,75 @@ pub fn baseline_parse_next_expr(
|
|||||||
Ok(binary)
|
Ok(binary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(hint) => match hint {
|
SyntaxType::Block => {
|
||||||
ExpressionKindHint::Block => {
|
let span = (first.span.start, second.span.end);
|
||||||
let span = (first.span.start, second.span.end);
|
|
||||||
|
|
||||||
let path: Spanned<hir::RawExpression> = match first {
|
let path: Spanned<hir::RawExpression> = match first {
|
||||||
|
Spanned {
|
||||||
|
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
||||||
|
span,
|
||||||
|
} => {
|
||||||
|
let string = Spanned::from_item(span.slice(source).to_string(), span);
|
||||||
|
let path = hir::Path::new(
|
||||||
|
Spanned::from_item(
|
||||||
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
|
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
||||||
|
(0, 0),
|
||||||
|
),
|
||||||
|
vec![string],
|
||||||
|
);
|
||||||
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
Spanned {
|
Spanned {
|
||||||
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
item: path,
|
||||||
|
span: first.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spanned {
|
||||||
|
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
||||||
|
span,
|
||||||
|
} => {
|
||||||
|
let string = Spanned::from_item(inner.slice(source).to_string(), span);
|
||||||
|
let path = hir::Path::new(
|
||||||
|
Spanned::from_item(
|
||||||
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
|
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
||||||
|
(0, 0),
|
||||||
|
),
|
||||||
|
vec![string],
|
||||||
|
);
|
||||||
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
|
Spanned {
|
||||||
|
item: path,
|
||||||
|
span: first.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spanned {
|
||||||
|
item: hir::RawExpression::Variable(..),
|
||||||
|
..
|
||||||
|
} => first,
|
||||||
|
Spanned { span, item } => {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"The first part of an un-braced block must be a column name",
|
||||||
|
item.type_name(),
|
||||||
span,
|
span,
|
||||||
} => {
|
))
|
||||||
let string = Spanned::from_item(span.slice(source).to_string(), span);
|
}
|
||||||
let path = hir::Path::new(
|
};
|
||||||
Spanned::from_item(
|
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
|
||||||
(0, 0),
|
|
||||||
),
|
|
||||||
vec![string],
|
|
||||||
);
|
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
|
||||||
Spanned {
|
|
||||||
item: path,
|
|
||||||
span: first.span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spanned {
|
|
||||||
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
|
||||||
span,
|
|
||||||
} => {
|
|
||||||
let string = Spanned::from_item(inner.slice(source).to_string(), span);
|
|
||||||
let path = hir::Path::new(
|
|
||||||
Spanned::from_item(
|
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
|
||||||
(0, 0),
|
|
||||||
),
|
|
||||||
vec![string],
|
|
||||||
);
|
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
|
||||||
Spanned {
|
|
||||||
item: path,
|
|
||||||
span: first.span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spanned {
|
|
||||||
item: hir::RawExpression::Variable(..),
|
|
||||||
..
|
|
||||||
} => first,
|
|
||||||
Spanned { span, item } => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"The first part of an un-braced block must be a column name",
|
|
||||||
item.type_name(),
|
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = Spanned::from_item(binary, span);
|
let binary = Spanned::from_item(binary, span);
|
||||||
|
|
||||||
let block = hir::RawExpression::Block(vec![binary]);
|
let block = hir::RawExpression::Block(vec![binary]);
|
||||||
let block = Spanned::from_item(block, span);
|
let block = Spanned::from_item(block, span);
|
||||||
|
|
||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
other => unimplemented!("coerce hint {:?}", other),
|
other => Err(ShellError::unimplemented(format!(
|
||||||
},
|
"coerce hint {:?}",
|
||||||
|
other
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +185,10 @@ pub fn baseline_parse_semantic_token(
|
|||||||
TokenNode::Delimited(delimited) => baseline_parse_delimited(delimited, registry, source),
|
TokenNode::Delimited(delimited) => baseline_parse_delimited(delimited, registry, source),
|
||||||
TokenNode::Pipeline(_pipeline) => unimplemented!(),
|
TokenNode::Pipeline(_pipeline) => unimplemented!(),
|
||||||
TokenNode::Operator(_op) => unreachable!(),
|
TokenNode::Operator(_op) => unreachable!(),
|
||||||
TokenNode::Flag(_flag) => Err(ShellError::unimplemented("passing flags is not supported yet.")),
|
TokenNode::Flag(_flag) => Err(ShellError::unimplemented(
|
||||||
TokenNode::Identifier(_span) => unreachable!(),
|
"passing flags is not supported yet.",
|
||||||
|
)),
|
||||||
|
TokenNode::Member(_span) => unreachable!(),
|
||||||
TokenNode::Whitespace(_span) => unreachable!(),
|
TokenNode::Whitespace(_span) => unreachable!(),
|
||||||
TokenNode::Error(error) => Err(*error.item.clone()),
|
TokenNode::Error(error) => Err(*error.item.clone()),
|
||||||
TokenNode::Path(path) => baseline_parse_path(path, registry, source),
|
TokenNode::Path(path) => baseline_parse_path(path, registry, source),
|
||||||
@ -210,7 +236,7 @@ pub fn baseline_parse_path(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
TokenNode::Identifier(span) => span.slice(source),
|
TokenNode::Member(span) => span.slice(source),
|
||||||
|
|
||||||
// TODO: Make this impossible
|
// TODO: Make this impossible
|
||||||
other => unreachable!("{:?}", other),
|
other => unreachable!("{:?}", other),
|
||||||
|
@ -152,7 +152,7 @@ pub fn var(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
trace_step(input, "var", move |input| {
|
trace_step(input, "var", move |input| {
|
||||||
let start = input.offset;
|
let start = input.offset;
|
||||||
let (input, _) = tag("$")(input)?;
|
let (input, _) = tag("$")(input)?;
|
||||||
let (input, bare) = identifier(input)?;
|
let (input, bare) = member(input)?;
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
@ -162,14 +162,7 @@ pub fn var(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// let start = input.offset;
|
pub fn member(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
// let (input, _) = take_while1(is_start_bare_char)(input)?;
|
|
||||||
// let (input, _) = take_while(is_bare_char)(input)?;
|
|
||||||
// let end = input.offset;
|
|
||||||
|
|
||||||
// Ok((input, TokenTreeBuilder::spanned_bare((start, end))))
|
|
||||||
|
|
||||||
pub fn identifier(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|
||||||
trace_step(input, "identifier", move |input| {
|
trace_step(input, "identifier", move |input| {
|
||||||
let start = input.offset;
|
let start = input.offset;
|
||||||
let (input, _) = take_while1(is_id_start)(input)?;
|
let (input, _) = take_while1(is_id_start)(input)?;
|
||||||
@ -177,7 +170,7 @@ pub fn identifier(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
Ok((input, TokenTreeBuilder::spanned_ident((start, end))))
|
Ok((input, TokenTreeBuilder::spanned_member((start, end))))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +423,7 @@ pub fn path(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
let left = input.offset;
|
let left = input.offset;
|
||||||
let (input, head) = node1(input)?;
|
let (input, head) = node1(input)?;
|
||||||
let (input, _) = tag(".")(input)?;
|
let (input, _) = tag(".")(input)?;
|
||||||
let (input, tail) = separated_list(tag("."), alt((identifier, string)))(input)?;
|
let (input, tail) = separated_list(tag("."), alt((member, string)))(input)?;
|
||||||
let right = input.offset;
|
let right = input.offset;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
@ -821,14 +814,14 @@ mod tests {
|
|||||||
let _ = pretty_env_logger::try_init();
|
let _ = pretty_env_logger::try_init();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
apply(node, "node", "$it.print"),
|
apply(node, "node", "$it.print"),
|
||||||
build_token(b::path(b::var("it"), vec![b::ident("print")]))
|
build_token(b::path(b::var("it"), vec![b::member("print")]))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
apply(node, "node", "$head.part1.part2"),
|
apply(node, "node", "$head.part1.part2"),
|
||||||
build_token(b::path(
|
build_token(b::path(
|
||||||
b::var("head"),
|
b::var("head"),
|
||||||
vec![b::ident("part1"), b::ident("part2")]
|
vec![b::member("part1"), b::member("part2")]
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -836,7 +829,7 @@ mod tests {
|
|||||||
apply(node, "node", "( hello ).world"),
|
apply(node, "node", "( hello ).world"),
|
||||||
build_token(b::path(
|
build_token(b::path(
|
||||||
b::parens(vec![b::sp(), b::bare("hello"), b::sp()]),
|
b::parens(vec![b::sp(), b::bare("hello"), b::sp()]),
|
||||||
vec![b::ident("world")]
|
vec![b::member("world")]
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -862,7 +855,7 @@ mod tests {
|
|||||||
b::sp(),
|
b::sp(),
|
||||||
b::path(
|
b::path(
|
||||||
b::var("it"),
|
b::var("it"),
|
||||||
vec![b::ident("is"), b::string("great news"), b::ident("right")]
|
vec![b::member("is"), b::string("great news"), b::member("right")]
|
||||||
),
|
),
|
||||||
b::sp(),
|
b::sp(),
|
||||||
b::bare("yep"),
|
b::bare("yep"),
|
||||||
@ -991,7 +984,7 @@ mod tests {
|
|||||||
vec![
|
vec![
|
||||||
b::sp(),
|
b::sp(),
|
||||||
b::braced(vec![
|
b::braced(vec![
|
||||||
b::path(b::var("it"), vec![b::ident("size")]),
|
b::path(b::var("it"), vec![b::member("size")]),
|
||||||
b::sp(),
|
b::sp(),
|
||||||
b::op(">"),
|
b::op(">"),
|
||||||
b::sp(),
|
b::sp(),
|
||||||
|
@ -15,7 +15,7 @@ pub enum TokenNode {
|
|||||||
Pipeline(Spanned<Pipeline>),
|
Pipeline(Spanned<Pipeline>),
|
||||||
Operator(Spanned<Operator>),
|
Operator(Spanned<Operator>),
|
||||||
Flag(Spanned<Flag>),
|
Flag(Spanned<Flag>),
|
||||||
Identifier(Span),
|
Member(Span),
|
||||||
Whitespace(Span),
|
Whitespace(Span),
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
Error(Spanned<Box<ShellError>>),
|
Error(Spanned<Box<ShellError>>),
|
||||||
@ -92,13 +92,29 @@ impl TokenNode {
|
|||||||
TokenNode::Pipeline(s) => s.span,
|
TokenNode::Pipeline(s) => s.span,
|
||||||
TokenNode::Operator(s) => s.span,
|
TokenNode::Operator(s) => s.span,
|
||||||
TokenNode::Flag(s) => s.span,
|
TokenNode::Flag(s) => s.span,
|
||||||
TokenNode::Identifier(s) => *s,
|
TokenNode::Member(s) => *s,
|
||||||
TokenNode::Whitespace(s) => *s,
|
TokenNode::Whitespace(s) => *s,
|
||||||
TokenNode::Error(s) => s.span,
|
TokenNode::Error(s) => s.span,
|
||||||
TokenNode::Path(s) => s.span,
|
TokenNode::Path(s) => s.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn type_name(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(t) => t.type_name(),
|
||||||
|
TokenNode::Call(s) => "command",
|
||||||
|
TokenNode::Delimited(d) => d.type_name(),
|
||||||
|
TokenNode::Pipeline(s) => "pipeline",
|
||||||
|
TokenNode::Operator(s) => "operator",
|
||||||
|
TokenNode::Flag(s) => "flag",
|
||||||
|
TokenNode::Member(s) => "member",
|
||||||
|
TokenNode::Whitespace(s) => "whitespace",
|
||||||
|
TokenNode::Error(s) => "error",
|
||||||
|
TokenNode::Path(s) => "path",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn debug(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
pub fn debug(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
||||||
DebugTokenNode { node: self, source }
|
DebugTokenNode { node: self, source }
|
||||||
}
|
}
|
||||||
@ -147,6 +163,16 @@ pub struct DelimitedNode {
|
|||||||
children: Vec<TokenNode>,
|
children: Vec<TokenNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DelimitedNode {
|
||||||
|
pub fn type_name(&self) -> &'static str {
|
||||||
|
match self.delimiter {
|
||||||
|
Delimiter::Brace => "braced expression",
|
||||||
|
Delimiter::Paren => "parenthesized expression",
|
||||||
|
Delimiter::Square => "array literal or index operator",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, FromStr)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, FromStr)]
|
||||||
pub enum Delimiter {
|
pub enum Delimiter {
|
||||||
Paren,
|
Paren,
|
||||||
|
@ -266,17 +266,17 @@ impl TokenTreeBuilder {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ident(input: impl Into<String>) -> CurriedToken {
|
pub fn member(input: impl Into<String>) -> CurriedToken {
|
||||||
let input = input.into();
|
let input = input.into();
|
||||||
|
|
||||||
Box::new(move |b| {
|
Box::new(move |b| {
|
||||||
let (start, end) = b.consume(&input);
|
let (start, end) = b.consume(&input);
|
||||||
TokenTreeBuilder::spanned_ident((start, end))
|
TokenTreeBuilder::spanned_member((start, end))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_ident(span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_member(span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Identifier(span.into())
|
TokenNode::Member(span.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall {
|
pub fn call(head: CurriedToken, input: Vec<CurriedToken>) -> CurriedCall {
|
||||||
|
@ -86,7 +86,7 @@ fn parse_command_tail(
|
|||||||
|
|
||||||
named.insert_switch(name, flag);
|
named.insert_switch(name, flag);
|
||||||
}
|
}
|
||||||
NamedType::Mandatory(kind) => {
|
NamedType::Mandatory(syntax_type) => {
|
||||||
match extract_mandatory(config, name, tail, source, command_span) {
|
match extract_mandatory(config, name, tail, source, command_span) {
|
||||||
Err(err) => return Err(err), // produce a correct diagnostic
|
Err(err) => return Err(err), // produce a correct diagnostic
|
||||||
Ok((pos, flag)) => {
|
Ok((pos, flag)) => {
|
||||||
@ -100,19 +100,15 @@ fn parse_command_tail(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = hir::baseline_parse_next_expr(
|
let expr =
|
||||||
tail,
|
hir::baseline_parse_next_expr(tail, registry, source, *syntax_type)?;
|
||||||
registry,
|
|
||||||
source,
|
|
||||||
kind.to_coerce_hint(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
tail.restart();
|
tail.restart();
|
||||||
named.insert_mandatory(name, expr);
|
named.insert_mandatory(name, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NamedType::Optional(kind) => match extract_optional(name, tail, source) {
|
NamedType::Optional(syntax_type) => match extract_optional(name, tail, source) {
|
||||||
Err(err) => return Err(err), // produce a correct diagnostic
|
Err(err) => return Err(err), // produce a correct diagnostic
|
||||||
Ok(Some((pos, flag))) => {
|
Ok(Some((pos, flag))) => {
|
||||||
tail.move_to(pos);
|
tail.move_to(pos);
|
||||||
@ -125,12 +121,7 @@ fn parse_command_tail(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = hir::baseline_parse_next_expr(
|
let expr = hir::baseline_parse_next_expr(tail, registry, source, *syntax_type)?;
|
||||||
tail,
|
|
||||||
registry,
|
|
||||||
source,
|
|
||||||
kind.to_coerce_hint(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
tail.restart();
|
tail.restart();
|
||||||
named.insert_optional(name, Some(expr));
|
named.insert_optional(name, Some(expr));
|
||||||
@ -169,7 +160,7 @@ fn parse_command_tail(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = hir::baseline_parse_next_expr(tail, registry, source, arg.to_coerce_hint())?;
|
let result = hir::baseline_parse_next_expr(tail, registry, source, arg.syntax_type())?;
|
||||||
|
|
||||||
positional.push(result);
|
positional.push(result);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||||
use crate::parser::{hir, hir::ExpressionKindHint, parse_command, CallNode, Spanned};
|
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode, Spanned};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
@ -12,55 +12,34 @@ use std::fmt;
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum NamedType {
|
pub enum NamedType {
|
||||||
Switch,
|
Switch,
|
||||||
Mandatory(NamedValue),
|
Mandatory(SyntaxType),
|
||||||
Optional(NamedValue),
|
Optional(SyntaxType),
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum NamedValue {
|
|
||||||
Single,
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
Block,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NamedValue {
|
|
||||||
crate fn to_coerce_hint(&self) -> Option<ExpressionKindHint> {
|
|
||||||
match self {
|
|
||||||
NamedValue::Single => None,
|
|
||||||
NamedValue::Block => Some(ExpressionKindHint::Block),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum PositionalType {
|
pub enum PositionalType {
|
||||||
Mandatory(String, PositionalValue),
|
Mandatory(String, SyntaxType),
|
||||||
Optional(String, PositionalValue),
|
Optional(String, SyntaxType),
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub enum PositionalValue {
|
|
||||||
Value,
|
|
||||||
Block,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionalType {
|
impl PositionalType {
|
||||||
pub fn mandatory(name: &str) -> PositionalType {
|
pub fn mandatory(name: &str, ty: SyntaxType) -> PositionalType {
|
||||||
PositionalType::Mandatory(name.to_string(), PositionalValue::Value)
|
PositionalType::Mandatory(name.to_string(), ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mandatory_any(name: &str) -> PositionalType {
|
||||||
|
PositionalType::Mandatory(name.to_string(), SyntaxType::Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mandatory_block(name: &str) -> PositionalType {
|
pub fn mandatory_block(name: &str) -> PositionalType {
|
||||||
PositionalType::Mandatory(name.to_string(), PositionalValue::Block)
|
PositionalType::Mandatory(name.to_string(), SyntaxType::Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn to_coerce_hint(&self) -> Option<ExpressionKindHint> {
|
crate fn to_coerce_hint(&self) -> Option<SyntaxType> {
|
||||||
match self {
|
match self {
|
||||||
PositionalType::Mandatory(_, PositionalValue::Block)
|
PositionalType::Mandatory(_, SyntaxType::Block)
|
||||||
| PositionalType::Optional(_, PositionalValue::Block) => {
|
| PositionalType::Optional(_, SyntaxType::Block) => Some(SyntaxType::Block),
|
||||||
Some(ExpressionKindHint::Block)
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +50,13 @@ impl PositionalType {
|
|||||||
PositionalType::Optional(s, _) => s,
|
PositionalType::Optional(s, _) => s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn syntax_type(&self) -> SyntaxType {
|
||||||
|
match *self {
|
||||||
|
PositionalType::Mandatory(_, t) => t,
|
||||||
|
PositionalType::Optional(_, t) => t,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Getters, Serialize, Deserialize)]
|
#[derive(Debug, Getters, Serialize, Deserialize)]
|
||||||
|
@ -17,7 +17,7 @@ impl Plugin for Inc {
|
|||||||
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
||||||
Ok(CommandConfig {
|
Ok(CommandConfig {
|
||||||
name: "inc".to_string(),
|
name: "inc".to_string(),
|
||||||
positional: vec![PositionalType::mandatory("Increment")],
|
positional: vec![PositionalType::mandatory_any("Increment")],
|
||||||
is_filter: true,
|
is_filter: true,
|
||||||
is_sink: false,
|
is_sink: false,
|
||||||
named: IndexMap::new(),
|
named: IndexMap::new(),
|
||||||
|
@ -101,7 +101,7 @@ fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
|||||||
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)),
|
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Identifier(..) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)),
|
TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)),
|
TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)),
|
||||||
TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)),
|
TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)),
|
||||||
@ -139,7 +139,12 @@ fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> Str
|
|||||||
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
||||||
}
|
}
|
||||||
|
|
||||||
styled.push_str(&Color::Cyan.bold().paint(pipeline_element.call().head().span().slice(line)).to_string());
|
styled.push_str(
|
||||||
|
&Color::Cyan
|
||||||
|
.bold()
|
||||||
|
.paint(pipeline_element.call().head().span().slice(line))
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(children) = pipeline_element.call().children() {
|
if let Some(children) = pipeline_element.call().children() {
|
||||||
for child in children {
|
for child in children {
|
||||||
|
Loading…
Reference in New Issue
Block a user