2025-10-06 10:30:17 -03:00
|
|
|
use rhai::Dynamic;
|
|
|
|
|
use rhai::Engine;
|
|
|
|
|
|
|
|
|
|
pub fn last_keyword(engine: &mut Engine) {
|
|
|
|
|
engine
|
|
|
|
|
.register_custom_syntax(&["LAST", "(", "$expr$", ")"], false, {
|
|
|
|
|
move |context, inputs| {
|
|
|
|
|
let input_string = context.eval_expression_tree(&inputs[0])?;
|
|
|
|
|
let input_str = input_string.to_string();
|
|
|
|
|
|
2025-11-04 23:11:33 -03:00
|
|
|
// Handle empty string case first
|
|
|
|
|
if input_str.trim().is_empty() {
|
|
|
|
|
return Ok(Dynamic::from(""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Split on any whitespace and filter out empty strings
|
|
|
|
|
let words: Vec<&str> = input_str
|
2025-10-06 10:30:17 -03:00
|
|
|
.split_whitespace()
|
2025-11-04 23:11:33 -03:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
// Get the last non-empty word
|
|
|
|
|
let last_word = words.last().map(|s| *s).unwrap_or("");
|
2025-10-06 10:30:17 -03:00
|
|
|
|
2025-11-04 23:11:33 -03:00
|
|
|
Ok(Dynamic::from(last_word.to_string()))
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use rhai::{Engine, Scope};
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_empty_string() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\"\")").unwrap();
|
|
|
|
|
assert_eq!(result, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_multiple_spaces() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\"hello world \")").unwrap();
|
|
|
|
|
assert_eq!(result, "world");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_tabs_and_newlines() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-11-04 23:11:33 -03:00
|
|
|
let result: String = engine.eval(r#"LAST("hello\tworld\n")"#).unwrap();
|
2025-10-06 10:30:17 -03:00
|
|
|
assert_eq!(result, "world");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_with_variable() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
|
|
|
|
let mut scope = Scope::new();
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
scope.push("text", "this is a test");
|
|
|
|
|
let result: String = engine.eval_with_scope(&mut scope, "LAST(text)").unwrap();
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
assert_eq!(result, "test");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_whitespace_only() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\" \")").unwrap();
|
|
|
|
|
assert_eq!(result, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_mixed_whitespace() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-11-04 23:11:33 -03:00
|
|
|
let result: String = engine.eval(r#"LAST("hello\t \n world \t final")"#).unwrap();
|
2025-10-06 10:30:17 -03:00
|
|
|
assert_eq!(result, "final");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_expression() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\"hello\" + \" \" + \"world\")").unwrap();
|
|
|
|
|
assert_eq!(result, "world");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_unicode() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\"hello 世界 мир world\")").unwrap();
|
|
|
|
|
assert_eq!(result, "world");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_in_expression() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: bool = engine.eval("LAST(\"hello world\") == \"world\"").unwrap();
|
|
|
|
|
assert!(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_complex_scenario() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
|
|
|
|
let mut scope = Scope::new();
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
scope.push("sentence", "The quick brown fox jumps over the lazy dog");
|
|
|
|
|
let result: String = engine.eval_with_scope(&mut scope, "LAST(sentence)").unwrap();
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
assert_eq!(result, "dog");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-10-11 12:29:03 -03:00
|
|
|
#[should_panic]
|
2025-10-06 10:30:17 -03:00
|
|
|
fn test_last_keyword_missing_parentheses() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let _: String = engine.eval("LAST \"hello world\"").unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-10-11 12:29:03 -03:00
|
|
|
#[should_panic]
|
2025-10-06 10:30:17 -03:00
|
|
|
fn test_last_keyword_missing_closing_parenthesis() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let _: String = engine.eval("LAST(\"hello world\"").unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-10-11 12:29:03 -03:00
|
|
|
#[should_panic]
|
2025-10-06 10:30:17 -03:00
|
|
|
fn test_last_keyword_missing_opening_parenthesis() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let _: String = engine.eval("LAST \"hello world\")").unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_dynamic_type() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result = engine.eval::<Dynamic>("LAST(\"test string\")").unwrap();
|
|
|
|
|
assert!(result.is::<String>());
|
|
|
|
|
assert_eq!(result.to_string(), "string");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_nested_expression() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(\"The result is: \" + \"hello world\")").unwrap();
|
|
|
|
|
assert_eq!(result, "world");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod integration_tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_in_script() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let script = r#"
|
|
|
|
|
let sentence1 = "first second third";
|
|
|
|
|
let sentence2 = "alpha beta gamma";
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let last1 = LAST(sentence1);
|
|
|
|
|
let last2 = LAST(sentence2);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
last1 + " and " + last2
|
|
|
|
|
"#;
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval(script).unwrap();
|
|
|
|
|
assert_eq!(result, "third and gamma");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_with_function() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
engine.register_fn("get_name", || -> String { "john doe".to_string() });
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval("LAST(get_name())").unwrap();
|
|
|
|
|
assert_eq!(result, "doe");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_last_keyword_multiple_calls() {
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
last_keyword(&mut engine);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let script = r#"
|
|
|
|
|
let text1 = "apple banana cherry";
|
|
|
|
|
let text2 = "cat dog elephant";
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result1 = LAST(text1);
|
|
|
|
|
let result2 = LAST(text2);
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
result1 + "-" + result2
|
|
|
|
|
"#;
|
2025-10-11 12:29:03 -03:00
|
|
|
|
2025-10-06 10:30:17 -03:00
|
|
|
let result: String = engine.eval(script).unwrap();
|
|
|
|
|
assert_eq!(result, "cherry-elephant");
|
|
|
|
|
}
|
2025-10-11 12:29:03 -03:00
|
|
|
}
|