1use std::path::{Path, PathBuf};
2use std::fs;
3use clap::{Parser, ArgAction};
4use inquire::{Select, MultiSelect};
5
6#[derive(Parser, Debug)]
7#[command(author, version, about = "Analyzes TypeScript/JavaScript modules for imports and exports")]
8pub struct Cli {
9 #[arg(short, long, value_name = "PATH", default_value = ".")]
11 pub path: String,
12
13 #[arg(short, long, action = ArgAction::SetTrue)]
15 pub interactive: bool,
16
17 #[arg(short, long, value_name = "FILE")]
19 pub output: Option<String>,
20}
21
22pub fn get_subdirectories(dir: &Path) -> Vec<PathBuf> {
23 let mut subdirs = Vec::new();
24
25 if let Ok(entries) = fs::read_dir(dir) {
26 for entry in entries.filter_map(|e| e.ok()) {
27 let path = entry.path();
28 if path.is_dir() {
29 subdirs.push(path);
30 }
31 }
32 }
33
34 subdirs
35}
36
37pub fn select_directory(interactive: bool, path: &str) -> PathBuf {
38 if !interactive {
39 return PathBuf::from(path);
40 }
41
42 let current_dir = std::env::current_dir().expect("Failed to get current directory");
43 let mut dirs = get_subdirectories(¤t_dir);
44
45 if dirs.is_empty() {
46 println!("No subdirectories found in current directory.");
47 return current_dir;
48 }
49
50 dirs.insert(0, current_dir.clone());
51
52 let options: Vec<String> = dirs.iter()
53 .map(|p| p.to_string_lossy().to_string())
54 .collect();
55
56 let default_option = options[0].clone();
57
58 let selection = Select::new("Select directory to analyze:", options)
59 .prompt()
60 .unwrap_or_else(|_| default_option);
61
62 PathBuf::from(selection)
63}
64
65pub fn select_files(interactive: bool, target_dir: &Path, all_files: Vec<PathBuf>) -> Vec<PathBuf> {
66 if !interactive || all_files.is_empty() {
67 return all_files;
68 }
69
70 let file_options: Vec<String> = all_files.iter()
71 .map(|p| p.strip_prefix(target_dir).unwrap_or(p).to_string_lossy().to_string())
72 .collect();
73
74 let selected = MultiSelect::new(
75 "Select files to analyze (Space to select, Enter to confirm):",
76 file_options
77 )
78 .prompt()
79 .unwrap_or_else(|_| Vec::new());
80
81 if selected.is_empty() {
82 println!("No files selected, analyzing all files");
83 all_files
84 } else {
85 selected.into_iter()
86 .map(|s| target_dir.join(s))
87 .collect()
88 }
89}