xacli-components 0.2.1

Interactive components for XaCLI
Documentation
use std::io::Write;
use std::thread;
use xacli_components::{Confirm, Input, MultiSelect, Select};
use xacli_core::{App, Command, InputComponent, InputValue};

fn main() {
    let app = create_app();
    if let Err(e) = app.execute() {
        eprintln!("Error: {}", e);
        std::process::exit(1);
    }
}

pub fn create_app() -> App {
    App::new("components-demo", "0.1.0")
        .command(
            Command::new("confirm")
                .description("Confirm component demo")
                .run(Box::new(|ctx| {
                    let mut confirm = Confirm::new("Are you sure?");
                    let result = confirm.run(ctx)?;
                    writeln!(ctx.stdout(), "Component returned: {:?}", result)?;
                    Ok(())
                })),
        )
        .command(
            Command::new("input")
                .description("Input component demo")
                .run(Box::new(|ctx| {
                    let input = Input::new("Enter your name:");
                    let result = input.run(ctx)?;
                    writeln!(ctx.stdout(), "Component returned: {:?}", result)?;
                    Ok(())
                })),
        )
        .command(
            Command::new("select")
                .description("Select component demo")
                .run(Box::new(|ctx| {
                    let select = Select::new("Choose an option:")
                        .option("Option 1", InputValue::String("opt1".to_string()))
                        .option("Option 2", InputValue::String("opt2".to_string()))
                        .option("Option 3", InputValue::String("opt3".to_string()));
                    let result = select.run(ctx)?;
                    writeln!(ctx.stdout(), "Component returned: {:?}", result)?;
                    Ok(())
                })),
        )
        .command(
            Command::new("multiselect")
                .description("MultiSelect component demo")
                .run(Box::new(|ctx| {
                    let multiselect = MultiSelect::new("Select multiple options:")
                        .option("Item 1", InputValue::String("item1".to_string()))
                        .option("Item 2", InputValue::String("item2".to_string()))
                        .option("Item 3", InputValue::String("item3".to_string()));
                    let result = multiselect.run(ctx)?;
                    writeln!(ctx.stdout(), "Component returned: {:?}", result)?;
                    Ok(())
                })),
        )
        .command(
            Command::new("progress")
                .description("Progress component demo")
                .run(Box::new(|ctx| {
                    // Progress component doesn't support Context properly yet, skip for now
                    writeln!(ctx.stdout(), "Component returned: Progress complete")?;
                    Ok(())
                })),
        )
        .command(
            Command::new("spinner")
                .description("Spinner component demo")
                .run(Box::new(|ctx| {
                    // Spinner component needs threading, simplified for demo
                    thread::sleep(std::time::Duration::from_millis(100));
                    writeln!(ctx.stdout(), "Component returned: Spinner complete")?;
                    Ok(())
                })),
        )
}

#[cfg(test)]
mod tests {
    use super::create_app;
    use xacli_testing::{report::terminal::print_report, SpecFile, TestingApp};

    #[test]
    fn test_components() {
        let app = TestingApp::new(create_app());
        // Use CARGO_MANIFEST_DIR to get crate root, then scan src folder
        let crate_dir = env!("CARGO_MANIFEST_DIR");
        let src_dir = std::path::Path::new(crate_dir).join("src");
        let spec = SpecFile::scan_dir(&src_dir).expect("Failed to scan .xacli test files");
        let result = app.execute_spec(&spec);

        // Save report to workspace_root/.xacli/reports/report.json
        // CARGO_MANIFEST_DIR is crates/xacli-components, so go up 2 levels
        let workspace_root = std::path::Path::new(crate_dir)
            .parent().unwrap()  // crates/
            .parent().unwrap(); // workspace root
        let report_dir = workspace_root.join(".xacli").join("reports");
        std::fs::create_dir_all(&report_dir).expect("Failed to create reports directory");
        let report_path = report_dir.join("report.json");
        result.to_file(&report_path).expect("Failed to save report");
    }
}