rgen_cli_lib/cmds/
search.rs1use anyhow::Result;
2use clap::Args;
3use colored::*;
4use rgen_core::RegistryClient;
5use serde_json;
6
7#[derive(Args, Debug)]
8pub struct SearchArgs {
9 pub query: String,
11
12 #[arg(short, long)]
14 pub category: Option<String>,
15
16 #[arg(short, long)]
18 pub keyword: Option<String>,
19
20 #[arg(short, long)]
22 pub author: Option<String>,
23
24 #[arg(long)]
26 pub stable: bool,
27
28 #[arg(short, long, default_value = "20")]
30 pub limit: usize,
31
32 #[arg(long)]
34 pub json: bool,
35
36 #[arg(short, long)]
38 pub detailed: bool,
39}
40
41pub async fn run(args: &SearchArgs) -> Result<()> {
42 let registry_client = RegistryClient::new()?;
43
44 let search_params = rgen_core::registry::SearchParams {
46 query: &args.query,
47 category: args.category.as_deref(),
48 keyword: args.keyword.as_deref(),
49 author: args.author.as_deref(),
50 stable_only: args.stable,
51 limit: args.limit,
52 };
53
54 let results = registry_client.advanced_search(&search_params).await?;
55
56 if args.json {
57 let json_output = serde_json::to_string_pretty(&results)?;
59 println!("{}", json_output);
60 } else {
61 if results.is_empty() {
63 println!("No rpacks found matching your criteria");
64 return Ok(());
65 }
66
67 println!("Found {} rpack(s):", results.len());
68 println!();
69
70 if args.detailed {
71 print_detailed_results(&results);
72 } else {
73 print_summary_results(&results);
74 }
75 }
76
77 Ok(())
78}
79
80fn print_summary_results(results: &[rgen_core::SearchResult]) {
81 println!(
83 "{:<40} {:<12} {:<20} {}",
84 "ID".bold(),
85 "LATEST".bold(),
86 "TAGS".bold(),
87 "DESCRIPTION".bold()
88 );
89 println!("{}", "-".repeat(80).dimmed());
90
91 for result in results {
93 let tags = result
94 .tags
95 .iter()
96 .map(|tag| format!("{}", tag.cyan()))
97 .collect::<Vec<_>>()
98 .join(", ");
99
100 let description = if result.description.len() > 30 {
101 format!("{}...", &result.description[..27])
102 } else {
103 result.description.clone()
104 };
105
106 println!(
107 "{:<40} {:<12} {:<20} {}",
108 result.id.green(),
109 result.latest_version.yellow(),
110 tags,
111 description
112 );
113 }
114}
115
116fn print_detailed_results(results: &[rgen_core::SearchResult]) {
117 for (i, result) in results.iter().enumerate() {
118 if i > 0 {
119 println!();
120 }
121
122 println!("{}", format!("{}. {}", i + 1, result.name).bold().green());
123 println!(" ID: {}", result.id.cyan());
124 println!(" Version: {}", result.latest_version.yellow());
125 println!(" Description: {}", result.description);
126
127 if !result.tags.is_empty() {
128 let tags = result
129 .tags
130 .iter()
131 .map(|tag| format!("{}", tag.cyan()))
132 .collect::<Vec<_>>()
133 .join(", ");
134 println!(" Tags: {}", tags);
135 }
136
137 if let Some(category) = &result.category {
138 println!(" Category: {}", category.magenta());
139 }
140
141 if let Some(author) = &result.author {
142 println!(" Author: {}", author.blue());
143 }
144
145 if let Some(downloads) = result.downloads {
146 println!(" Downloads: {}", format!("{}", downloads).dimmed());
147 }
148
149 if let Some(updated) = &result.updated {
150 println!(" Updated: {}", updated.format("%Y-%m-%d %H:%M:%S UTC"));
151 }
152 }
153}