1use super::{
5 build::{BuildConfig, BuildSystem},
6 PackageManager,
7};
8use crate::errors::Result;
9use clap::{Parser, Subcommand};
10use std::path::PathBuf;
11
12#[derive(Parser)]
14#[command(name = "pdm")]
15#[command(about = "Palladium package manager - Manage your legendary packages")]
16#[command(version)]
17pub struct Cli {
18 #[command(subcommand)]
19 pub command: Commands,
20}
21
22#[derive(Subcommand)]
23pub enum Commands {
24 New {
26 name: String,
28 #[arg(long)]
30 path: Option<PathBuf>,
31 },
32
33 Init {
35 #[arg(long)]
37 name: Option<String>,
38 },
39
40 Build {
42 #[arg(long, short)]
44 release: bool,
45 #[arg(long)]
47 llvm: bool,
48 #[arg(long, short)]
50 verbose: bool,
51 #[arg(long, short, default_value_t = 0)]
53 jobs: usize,
54 #[arg(long)]
56 features: Vec<String>,
57 },
58
59 Run {
61 #[arg(long, short)]
63 release: bool,
64 #[arg(trailing_var_arg = true)]
66 args: Vec<String>,
67 },
68
69 Test {
71 filter: Option<String>,
73 #[arg(long, short)]
75 release: bool,
76 #[arg(long, short)]
78 verbose: bool,
79 },
80
81 Clean,
83
84 Add {
86 name: String,
88 #[arg(default_value = "*")]
90 version: String,
91 #[arg(long)]
93 dev: bool,
94 },
95
96 Remove {
98 name: String,
100 #[arg(long)]
102 dev: bool,
103 },
104
105 Update {
107 package: Option<String>,
109 },
110
111 Search {
113 query: String,
115 #[arg(long, default_value_t = 10)]
117 limit: usize,
118 },
119
120 Info {
122 name: String,
124 },
125
126 Publish {
128 #[arg(long)]
130 dry_run: bool,
131 },
132
133 Install {
135 name: String,
137 #[arg(long)]
139 version: Option<String>,
140 },
141
142 Uninstall {
144 name: String,
146 },
147
148 List {
150 #[arg(long)]
152 global: bool,
153 #[arg(long)]
155 tree: bool,
156 },
157}
158
159impl Cli {
160 pub fn execute(self) -> Result<()> {
162 match self.command {
163 Commands::New { name, path } => {
164 let target_path = path.unwrap_or_else(|| PathBuf::from(&name));
165
166 if target_path.exists() {
167 return Err(crate::errors::CompileError::Generic(format!(
168 "Directory '{}' already exists",
169 target_path.display()
170 )));
171 }
172
173 std::fs::create_dir_all(&target_path)?;
174 PackageManager::init(&name, &target_path)?;
175
176 println!("\n๐ Next steps:");
177 println!(" cd {}", target_path.display());
178 println!(" pdm build");
179 println!(" pdm run");
180 }
181
182 Commands::Init { name } => {
183 let current_dir = std::env::current_dir()?;
184 let package_name = name.unwrap_or_else(|| {
185 current_dir
186 .file_name()
187 .and_then(|n| n.to_str())
188 .unwrap_or("my_package")
189 .to_string()
190 });
191
192 PackageManager::init(&package_name, ¤t_dir)?;
193 }
194
195 Commands::Build {
196 release,
197 llvm,
198 verbose,
199 jobs,
200 features,
201 } => {
202 let config = BuildConfig {
203 release,
204 use_llvm: llvm,
205 verbose,
206 jobs: if jobs == 0 {
207 super::build::num_cpus::get()
208 } else {
209 jobs
210 },
211 features: features.into_iter().collect(),
212 ..Default::default()
213 };
214
215 let mut build_system = BuildSystem::new(config);
216 build_system.build()?;
217 }
218
219 Commands::Run { release, args } => {
220 let config = BuildConfig {
221 release,
222 ..Default::default()
223 };
224
225 let mut build_system = BuildSystem::new(config);
226 build_system.run(args)?;
227 }
228
229 Commands::Test {
230 filter,
231 release,
232 verbose,
233 } => {
234 let config = BuildConfig {
235 release,
236 verbose,
237 ..Default::default()
238 };
239
240 let mut build_system = BuildSystem::new(config);
241 build_system.test(filter.as_deref())?;
242 }
243
244 Commands::Clean => {
245 let build_system = BuildSystem::new(BuildConfig::default());
246 build_system.clean()?;
247 }
248
249 Commands::Add { name, version, dev } => {
250 let mut pm = PackageManager::new()?;
251 pm.add_dependency(&name, &version, dev)?;
252 }
253
254 Commands::Remove { name: _, dev: _ } => {
255 println!("๐ง Remove command not yet implemented");
256 }
258
259 Commands::Update { package: _ } => {
260 println!("๐ง Update command not yet implemented");
261 }
263
264 Commands::Search { query, limit } => {
265 println!("๐ Searching for '{}'...", query);
266 println!("๐ง Search functionality not yet implemented");
267 println!(" (Would show up to {} results)", limit);
268 }
270
271 Commands::Info { name } => {
272 println!("๐ฆ Package: {}", name);
273 println!("๐ง Info command not yet implemented");
274 }
276
277 Commands::Publish { dry_run } => {
278 if dry_run {
279 println!("๐งช Dry run mode");
280 }
281 println!("๐ง Publish command not yet implemented");
282 }
284
285 Commands::Install { name, version } => {
286 println!(
287 "๐ฅ Installing {} {}",
288 name,
289 version.as_deref().unwrap_or("latest")
290 );
291 println!("๐ง Install command not yet implemented");
292 }
294
295 Commands::Uninstall { name } => {
296 println!("๐ค Uninstalling {}", name);
297 println!("๐ง Uninstall command not yet implemented");
298 }
300
301 Commands::List { global, tree } => {
302 if global {
303 println!("๐ Global packages:");
304 } else {
305 println!("๐ฆ Local dependencies:");
306 }
307
308 if tree {
309 println!("๐ณ Dependency tree view");
310 }
311
312 println!("๐ง List command not yet implemented");
313 }
315 }
316
317 Ok(())
318 }
319}
320
321pub fn run_cli() -> Result<()> {
323 let cli = Cli::parse();
324 cli.execute()
325}
326
327#[cfg(test)]
328mod tests {
329 use super::*;
330
331 #[test]
332 fn test_cli_parsing() {
333 let _cli = Cli::try_parse_from(&["pdm", "build", "--release"]);
335 }
336}