mirror of
https://github.com/nushell/nushell
synced 2025-01-13 21:55:07 +00:00
Default values (#4770)
This commit is contained in:
parent
a3df2e5631
commit
1837bf775c
17 changed files with 289 additions and 19 deletions
|
@ -62,6 +62,9 @@ fn eval_call(
|
||||||
if let Some(arg) = call.positional.get(param_idx) {
|
if let Some(arg) = call.positional.get(param_idx) {
|
||||||
let result = eval_expression(engine_state, caller_stack, arg)?;
|
let result = eval_expression(engine_state, caller_stack, arg)?;
|
||||||
callee_stack.add_var(var_id, result);
|
callee_stack.add_var(var_id, result);
|
||||||
|
} else if let Some(arg) = ¶m.default_value {
|
||||||
|
let result = eval_expression(engine_state, caller_stack, arg)?;
|
||||||
|
callee_stack.add_var(var_id, result);
|
||||||
} else {
|
} else {
|
||||||
callee_stack.add_var(var_id, Value::nothing(call.head));
|
callee_stack.add_var(var_id, Value::nothing(call.head));
|
||||||
}
|
}
|
||||||
|
@ -103,6 +106,10 @@ fn eval_call(
|
||||||
if let Some(arg) = &call_named.1 {
|
if let Some(arg) = &call_named.1 {
|
||||||
let result = eval_expression(engine_state, caller_stack, arg)?;
|
let result = eval_expression(engine_state, caller_stack, arg)?;
|
||||||
|
|
||||||
|
callee_stack.add_var(var_id, result);
|
||||||
|
} else if let Some(arg) = &named.default_value {
|
||||||
|
let result = eval_expression(engine_state, caller_stack, arg)?;
|
||||||
|
|
||||||
callee_stack.add_var(var_id, result);
|
callee_stack.add_var(var_id, result);
|
||||||
} else {
|
} else {
|
||||||
callee_stack.add_var(
|
callee_stack.add_var(
|
||||||
|
@ -126,6 +133,10 @@ fn eval_call(
|
||||||
span: call.head,
|
span: call.head,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
} else if let Some(arg) = &named.default_value {
|
||||||
|
let result = eval_expression(engine_state, caller_stack, arg)?;
|
||||||
|
|
||||||
|
callee_stack.add_var(var_id, result);
|
||||||
} else {
|
} else {
|
||||||
callee_stack.add_var(var_id, Value::Nothing { span: call.head })
|
callee_stack.add_var(var_id, Value::Nothing { span: call.head })
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,13 @@ pub enum ParseError {
|
||||||
#[diagnostic(code(nu::parser::extra_positional), url(docsrs), help("Usage: {0}"))]
|
#[diagnostic(code(nu::parser::extra_positional), url(docsrs), help("Usage: {0}"))]
|
||||||
ExtraPositional(String, #[label = "extra positional argument"] Span),
|
ExtraPositional(String, #[label = "extra positional argument"] Span),
|
||||||
|
|
||||||
|
#[error("Require positional parameter after optional parameter")]
|
||||||
|
#[diagnostic(code(nu::parser::required_after_optional), url(docsrs))]
|
||||||
|
RequiredAfterOptional(
|
||||||
|
String,
|
||||||
|
#[label = "required parameter {0} after optional parameter"] Span,
|
||||||
|
),
|
||||||
|
|
||||||
#[error("Unexpected end of code.")]
|
#[error("Unexpected end of code.")]
|
||||||
#[diagnostic(code(nu::parser::unexpected_eof), url(docsrs))]
|
#[diagnostic(code(nu::parser::unexpected_eof), url(docsrs))]
|
||||||
UnexpectedEof(String, #[label("expected closing {0}")] Span),
|
UnexpectedEof(String, #[label("expected closing {0}")] Span),
|
||||||
|
@ -246,6 +253,7 @@ impl ParseError {
|
||||||
ParseError::UnknownCommand(s) => *s,
|
ParseError::UnknownCommand(s) => *s,
|
||||||
ParseError::NonUtf8(s) => *s,
|
ParseError::NonUtf8(s) => *s,
|
||||||
ParseError::UnknownFlag(_, _, s) => *s,
|
ParseError::UnknownFlag(_, _, s) => *s,
|
||||||
|
ParseError::RequiredAfterOptional(_, s) => *s,
|
||||||
ParseError::UnknownType(s) => *s,
|
ParseError::UnknownType(s) => *s,
|
||||||
ParseError::MissingFlagParam(_, s) => *s,
|
ParseError::MissingFlagParam(_, s) => *s,
|
||||||
ParseError::ShortFlagBatchCantTakeArg(s) => *s,
|
ParseError::ShortFlagBatchCantTakeArg(s) => *s,
|
||||||
|
|
|
@ -176,6 +176,7 @@ pub fn parse_for(
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
var_id: Some(*var_id),
|
var_id: Some(*var_id),
|
||||||
|
default_value: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2677,6 +2677,7 @@ pub fn parse_row_condition(
|
||||||
desc: "row condition".into(),
|
desc: "row condition".into(),
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
working_set.add_block(block)
|
working_set.add_block(block)
|
||||||
|
@ -2742,11 +2743,14 @@ pub fn parse_signature_helper(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Box<Signature>, Option<ParseError>) {
|
) -> (Box<Signature>, Option<ParseError>) {
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
enum ParseMode {
|
enum ParseMode {
|
||||||
ArgMode,
|
ArgMode,
|
||||||
TypeMode,
|
TypeMode,
|
||||||
|
DefaultValueMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum Arg {
|
enum Arg {
|
||||||
Positional(PositionalArg, bool), // bool - required
|
Positional(PositionalArg, bool), // bool - required
|
||||||
RestPositional(PositionalArg),
|
RestPositional(PositionalArg),
|
||||||
|
@ -2756,7 +2760,13 @@ pub fn parse_signature_helper(
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
let source = working_set.get_span_contents(span);
|
let source = working_set.get_span_contents(span);
|
||||||
|
|
||||||
let (output, err) = lex(source, span.start, &[b'\n', b'\r', b','], &[b':'], false);
|
let (output, err) = lex(
|
||||||
|
source,
|
||||||
|
span.start,
|
||||||
|
&[b'\n', b'\r', b','],
|
||||||
|
&[b':', b'='],
|
||||||
|
false,
|
||||||
|
);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let mut args: Vec<Arg> = vec![];
|
let mut args: Vec<Arg> = vec![];
|
||||||
|
@ -2776,12 +2786,24 @@ pub fn parse_signature_helper(
|
||||||
ParseMode::ArgMode => {
|
ParseMode::ArgMode => {
|
||||||
parse_mode = ParseMode::TypeMode;
|
parse_mode = ParseMode::TypeMode;
|
||||||
}
|
}
|
||||||
ParseMode::TypeMode => {
|
ParseMode::TypeMode | ParseMode::DefaultValueMode => {
|
||||||
// We're seeing two types for the same thing for some reason, error
|
// We're seeing two types for the same thing for some reason, error
|
||||||
error =
|
error =
|
||||||
error.or_else(|| Some(ParseError::Expected("type".into(), span)));
|
error.or_else(|| Some(ParseError::Expected("type".into(), span)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if contents == b"=" {
|
||||||
|
match parse_mode {
|
||||||
|
ParseMode::ArgMode | ParseMode::TypeMode => {
|
||||||
|
parse_mode = ParseMode::DefaultValueMode;
|
||||||
|
}
|
||||||
|
ParseMode::DefaultValueMode => {
|
||||||
|
// We're seeing two default values for some reason, error
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::Expected("default value".into(), span))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
match parse_mode {
|
match parse_mode {
|
||||||
ParseMode::ArgMode => {
|
ParseMode::ArgMode => {
|
||||||
|
@ -2802,6 +2824,7 @@ pub fn parse_signature_helper(
|
||||||
short: None,
|
short: None,
|
||||||
required: false,
|
required: false,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
let short_flag = &flags[1];
|
let short_flag = &flags[1];
|
||||||
|
@ -2832,6 +2855,7 @@ pub fn parse_signature_helper(
|
||||||
short: Some(chars[0]),
|
short: Some(chars[0]),
|
||||||
required: false,
|
required: false,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
|
@ -2864,6 +2888,7 @@ pub fn parse_signature_helper(
|
||||||
short: Some(chars[0]),
|
short: Some(chars[0]),
|
||||||
required: false,
|
required: false,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
}));
|
}));
|
||||||
} else if contents.starts_with(b"(-") {
|
} else if contents.starts_with(b"(-") {
|
||||||
let short_flag = &contents[2..];
|
let short_flag = &contents[2..];
|
||||||
|
@ -2921,6 +2946,7 @@ pub fn parse_signature_helper(
|
||||||
name,
|
name,
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
))
|
))
|
||||||
|
@ -2935,6 +2961,7 @@ pub fn parse_signature_helper(
|
||||||
name,
|
name,
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
let name = String::from_utf8_lossy(contents).to_string();
|
let name = String::from_utf8_lossy(contents).to_string();
|
||||||
|
@ -2949,6 +2976,7 @@ pub fn parse_signature_helper(
|
||||||
name,
|
name,
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
var_id: Some(var_id),
|
var_id: Some(var_id),
|
||||||
|
default_value: None,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
))
|
))
|
||||||
|
@ -2982,6 +3010,97 @@ pub fn parse_signature_helper(
|
||||||
}
|
}
|
||||||
parse_mode = ParseMode::ArgMode;
|
parse_mode = ParseMode::ArgMode;
|
||||||
}
|
}
|
||||||
|
ParseMode::DefaultValueMode => {
|
||||||
|
if let Some(last) = args.last_mut() {
|
||||||
|
let (expression, err) =
|
||||||
|
parse_value(working_set, span, &SyntaxShape::Any);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
//TODO check if we're replacing a custom parameter already
|
||||||
|
match last {
|
||||||
|
Arg::Positional(
|
||||||
|
PositionalArg {
|
||||||
|
shape,
|
||||||
|
var_id,
|
||||||
|
default_value,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
required,
|
||||||
|
) => {
|
||||||
|
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
||||||
|
let var_type = working_set.get_variable(var_id);
|
||||||
|
match var_type {
|
||||||
|
Type::Unknown => {
|
||||||
|
working_set.set_variable_type(
|
||||||
|
var_id,
|
||||||
|
expression.ty.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
t => {
|
||||||
|
if t != &expression.ty {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::AssignmentMismatch(
|
||||||
|
"Default value wrong type".into(),
|
||||||
|
format!("default value not {}", t),
|
||||||
|
expression.span,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*shape = expression.ty.to_shape();
|
||||||
|
*default_value = Some(expression);
|
||||||
|
*required = false;
|
||||||
|
}
|
||||||
|
Arg::RestPositional(..) => {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::AssignmentMismatch(
|
||||||
|
"Rest parameter given default value".into(),
|
||||||
|
"can't have default value".into(),
|
||||||
|
expression.span,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Arg::Flag(Flag {
|
||||||
|
arg,
|
||||||
|
var_id,
|
||||||
|
default_value,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
||||||
|
let var_type = working_set.get_variable(var_id);
|
||||||
|
|
||||||
|
let expression_ty = expression.ty.clone();
|
||||||
|
let expression_span = expression.span;
|
||||||
|
|
||||||
|
*default_value = Some(expression);
|
||||||
|
|
||||||
|
// Flags with a boolean type are just present/not-present switches
|
||||||
|
if var_type != &Type::Bool {
|
||||||
|
match var_type {
|
||||||
|
Type::Unknown => {
|
||||||
|
*arg = Some(expression_ty.to_shape());
|
||||||
|
working_set
|
||||||
|
.set_variable_type(var_id, expression_ty);
|
||||||
|
}
|
||||||
|
t => {
|
||||||
|
if t != &expression_ty {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::AssignmentMismatch(
|
||||||
|
"Default value wrong type".into(),
|
||||||
|
format!("default value not {}", t),
|
||||||
|
expression_span,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parse_mode = ParseMode::ArgMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3030,6 +3149,14 @@ pub fn parse_signature_helper(
|
||||||
match arg {
|
match arg {
|
||||||
Arg::Positional(positional, required) => {
|
Arg::Positional(positional, required) => {
|
||||||
if required {
|
if required {
|
||||||
|
if !sig.optional_positional.is_empty() {
|
||||||
|
error = error.or_else(|| {
|
||||||
|
Some(ParseError::RequiredAfterOptional(
|
||||||
|
positional.name.clone(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
sig.required_positional.push(positional)
|
sig.required_positional.push(positional)
|
||||||
} else {
|
} else {
|
||||||
sig.optional_positional.push(positional)
|
sig.optional_positional.push(positional)
|
||||||
|
@ -3379,6 +3506,7 @@ pub fn parse_block_expression(
|
||||||
name: "$it".into(),
|
name: "$it".into(),
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
output.signature = Box::new(signature);
|
output.signature = Box::new(signature);
|
||||||
}
|
}
|
||||||
|
@ -4503,6 +4631,7 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
|
||||||
name: "$in".into(),
|
name: "$in".into(),
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
shape: SyntaxShape::Any,
|
shape: SyntaxShape::Any,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut expr = expr.clone();
|
let mut expr = expr.clone();
|
||||||
|
|
|
@ -218,6 +218,7 @@ fn deserialize_argument(reader: argument::Reader) -> Result<PositionalArg, Shell
|
||||||
desc: desc.to_string(),
|
desc: desc.to_string(),
|
||||||
shape,
|
shape,
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +263,7 @@ fn deserialize_flag(reader: flag::Reader) -> Result<Flag, ShellError> {
|
||||||
required,
|
required,
|
||||||
desc: desc.to_string(),
|
desc: desc.to_string(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::Expression;
|
use super::Expression;
|
||||||
use crate::{DeclId, Span, Spanned};
|
use crate::{DeclId, Span, Spanned};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
/// identifier of the declaration to call
|
/// identifier of the declaration to call
|
||||||
pub decl_id: DeclId,
|
pub decl_id: DeclId,
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl CellPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct FullCellPath {
|
pub struct FullCellPath {
|
||||||
pub head: Expression,
|
pub head: Expression,
|
||||||
pub tail: Vec<PathMember>,
|
pub tail: Vec<PathMember>,
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use chrono::FixedOffset;
|
use chrono::FixedOffset;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{Call, CellPath, Expression, FullCellPath, Operator, RangeOperator};
|
use super::{Call, CellPath, Expression, FullCellPath, Operator, RangeOperator};
|
||||||
use crate::{ast::ImportPattern, BlockId, Signature, Span, Spanned, Unit, VarId};
|
use crate::{ast::ImportPattern, BlockId, Signature, Span, Spanned, Unit, VarId};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{Expr, Operator};
|
use super::{Expr, Operator};
|
||||||
use crate::ast::ImportPattern;
|
use crate::ast::ImportPattern;
|
||||||
use crate::{engine::StateWorkingSet, BlockId, Signature, Span, Type, VarId, IN_VARIABLE_ID};
|
use crate::{engine::StateWorkingSet, BlockId, Signature, Span, Type, VarId, IN_VARIABLE_ID};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Expression {
|
pub struct Expression {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{span, OverlayId, Span};
|
use crate::{span, OverlayId, Span};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ImportPatternMember {
|
pub enum ImportPatternMember {
|
||||||
Glob { span: Span },
|
Glob { span: Span },
|
||||||
Name { name: Vec<u8>, span: Span },
|
Name { name: Vec<u8>, span: Span },
|
||||||
List { names: Vec<(Vec<u8>, Span)> },
|
List { names: Vec<(Vec<u8>, Span)> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ImportPatternHead {
|
pub struct ImportPatternHead {
|
||||||
pub name: Vec<u8>,
|
pub name: Vec<u8>,
|
||||||
pub id: Option<OverlayId>,
|
pub id: Option<OverlayId>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ImportPattern {
|
pub struct ImportPattern {
|
||||||
pub head: ImportPatternHead,
|
pub head: ImportPatternHead,
|
||||||
pub members: Vec<ImportPatternMember>,
|
pub members: Vec<ImportPatternMember>,
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub enum RangeInclusion {
|
||||||
RightExclusive,
|
RightExclusive,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct RangeOperator {
|
pub struct RangeOperator {
|
||||||
pub inclusion: RangeInclusion,
|
pub inclusion: RangeInclusion,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::ast::Call;
|
use crate::ast::Call;
|
||||||
|
use crate::ast::Expression;
|
||||||
use crate::engine::Command;
|
use crate::engine::Command;
|
||||||
use crate::engine::EngineState;
|
use crate::engine::EngineState;
|
||||||
use crate::engine::Stack;
|
use crate::engine::Stack;
|
||||||
|
@ -10,24 +11,28 @@ use crate::PipelineData;
|
||||||
use crate::SyntaxShape;
|
use crate::SyntaxShape;
|
||||||
use crate::VarId;
|
use crate::VarId;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
pub long: String,
|
pub long: String,
|
||||||
pub short: Option<char>,
|
pub short: Option<char>,
|
||||||
pub arg: Option<SyntaxShape>,
|
pub arg: Option<SyntaxShape>,
|
||||||
pub required: bool,
|
pub required: bool,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
|
|
||||||
// For custom commands
|
// For custom commands
|
||||||
pub var_id: Option<VarId>,
|
pub var_id: Option<VarId>,
|
||||||
|
pub default_value: Option<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct PositionalArg {
|
pub struct PositionalArg {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
pub shape: SyntaxShape,
|
pub shape: SyntaxShape,
|
||||||
|
|
||||||
// For custom commands
|
// For custom commands
|
||||||
pub var_id: Option<VarId>,
|
pub var_id: Option<VarId>,
|
||||||
|
pub default_value: Option<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -123,6 +128,7 @@ impl Signature {
|
||||||
desc: "Display this help message".into(),
|
desc: "Display this help message".into(),
|
||||||
required: false,
|
required: false,
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Signature {
|
Signature {
|
||||||
|
@ -160,6 +166,7 @@ impl Signature {
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
shape: shape.into(),
|
shape: shape.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -177,6 +184,7 @@ impl Signature {
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
shape: shape.into(),
|
shape: shape.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -193,6 +201,7 @@ impl Signature {
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
shape: shape.into(),
|
shape: shape.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -215,6 +224,7 @@ impl Signature {
|
||||||
required: false,
|
required: false,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -237,6 +247,7 @@ impl Signature {
|
||||||
required: true,
|
required: true,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -258,6 +269,7 @@ impl Signature {
|
||||||
required: false,
|
required: false,
|
||||||
desc: desc.into(),
|
desc: desc.into(),
|
||||||
var_id: None,
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
|
@ -2,7 +2,7 @@ use miette::SourceSpan;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// A spanned area of interest, generic over what kind of thing is of interest
|
/// A spanned area of interest, generic over what kind of thing is of interest
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct Spanned<T>
|
pub struct Spanned<T>
|
||||||
where
|
where
|
||||||
T: Clone + std::fmt::Debug,
|
T: Clone + std::fmt::Debug,
|
||||||
|
|
|
@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use crate::SyntaxShape;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Int,
|
Int,
|
||||||
|
@ -27,6 +29,34 @@ pub enum Type {
|
||||||
Signature,
|
Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn to_shape(&self) -> SyntaxShape {
|
||||||
|
match self {
|
||||||
|
Type::Int => SyntaxShape::Int,
|
||||||
|
Type::Float => SyntaxShape::Number,
|
||||||
|
Type::Range => SyntaxShape::Range,
|
||||||
|
Type::Bool => SyntaxShape::Boolean,
|
||||||
|
Type::String => SyntaxShape::String,
|
||||||
|
Type::Block => SyntaxShape::Block(None), // FIXME needs more accuracy
|
||||||
|
Type::CellPath => SyntaxShape::CellPath,
|
||||||
|
Type::Duration => SyntaxShape::Duration,
|
||||||
|
Type::Date => SyntaxShape::DateTime,
|
||||||
|
Type::Filesize => SyntaxShape::Filesize,
|
||||||
|
Type::List(x) => SyntaxShape::List(Box::new(x.to_shape())),
|
||||||
|
Type::Number => SyntaxShape::Number,
|
||||||
|
Type::Nothing => SyntaxShape::Any,
|
||||||
|
Type::Record(_) => SyntaxShape::Record,
|
||||||
|
Type::Table => SyntaxShape::Table,
|
||||||
|
Type::ListStream => SyntaxShape::List(Box::new(SyntaxShape::Any)),
|
||||||
|
Type::Unknown => SyntaxShape::Any,
|
||||||
|
Type::Error => SyntaxShape::Any,
|
||||||
|
Type::Binary => SyntaxShape::Binary,
|
||||||
|
Type::Custom => SyntaxShape::Custom(Box::new(SyntaxShape::Any), String::new()),
|
||||||
|
Type::Signature => SyntaxShape::Signature,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Type {
|
impl Display for Type {
|
||||||
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 {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#[derive(Debug, Clone, Copy)]
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Unit {
|
pub enum Unit {
|
||||||
// Filesize units: metric
|
// Filesize units: metric
|
||||||
Byte,
|
Byte,
|
||||||
|
|
|
@ -46,7 +46,8 @@ fn test_signature_chained() {
|
||||||
name: "required".to_string(),
|
name: "required".to_string(),
|
||||||
desc: "required description".to_string(),
|
desc: "required description".to_string(),
|
||||||
shape: SyntaxShape::String,
|
shape: SyntaxShape::String,
|
||||||
var_id: None
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -55,7 +56,8 @@ fn test_signature_chained() {
|
||||||
name: "optional".to_string(),
|
name: "optional".to_string(),
|
||||||
desc: "optional description".to_string(),
|
desc: "optional description".to_string(),
|
||||||
shape: SyntaxShape::String,
|
shape: SyntaxShape::String,
|
||||||
var_id: None
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -64,7 +66,8 @@ fn test_signature_chained() {
|
||||||
name: "rest".to_string(),
|
name: "rest".to_string(),
|
||||||
desc: "rest description".to_string(),
|
desc: "rest description".to_string(),
|
||||||
shape: SyntaxShape::String,
|
shape: SyntaxShape::String,
|
||||||
var_id: None
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -76,7 +79,8 @@ fn test_signature_chained() {
|
||||||
arg: Some(SyntaxShape::String),
|
arg: Some(SyntaxShape::String),
|
||||||
required: true,
|
required: true,
|
||||||
desc: "required named description".to_string(),
|
desc: "required named description".to_string(),
|
||||||
var_id: None
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -88,7 +92,8 @@ fn test_signature_chained() {
|
||||||
arg: Some(SyntaxShape::String),
|
arg: Some(SyntaxShape::String),
|
||||||
required: true,
|
required: true,
|
||||||
desc: "required named description".to_string(),
|
desc: "required named description".to_string(),
|
||||||
var_id: None
|
var_id: None,
|
||||||
|
default_value: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,3 +287,66 @@ fn bool_variable() -> TestResult {
|
||||||
fn bool_variable2() -> TestResult {
|
fn bool_variable2() -> TestResult {
|
||||||
run_test(r#"$false"#, "false")
|
run_test(r#"$false"#, "false")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value1() -> TestResult {
|
||||||
|
run_test(r#"def foo [x = 3] { $x }; foo"#, "3")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value2() -> TestResult {
|
||||||
|
run_test(r#"def foo [x: int = 3] { $x }; foo"#, "3")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value3() -> TestResult {
|
||||||
|
run_test(r#"def foo [--x = 3] { $x }; foo"#, "3")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value4() -> TestResult {
|
||||||
|
run_test(r#"def foo [--x: int = 3] { $x }; foo"#, "3")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value5() -> TestResult {
|
||||||
|
run_test(r#"def foo [x = 3] { $x }; foo 10"#, "10")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value6() -> TestResult {
|
||||||
|
run_test(r#"def foo [x: int = 3] { $x }; foo 10"#, "10")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value7() -> TestResult {
|
||||||
|
run_test(r#"def foo [--x = 3] { $x }; foo --x 10"#, "10")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value8() -> TestResult {
|
||||||
|
run_test(r#"def foo [--x: int = 3] { $x }; foo --x 10"#, "10")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value9() -> TestResult {
|
||||||
|
fail_test(r#"def foo [--x = 3] { $x }; foo --x a"#, "expected int")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value10() -> TestResult {
|
||||||
|
fail_test(r#"def foo [x = 3] { $x }; foo a"#, "expected int")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value11() -> TestResult {
|
||||||
|
fail_test(
|
||||||
|
r#"def foo [x = 3, y] { $x }; foo a"#,
|
||||||
|
"after optional parameter",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value12() -> TestResult {
|
||||||
|
fail_test(r#"def foo [--x:int = "a"] { $x }"#, "default value not int")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue