pub struct VerbHelp {
pub name: &'static str,
pub summary: &'static str,
pub flags: &'static [&'static str],
}
pub const VERB_HELP: &[VerbHelp] = &[
VerbHelp {
name: "append",
summary: "Append bytes to a regular file (creates if missing).",
flags: &["text", "expected-revision"],
},
VerbHelp {
name: "batch",
summary: "Atomically execute a list of metadata operations from a file or stdin.",
flags: &["file"],
},
VerbHelp {
name: "cat",
summary: "Stream a regular file's contents to stdout.",
flags: &["range", "no-follow"],
},
VerbHelp {
name: "changes",
summary: "Stream the workspace change feed (cursor-paginated).",
flags: &["after", "cursor", "limit"],
},
VerbHelp {
name: "cp",
summary: "Copy a node within the workspace.",
flags: &["recursive", "overwrite", "expected-revision"],
},
VerbHelp {
name: "exists",
summary: "Test whether a path resolves to a visible node (exit 0 if yes).",
flags: &["no-follow"],
},
VerbHelp {
name: "find",
summary: "Match nodes by bounded metadata predicates (kind, size, mtime, name).",
flags: &[
"name-contains",
"kind",
"min-size",
"max-size",
"modified-after",
"modified-before",
"cursor",
"limit",
],
},
VerbHelp {
name: "glob",
summary: "Match absolute paths by shape (e.g. `/logs/*.txt`).",
flags: &["cursor", "limit"],
},
VerbHelp {
name: "grep",
summary: "Literal byte matches inside regular files (returns matched ranges).",
flags: &["cursor", "limit"],
},
VerbHelp {
name: "ln",
summary: "Create a symbolic link.",
flags: &["parents", "exist-ok", "expected-revision"],
},
VerbHelp {
name: "ls",
summary: "List one directory's direct children (cursor-paginated).",
flags: &["cursor", "limit"],
},
VerbHelp {
name: "mkdir",
summary: "Create a directory.",
flags: &["parents", "exist-ok", "expected-revision"],
},
VerbHelp {
name: "mv",
summary: "Move a node within the workspace.",
flags: &["overwrite", "expected-revision"],
},
VerbHelp {
name: "purge",
summary: "Permanently delete a trashed node.",
flags: &[],
},
VerbHelp {
name: "readlink",
summary: "Print a symbolic link's stored target.",
flags: &[],
},
VerbHelp {
name: "restore",
summary: "Restore a trashed node (optionally to a different path).",
flags: &["to", "expected-revision"],
},
VerbHelp {
name: "rm",
summary: "Permanently remove a node and (recursively) its subtree.",
flags: &["recursive", "expected-revision"],
},
VerbHelp {
name: "rmattr",
summary: "Remove a custom attribute from a node.",
flags: &["expected-revision"],
},
VerbHelp {
name: "setattr",
summary: "Set an opaque custom attribute on a node.",
flags: &["value", "expected-revision"],
},
VerbHelp {
name: "stat",
summary: "Print metadata for one path.",
flags: &["no-follow"],
},
VerbHelp {
name: "touch",
summary: "Update timestamps or create an empty regular file.",
flags: &["no-create", "expected-revision"],
},
VerbHelp {
name: "trash",
summary: "Move a node into recoverable trash.",
flags: &["expected-revision"],
},
VerbHelp {
name: "trash-ls",
summary: "List recoverable trash records (cursor-paginated).",
flags: &["cursor", "limit"],
},
VerbHelp {
name: "tree",
summary: "Recursively enumerate a subtree (cursor-paginated).",
flags: &["max-depth", "follow-symlinks", "cursor", "limit"],
},
VerbHelp {
name: "truncate",
summary: "Set a regular file's logical length.",
flags: &["length", "expected-revision"],
},
VerbHelp {
name: "usage",
summary: "Print workspace byte/node usage and quota limits.",
flags: &[],
},
VerbHelp {
name: "write",
summary: "Replace a regular file's contents (creates by default).",
flags: &["text", "no-create", "expected-revision"],
},
VerbHelp {
name: "write-at",
summary: "Write bytes beginning at a logical offset.",
flags: &["offset", "text", "no-create", "expected-revision"],
},
];
pub fn print_verb_table() {
let mut entries: Vec<&VerbHelp> = VERB_HELP.iter().collect();
entries.sort_by_key(|e| e.name);
let name_width = entries.iter().map(|e| e.name.len()).max().unwrap_or(0);
for entry in entries {
println!(
" {:<width$} {}",
entry.name,
entry.summary,
width = name_width,
);
}
}
pub fn print_verb_help(verb: &str) -> Option<&'static VerbHelp> {
let entry = VERB_HELP.iter().find(|e| e.name == verb)?;
println!("{}", entry.summary);
println!();
println!("Flags:");
if entry.flags.is_empty() {
println!(" (none)");
} else {
for flag in entry.flags {
println!(" --{flag}");
}
}
Some(entry)
}