Add several functions for simple expressions (#407)

Co-authored-by: elkowar <5300871+elkowar@users.noreply.github.com>
Co-authored-by: MartinJM <>
This commit is contained in:
MartinJM 2022-04-19 13:29:17 +02:00 committed by GitHub
parent 7648eb8086
commit 0f9847c518
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 2 deletions

View file

@ -27,6 +27,7 @@ All notable changes to eww will be listed here, starting at changes since versio
- Add `scroll` widget (By: viandoxdev)
- Add `notification` window type
- Add drag and drop functionality to eventbox
- Add `search`, `captures`, `stringlength`, `arraylength` and `objectlength` functions for expressions (By: MartinJM, ElKowar)
### Notable Internal changes
- Rework state management completely, now making local state and dynamic widget hierarchy changes possible.

View file

@ -14,7 +14,7 @@ pub struct ConversionError {
}
impl ConversionError {
fn new(value: DynVal, target_type: &'static str, source: impl std::error::Error + 'static + Sync + Send) -> Self {
pub fn new(value: DynVal, target_type: &'static str, source: impl std::error::Error + 'static + Sync + Send) -> Self {
ConversionError { value, target_type, source: Some(Box::new(source)) }
}
}
@ -214,6 +214,22 @@ impl DynVal {
serde_json::from_str::<serde_json::Value>(&self.0)
.map_err(|e| ConversionError::new(self.clone(), "json-value", Box::new(e)))
}
pub fn as_json_array(&self) -> Result<Vec<serde_json::Value>> {
serde_json::from_str::<serde_json::Value>(&self.0)
.map_err(|e| ConversionError::new(self.clone(), "json-value", Box::new(e)))?
.as_array()
.cloned()
.ok_or_else(|| ConversionError { value: self.clone(), target_type: "json-array", source: None })
}
pub fn as_json_object(&self) -> Result<serde_json::Map<String, serde_json::Value>> {
serde_json::from_str::<serde_json::Value>(&self.0)
.map_err(|e| ConversionError::new(self.clone(), "json-value", Box::new(e)))?
.as_object()
.cloned()
.ok_or_else(|| ConversionError { value: self.clone(), target_type: "json-object", source: None })
}
}
#[cfg(test)]

View file

@ -5,7 +5,10 @@ use crate::{
dynval::{ConversionError, DynVal},
};
use eww_shared_util::{Span, Spanned, VarName};
use std::{collections::HashMap, convert::TryFrom};
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
};
#[derive(Debug, thiserror::Error)]
pub enum EvalError {
@ -276,6 +279,46 @@ fn call_expr_function(name: &str, args: Vec<DynVal>) -> Result<DynVal, EvalError
}
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
"search" => match args.as_slice() {
[string, pattern] => {
use serde_json::Value;
let string = string.as_string()?;
let pattern = regex::Regex::new(&pattern.as_string()?)?;
Ok(Value::Array(pattern.find_iter(&string).map(|x| Value::String(x.as_str().to_string())).collect())
.try_into()?)
}
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
"captures" => match args.as_slice() {
[string, pattern] => {
use serde_json::Value;
let string = string.as_string()?;
let pattern = regex::Regex::new(&pattern.as_string()?)?;
Ok(Value::Array(
pattern
.captures_iter(&string)
.map(|captures| {
Value::Array(captures.iter().flatten().map(|x| Value::String(x.as_str().to_string())).collect())
})
.collect(),
)
.try_into()?)
}
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
"strlength" => match args.as_slice() {
[string] => Ok(DynVal::from(string.as_string()?.len() as i32)),
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
"arraylength" => match args.as_slice() {
[json] => Ok(DynVal::from(json.as_json_array()?.len() as i32)),
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
"objectlength" => match args.as_slice() {
[json] => Ok(DynVal::from(json.as_json_object()?.len() as i32)),
_ => Err(EvalError::WrongArgCount(name.to_string())),
},
_ => Err(EvalError::UnknownFunction(name.to_string())),
}
}

View file

@ -32,4 +32,8 @@ Supported currently are the following features:
- some function calls:
- `round(number, decimal_digits)`: Round a number to the given amount of decimals
- `replace(string, regex, replacement)`: Replace matches of a given regex in a string
- `search(string, regex)`: Search for a given regex in a string (returns array)
- `captures(string, regex)`: Get the captures of a given regex in a string (returns array)
- `hex_decode(string)`: Hex decodes the string
- `length(value)`: Gets the length of the value, as string length, json array length, or json object length