nushell/src/parser/registry.rs

113 lines
3.2 KiB
Rust
Raw Normal View History

2019-05-28 08:45:18 +02:00
use crate::evaluate::{evaluate_expr, Scope};
use crate::prelude::*;
2019-05-26 08:54:41 +02:00
use indexmap::IndexMap;
#[allow(unused)]
2019-05-28 08:45:18 +02:00
#[derive(Debug)]
pub enum NamedType {
Switch(String),
Single(String),
Array(String),
Block(String),
2019-05-26 08:54:41 +02:00
}
#[allow(unused)]
2019-05-28 08:45:18 +02:00
#[derive(Debug, Clone)]
pub enum PositionalType {
Value(String),
Block(String),
}
impl PositionalType {
crate fn name(&self) -> String {
match self {
PositionalType::Value(s) => s.clone(),
PositionalType::Block(s) => s.clone(),
}
}
crate fn evaluate(&self, arg: ast::Expression, scope: &Scope) -> Result<Value, ShellError> {
match self {
PositionalType::Value(_) => evaluate_expr(&arg, scope),
PositionalType::Block(_) => match arg {
ast::Expression::Block(b) => Ok(Value::block(b.expr)),
ast::Expression::Binary(b) => {
if let Some(s) = b.left.as_string() {
Ok(Value::block(ast::Expression::Binary(Box::new(
ast::Binary::new(
ast::Expression::Path(Box::new(ast::Path::new(
ast::Expression::VariableReference(ast::Variable::It),
vec![s],
))),
b.operator,
b.right,
),
))))
} else {
Ok(Value::block(ast::Expression::Binary(b)))
}
}
other => Ok(Value::block(other)), // other =>
},
}
}
}
#[derive(Debug)]
2019-05-26 08:54:41 +02:00
pub struct CommandConfig {
crate name: String,
2019-05-28 08:45:18 +02:00
crate mandatory_positional: Vec<PositionalType>,
crate optional_positional: Vec<PositionalType>,
2019-05-26 08:54:41 +02:00
crate rest_positional: bool,
2019-05-28 08:45:18 +02:00
crate named: IndexMap<String, NamedType>,
}
impl CommandConfig {
crate fn evaluate_args(
&self,
mut args: impl Iterator<Item = &'expr ast::Expression>,
scope: &Scope,
) -> Result<Vec<Value>, ShellError> {
let mut results: Vec<Value> = vec![];
for param in &self.mandatory_positional {
let arg = args.next();
let value = match arg {
None => {
return Err(ShellError::string(format!(
"expected mandatory positional argument {}",
param.name()
)))
}
Some(arg) => param.evaluate(arg.clone(), scope)?,
};
results.push(value);
}
if self.rest_positional {
let rest: Result<Vec<Value>, _> =
args.map(|i| evaluate_expr(i, &Scope::empty())).collect();
results.extend(rest?);
} else {
match args.next() {
None => {}
Some(_) => return Err(ShellError::string("Too many arguments")),
}
}
Ok(results)
}
#[allow(unused)]
crate fn signature(&self) -> String {
format!("TODO")
}
2019-05-26 08:54:41 +02:00
}
pub trait CommandRegistry {
fn get(&self, name: &str) -> CommandConfig;
}