1use clap::{Args, Parser, Subcommand};
2
3#[derive(Parser, Debug)]
5#[command(name = "cargo", bin_name = "cargo", version)]
6pub struct Cargo {
7 #[command(subcommand)]
8 pub command: CargoCommand,
9}
10
11#[derive(Subcommand, Debug)]
12pub enum CargoCommand {
13 Brief(BriefDirect),
15}
16
17#[derive(Parser, Debug)]
19#[command(
20 version,
21 about = "Visibility-aware Rust API extractor for AI agents",
22 after_help = "Run `cargo brief --help` for AI agent quick guide, or `cargo brief <cmd> --help` for details.",
23 after_long_help = "\
24QUICK GUIDE — which subcommand for which task:
25
26 \"What's the signature of X?\" → search [--members]
27 \"Show a module's full API surface\" → api [--depth N] [--compact]
28 \"Where is X defined? Show source\" → code [--refs]
29 \"What modules exist in this crate?\" → summary
30 \"What features does crate X have?\" → features [-C <crate>]
31 \"How is X used in practice?\" → examples [--tests]
32 \"Find structural patterns in AST\" → ts '<s-expr>'
33 \"Who calls X? All references\" → lsp references <symbol>
34 \"What breaks if I change X?\" → lsp blast-radius <symbol> [--depth N]
35 \"What does X call / who calls X?\" → lsp call-hierarchy <symbol> [--outgoing]
36
37TYPICAL WORKFLOW:
38 cargo brief summary self # 1. overview of modules
39 cargo brief api self::some_module # 2. drill into a module
40 cargo brief search self SomeType --members # 3. find a specific item
41 cargo brief code fn some_function --refs # 4. read source + references
42 cargo brief lsp references some_function # 5. cross-crate reference tracking
43
44REMOTE CRATES (-C):
45 cargo brief -C summary tokio@1 # explore an unfamiliar crate
46 cargo brief -C features serde@1 # inspect a crate's feature graph
47 cargo brief -C -F rt,net api tokio@1 net # feature-gated APIs need -F
48 cargo brief -C search serde@1 Serialize # search a crates.io dependency
49
50TIPS:
51 - Feature-gated items: run `features` to see what flags are available, then -F.
52 - api output annotates gated items (// requires feature \"...\") even when enabled.
53 - Smart-case: all-lowercase pattern = case-insensitive, any uppercase = exact.
54 - `code` searches ALL workspace members by default (not just current package).
55 - `lsp` resolves symbols by name. Workspace items are found instantly;
56 external deps (e.g., hecs::World) use usage-site fallback (slower).
57 Use unique names; common methods like \"new\" may still be ambiguous.
58 - `lsp` spawns a persistent rust-analyzer daemon; first query may be slow
59 while indexing. Use `lsp touch` to pre-warm.
60
61Run `cargo brief <subcommand> --help` for subcommand-specific options and examples."
62)]
63pub struct BriefDirect {
64 #[arg(short = 'C', long, global = true)]
66 pub crates: bool,
67
68 #[arg(
70 short = 'F',
71 long,
72 value_name = "FEATURES",
73 global = true,
74 requires = "crates"
75 )]
76 pub features: Option<String>,
77
78 #[arg(long, global = true, requires = "crates")]
80 pub no_default_features: bool,
81
82 #[arg(long, global = true, requires = "crates")]
84 pub no_cache: bool,
85
86 #[command(subcommand)]
87 pub command: BriefCommand,
88}
89
90impl BriefDirect {
91 pub fn remote_opts(&self) -> RemoteOpts {
93 RemoteOpts {
94 crates: self.crates,
95 features: self.features.clone(),
96 no_default_features: self.no_default_features,
97 no_cache: self.no_cache,
98 }
99 }
100}
101
102#[derive(Debug, Clone, Default)]
104pub struct RemoteOpts {
105 pub crates: bool,
106 pub features: Option<String>,
107 pub no_default_features: bool,
108 pub no_cache: bool,
109}
110
111#[derive(Subcommand, Debug, Clone)]
112pub enum BriefCommand {
113 #[command(after_help = "\
115EXAMPLES:
116 # Browse the current crate's API (run inside a Cargo project)
117 cargo brief api
118
119 # Browse a specific module in the current crate
120 cargo brief api self::net::tcp
121
122 # Inspect a crates.io dependency (cached after first run)
123 cargo brief -C api serde@1 --compact
124 cargo brief -C -F rt,net,io-util api tokio@1
125
126 # Browse a specific module of a remote crate
127 cargo brief -C api tokio@1::net
128 cargo brief -C -F net api tokio@1 net
129
130 # Reduce output verbosity for large crates
131 cargo brief -C api tokio@1 --compact
132 cargo brief -C api tokio@1 --doc-lines 1
133
134RESOLUTION RULES:
135 The <TARGET> argument is resolved as follows:
136 1. \"self\" → current package (cwd-based detection)
137 2. \"self::mod\" → current package, specific module
138 3. \"crate::mod\" → named crate + module in one argument
139 4. \"src/foo.rs\" → file path auto-converted to module path
140 5. \"crate_name\" → workspace package (hyphen/underscore normalized)
141 6. \"unknown_name\" → treated as package name (use \"self::mod\" for modules)
142
143 With -C, TARGET is the crate spec (e.g., serde@1, tokio@1.0).
144
145 The [MODULE_PATH] argument also accepts file paths (e.g., src/foo.rs).")]
146 Api(ApiArgs),
147
148 #[command(after_help = "\
150EXAMPLES:
151 # Substring search (smart-case: all-lowercase = insensitive)
152 cargo brief -C search axum@0.8 Router route
153 cargo brief -C search bevy ShaderRef Material
154
155 # OR-match with comma, methods-of
156 cargo brief search self \"EventReader,EventWriter\"
157 cargo brief -C search bytes@1 --methods-of Bytes
158
159 # Glob, exact match, exclusion
160 cargo brief search bevy \"Shader*Ref\" # * = 0+ chars, ? = 1 char
161 cargo brief search bevy \"=Router\" # final :: segment only
162 cargo brief search bevy -- spawn -test # -- needed for -prefix args
163 cargo brief search bevy \"*Plugin*,*Resource* -test\"
164
165 # Signature type filters
166 cargo brief search self \"\" --in-params PathBuf
167 cargo brief search self parse --in-returns \"Result -Vec\"
168
169PATTERN SYNTAX:
170 Smart-case: all-lowercase → case-insensitive, any uppercase → case-sensitive.
171 Space = AND, comma = OR. Multiple args are joined with spaces.
172
173 Operators (per token):
174 word substring — path contains \"word\"
175 w*ld glob — * matches 0+ chars, ? matches 1 char (full-path anchored)
176 =Name exact — final path segment (after last ::) equals \"Name\"
177 -term exclude — remove matches (works with substring, glob, or -=exact)
178
179 Exclusions are global across all OR groups.
180 Type filters use the same syntax against rendered type strings. Quote multi-token
181 filter values, e.g. --in-params \"TokenStream -Option\".")]
182 Search(SearchArgs),
183
184 #[command(after_help = "\
186EXAMPLES:
187 # List example files with their module docs
188 cargo brief examples self
189 cargo brief -C examples tokio@1
190
191 # Grep for a pattern in example files
192 cargo brief examples self spawn
193 cargo brief -C examples hecs spawn_at --context 3
194
195 # Multiple patterns are AND-matched (no quotes needed)
196 cargo brief examples self spawn async
197
198 # Include tests and benches directories
199 cargo brief -C examples serde --tests --benches derive
200
201MATCHING:
202 Multiple pattern arguments are joined with spaces (AND-matched).
203 Smart-case: all-lowercase pattern = case-insensitive, any uppercase = case-sensitive.
204 Without a pattern, lists files with their //! doc comments.")]
205 Examples(ExamplesArgs),
206
207 #[command(after_help = "\
209EXAMPLES:
210 # Summarize the current crate
211 cargo brief summary self
212
213 # Summarize a remote crate
214 cargo brief -C -F full summary tokio@1
215
216 # Summarize a specific module
217 cargo brief -C summary bevy bevy::ecs
218
219RESOLUTION RULES:
220 The <TARGET> argument is resolved as follows:
221 1. \"self\" → current package (cwd-based detection)
222 2. \"self::mod\" → current package, specific module
223 3. \"crate::mod\" → named crate + module in one argument
224 4. \"src/foo.rs\" → file path auto-converted to module path
225 5. \"crate_name\" → workspace package (hyphen/underscore normalized)
226 6. \"unknown_name\" → treated as package name
227
228 With -C, TARGET is the crate spec (e.g., serde@1, tokio@1.0).
229
230 The [MODULE_PATH] argument also accepts file paths (e.g., src/foo.rs).")]
231 Summary(SummaryArgs),
232
233 #[command(after_help = "\
235EXAMPLES:
236 # Find all function definitions
237 cargo brief ts self '(function_item)'
238
239 # Capture function names
240 cargo brief ts self '(function_item name: (identifier) @name)' --captures
241
242 # Find impl blocks for a specific trait
243 cargo brief ts self '(impl_item trait: (type_identifier) @t (#eq? @t \"MyTrait\"))'
244
245 # Find struct definitions with their fields
246 cargo brief ts self '(struct_item name: (type_identifier) @name body: (field_declaration_list) @fields)' --captures
247
248 # Find functions returning Result
249 cargo brief ts self '(function_item return_type: (generic_type type: (type_identifier) @r (#eq? @r \"Result\")))'
250
251 # Find let bindings with type annotations
252 cargo brief ts self '(let_declaration pattern: (_) @pat type: (_) @type)' --captures
253
254 # Find all call expressions to a specific function
255 cargo brief ts self '(call_expression function: (identifier) @fn (#eq? @fn \"spawn\"))'
256
257 # Location-only output for large result sets
258 cargo brief ts self '(function_item)' --quiet
259
260 # Limit results
261 cargo brief ts self '(function_item)' --limit 10
262
263 # Only search src/ (skip tests/examples/benches)
264 cargo brief ts self '(function_item)' --src-only
265
266 # Query a remote crate's source
267 cargo brief -C ts serde@1 '(struct_item)'
268
269QUERY SYNTAX:
270 Tree-sitter S-expression patterns match AST nodes by type and structure.
271 Explore the AST interactively: https://tree-sitter.github.io/tree-sitter/playground
272
273NODE TYPES (common Rust constructs):
274 Items: function_item, struct_item, enum_item, impl_item, trait_item,
275 type_item, const_item, static_item, macro_definition,
276 use_declaration, mod_item
277 Expressions: call_expression, method_call_expression, field_expression,
278 match_expression, if_expression, closure_expression,
279 return_expression, await_expression
280 Statements: let_declaration, expression_statement, assignment_expression
281 Types: type_identifier, generic_type, reference_type, array_type,
282 function_type, tuple_type
283 Other: attribute_item, line_comment, block_comment, string_literal,
284 identifier, field_identifier
285
286CAPTURES:
287 @name binds a node. In default mode, the outermost matched node is shown
288 (captures used only in predicates don't affect output). With --captures,
289 each @name: text pair is shown separately. Capture-less queries work too —
290 an internal @_match capture is auto-added.
291
292PREDICATES:
293 (#eq? @cap \"value\") — exact string match on captured node text
294 (#match? @cap \"regex\") — regex match on captured node text
295 (#not-eq? @cap \"value\") — negated exact match
296 (#any-of? @cap \"a\" \"b\") — match any of the listed strings
297
298TIPS:
299 - Rust async functions are function_item with modifiers, not a separate type
300 - Use (type_identifier) for type names, (identifier) for variable/fn names
301 - Nested captures: (struct_item (field_declaration_list
302 (field_declaration name: (field_identifier) @field)))
303 - Wildcards: (_) matches any single node type
304 - #[derive(...)] is: (attribute_item (attribute (identifier) @a (#eq? @a \"derive\")))")]
305 Ts(TsArgs),
306
307 #[command(after_help = "\
309EXAMPLES:
310 # Search current workspace (TARGET omitted — defaults to \"self\")
311 cargo brief code spawn
312 cargo brief code struct Commands
313
314 # Search a specific crate in the workspace
315 cargo brief code my-crate fn spawn
316 cargo brief code my-crate struct Commands
317
318 # Remote crate (TARGET required with -C)
319 cargo brief -C code serde@1 struct Serializer
320
321 # Smart-case: all-lowercase = case-insensitive
322 cargo brief code pubstruct # finds PubStruct
323 cargo brief code PubStruct # case-sensitive
324
325 # Show definitions + references
326 cargo brief code fn spawn --refs
327
328 # References only
329 cargo brief code spawn --refs-only
330
331 # Scope to items inside a type
332 cargo brief code --in Commands fn new
333 cargo brief code --in PubStruct field
334
335 # Quiet mode (location only, no source text)
336 cargo brief code fn spawn -q
337
338 # Limit results
339 cargo brief code fn spawn --limit 5
340
341POSITIONAL ARGS:
342 1 arg: code NAME search all workspace members, all kinds
343 (error if NAME is a kind keyword — use 2-arg form instead)
344 2 args: code KIND NAME if first arg is a kind keyword (see below)
345 code TARGET NAME otherwise: search named crate, all kinds
346 3 args: code TARGET KIND NAME search named crate, filter by kind
347
348 Disambiguation: if the first of two args matches a kind keyword, it is
349 treated as KIND (not TARGET). Use the 3-arg form to force a target that
350 happens to shadow a kind keyword.
351
352TARGET RESOLUTION:
353 \"self\" (default when TARGET omitted):
354 Searches ALL workspace members — not just the current package.
355 This differs from other subcommands where \"self\" = current package,
356 because code is a source-level lookup tool where project-wide search
357 is the common case.
358 Named crate:
359 Searches only that specific package (hyphen/underscore normalized).
360 With -C (remote):
361 TARGET is a crates.io spec (e.g., serde@1). Implicit \"self\" is not
362 allowed — you must provide an explicit TARGET.
363
364DEPENDENCY SEARCH:
365 Default: workspace members + accessible dependencies (via rustdoc JSON
366 reachability analysis; requires nightly).
367 --no-deps: workspace members (or named target) only.
368 --all-deps: workspace members + all direct dependencies (via cargo
369 metadata; no nightly needed, wider but noisier).
370
371ITEM KINDS:
372 fn, struct, enum, trait, field, type, impl, macro, const, use
373 Omit KIND to search all kinds (except use, to reduce noise).
374
375OUTPUT FORMAT:
376 Each match is printed as:
377 @<file>:<line> — source location
378 in <crate>::<module>[, <parent>] — module path + parent context
379 (e.g., impl Type, trait Trait)
380 <source text> — full item definition
381
382 With --quiet (-q), only the location and module-path lines are shown.
383
384NAME MATCHING:
385 Smart-case: all-lowercase pattern = case-insensitive, any uppercase =
386 case-sensitive. The name must match the item's identifier exactly (not
387 a substring).
388
389REFERENCE SEARCH (--refs, --refs-only):
390 After definitions, grep for literal name occurrences across the same
391 source files. Output uses * markers on match lines with 2 lines of
392 surrounding context. --refs-only skips definitions entirely.
393 --limit applies to definitions (--refs) or grep matches (--refs-only).
394
395PARENT SCOPING (--in <TYPE>):
396 Filter definitions to items inside a specific type, impl block, or
397 trait. Matches the type identifier with smart-case rules.
398 --in Commands matches impl Commands, impl T for Commands, etc.
399 --in commands case-insensitive match
400 Top-level items (not inside any type) are excluded.")]
401 Code(CodeArgs),
402
403 #[command(after_help = "\
405EXAMPLES:
406 # Show feature graph for the current workspace crate
407 cargo brief features
408
409 # Show feature graph for a specific workspace member
410 cargo brief features my-crate
411
412 # Show feature graph for a crates.io crate (requires -C)
413 cargo brief -C features serde@1
414 cargo brief -C features tokio@1")]
415 Features(FeaturesArgs),
416
417 #[command(after_help = "\
419EXAMPLES:
420 # Clear all cached workspaces
421 cargo brief clean
422
423 # Clear caches for a specific crate
424 cargo brief clean serde")]
425 Clean(CleanArgs),
426
427 #[command(after_help = "\
429EXAMPLES:
430 # Find all references to a symbol across the workspace
431 cargo brief lsp references resolve_symbol
432 cargo brief lsp references Foo::bar -q # quiet: locations only
433
434 # Blast radius: direct + transitive callers (\"what breaks if I change X?\")
435 cargo brief lsp blast-radius handle_request
436 cargo brief lsp blast-radius handle_request --depth 3
437
438 # Call hierarchy: who calls X (incoming) / what does X call (outgoing)
439 cargo brief lsp call-hierarchy spawn
440 cargo brief lsp call-hierarchy spawn --outgoing -q
441
442 # Daemon lifecycle (daemon auto-starts on first query)
443 cargo brief lsp touch # pre-warm rust-analyzer
444 cargo brief lsp status # check if running
445 cargo brief lsp stop # shut down daemon
446
447SYMBOL RESOLUTION:
448 Symbols are resolved in two stages:
449 1. workspace/symbol search (fast, finds workspace-defined items)
450 2. Fallback: grep workspace source for usage sites, then resolve via
451 textDocument/definition (slower, finds external deps like hecs::World)
452
453 Tips:
454 - Qualified names work: \"hecs::World\", \"App::new\", \"MyStruct::method\"
455 - Common names like \"new\" or \"get\" may return Ambiguous (many matches).
456 Use a qualified form to narrow down.
457 - call-hierarchy and blast-radius work on functions/methods, not types.
458 Use `references` for tracking struct/enum/trait usage.
459 - If resolution still fails, try `code --refs <name>` as a last resort.
460
461NOTE:
462 The LSP daemon spawns automatically on first query. Initial indexing may
463 take time; subsequent queries are fast. Use `lsp touch` to pre-warm.")]
464 Lsp(LspArgs),
465}
466
467#[derive(Args, Debug, Clone)]
471pub struct TargetArgs {
472 #[arg(value_name = "TARGET", default_value = "self")]
474 pub crate_name: String,
475
476 pub module_path: Option<String>,
478
479 #[arg(long, help_heading = "Local Workspace")]
481 pub at_package: Option<String>,
482
483 #[arg(long, help_heading = "Local Workspace")]
485 pub at_mod: Option<String>,
486
487 #[arg(long, help_heading = "Local Workspace")]
489 pub manifest_path: Option<String>,
490}
491
492#[derive(Args, Debug, Clone)]
494pub struct FilterArgs {
495 #[arg(long, help_heading = "Filtering")]
497 pub no_structs: bool,
498
499 #[arg(long, help_heading = "Filtering")]
501 pub no_enums: bool,
502
503 #[arg(long, help_heading = "Filtering")]
505 pub no_traits: bool,
506
507 #[arg(long, help_heading = "Filtering")]
509 pub no_functions: bool,
510
511 #[arg(long, help_heading = "Filtering")]
513 pub no_aliases: bool,
514
515 #[arg(long, help_heading = "Filtering")]
517 pub no_constants: bool,
518
519 #[arg(long, help_heading = "Filtering")]
521 pub no_unions: bool,
522
523 #[arg(long, help_heading = "Filtering")]
525 pub no_macros: bool,
526
527 #[arg(long, help_heading = "Filtering")]
529 pub no_docs: bool,
530
531 #[arg(long, help_heading = "Filtering")]
533 pub no_crate_docs: bool,
534
535 #[arg(long, value_name = "N", help_heading = "Filtering")]
537 pub doc_lines: Option<usize>,
538
539 #[arg(long, help_heading = "Filtering")]
541 pub compact: bool,
542
543 #[arg(long, help_heading = "Filtering")]
545 pub verbose_metadata: bool,
546
547 #[arg(long)]
549 pub all: bool,
550
551 #[arg(long, help_heading = "Filtering")]
553 pub no_feature_gates: bool,
554}
555
556#[derive(Args, Debug, Clone)]
558pub struct GlobalArgs {
559 #[arg(long, default_value = "nightly", help_heading = "Advanced")]
561 pub toolchain: String,
562
563 #[arg(short, long)]
565 pub verbose: bool,
566}
567
568#[derive(Args, Debug, Clone)]
572pub struct ApiArgs {
573 #[command(flatten)]
574 pub target: TargetArgs,
575
576 #[command(flatten)]
577 pub filter: FilterArgs,
578
579 #[command(flatten)]
580 pub global: GlobalArgs,
581
582 #[arg(long, default_value = "1")]
584 pub depth: u32,
585
586 #[arg(long)]
588 pub recursive: bool,
589
590 #[arg(long)]
592 pub no_expand_glob: bool,
593}
594
595#[derive(Args, Debug, Clone)]
597pub struct SearchArgs {
598 #[arg(value_name = "TARGET", default_value = "self")]
600 pub crate_name: String,
601
602 #[arg(value_name = "PATTERN", num_args = 0..)]
604 pub patterns: Vec<String>,
605
606 #[command(flatten)]
607 pub filter: FilterArgs,
608
609 #[command(flatten)]
610 pub global: GlobalArgs,
611
612 #[arg(long, help_heading = "Local Workspace")]
614 pub at_package: Option<String>,
615
616 #[arg(long, help_heading = "Local Workspace")]
618 pub at_mod: Option<String>,
619
620 #[arg(long, help_heading = "Local Workspace")]
622 pub manifest_path: Option<String>,
623
624 #[arg(long, value_name = "[OFFSET:]N")]
626 pub limit: Option<String>,
627
628 #[arg(long, value_name = "TYPE")]
630 pub methods_of: Option<String>,
631
632 #[arg(long, value_name = "KINDS", help_heading = "Filtering")]
634 pub search_kind: Option<String>,
635
636 #[arg(long)]
638 pub members: bool,
639
640 #[arg(long, value_name = "PATTERN", help_heading = "Filtering")]
642 pub in_params: Option<String>,
643
644 #[arg(long, value_name = "PATTERN", help_heading = "Filtering")]
646 pub in_returns: Option<String>,
647}
648
649impl SearchArgs {
650 pub fn pattern(&self) -> String {
652 self.patterns.join(" ")
653 }
654}
655
656#[derive(Args, Debug, Clone)]
658pub struct ExamplesArgs {
659 #[arg(value_name = "TARGET", default_value = "self")]
661 pub crate_name: String,
662
663 #[arg(value_name = "PATTERN", num_args = 0..)]
665 pub patterns: Vec<String>,
666
667 #[command(flatten)]
668 pub global: GlobalArgs,
669
670 #[arg(long, help_heading = "Local Workspace")]
672 pub manifest_path: Option<String>,
673
674 #[arg(long, default_value = "2")]
676 pub context: String,
677
678 #[arg(long, num_args(0..=1), default_missing_value = "999", value_name = "DEPTH")]
680 pub tests: Option<u32>,
681
682 #[arg(long, num_args(0..=1), default_missing_value = "999", value_name = "DEPTH")]
684 pub benches: Option<u32>,
685}
686
687#[derive(Args, Debug, Clone)]
689pub struct TsArgs {
690 #[arg(value_name = "TARGET")]
692 pub crate_name: String,
693
694 #[arg(value_name = "QUERY")]
696 pub query: String,
697
698 #[command(flatten)]
699 pub global: GlobalArgs,
700
701 #[arg(long, help_heading = "Local Workspace")]
703 pub manifest_path: Option<String>,
704
705 #[arg(long)]
707 pub captures: bool,
708
709 #[arg(long, default_value = "0")]
711 pub context: String,
712
713 #[arg(long)]
715 pub src_only: bool,
716
717 #[arg(long, value_name = "[OFFSET:]N")]
719 pub limit: Option<String>,
720
721 #[arg(short = 'q', long)]
723 pub quiet: bool,
724}
725
726#[derive(Args, Debug, Clone)]
728pub struct CodeArgs {
729 #[arg(value_name = "ARGS", num_args = 1..=3)]
731 pub args: Vec<String>,
732
733 #[command(flatten)]
734 pub global: GlobalArgs,
735
736 #[arg(long, help_heading = "Local Workspace")]
738 pub manifest_path: Option<String>,
739
740 #[arg(long)]
742 pub src_only: bool,
743
744 #[arg(long)]
746 pub no_deps: bool,
747
748 #[arg(long, conflicts_with = "no_deps")]
750 pub all_deps: bool,
751
752 #[arg(long, value_name = "[OFFSET:]N")]
754 pub limit: Option<String>,
755
756 #[arg(short = 'q', long)]
758 pub quiet: bool,
759
760 #[arg(long)]
762 pub refs: bool,
763
764 #[arg(long, conflicts_with = "refs")]
766 pub refs_only: bool,
767
768 #[arg(long, value_name = "TYPE")]
770 pub in_type: Option<String>,
771}
772
773#[derive(Args, Debug, Clone)]
775pub struct SummaryArgs {
776 #[command(flatten)]
777 pub target: TargetArgs,
778
779 #[command(flatten)]
780 pub global: GlobalArgs,
781}
782
783#[derive(Args, Debug, Clone)]
785pub struct FeaturesArgs {
786 #[arg(value_name = "CRATE", default_value = "self")]
788 pub crate_name: String,
789
790 #[command(flatten)]
791 pub global: GlobalArgs,
792
793 #[arg(long, help_heading = "Local Workspace")]
795 pub manifest_path: Option<String>,
796}
797
798#[derive(Args, Debug, Clone)]
800pub struct CleanArgs {
801 #[arg(value_name = "SPEC")]
803 pub spec: Option<String>,
804}
805
806#[derive(Args, Debug, Clone)]
808pub struct LspArgs {
809 #[command(subcommand)]
810 pub command: LspCommand,
811
812 #[command(flatten)]
813 pub global: GlobalArgs,
814
815 #[arg(long, help_heading = "Local Workspace")]
817 pub manifest_path: Option<String>,
818}
819
820#[derive(Subcommand, Debug, Clone)]
821pub enum LspCommand {
822 Touch {
824 #[arg(long)]
826 no_wait: bool,
827 },
828 Stop,
830 Status,
832 References {
834 symbol: String,
836 #[arg(long, short)]
838 quiet: bool,
839 },
840 BlastRadius {
842 symbol: String,
844 #[arg(long, default_value = "1")]
846 depth: u32,
847 #[arg(long, short)]
849 quiet: bool,
850 },
851 CallHierarchy {
853 symbol: String,
855 #[arg(long)]
857 outgoing: bool,
858 #[arg(long, short)]
860 quiet: bool,
861 },
862}
863
864impl ExamplesArgs {
865 pub fn pattern(&self) -> Option<String> {
867 if self.patterns.is_empty() {
868 None
869 } else {
870 Some(self.patterns.join(" "))
871 }
872 }
873}