From 6a64a286291456984011c4fb160def106ee55dff Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Thu, 5 Jan 2023 20:21:29 +0100 Subject: [PATCH] Add support for null safe indexing e.g. for arrays (#631) * Add support for null safe indexing e.g. for arrays This follows the JavaScript syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#syntax * add docs * Add test for safe access index to non indexable Co-authored-by: Josiah Hilden Co-authored-by: Josiah Hilden Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> --- CHANGELOG.md | 1 + crates/simplexpr/src/eval.rs | 3 +++ crates/simplexpr/src/simplexpr_parser.lalrpop | 4 ++++ docs/src/expression_language.md | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c7ba21..2af69e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to eww will be listed here, starting at changes since versio ### Features - Add support for safe access (`?.`) in simplexpr (By: oldwomanjosiah) - Allow floating-point numbers in percentages for window-geometry +- Add support for safe access with index (`?.[n]`) (By: ModProg) - Made `and`, `or` and `?:` lazily evaluated in simplexpr (By: ModProg) ## [0.4.0] (04.09.2022) diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs index 07c0066..3b75048 100644 --- a/crates/simplexpr/src/eval.rs +++ b/crates/simplexpr/src/eval.rs @@ -401,6 +401,9 @@ mod tests { string_to_string(r#""Hello""#) => Ok(DynVal::from("Hello".to_string())), safe_access_to_existing(r#"{ "a": { "b": 2 } }.a?.b"#) => Ok(DynVal::from(2)), safe_access_to_missing(r#"{ "a": { "b": 2 } }.b?.b"#) => Ok(DynVal::from(&serde_json::Value::Null)), + safe_access_index_to_existing(r#"[1, 2]?.[1]"#) => Ok(DynVal::from(2)), + safe_access_index_to_missing(r#""null"?.[1]"#) => Ok(DynVal::from(&serde_json::Value::Null)), + safe_access_index_to_non_indexable(r#"32?.[1]"#) => Err(super::EvalError::CannotIndex("32".to_string())), normal_access_to_existing(r#"{ "a": { "b": 2 } }.a.b"#) => Ok(DynVal::from(2)), normal_access_to_missing(r#"{ "a": { "b": 2 } }.b.b"#) => Err(super::EvalError::CannotIndex("null".to_string())), lazy_evaluation_and(r#"false && "null".test"#) => Ok(DynVal::from(false)), diff --git a/crates/simplexpr/src/simplexpr_parser.lalrpop b/crates/simplexpr/src/simplexpr_parser.lalrpop index c215ee4..ce4c91e 100644 --- a/crates/simplexpr/src/simplexpr_parser.lalrpop +++ b/crates/simplexpr/src/simplexpr_parser.lalrpop @@ -76,9 +76,13 @@ pub Expr: SimplExpr = { #[precedence(level="1")] #[assoc(side="right")] "(" > ")" => FunctionCall(Span(l, r, fid), ident, args), + "[" "]" => { JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(index)) }, + "?." "[" "]" => { + JsonAccess(Span(l, r, fid), AccessType::Safe, b(value), b(index)) + }, "." => { JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(Literal(index.into()))) diff --git a/docs/src/expression_language.md b/docs/src/expression_language.md index e00da1c..f11c8ee 100644 --- a/docs/src/expression_language.md +++ b/docs/src/expression_language.md @@ -26,7 +26,7 @@ Supported currently are the following features: - elvis operator (`?:`) - if the left side is `""` or a JSON `null`, then returns the right side, otherwise evaluates to the left side. -- Safe Access operator (`?.`) +- Safe Access operator (`?.`) or (`?.[index]`) - if the left side is `""` or a JSON `null`, then return `null`. Otherwise, attempt to index. - This can still cause an error to occur if the left hand side exists but is