Skip to main content

Registry

Struct Registry 

Source
pub struct Registry { /* private fields */ }
Expand description

Owns the registered command tree and provides query/search operations.

Create a Registry with Registry::new, passing the fully-built list of top-level commands. The registry takes ownership of the command list and makes it available through a variety of lookup and search methods.

§Examples

let registry = Registry::new(vec![
    Command::builder("deploy").summary("Deploy the app").build().unwrap(),
]);

let cmd = registry.get_command("deploy").unwrap();
assert_eq!(cmd.summary, "Deploy the app");

Implementations§

Source§

impl Registry

Source

pub fn new(commands: Vec<Command>) -> Self

Create a new Registry owning the given command list.

§Arguments
  • commands — The top-level command list. Subcommands are nested inside the respective Command::subcommands fields.
§Examples
let registry = Registry::new(vec![
    Command::builder("run").build().unwrap(),
]);
assert_eq!(registry.list_commands().len(), 1);
Source

pub fn commands(&self) -> &[Command]

Borrow the raw command slice (useful for constructing a Parser).

§Examples
let registry = Registry::new(vec![Command::builder("ping").build().unwrap()]);
let parser = Parser::new(registry.commands());
let parsed = parser.parse(&["ping"]).unwrap();
assert_eq!(parsed.command.canonical, "ping");
Source

pub fn list_commands(&self) -> Vec<&Command>

Return references to all top-level commands.

§Examples
let registry = Registry::new(vec![
    Command::builder("a").build().unwrap(),
    Command::builder("b").build().unwrap(),
]);
assert_eq!(registry.list_commands().len(), 2);
Source

pub fn get_command(&self, canonical: &str) -> Option<&Command>

Look up a top-level command by its exact canonical name.

Returns None if no command with that canonical name exists. Does not match aliases or spellings — use crate::Resolver for fuzzy/prefix matching.

§Arguments
  • canonical — The exact canonical name to look up.
§Examples
let registry = Registry::new(vec![
    Command::builder("deploy").alias("d").build().unwrap(),
]);

assert!(registry.get_command("deploy").is_some());
assert!(registry.get_command("d").is_none()); // alias, not canonical
Source

pub fn get_subcommand(&self, path: &[&str]) -> Option<&Command>

Walk a path of canonical names into the subcommand tree.

path = &["remote", "add"] returns the add subcommand of remote. Each path segment must be an exact canonical name at that level of the tree.

Returns None if any segment fails to match or if path is empty.

§Arguments
  • path — Ordered slice of canonical command names from top-level down.
§Examples
let registry = Registry::new(vec![
    Command::builder("remote")
        .subcommand(Command::builder("add").build().unwrap())
        .build()
        .unwrap(),
]);

let sub = registry.get_subcommand(&["remote", "add"]).unwrap();
assert_eq!(sub.canonical, "add");

assert!(registry.get_subcommand(&[]).is_none());
assert!(registry.get_subcommand(&["remote", "nope"]).is_none());
Source

pub fn get_examples(&self, canonical: &str) -> Option<&[Example]>

Return the examples slice for a top-level command, or None if the command does not exist.

An empty examples list returns Some(&[]).

§Arguments
  • canonical — The exact canonical name of the command.
§Examples
let registry = Registry::new(vec![
    Command::builder("run")
        .example(Example::new("basic run", "myapp run"))
        .build()
        .unwrap(),
]);

assert_eq!(registry.get_examples("run").unwrap().len(), 1);
assert!(registry.get_examples("missing").is_none());
Source

pub fn search(&self, query: &str) -> Vec<&Command>

Substring search across canonical name, summary, and description.

The search is case-insensitive. Returns all top-level commands for which the query appears in at least one of the three text fields.

§Arguments
  • query — The substring to search for (case-insensitive).
§Examples
let registry = Registry::new(vec![
    Command::builder("list").summary("List all records").build().unwrap(),
    Command::builder("get").summary("Get a single record").build().unwrap(),
]);

let results = registry.search("record");
assert_eq!(results.len(), 2);
assert!(registry.search("zzz").is_empty());

Fuzzy search across canonical name, summary, and description.

Uses the skim fuzzy-matching algorithm (requires the fuzzy feature). Returns matches sorted descending by score (best match first). Commands that produce no fuzzy match are excluded.

§Arguments
  • query — The fuzzy query string.
§Examples
let registry = Registry::new(vec![
    Command::builder("deploy").summary("Deploy a service").build().unwrap(),
    Command::builder("delete").summary("Delete a resource").build().unwrap(),
    Command::builder("describe").summary("Describe a resource").build().unwrap(),
]);

// Fuzzy-matches all commands starting with 'de'
let results = registry.fuzzy_search("dep");
assert!(!results.is_empty());
// Results are sorted by match score descending
assert_eq!(results[0].0.canonical, "deploy");
// Scores are positive integers — higher is a better match
assert!(results[0].1 > 0);
Source

pub fn match_intent(&self, phrase: &str) -> Vec<(&Command, u32)>

Match commands by natural-language intent phrase.

Scores each command by how many words from phrase appear in its combined text (canonical name, aliases, semantic aliases, summary, description). Returns matches sorted by score descending.

§Examples
let registry = Registry::new(vec![
    Command::builder("deploy")
        .summary("Deploy a service to an environment")
        .semantic_alias("release to production")
        .semantic_alias("push to environment")
        .build().unwrap(),
    Command::builder("status")
        .summary("Check service status")
        .build().unwrap(),
]);

let results = registry.match_intent("deploy to production");
assert!(!results.is_empty());
assert_eq!(results[0].0.canonical, "deploy");
Source

pub fn to_json(&self) -> Result<String, QueryError>

Serialize the entire command tree to a pretty-printed JSON string.

Handler closures are excluded from the output (they are skipped by the serde configuration on Command).

§Errors

Returns QueryError::Serialization if serde_json fails (in practice this should not happen for well-formed command trees).

§Examples
let registry = Registry::new(vec![
    Command::builder("deploy").summary("Deploy").build().unwrap(),
]);

let json = registry.to_json().unwrap();
assert!(json.contains("deploy"));
Source

pub fn to_json_with_fields(&self, fields: &[&str]) -> Result<String, QueryError>

Serialize the entire command tree to a pretty-printed JSON string, filtering each command object to only include the requested top-level fields.

Each command object (including nested subcommands at any depth) is filtered so that only keys listed in fields are retained. The subcommands key is always walked recursively even if it is not in fields; its entries are filtered before being emitted.

If fields is empty the method falls back to the same output as Registry::to_json.

Field names that do not exist in the serialized command are silently ignored (no error is returned for missing fields).

Valid field names correspond to the top-level keys of the serialized Command object: canonical, aliases, spellings, semantic_aliases, summary, description, arguments, flags, examples, best_practices, anti_patterns, subcommands, meta, mutating, etc.

§Errors

Returns QueryError::Serialization if serde_json fails.

§Examples
let registry = Registry::new(vec![
    Command::builder("deploy")
        .summary("Deploy the app")
        .build()
        .unwrap(),
]);

let json = registry.to_json_with_fields(&["canonical", "summary"]).unwrap();
let v: serde_json::Value = serde_json::from_str(&json).unwrap();
let obj = &v[0];
assert_eq!(obj["canonical"], "deploy");
assert_eq!(obj["summary"], "Deploy the app");
// fields not requested are absent
assert!(obj.get("examples").is_none());
Source

pub fn to_ndjson(&self) -> Result<String, QueryError>

Serialize the command tree as NDJSON (one compact JSON object per line).

Commands are emitted depth-first using Registry::iter_all_recursive. Each line is a single, self-contained JSON object representing one command (handler closures excluded). Subcommands appear as their own lines rather than being nested inside their parent, which lets agents process the registry incrementally without buffering the entire tree.

An empty registry returns an empty string (no trailing newline). A non-empty registry ends with a trailing newline.

§Errors

Returns QueryError::Serialization if serialization fails.

§Examples
let registry = Registry::new(vec![
    Command::builder("remote")
        .subcommand(Command::builder("add").build().unwrap())
        .build()
        .unwrap(),
]);

let ndjson = registry.to_ndjson().unwrap();
let lines: Vec<&str> = ndjson.trim_end_matches('\n').split('\n').collect();
assert_eq!(lines.len(), 2); // "remote" + "remote add"
// Every line must be valid JSON.
for line in &lines {
    assert!(serde_json::from_str::<serde_json::Value>(line).is_ok());
}
Source

pub fn to_ndjson_with_fields( &self, fields: &[&str], ) -> Result<String, QueryError>

Serialize the command tree as NDJSON, filtering each object to the given field names.

Behaves identically to Registry::to_ndjson except that each JSON object is filtered to include only the keys listed in fields. When fields is empty, all fields are included (equivalent to Registry::to_ndjson).

§Arguments
  • fields — Field names to keep in each output object. Pass &[] to include all fields.
§Errors

Returns QueryError::Serialization if serialization fails.

§Examples
let registry = Registry::new(vec![
    Command::builder("deploy").summary("Deploy the app").build().unwrap(),
]);

let ndjson = registry.to_ndjson_with_fields(&["canonical", "summary"]).unwrap();
let val: serde_json::Value = serde_json::from_str(ndjson.trim_end_matches('\n')).unwrap();
assert!(val.get("canonical").is_some());
assert!(val.get("summary").is_some());
assert!(val.get("description").is_none());
Source

pub fn iter_all_recursive(&self) -> Vec<CommandEntry<'_>>

Iterate over every command in the tree depth-first, including all nested subcommands at any depth.

Each entry carries the CommandEntry::path (canonical names from the registry root to the command) and a reference to the Command.

Commands are yielded in depth-first order: a parent command appears immediately before all of its descendants. Within each level, commands appear in registration order.

§Examples
let registry = Registry::new(vec![
    Command::builder("remote")
        .subcommand(Command::builder("add").build().unwrap())
        .subcommand(Command::builder("remove").build().unwrap())
        .build()
        .unwrap(),
    Command::builder("status").build().unwrap(),
]);

let all: Vec<_> = registry.iter_all_recursive();
let names: Vec<String> = all.iter().map(|e| e.path_str()).collect();

assert_eq!(names, ["remote", "remote.add", "remote.remove", "status"]);

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.