nomad-cli 0.1.0

Nomad CLI - extract structured web content
Documentation
use crate::cli::FormatArgs;

const FORMATS: &[(u8, &str, &str, &str)] = &[
    (0,  "RAW",       "874 B",  "Machine IPC — binary bincode EcsFrame"),
    (1,  "JSON",      "2223 B", "Full verbose debug with bounds and styles"),
    (2,  "MARKDOWN",  "159 B",  "Human-readable Markdown"),
    (3,  "AGENT",     "683 B",  "LLM analysis with roles and intents"),
    (4,  "SUMMARY",   "107 B",  "LLM token-efficient — interactive only"),
    (5,  "MINIMAL",   "326 B",  "Shortest JSON — single-char keys"),
    (6,  "SECTION",   "348 B",  "Interactive by HTML5 landmarks"),
    (7,  "A11Y",      "299 B",  "ARIA accessibility tree"),
    (8,  "TREE",      "367 B",  "Nested hierarchical DOM tree"),
    (9,  "READER",    "125 B",  "Clean article body (Reader Mode)"),
    (10, "FORM",      "12 B",   "Structured form fields"),
];

pub fn run(args: FormatArgs) -> Result<(), Box<dyn std::error::Error>> {
    match args.format {
        Some(f) => show_detail(&f),
        None => show_all(),
    }
}

fn show_all() -> Result<(), Box<dyn std::error::Error>> {
    println!("Available output formats:");
    println!();
    for (id, name, size, desc) in FORMATS {
        let default = if *id == 4 { " ◄ default" } else { "" };
        println!("  {id:2}  {name:<10} {size:<7} {desc}{default}");
    }
    println!();
    println!("Use with: nom browse <url> --format <name|number>");
    Ok(())
}

fn show_detail(name: &str) -> Result<(), Box<dyn std::error::Error>> {
    if name == "list" || name == "all" {
        return show_all();
    }
    let id = if let Ok(n) = name.parse::<u8>() {
        n
    } else {
        match name.to_lowercase().as_str() {
            "raw" => 0, "json" => 1, "markdown" | "md" => 2,
            "agent" => 3, "summary" => 4, "minimal" => 5,
            "section" => 6, "a11y" => 7, "tree" => 8,
            "reader" => 9, "form" => 10,
            _ => {
                println!("Unknown format: {name}");
                println!("Valid: raw, json, markdown, agent, summary, minimal, section, a11y, tree, reader, form");
                return Ok(());
            }
        }
    };

    if let Some((_, name, size, desc)) = FORMATS.iter().find(|(i, _, _, _)| *i == id) {
        println!("Format {id}: {name}");
        println!("  Default size: {size}");
        println!("  Description: {desc}");
        println!();
        print_example(id);
    }
    Ok(())
}

fn print_example(fmt: u8) {
    match fmt {
        0 => println!("  Binary — not human-readable. Pipe to a file."),
        1 => println!("  Example: {{\"tab_id\":1,\"viewport\":{{\"width\":800,\"height\":600}},\"entities\":[...]}}"),
        2 => println!("  Example: # Title\\n\\nParagraph text..."),
        3 => println!("  Example: {{\"tab_id\":1,\"viewport\":[800,600],\"entities\":[{{\"id\":1,\"tag\":\"a\",\"text\":\"...\"}}]}}"),
        4 => println!("  Example: {{\"title\":\"...\",\"url\":\"...\",\"count\":5,\"interactive\":[{{\"id\":4,\"t\":\"a\",\"x\":\"...\"}}]}}"),
        5 => println!("  Example: [{{\"i\":0,\"t\":\"h1\",\"x\":\"...\"}}]"),
        6 => println!("  Example: {{\"sections\":{{\"nav\":[...],\"main\":[...]}}}}"),
        7 => println!("  Example: [{{\"role\":\"heading\",\"name\":\"...\"}}]"),
        8 => println!("  Example: {{\"t\":\"root\",\"c\":[{{\"i\":0,\"t\":\"h1\",\"x\":\"...\"}}]}}"),
        9 => println!("  Example: # Title\\n\\nClean article body..."),
        10 => println!("  Example: {{\"forms\":[{{\"fields\":[{{\"name\":\"email\",\"type\":\"text\"}}]}}]}}"),
        _ => {}
    }
}