1pub struct VerbHelp {
17 pub name: &'static str,
20 pub summary: &'static str,
23 pub flags: &'static [&'static str],
26}
27
28pub const VERB_HELP: &[VerbHelp] = &[
32 VerbHelp {
33 name: "append",
34 summary: "Append bytes to a regular file (creates if missing).",
35 flags: &["text", "expected-revision"],
36 },
37 VerbHelp {
38 name: "batch",
39 summary: "Atomically execute a list of metadata operations from a file or stdin.",
40 flags: &["file"],
41 },
42 VerbHelp {
43 name: "cat",
44 summary: "Stream a regular file's contents to stdout.",
45 flags: &["range", "no-follow"],
46 },
47 VerbHelp {
48 name: "changes",
49 summary: "Stream the workspace change feed (cursor-paginated).",
50 flags: &["after", "cursor", "limit"],
51 },
52 VerbHelp {
53 name: "cp",
54 summary: "Copy a node within the workspace.",
55 flags: &["recursive", "overwrite", "expected-revision"],
56 },
57 VerbHelp {
58 name: "exists",
59 summary: "Test whether a path resolves to a visible node (exit 0 if yes).",
60 flags: &["no-follow"],
61 },
62 VerbHelp {
63 name: "find",
64 summary: "Match nodes by bounded metadata predicates (kind, size, mtime, name).",
65 flags: &[
66 "name-contains",
67 "kind",
68 "min-size",
69 "max-size",
70 "modified-after",
71 "modified-before",
72 "cursor",
73 "limit",
74 ],
75 },
76 VerbHelp {
77 name: "glob",
78 summary: "Match absolute paths by shape (e.g. `/logs/*.txt`).",
79 flags: &["cursor", "limit"],
80 },
81 VerbHelp {
82 name: "grep",
83 summary: "Literal byte matches inside regular files (returns matched ranges).",
84 flags: &["cursor", "limit"],
85 },
86 VerbHelp {
87 name: "ln",
88 summary: "Create a symbolic link.",
89 flags: &["parents", "exist-ok", "expected-revision"],
90 },
91 VerbHelp {
92 name: "ls",
93 summary: "List one directory's direct children (cursor-paginated).",
94 flags: &["cursor", "limit"],
95 },
96 VerbHelp {
97 name: "mkdir",
98 summary: "Create a directory.",
99 flags: &["parents", "exist-ok", "expected-revision"],
100 },
101 VerbHelp {
102 name: "mv",
103 summary: "Move a node within the workspace.",
104 flags: &["overwrite", "expected-revision"],
105 },
106 VerbHelp {
107 name: "purge",
108 summary: "Permanently delete a trashed node.",
109 flags: &[],
110 },
111 VerbHelp {
112 name: "readlink",
113 summary: "Print a symbolic link's stored target.",
114 flags: &[],
115 },
116 VerbHelp {
117 name: "restore",
118 summary: "Restore a trashed node (optionally to a different path).",
119 flags: &["to", "expected-revision"],
120 },
121 VerbHelp {
122 name: "rm",
123 summary: "Permanently remove a node and (recursively) its subtree.",
124 flags: &["recursive", "expected-revision"],
125 },
126 VerbHelp {
127 name: "rmattr",
128 summary: "Remove a custom attribute from a node.",
129 flags: &["expected-revision"],
130 },
131 VerbHelp {
132 name: "setattr",
133 summary: "Set an opaque custom attribute on a node.",
134 flags: &["value", "expected-revision"],
135 },
136 VerbHelp {
137 name: "stat",
138 summary: "Print metadata for one path.",
139 flags: &["no-follow"],
140 },
141 VerbHelp {
142 name: "touch",
143 summary: "Update timestamps or create an empty regular file.",
144 flags: &["no-create", "expected-revision"],
145 },
146 VerbHelp {
147 name: "trash",
148 summary: "Move a node into recoverable trash.",
149 flags: &["expected-revision"],
150 },
151 VerbHelp {
152 name: "trash-ls",
153 summary: "List recoverable trash records (cursor-paginated).",
154 flags: &["cursor", "limit"],
155 },
156 VerbHelp {
157 name: "tree",
158 summary: "Recursively enumerate a subtree (cursor-paginated).",
159 flags: &["max-depth", "follow-symlinks", "cursor", "limit"],
160 },
161 VerbHelp {
162 name: "truncate",
163 summary: "Set a regular file's logical length.",
164 flags: &["length", "expected-revision"],
165 },
166 VerbHelp {
167 name: "usage",
168 summary: "Print workspace byte/node usage and quota limits.",
169 flags: &[],
170 },
171 VerbHelp {
172 name: "write",
173 summary: "Replace a regular file's contents (creates by default).",
174 flags: &["text", "no-create", "expected-revision"],
175 },
176 VerbHelp {
177 name: "write-at",
178 summary: "Write bytes beginning at a logical offset.",
179 flags: &["offset", "text", "no-create", "expected-revision"],
180 },
181];
182
183pub fn print_verb_table() {
187 let mut entries: Vec<&VerbHelp> = VERB_HELP.iter().collect();
188 entries.sort_by_key(|e| e.name);
189 let name_width = entries.iter().map(|e| e.name.len()).max().unwrap_or(0);
190 for entry in entries {
191 println!(
192 " {:<width$} {}",
193 entry.name,
194 entry.summary,
195 width = name_width,
196 );
197 }
198}
199
200pub fn print_verb_help(verb: &str) -> Option<&'static VerbHelp> {
208 let entry = VERB_HELP.iter().find(|e| e.name == verb)?;
209 println!("{}", entry.summary);
210 println!();
211 println!("Flags:");
212 if entry.flags.is_empty() {
213 println!(" (none)");
214 } else {
215 for flag in entry.flags {
216 println!(" --{flag}");
217 }
218 }
219 Some(entry)
220}