...
This commit is contained in:
32
rhai_engine/examples/loadscripts/scripts/math_utils.rhai
Normal file
32
rhai_engine/examples/loadscripts/scripts/math_utils.rhai
Normal file
@@ -0,0 +1,32 @@
|
||||
// Math utility functions for Tera templates
|
||||
|
||||
// Format a number with commas as thousands separators
|
||||
fn format_number(num) {
|
||||
let str = num.to_string();
|
||||
let result = "";
|
||||
let len = str.len;
|
||||
|
||||
for i in 0..len {
|
||||
if i > 0 && (len - i) % 3 == 0 {
|
||||
result += ",";
|
||||
}
|
||||
result += str.substr(i, 1);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// Calculate percentage
|
||||
fn percentage(value, total) {
|
||||
if total == 0 {
|
||||
return "0%";
|
||||
}
|
||||
|
||||
let pct = (value / total) * 100.0;
|
||||
pct.round().to_string() + "%"
|
||||
}
|
||||
|
||||
// Format currency
|
||||
fn currency(amount, symbol) {
|
||||
symbol + format_number(amount.round(2))
|
||||
}
|
43
rhai_engine/examples/loadscripts/scripts/string_utils.rhai
Normal file
43
rhai_engine/examples/loadscripts/scripts/string_utils.rhai
Normal file
@@ -0,0 +1,43 @@
|
||||
// String manipulation functions that will be exposed to Tera templates
|
||||
|
||||
// Capitalize the first letter of each word
|
||||
fn capitalize(text) {
|
||||
if text.len == 0 {
|
||||
return "";
|
||||
}
|
||||
|
||||
let words = text.split(" ");
|
||||
let result = [];
|
||||
|
||||
for word in words {
|
||||
if word.len > 0 {
|
||||
let first_char = word.substr(0, 1).to_upper();
|
||||
let rest = word.substr(1, word.len - 1);
|
||||
result.push(first_char + rest);
|
||||
} else {
|
||||
result.push("");
|
||||
}
|
||||
}
|
||||
|
||||
result.join(" ")
|
||||
}
|
||||
|
||||
// Truncate text with ellipsis
|
||||
fn truncate(text, max_length) {
|
||||
if text.len <= max_length {
|
||||
return text;
|
||||
}
|
||||
|
||||
text.substr(0, max_length - 3) + "..."
|
||||
}
|
||||
|
||||
// Convert text to slug format (lowercase, hyphens)
|
||||
fn slugify(text) {
|
||||
let slug = text.to_lower();
|
||||
slug = slug.replace(" ", "-");
|
||||
slug = slug.replace(".", "");
|
||||
slug = slug.replace(",", "");
|
||||
slug = slug.replace("!", "");
|
||||
slug = slug.replace("?", "");
|
||||
slug
|
||||
}
|
56
rhai_engine/examples/loadscripts/scripts/test_utils.rhai
Normal file
56
rhai_engine/examples/loadscripts/scripts/test_utils.rhai
Normal file
@@ -0,0 +1,56 @@
|
||||
// Test utility functions to verify dynamic function discovery
|
||||
// These functions were not in the original hardcoded lists
|
||||
|
||||
// Reverse a string
|
||||
fn reverse_string(text) {
|
||||
let result = "";
|
||||
let i = text.len - 1;
|
||||
|
||||
// Using a different approach to reverse the string
|
||||
// We'll iterate backwards with a while loop instead of using step
|
||||
while i >= 0 {
|
||||
result += text.substr(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
// Count words in a string - rewritten to avoid split issues
|
||||
fn count_words(text) {
|
||||
if text.len == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Manual word counting implementation
|
||||
let count = 1; // Start with 1 for the first word
|
||||
let in_word = true;
|
||||
|
||||
for i in 0..text.len {
|
||||
let char = text.substr(i, 1);
|
||||
|
||||
if char == " " {
|
||||
in_word = false;
|
||||
} else if !in_word {
|
||||
// Found a non-space after a space = new word
|
||||
count += 1;
|
||||
in_word = true;
|
||||
}
|
||||
}
|
||||
|
||||
if text.substr(0, 1) == " " {
|
||||
// If text starts with space, reduce count
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
// Calculate factorial
|
||||
fn factorial(n) {
|
||||
// Ensure consistent integer type using to_int()
|
||||
let num = n.to_int();
|
||||
if num <= 1 {
|
||||
return 1;
|
||||
}
|
||||
num * factorial(num-1)
|
||||
}
|
93
rhai_engine/examples/loadscripts/test_dynamic_loading.rs
Normal file
93
rhai_engine/examples/loadscripts/test_dynamic_loading.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
use crate::tera_integration::RhaiTeraIntegration;
|
||||
use std::collections::HashMap;
|
||||
use rhai::Dynamic;
|
||||
|
||||
/// Test the dynamic loading of Rhai scripts and functions
|
||||
pub fn test_dynamic_loading() -> Result<(), String> {
|
||||
println!("\n=== TESTING DYNAMIC FUNCTION LOADING ===\n");
|
||||
|
||||
// Create a new RhaiTeraIntegration
|
||||
let mut integration = RhaiTeraIntegration::new();
|
||||
|
||||
println!("Loading Rhai scripts...");
|
||||
|
||||
// Load the original scripts
|
||||
integration.load_script("string_utils", "src/tera_integration/scripts/string_utils.rhai")?;
|
||||
integration.load_script("math_utils", "src/tera_integration/scripts/math_utils.rhai")?;
|
||||
|
||||
// Load the new test script (which wasn't in the original hardcoded lists)
|
||||
integration.load_script("test_utils", "src/tera_integration/scripts/test_utils.rhai")?;
|
||||
|
||||
// Get function names
|
||||
let function_names = integration.get_function_names();
|
||||
|
||||
// Print all available functions
|
||||
println!("\nAll available functions:");
|
||||
for name in &function_names {
|
||||
println!(" - {}", name);
|
||||
}
|
||||
|
||||
// Group functions by their script prefix to display nicely
|
||||
let scripts = group_functions_by_script(&function_names);
|
||||
|
||||
// Display functions by script
|
||||
display_functions_by_script(&scripts);
|
||||
|
||||
// Test some functions from each script
|
||||
println!("\nDynamic function testing:");
|
||||
|
||||
// Test original string utils functions
|
||||
test_function(&integration, "string_utils:capitalize", vec![Dynamic::from("hello world")])?;
|
||||
|
||||
// Test original math utils functions
|
||||
test_function(&integration, "math_utils:format_number", vec![Dynamic::from(1234567)])?;
|
||||
|
||||
// Test new functions from test_utils
|
||||
test_function(&integration, "test_utils:reverse_string", vec![Dynamic::from("hello world")])?;
|
||||
|
||||
test_function(&integration, "test_utils:count_words",
|
||||
vec![Dynamic::from("this is a test sentence")])?;
|
||||
|
||||
test_function(&integration, "test_utils:factorial",
|
||||
vec![Dynamic::from(5)])?;
|
||||
|
||||
println!("\n=== DYNAMIC FUNCTION LOADING TEST COMPLETE ===\n");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Helper function to group functions by script
|
||||
fn group_functions_by_script(function_names: &[String]) -> HashMap<String, Vec<String>> {
|
||||
let mut scripts = HashMap::new();
|
||||
|
||||
for name in function_names {
|
||||
let parts: Vec<&str> = name.split(':').collect();
|
||||
if parts.len() == 2 {
|
||||
let script = parts[0].to_string();
|
||||
let func = parts[1].to_string();
|
||||
|
||||
scripts.entry(script).or_insert_with(Vec::new).push(func);
|
||||
}
|
||||
}
|
||||
|
||||
scripts
|
||||
}
|
||||
|
||||
// Helper function to display functions grouped by script
|
||||
fn display_functions_by_script(scripts: &HashMap<String, Vec<String>>) {
|
||||
println!("\nFunctions by script:");
|
||||
|
||||
for (script, funcs) in scripts {
|
||||
println!(" {}:", script);
|
||||
for func in funcs {
|
||||
println!(" - {}", func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to test a function and display its result
|
||||
fn test_function(integration: &RhaiTeraIntegration, name: &str, args: Vec<Dynamic>) -> Result<(), String> {
|
||||
let result = integration.call_function(name, args)?;
|
||||
println!(" {}() => {}", name, result);
|
||||
Ok(())
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
# Product Catalog
|
||||
|
||||
{% let products = get_products() %}
|
||||
|
||||
## All Products
|
||||
|
||||
{% for product in products %}
|
||||
### {{ product.name }}
|
||||
|
||||
**Price:** {{ format_price(product.price) }}
|
||||
|
||||
#### Features:
|
||||
{% for feature in product.features %}
|
||||
- {{ feature }}
|
||||
{% endfor %}
|
||||
|
||||
*Status: {% if product.available %}✅ In Stock{% else %}❌ Out of Stock{% endif %}*
|
||||
|
||||
---
|
||||
{% endfor %}
|
||||
|
||||
## Available Products
|
||||
|
||||
{% let available_products = get_available_products() %}
|
||||
*Available Products: {{ available_products.len() }}*
|
||||
|
||||
{% for product in available_products %}
|
||||
### {{ product.name }}
|
||||
|
||||
**Price:** {{ format_price(product.price) }}
|
||||
|
||||
---
|
||||
{% endfor %}
|
||||
|
||||
## Total Catalog Value
|
||||
|
||||
**Total Value:** {{ format_price(calculate_total_price()) }}
|
||||
|
||||
## User Information
|
||||
|
||||
{% let user = get_user() %}
|
||||
|
||||
**Name:** {{ user.name }}
|
||||
**Email:** {{ user.email }}
|
||||
**Role:** {{ user.role }}
|
||||
**Theme:** {{ user.settings.theme }}
|
||||
|
||||
### Order History
|
||||
|
||||
{% for order in user.orders %}
|
||||
- **{{ order.id }}** ({{ order.date }}) - {{ format_price(order.total) }}
|
||||
{% endfor %}
|
||||
|
||||
## All Product Features
|
||||
|
||||
{% let features = get_all_features() %}
|
||||
{% for feature in features %}
|
||||
- {{ feature }}
|
||||
{% endfor %}
|
2
rhai_engine/examples/simple/producttemplates/readme.md
Normal file
2
rhai_engine/examples/simple/producttemplates/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
the data objects which need to be filled into product_catalog.tera come from ../scripts/
|
||||
|
@@ -0,0 +1,146 @@
|
||||
// Data objects for Tera template integration
|
||||
// This script defines complex objects that can be accessed from Tera templates
|
||||
|
||||
// Create a products catalog object
|
||||
fn create_products() {
|
||||
let products = [
|
||||
#{
|
||||
id: 1,
|
||||
name: "Laptop",
|
||||
price: 1299.99,
|
||||
features: [
|
||||
"16GB RAM",
|
||||
"512GB SSD",
|
||||
"Intel i7 processor"
|
||||
],
|
||||
available: true
|
||||
},
|
||||
#{
|
||||
id: 2,
|
||||
name: "Smartphone",
|
||||
price: 899.99,
|
||||
features: [
|
||||
"6.7 inch display",
|
||||
"128GB storage",
|
||||
"12MP camera"
|
||||
],
|
||||
available: true
|
||||
},
|
||||
#{
|
||||
id: 3,
|
||||
name: "Tablet",
|
||||
price: 499.99,
|
||||
features: [
|
||||
"10.9 inch display",
|
||||
"64GB storage",
|
||||
"A14 chip"
|
||||
],
|
||||
available: false
|
||||
},
|
||||
#{
|
||||
id: 4,
|
||||
name: "Headphones",
|
||||
price: 249.99,
|
||||
features: [
|
||||
"Noise cancellation",
|
||||
"Wireless",
|
||||
"20h battery life"
|
||||
],
|
||||
available: true
|
||||
}
|
||||
];
|
||||
|
||||
products
|
||||
}
|
||||
|
||||
// Get all products
|
||||
fn get_products() {
|
||||
create_products()
|
||||
}
|
||||
|
||||
// Get available products only
|
||||
fn get_available_products() {
|
||||
let all_products = create_products();
|
||||
let available = [];
|
||||
|
||||
for product in all_products {
|
||||
if product.available {
|
||||
available.push(product);
|
||||
}
|
||||
}
|
||||
|
||||
available
|
||||
}
|
||||
|
||||
// Get a specific product by ID
|
||||
fn get_product_by_id(id) {
|
||||
let products = create_products();
|
||||
|
||||
// Convert ID to integer to ensure type compatibility
|
||||
let search_id = id.to_int();
|
||||
|
||||
for product in products {
|
||||
if product.id == search_id {
|
||||
return product;
|
||||
}
|
||||
}
|
||||
|
||||
#{} // Return empty object if not found
|
||||
}
|
||||
|
||||
// Calculate total price of all products
|
||||
fn calculate_total_price() {
|
||||
let products = create_products();
|
||||
let total = 0.0;
|
||||
|
||||
for product in products {
|
||||
total += product.price;
|
||||
}
|
||||
|
||||
total
|
||||
}
|
||||
|
||||
// Format price with currency symbol
|
||||
fn format_price(price) {
|
||||
"$" + price.to_string()
|
||||
}
|
||||
|
||||
// Get all product features as a flattened array
|
||||
fn get_all_features() {
|
||||
let products = create_products();
|
||||
let all_features = [];
|
||||
|
||||
for product in products {
|
||||
for feature in product.features {
|
||||
all_features.push(feature);
|
||||
}
|
||||
}
|
||||
|
||||
all_features
|
||||
}
|
||||
|
||||
// Get a user object
|
||||
fn get_user() {
|
||||
#{
|
||||
name: "John Doe",
|
||||
email: "john@example.com",
|
||||
role: "admin",
|
||||
settings: #{
|
||||
theme: "dark",
|
||||
notifications: true,
|
||||
language: "en"
|
||||
},
|
||||
orders: [
|
||||
#{
|
||||
id: "ORD-001",
|
||||
date: "2025-03-25",
|
||||
total: 1299.99
|
||||
},
|
||||
#{
|
||||
id: "ORD-002",
|
||||
date: "2025-04-01",
|
||||
total: 249.99
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user