Evaluation of command arguments (#1801)

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Finish adding the baseline refactors for argument invocation

* Finish cleanup and add test

* Add missing plugin references
This commit is contained in:
Jonathan Turner
2020-05-15 20:18:24 -07:00
committed by GitHub
parent 822440d5ff
commit 076fde16dd
139 changed files with 2496 additions and 2188 deletions

View File

@ -73,13 +73,17 @@ fn parse_simple_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, O
}
/// Parses a column path, adding in the preceding reference to $it if it's elided
fn parse_full_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, Option<ParseError>) {
fn parse_full_column_path(
lite_arg: &Spanned<String>,
registry: &dyn SignatureRegistry,
) -> (SpannedExpression, Option<ParseError>) {
let mut delimiter = '.';
let mut inside_delimiter = false;
let mut output = vec![];
let mut current_part = String::new();
let mut start_index = 0;
let mut last_index = 0;
let mut error = None;
let mut head = None;
@ -98,7 +102,28 @@ fn parse_full_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, Opt
lite_arg.span.start() + idx,
);
if head.is_none() && current_part.clone().starts_with('$') {
if head.is_none() && current_part.starts_with("$(") && current_part.ends_with(')') {
// We have a command invocation
let string: String = current_part
.chars()
.skip(2)
.take(current_part.len() - 3)
.collect();
// We haven't done much with the inner string, so let's go ahead and work with it
let lite_block = match lite_parse(&string, lite_arg.span.start() + 2) {
Ok(lp) => lp,
Err(e) => return (garbage(lite_arg.span), Some(e)),
};
let classified_block = classify_block(&lite_block, registry);
let err = classified_block.failed;
if error.is_none() {
error = err;
}
head = Some(Expression::Invocation(classified_block.block))
} else if head.is_none() && current_part.starts_with('$') {
// We have the variable head
head = Some(Expression::variable(current_part.clone(), part_span))
} else if let Ok(row_number) = current_part.parse::<u64>() {
@ -127,7 +152,28 @@ fn parse_full_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, Opt
);
if head.is_none() {
if current_part.starts_with('$') {
if current_part.starts_with("$(") && current_part.ends_with(')') {
// We have a command invocation
let string: String = current_part
.chars()
.skip(2)
.take(current_part.len() - 3)
.collect();
// We haven't done much with the inner string, so let's go ahead and work with it
let lite_block = match lite_parse(&string, lite_arg.span.start() + 2) {
Ok(lp) => lp,
Err(e) => return (garbage(lite_arg.span), Some(e)),
};
let classified_block = classify_block(&lite_block, registry);
let err = classified_block.failed;
if error.is_none() {
error = err;
}
head = Some(Expression::Invocation(classified_block.block));
} else if current_part.starts_with('$') {
// We have the variable head
head = Some(Expression::variable(current_part, lite_arg.span));
} else if let Ok(row_number) = current_part.parse::<u64>() {
@ -154,7 +200,7 @@ fn parse_full_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, Opt
Expression::path(SpannedExpression::new(head, lite_arg.span), output),
lite_arg.span,
),
None,
error,
)
} else {
(
@ -168,7 +214,7 @@ fn parse_full_column_path(lite_arg: &Spanned<String>) -> (SpannedExpression, Opt
),
lite_arg.span,
),
None,
error,
)
}
}
@ -310,7 +356,7 @@ fn parse_arg(
lite_arg: &Spanned<String>,
) -> (SpannedExpression, Option<ParseError>) {
if lite_arg.item.starts_with('$') {
return parse_full_column_path(&lite_arg);
return parse_full_column_path(&lite_arg, registry);
}
match expected_type {
@ -374,7 +420,7 @@ fn parse_arg(
)
}
SyntaxShape::ColumnPath => parse_simple_column_path(lite_arg),
SyntaxShape::FullColumnPath => parse_full_column_path(lite_arg),
SyntaxShape::FullColumnPath => parse_full_column_path(lite_arg, registry),
SyntaxShape::Any => {
let shapes = vec![
SyntaxShape::Int,

View File

@ -6,6 +6,7 @@ use nu_source::{Spanned, SpannedItem};
pub fn expression_to_flat_shape(e: &SpannedExpression) -> Vec<Spanned<FlatShape>> {
match &e.expr {
Expression::Block(exprs) => shapes(exprs),
Expression::Invocation(exprs) => shapes(exprs),
Expression::FilePath(_) => vec![FlatShape::Path.spanned(e.span)],
Expression::Garbage => vec![FlatShape::Garbage.spanned(e.span)],
Expression::List(exprs) => {