cli-boxes 0.1.1

Unicode box drawing characters for creating beautiful CLI interfaces
Documentation
//! Comprehensive example showcasing all features of the cli-boxes crate.
//!
//! This example demonstrates:
//! - All predefined box styles
//! - Custom box creation with builder pattern
//! - String parsing and error handling
//! - Real-world usage patterns
//! - Performance considerations

use cli_boxes::{BorderStyle, BoxChars};
use std::collections::HashMap;

fn main() {
    println!("🎨 CLI Boxes - Comprehensive Example\n");

    // Demonstrate all predefined styles
    showcase_all_styles();

    // Show custom box creation
    demonstrate_custom_boxes();

    // String parsing examples
    demonstrate_string_parsing();

    // Real-world usage patterns
    demonstrate_real_world_usage();

    // Performance showcase
    demonstrate_performance_features();
}

/// Display all predefined box styles with descriptions
fn showcase_all_styles() {
    println!("📦 All Available Box Styles:");
    println!("{:-<60}", "");

    let descriptions = [
        (BorderStyle::None, "Invisible borders (spacing only)"),
        (BorderStyle::Single, "Clean, professional single-line"),
        (BorderStyle::Double, "Bold emphasis with double-line"),
        (BorderStyle::Round, "Modern rounded corners"),
        (BorderStyle::Bold, "Maximum emphasis with thick lines"),
        (
            BorderStyle::SingleDouble,
            "Mixed: single horizontal, double vertical",
        ),
        (
            BorderStyle::DoubleSingle,
            "Mixed: double horizontal, single vertical",
        ),
        (BorderStyle::Classic, "ASCII-compatible for legacy systems"),
        (BorderStyle::Arrow, "Decorative arrows for special effects"),
    ];

    for (style, description) in &descriptions {
        let chars = style.chars();
        println!("{:12} | {} | {}", style.to_string(), chars, description);
    }
    println!();
}

/// Demonstrate custom box creation with builder pattern
fn demonstrate_custom_boxes() {
    println!("🔧 Custom Box Creation:");
    println!("{:-<60}", "");

    // Uniform styling
    let uniform = BoxChars::builder()
        .corners('')
        .horizontal('')
        .vertical('')
        .build();
    println!("Uniform style:     {}", uniform);

    // Selective override
    let mixed = BoxChars::builder()
        .corners('')
        .horizontal('')
        .vertical('')
        .top_left('')
        .build();
    println!("Selective override: {}", mixed);

    // Asymmetric design
    let asymmetric = BoxChars::builder()
        .top_left('')
        .top('')
        .top_right('')
        .left('')
        .right('')
        .bottom_left('')
        .bottom('')
        .bottom_right('')
        .build();
    println!("Asymmetric design:  {}", asymmetric);

    // Direct constructor
    let direct = BoxChars::new('*', '-', '*', '|', '*', '-', '*', '|');
    println!("Direct constructor: {}", direct);
    println!();
}

/// Show string parsing capabilities and error handling
fn demonstrate_string_parsing() {
    println!("📝 String Parsing & Error Handling:");
    println!("{:-<60}", "");

    let test_inputs = [
        "single",        // Valid
        "DOUBLE",        // Case insensitive
        "single-double", // Kebab case
        "single_double", // Snake case
        "Round",         // Mixed case
        "invalid_style", // Invalid - will show helpful error
        "",              // Empty - will show error
    ];

    for input in &test_inputs {
        match input.parse::<BorderStyle>() {
            Ok(style) => {
                let chars = style.chars();
                println!("✓ '{}' -> {} ({})", input, style, chars);
            }
            Err(e) => {
                println!("✗ '{}' -> {}", input, e);
            }
        }
    }
    println!();
}

/// Demonstrate real-world usage patterns
fn demonstrate_real_world_usage() {
    println!("🌍 Real-World Usage Patterns:");
    println!("{:-<60}", "");

    // Configuration-driven style selection
    let config_styles: HashMap<&str, BorderStyle> = [
        ("info", BorderStyle::Single),
        ("warning", BorderStyle::Bold),
        ("error", BorderStyle::Double),
        ("success", BorderStyle::Round),
    ]
    .iter()
    .cloned()
    .collect();

    println!("Configuration-driven styles:");
    for (level, style) in &config_styles {
        let chars = style.chars();
        println!("  {}: {} ({})", level, style, chars);
    }

    // Create actual boxes
    println!("\nSample message boxes:");
    create_message_box(
        "Information",
        "This is an info message",
        BorderStyle::Single,
    );
    create_message_box("Warning", "This is a warning!", BorderStyle::Bold);
    create_message_box("Error", "Something went wrong!", BorderStyle::Double);

    // Dynamic width adjustment
    println!("\nDynamic width adjustment:");
    let messages = [
        "Short",
        "Medium length message",
        "This is a very long message that needs more space",
    ];
    for msg in &messages {
        let width = msg.len() + 4; // Add padding
        create_simple_box(msg, width, BorderStyle::Round);
    }
    println!();
}

/// Show performance features and optimizations
fn demonstrate_performance_features() {
    println!("⚡ Performance Features:");
    println!("{:-<60}", "");

    // Compile-time constants
    println!("✓ Compile-time constants (zero runtime cost)");
    const COMPILE_TIME_BOX: BoxChars = BoxChars::SINGLE;
    println!("  Const box: {}", COMPILE_TIME_BOX);

    // Zero-allocation parsing demonstration
    println!("✓ Zero-allocation string parsing");
    let parse_count = 1000;
    let start = std::time::Instant::now();

    for _ in 0..parse_count {
        let _ = "single".parse::<BorderStyle>().unwrap();
        let _ = "double".parse::<BorderStyle>().unwrap();
        let _ = "single-double".parse::<BorderStyle>().unwrap();
    }

    let duration = start.elapsed();
    println!(
        "  Parsed {} styles in {:?} (avg: {:?} per parse)",
        parse_count * 3,
        duration,
        duration / (parse_count * 3)
    );

    // Memory efficiency
    println!("✓ Memory efficiency");
    println!("  BoxChars size: {} bytes", std::mem::size_of::<BoxChars>());
    println!(
        "  BorderStyle size: {} bytes",
        std::mem::size_of::<BorderStyle>()
    );

    // Iteration performance
    println!("✓ Efficient iteration over all styles");
    let start = std::time::Instant::now();
    let mut count = 0;
    for _ in 0..10000 {
        for style in BorderStyle::all() {
            let _chars = style.chars();
            count += 1;
        }
    }
    let duration = start.elapsed();
    println!("  Processed {} style conversions in {:?}", count, duration);
    println!();
}

/// Create a formatted message box
fn create_message_box(title: &str, message: &str, style: BorderStyle) {
    let chars = style.chars();
    let width = std::cmp::max(title.len(), message.len()) + 4;

    // Top border
    print!("{}", chars.top_left);
    print!("{}", chars.top.to_string().repeat(width));
    println!("{}", chars.top_right);

    // Title row
    let title_padding = width - title.len() - 2;
    let left_pad = title_padding / 2;
    let right_pad = title_padding - left_pad;
    print!("{}", chars.left);
    print!("{}", " ".repeat(left_pad));
    print!("{}", title);
    print!("{}", " ".repeat(right_pad));
    println!("{}", chars.right);

    // Separator (if title and message are different)
    if title != message {
        print!("{}", chars.left);
        print!("{}", chars.top.to_string().repeat(width));
        println!("{}", chars.right);
    }

    // Message row
    let msg_padding = width - message.len() - 2;
    let left_pad = msg_padding / 2;
    let right_pad = msg_padding - left_pad;
    print!("{}", chars.left);
    print!("{}", " ".repeat(left_pad));
    print!("{}", message);
    print!("{}", " ".repeat(right_pad));
    println!("{}", chars.right);

    // Bottom border
    print!("{}", chars.bottom_left);
    print!("{}", chars.bottom.to_string().repeat(width));
    println!("{}", chars.bottom_right);
    println!();
}

/// Create a simple box with specified width
fn create_simple_box(content: &str, width: usize, style: BorderStyle) {
    let chars = style.chars();
    let content_width = width.saturating_sub(2);
    let padding = content_width.saturating_sub(content.len());
    let left_pad = padding / 2;
    let right_pad = padding - left_pad;

    // Top
    print!("{}", chars.top_left);
    print!("{}", chars.top.to_string().repeat(content_width));
    println!("{}", chars.top_right);

    // Content
    print!("{}", chars.left);
    print!("{}", " ".repeat(left_pad));
    print!("{}", content);
    print!("{}", " ".repeat(right_pad));
    println!("{}", chars.right);

    // Bottom
    print!("{}", chars.bottom_left);
    print!("{}", chars.bottom.to_string().repeat(content_width));
    println!("{}", chars.bottom_right);
}