zc2 0.0.25

P2P compute broker with credit-based billing, WAL, and broker mesh support
//! Declarative command specifications.
//!
//! Phase 0 of the terminal refactor (see `docs/TERMINAL_REFACTOR.md`).
//!
//! A [`CommandSpec`] is the single declarative description of a command. Both
//! the non-interactive CLI (`zc <cmd> …`) and the interactive REPL palette read
//! from the same specs, so help text, autocompletion, and dispatch can never
//! drift apart. Phase 2 wires these specs to executable handlers; Phase 0 just
//! establishes the catalog and the types.

#![allow(dead_code)]

/// Grouping used for help output and the command palette.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Category {
    Broker,
    Cluster,
    Benchmark,
    Identity,
    Monitoring,
    Diagnostics,
    Container,
    Ui,
    Meta,
}

impl Category {
    /// Section title used in generated help.
    pub fn title(self) -> &'static str {
        match self {
            Category::Broker => "Broker Commands",
            Category::Cluster => "Cluster Commands",
            Category::Benchmark => "Benchmark Commands",
            Category::Identity => "Identity",
            Category::Monitoring => "Monitoring",
            Category::Diagnostics => "Diagnostics",
            Category::Container => "Container Commands",
            Category::Ui => "Interface",
            Category::Meta => "General",
        }
    }

    /// Stable display order for help sections.
    pub fn order() -> &'static [Category] {
        &[
            Category::Broker,
            Category::Cluster,
            Category::Benchmark,
            Category::Identity,
            Category::Monitoring,
            Category::Diagnostics,
            Category::Container,
            Category::Ui,
            Category::Meta,
        ]
    }
}

/// A single positional argument of a command.
#[derive(Debug, Clone, Copy)]
pub struct ArgSpec {
    /// Argument name as shown in usage, e.g. `port` or `zc://node`.
    pub name: &'static str,
    /// Whether the argument must be supplied.
    pub required: bool,
    /// One-line description for hints.
    pub summary: &'static str,
}

impl ArgSpec {
    pub const fn required(name: &'static str, summary: &'static str) -> Self {
        ArgSpec {
            name,
            required: true,
            summary,
        }
    }
    pub const fn optional(name: &'static str, summary: &'static str) -> Self {
        ArgSpec {
            name,
            required: false,
            summary,
        }
    }
}

/// Declarative description of a command.
#[derive(Debug, Clone, Copy)]
pub struct CommandSpec {
    /// Canonical name, e.g. `workers`.
    pub name: &'static str,
    /// Alternate names that resolve to the same command, e.g. `me` => `whoami`.
    pub aliases: &'static [&'static str],
    /// Positional arguments, in order.
    pub args: &'static [ArgSpec],
    /// One-line summary for palette + help.
    pub summary: &'static str,
    /// Full help, in markdown, rendered in the REPL and on `zc help <cmd>`.
    pub help_md: &'static str,
    /// Category for grouping in help/palette.
    pub category: Category,
}

impl CommandSpec {
    /// Does `token` name this command (canonical name or any alias)?
    pub fn matches(&self, token: &str) -> bool {
        self.name == token || self.aliases.contains(&token)
    }

    /// A usage string like `attach <zc://node> [--key]`.
    pub fn usage(&self) -> String {
        let mut s = String::from(self.name);
        for a in self.args {
            if a.required {
                s.push_str(&format!(" <{}>", a.name));
            } else {
                s.push_str(&format!(" [{}]", a.name));
            }
        }
        s
    }
}