Custom switch support

This commit is contained in:
JT 2021-10-12 17:49:17 +13:00
parent 60f0394106
commit 5f14faf4b4
4 changed files with 88 additions and 9 deletions

View File

@ -62,11 +62,13 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<V
}
for named in decl.signature().named {
let var_id = named
.var_id
.expect("internal error: all custom parameters must have var_ids");
let mut found = false;
for call_named in &call.named {
if call_named.0.item == named.long {
let var_id = named
.var_id
.expect("internal error: all custom parameters must have var_ids");
if let Some(arg) = &call_named.1 {
let result = eval_expression(&state, arg)?;
@ -80,8 +82,19 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<V
},
)
}
found = true;
}
}
if !found && named.arg.is_none() {
state.add_var(
var_id,
Value::Bool {
val: false,
span: call.head,
},
)
}
}
let engine_state = state.engine_state.borrow();
let block = engine_state.get_block(block_id);

View File

@ -1664,6 +1664,7 @@ pub fn parse_shape_name(
b"variable" => SyntaxShape::Variable,
b"signature" => SyntaxShape::Signature,
b"expr" => SyntaxShape::Expression,
b"bool" => SyntaxShape::Boolean,
_ => return (SyntaxShape::Any, Some(ParseError::UnknownType(span))),
};
@ -1671,10 +1672,17 @@ pub fn parse_shape_name(
}
pub fn parse_type(_working_set: &StateWorkingSet, bytes: &[u8]) -> Type {
if bytes == b"int" {
Type::Int
} else {
Type::Unknown
match bytes {
b"int" => Type::Int,
b"bool" => Type::Bool,
b"string" => Type::String,
b"block" => Type::Block,
b"float" => Type::Float,
b"filesize" => Type::Filesize,
b"binary" => Type::Binary,
b"date" => Type::Date,
_ => Type::Unknown,
}
}
@ -2153,8 +2161,11 @@ pub fn parse_signature_helper(
*shape = syntax_shape;
}
Arg::Flag(Flag { arg, var_id, .. }) => {
working_set.set_variable_type(var_id.expect("internal error: all custom parameters must have var_ids"), syntax_shape.to_type());
*arg = Some(syntax_shape)
// Flags with a boolean type are just present/not-present switches
if syntax_shape != SyntaxShape::Boolean {
working_set.set_variable_type(var_id.expect("internal error: all custom parameters must have var_ids"), syntax_shape.to_type());
*arg = Some(syntax_shape)
}
}
}
}
@ -2689,6 +2700,25 @@ pub fn parse_value(
error,
)
}
SyntaxShape::Boolean => {
// Redundant, though we catch bad boolean parses here
if bytes == b"$true" || bytes == b"$false" {
(
Expression {
expr: Expr::Bool(true),
span,
ty: Type::Bool,
custom_completion: None,
},
None,
)
} else {
(
garbage(span),
Some(ParseError::Expected("bool".into(), span)),
)
}
}
SyntaxShape::Any => {
if bytes.starts_with(b"[") {
parse_value(working_set, span, &SyntaxShape::Table)

View File

@ -73,6 +73,9 @@ pub enum SyntaxShape {
/// A general expression, eg `1 + 2` or `foo --bar`
Expression,
/// A boolean value
Boolean,
/// A custom shape with custom completion logic
Custom(Box<SyntaxShape>, String),
}
@ -102,6 +105,7 @@ impl SyntaxShape {
SyntaxShape::Operator => Type::Unknown,
SyntaxShape::Range => Type::Unknown,
SyntaxShape::RowCondition => Type::Bool,
SyntaxShape::Boolean => Type::Bool,
SyntaxShape::Signature => Type::Unknown,
SyntaxShape::String => Type::String,
SyntaxShape::Table => Type::List(Box::new(Type::Unknown)), // FIXME

View File

@ -727,3 +727,35 @@ fn flag_param_value() -> TestResult {
fn do_rest_args() -> TestResult {
run_test(r#"(do { |...rest| $rest } 1 2).1 + 10"#, "12")
}
#[test]
fn custom_switch1() -> TestResult {
run_test(
r#"def florb [ --dry-run: bool ] { if ($dry-run) { "foo" } else { "bar" } }; florb --dry-run"#,
"foo",
)
}
#[test]
fn custom_switch2() -> TestResult {
run_test(
r#"def florb [ --dry-run: bool ] { if ($dry-run) { "foo" } else { "bar" } }; florb"#,
"bar",
)
}
#[test]
fn custom_switch3() -> TestResult {
run_test(
r#"def florb [ --dry-run ] { if ($dry-run) { "foo" } else { "bar" } }; florb --dry-run"#,
"foo",
)
}
#[test]
fn custom_switch4() -> TestResult {
run_test(
r#"def florb [ --dry-run ] { if ($dry-run) { "foo" } else { "bar" } }; florb"#,
"bar",
)
}