feat(stdlib): added std::regex for regex matching

This commit is contained in:
Byson94
2025-09-23 20:00:21 +05:30
parent 9a92276bd0
commit 01e6f2d6b8
5 changed files with 134 additions and 2 deletions

View File

@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- `state` command to print the current poll/listen variable state.
- `m` as another duration unit for minute.
- `std::regex` library for regex matching.
### Fixed

1
Cargo.lock generated
View File

@@ -1843,6 +1843,7 @@ dependencies = [
"log",
"nix",
"once_cell",
"regex",
"rhai",
"rhai_trace",
"serde",

View File

@@ -23,4 +23,5 @@ nix = { workspace = true, features = ["process", "fs", "signal"] }
libc.workspace = true
# error handling
rhai_trace = "0.2.0"
codespan-reporting.workspace = true
codespan-reporting.workspace = true
regex.workspace = true

View File

@@ -1,23 +1,28 @@
pub mod command;
pub mod env;
pub mod monitor;
pub mod regex;
pub mod text;
use rhai::exported_module;
use rhai::module_resolvers::StaticModuleResolver;
pub fn register_stdlib(resolver: &mut StaticModuleResolver) {
use crate::providers::stdlib::{command::command, env::env, monitor::monitor, text::text};
use crate::providers::stdlib::{
command::command, env::env, monitor::monitor, regex::regex_lib, text::text,
};
// adding modules
let text_mod = exported_module!(text);
let env_mod = exported_module!(env);
let monitor_mod = exported_module!(monitor);
let command_mod = exported_module!(command);
let regex_mod = exported_module!(regex_lib);
// inserting modules
resolver.insert("std::text", text_mod);
resolver.insert("std::env", env_mod);
resolver.insert("std::monitor", monitor_mod);
resolver.insert("std::command", command_mod);
resolver.insert("std::regex", regex_mod);
}

View File

@@ -0,0 +1,124 @@
use regex::Regex;
use rhai::plugin::*;
use rhai::{Array, Dynamic};
/// A module providing regular expression support.
#[export_module]
pub mod regex_lib {
/// Checks if a regex pattern matches the given text.
///
/// # Arguments
///
/// * `text` - A string to be matched with the pattern.
/// * `pattern` - The pattern to match on the string.
///
/// # Returns
///
/// Returns a boolean (true/false) based on if the pattern is matched on the text provided.
///
/// # Example
///
/// ```javascript
/// import "std::regex" as regex;
///
/// let result = regex::is_match("This is an example!", "example");
/// if result == true {
/// print("The pattern is matched!");
/// }
/// ```
#[rhai_fn(return_raw)]
pub fn is_match(text: &str, pattern: &str) -> Result<bool, Box<EvalAltResult>> {
let re = Regex::new(pattern).map_err(|e| format!("Failed to read regex pattern: {}", e))?;
Ok(re.is_match(text))
}
/// Returns the first match of a regex pattern in the text.
///
/// # Arguments
///
/// * `text` - A string to be matched with the pattern.
/// * `pattern` - The pattern to match on the string.
///
/// # Returns
///
/// Returns a string which is the first match of a regex pattern.
///
/// # Example
///
/// ```javascript
/// import "std::regex" as regex;
///
/// let result = regex::find("This is an example!", `\be\w*\b`);
/// print(result); // output: "example"
/// ```
#[rhai_fn(return_raw)]
pub fn find(text: &str, pattern: &str) -> Result<String, Box<EvalAltResult>> {
let re = Regex::new(pattern).map_err(|e| format!("Failed to read regex pattern: {}", e))?;
match re.find(text).map(|m| m.as_str().to_string()) {
Some(s) => Ok(s),
None => Ok(String::new()),
}
}
/// Returns all matches of a regex pattern in the text.
///
/// # Arguments
///
/// * `text` - A string to be matched with the pattern.
/// * `pattern` - The pattern to match on the string.
///
/// # Returns
///
/// Returns aan array of strings containing the all the things that match the regex pattern in the provided text.
///
/// # Example
///
/// # Example
///
/// ```javascript
/// import "std::regex" as regex;
///
/// let result = regex::find("This is an example!", `\be\w*\b`);
/// print(result); // output: ["example"]
/// ```
#[rhai_fn(return_raw)]
pub fn find_all(text: &str, pattern: &str) -> Result<Array, Box<EvalAltResult>> {
let re = Regex::new(pattern).map_err(|e| format!("Failed to read regex pattern: {}", e))?;
let results: Array = re
.find_iter(text)
.map(|m| Dynamic::from(m.as_str().to_string()))
.collect();
Ok(results)
}
/// Replaces all matches of a regex pattern with a replacement string.
///
/// # Arguments
///
/// * `text` - A string to be matched with the pattern.
/// * `pattern` - The pattern to match on the string.
/// * `replacement` - A string that the matched pattern will get replaced with.
///
/// # Returns
///
/// Returns the provided text with the matches of the regex pattern replaced with the provided replacement argument.
///
/// # Example
///
/// ```javascript
/// import "std::regex" as regex;
///
/// let result = regex::replace("This is an example!", "an example", "a test");
/// print(result); // output: "This is a test!"
/// ```
#[rhai_fn(return_raw)]
pub fn replace(
text: &str,
pattern: &str,
replacement: &str,
) -> Result<String, Box<EvalAltResult>> {
let re = Regex::new(pattern).map_err(|e| format!("Failed to read regex pattern: {}", e))?;
Ok(re.replace_all(text, replacement).to_string())
}
}