tron 2.1.0

A rust based template system built for speed and simplicity.
Documentation
//! Template Loading Example
//!
//! This example demonstrates how to load templates from directories, glob patterns,
//! and multiple sources using Tron's template loading functionality.

use tron::{TronTemplate, TemplateLoader, LoaderConfig};
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Tron Template Loading Example ===\n");

    // Basic file loading
    println!("1. Loading single template from file:");
    if Path::new("templates/rust_function.tron").exists() {
        let template = TronTemplate::from_file("templates/rust_function.tron")?;
        println!("   - Loaded template with {} placeholders", template.placeholder_names().len());
        println!("   - Placeholders: {:?}", template.placeholder_names());
    } else {
        println!("   - Template file not found (run from project root)");
    }

    println!();

    // Directory loading
    println!("2. Loading templates from directory:");
    if let Ok(templates) = TronTemplate::from_directory("templates") {
        println!("   - Loaded {} templates from directory", templates.len());
        for (name, template) in &templates {
            println!("     * {}: {} placeholders", name, template.placeholder_names().len());
        }
    } else {
        println!("   - Templates directory not found (run from project root)");
    }

    println!();

    // Glob pattern loading
    println!("3. Loading templates with glob patterns:");
    if let Ok(tron_templates) = TronTemplate::from_glob("templates/*.tron") {
        println!("   - Found {} .tron files", tron_templates.len());
        for (name, _) in &tron_templates {
            println!("     * {}", name);
        }
    } else {
        println!("   - No .tron files found");
    }

    if let Ok(all_templates) = TronTemplate::from_glob("templates/*.{tron,tpl}") {
        println!("   - Found {} template files (.tron + .tpl)", all_templates.len());
    }

    println!();

    // Multiple sources loading
    println!("4. Loading from multiple sources:");
    let sources = &[
        "templates/",           // directory
        "templates/*.tpl",      // glob pattern
    ];
    
    if let Ok(templates) = TronTemplate::from_sources(sources) {
        println!("   - Loaded {} templates from multiple sources", templates.len());
        
        // Group by extension
        let mut by_extension = std::collections::HashMap::new();
        for (name, _) in &templates {
            let ext = Path::new(name)
                .extension()
                .unwrap_or_default()
                .to_string_lossy()
                .to_string();
            *by_extension.entry(ext).or_insert(0) += 1;
        }
        
        for (ext, count) in by_extension {
            println!("     * .{}: {} files", ext, count);
        }
    }

    println!();

    // Advanced loading with TemplateLoader
    println!("5. Advanced loading with TemplateLoader:");
    
    let config = LoaderConfig {
        recursive: true,
        extensions: vec!["tron".to_string(), "tpl".to_string()],
        track_changes: true,
        max_depth: Some(3),
        enable_caching: true, // or false, depending on your needs
        cache_config: Default::default(), // or specify your cache config
    };
    
    let mut loader = TemplateLoader::with_config(config);
    
    // Discover templates without loading them
    if let Ok(discovered) = loader.discover_templates("templates") {
        println!("   - Discovered {} templates:", discovered.len());
        for (name, metadata) in &discovered {
            println!("     * {} ({} bytes)", name, metadata.size);
        }
    }
    
    println!();
    
    // Load with caching
    if let Ok(templates) = loader.load_from_directory("templates") {
        println!("   - Loaded {} templates with caching", templates.len());
        println!("   - Cache size: {}", loader.cache_size());
        
        // Load again to test caching
        let _templates2 = loader.load_from_directory("templates")?;
        println!("   - Cache size after second load: {}", loader.cache_size());
    }

    println!();

    // Demonstrate template usage after loading
    println!("6. Using loaded templates:");
    if let Ok(templates) = TronTemplate::from_glob("templates/rust_function.tron") {
        if let Some((_, mut template)) = templates.into_iter().next() {
            println!("   - Using rust_function template:");
            
            // Fill the template
            template.set("function_name", "fibonacci").unwrap_or(());
            template.set("parameters", "n: u32").unwrap_or(());
            template.set("return_type", "u64").unwrap_or(());
            template.set("description", "Calculate the nth Fibonacci number").unwrap_or(());
            template.set("body", "if n <= 1 { n as u64 } else { fibonacci(n-1) + fibonacci(n-2) }").unwrap_or(());
            
            if let Ok(result) = template.render_partial() {
                println!("   - Generated code:");
                for (i, line) in result.lines().enumerate() {
                    println!("     {:2}: {}", i + 1, line);
                }
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_template_loading_functionality() -> Result<(), Box<dyn std::error::Error>> {
        // Test basic loading functionality works
        let loader = TemplateLoader::new();
        assert_eq!(loader.cache_size(), 0);
        
        // Test config creation
        let config = LoaderConfig::default();
        assert!(config.recursive);
        assert!(config.extensions.contains(&"tron".to_string()));
        
        Ok(())
    }
}