@@ -84,6 +84,24 @@ enum Commands {
8484 #[ arg( short, long) ]
8585 debug : bool ,
8686 } ,
87+ /// List all items in a crate (using rust-analyzer)
88+ ListCrateItems {
89+ /// Crate name (e.g., serde)
90+ #[ arg( long) ]
91+ crate_name : String ,
92+ /// Crate version (e.g., 1.0.0)
93+ #[ arg( long) ]
94+ version : String ,
95+ /// Filter by item type (struct, enum, trait, fn, macro, mod)
96+ #[ arg( long) ]
97+ item_type : Option < String > ,
98+ /// Filter by visibility (pub, private)
99+ #[ arg( long) ]
100+ visibility : Option < String > ,
101+ /// Filter by module path (e.g., serde::de)
102+ #[ arg( long) ]
103+ module : Option < String > ,
104+ } ,
87105}
88106
89107#[ tokio:: main]
@@ -118,6 +136,23 @@ async fn main() -> Result<()> {
118136 max_tokens,
119137 debug
120138 } ) . await ,
139+ Commands :: ListCrateItems {
140+ crate_name,
141+ version,
142+ item_type,
143+ visibility,
144+ module,
145+ } => {
146+ use cratedocs_mcp:: tools:: item_list:: { list_crate_items, ItemListFilters } ;
147+ let filters = ItemListFilters {
148+ item_type,
149+ visibility,
150+ module,
151+ } ;
152+ let result = list_crate_items ( & crate_name, & version, Some ( filters) ) . await ?;
153+ println ! ( "{}" , result) ;
154+ Ok ( ( ) )
155+ }
121156 }
122157}
123158
@@ -182,32 +217,25 @@ fn apply_tldr(input: &str) -> String {
182217 let mut output = Vec :: new ( ) ;
183218 let mut skip = false ;
184219
185- let license_re = Regex :: new ( r"(?i)^\s*#+\s*license\b" ) . unwrap ( ) ;
186- let version_re = Regex :: new ( r"(?i)^\s*#+\s*version(s)?\b" ) . unwrap ( ) ;
187- let heading_re = Regex :: new ( r"^\s*#+\s*\S+" ) . unwrap ( ) ;
220+ // Match any heading (with or without space) for LICENSE or VERSION(S)
221+ let tldr_section_re = Regex :: new ( r"(?i)^\s*#+\s*license\b|^\s*#+\s*version(s)?\b|^\s*#+license\b|^\s*#+version(s)?\b" ) . unwrap ( ) ;
222+ // Match any heading (for ending the skip)
223+ let heading_re = Regex :: new ( r"^\s*#+" ) . unwrap ( ) ;
188224
189- let mut just_skipped_section = false ;
190225 for line in input. lines ( ) {
191226 // Start skipping if we hit a LICENSE or VERSION(S) heading
192- if !skip && ( license_re . is_match ( line) || version_re . is_match ( line ) ) {
227+ if !skip && tldr_section_re . is_match ( line) {
193228 skip = true ;
194- just_skipped_section = true ;
195229 continue ; // skip the heading line itself
196230 }
197- // If we just skipped a section heading, also skip blank lines and lines containing only "license" or "versions"
198- if just_skipped_section && ( line. trim ( ) . is_empty ( ) || line. trim ( ) . eq_ignore_ascii_case ( "license" ) || line. trim ( ) . eq_ignore_ascii_case ( "versions" ) || line. trim ( ) . eq_ignore_ascii_case ( "version" ) ) {
199- continue ;
200- }
201231 // Stop skipping at the next heading (but do not skip the heading itself)
202- if skip && heading_re. is_match ( line) {
232+ if skip && heading_re. is_match ( line) && !tldr_section_re . is_match ( line ) {
203233 skip = false ;
204- just_skipped_section = false ;
205234 }
206235 if !skip {
207236 output. push ( line) ;
208237 }
209238 }
210- // If the section to skip is at the end, skip will remain true and those lines will be omitted.
211239 output. join ( "\n " )
212240}
213241
0 commit comments