Skip to main content

clean_dev_dirs/config/
filter.rs

1//! Filtering configuration for project selection.
2//!
3//! This module defines the filtering options, project type filters, and sorting
4//! criteria used to determine which projects should be scanned, cleaned, and
5//! how they should be ordered in the output.
6
7use clap::ValueEnum;
8
9/// Enumeration of supported project type filters.
10///
11/// This enum is used to restrict scanning and cleaning to specific types of
12/// development projects.
13#[derive(Clone, Copy, PartialEq, Eq, Debug, ValueEnum, Default)]
14pub enum ProjectFilter {
15    /// Include all supported project types
16    #[default]
17    All,
18
19    /// Include only Rust projects (Cargo.toml + target/)
20    Rust,
21
22    /// Include only Node.js projects (package.json + `node_modules`/)
23    Node,
24
25    /// Include only Python projects (Python config files + cache dirs)
26    Python,
27
28    /// Include only Go projects (go.mod + vendor/)
29    Go,
30
31    /// Include only Java/Kotlin projects (pom.xml or build.gradle + target/ or build/)
32    Java,
33
34    /// Include only C/C++ projects (CMakeLists.txt or Makefile + build/)
35    Cpp,
36
37    /// Include only Swift projects (Package.swift + .build/)
38    Swift,
39
40    /// Include only .NET/C# projects (.csproj + bin/ + obj/)
41    #[value(name = "dotnet")]
42    DotNet,
43
44    /// Include only Ruby projects (Gemfile + .bundle/ or vendor/bundle/)
45    Ruby,
46
47    /// Include only Elixir projects (mix.exs + _build/)
48    Elixir,
49
50    /// Include only Deno projects (deno.json + vendor/ or `node_modules`/)
51    Deno,
52
53    /// Include only PHP projects (composer.json + vendor/)
54    #[value(name = "php")]
55    Php,
56
57    /// Include only Haskell projects (stack.yaml or cabal.project + .stack-work/ or dist-newstyle/)
58    Haskell,
59
60    /// Include only Dart/Flutter projects (pubspec.yaml + `.dart_tool`/ or build/)
61    Dart,
62
63    /// Include only Zig projects (build.zig + zig-cache/ or zig-out/)
64    Zig,
65
66    /// Include only Scala projects (build.sbt + target/)
67    Scala,
68}
69
70/// Configuration for project filtering criteria.
71///
72/// This struct contains the filtering options used to determine which projects
73/// should be considered for cleanup based on size and modification time.
74#[derive(Clone)]
75pub struct FilterOptions {
76    /// Minimum size threshold for build directories
77    pub keep_size: String,
78
79    /// Minimum age in days for projects to be considered
80    pub keep_days: u32,
81}
82
83/// Enumeration of supported sorting criteria for project output.
84///
85/// This enum determines how projects are ordered in the output.
86/// Each variant has a natural default direction:
87/// - `Size`: largest first (descending)
88/// - `Age`: oldest first (ascending)
89/// - `Name`: alphabetical (ascending)
90/// - `Type`: grouped by type name alphabetically
91#[derive(Clone, Copy, PartialEq, Eq, Debug, ValueEnum)]
92pub enum SortCriteria {
93    /// Sort by build artifacts size (largest first by default)
94    Size,
95
96    /// Sort by build artifacts modification time (oldest first by default)
97    Age,
98
99    /// Sort by project name alphabetically (A-Z by default)
100    Name,
101
102    /// Sort by project type name alphabetically
103    Type,
104}
105
106/// Configuration for project sorting behavior.
107///
108/// Controls how the list of projects is ordered before display or processing.
109/// When `criteria` is `None`, projects are displayed in scan order.
110#[derive(Clone)]
111pub struct SortOptions {
112    /// The sorting criterion to apply, or `None` to preserve scan order
113    pub criteria: Option<SortCriteria>,
114
115    /// Whether to reverse the sort order
116    pub reverse: bool,
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_project_filter_equality() {
125        assert_eq!(ProjectFilter::All, ProjectFilter::All);
126        assert_eq!(ProjectFilter::Rust, ProjectFilter::Rust);
127        assert_eq!(ProjectFilter::Node, ProjectFilter::Node);
128        assert_eq!(ProjectFilter::Python, ProjectFilter::Python);
129        assert_eq!(ProjectFilter::Go, ProjectFilter::Go);
130        assert_eq!(ProjectFilter::Java, ProjectFilter::Java);
131        assert_eq!(ProjectFilter::Cpp, ProjectFilter::Cpp);
132        assert_eq!(ProjectFilter::Swift, ProjectFilter::Swift);
133        assert_eq!(ProjectFilter::DotNet, ProjectFilter::DotNet);
134        assert_eq!(ProjectFilter::Ruby, ProjectFilter::Ruby);
135        assert_eq!(ProjectFilter::Elixir, ProjectFilter::Elixir);
136        assert_eq!(ProjectFilter::Deno, ProjectFilter::Deno);
137        assert_eq!(ProjectFilter::Php, ProjectFilter::Php);
138        assert_eq!(ProjectFilter::Haskell, ProjectFilter::Haskell);
139        assert_eq!(ProjectFilter::Dart, ProjectFilter::Dart);
140        assert_eq!(ProjectFilter::Zig, ProjectFilter::Zig);
141        assert_eq!(ProjectFilter::Scala, ProjectFilter::Scala);
142
143        assert_ne!(ProjectFilter::All, ProjectFilter::Rust);
144        assert_ne!(ProjectFilter::Rust, ProjectFilter::Node);
145        assert_ne!(ProjectFilter::Node, ProjectFilter::Python);
146        assert_ne!(ProjectFilter::Python, ProjectFilter::Go);
147        assert_ne!(ProjectFilter::Go, ProjectFilter::Java);
148        assert_ne!(ProjectFilter::Java, ProjectFilter::Cpp);
149        assert_ne!(ProjectFilter::Cpp, ProjectFilter::Swift);
150        assert_ne!(ProjectFilter::Swift, ProjectFilter::DotNet);
151        assert_ne!(ProjectFilter::DotNet, ProjectFilter::Ruby);
152        assert_ne!(ProjectFilter::Ruby, ProjectFilter::Elixir);
153        assert_ne!(ProjectFilter::Elixir, ProjectFilter::Deno);
154        assert_ne!(ProjectFilter::Deno, ProjectFilter::Php);
155        assert_ne!(ProjectFilter::Php, ProjectFilter::Haskell);
156        assert_ne!(ProjectFilter::Haskell, ProjectFilter::Dart);
157        assert_ne!(ProjectFilter::Dart, ProjectFilter::Zig);
158        assert_ne!(ProjectFilter::Zig, ProjectFilter::Scala);
159    }
160
161    #[test]
162    fn test_project_filter_copy() {
163        let original = ProjectFilter::Rust;
164        let copied = original;
165
166        assert_eq!(original, copied);
167    }
168
169    #[test]
170    fn test_project_filter_default() {
171        let default_filter = ProjectFilter::default();
172        assert_eq!(default_filter, ProjectFilter::All);
173    }
174
175    #[test]
176    fn test_filter_options_creation() {
177        let filter_opts = FilterOptions {
178            keep_size: "100MB".to_string(),
179            keep_days: 30,
180        };
181
182        assert_eq!(filter_opts.keep_size, "100MB");
183        assert_eq!(filter_opts.keep_days, 30);
184    }
185
186    #[test]
187    fn test_filter_options_clone() {
188        let original = FilterOptions {
189            keep_size: "100MB".to_string(),
190            keep_days: 30,
191        };
192        let cloned = original.clone();
193
194        assert_eq!(original.keep_size, cloned.keep_size);
195        assert_eq!(original.keep_days, cloned.keep_days);
196    }
197
198    #[test]
199    fn test_sort_criteria_equality() {
200        assert_eq!(SortCriteria::Size, SortCriteria::Size);
201        assert_eq!(SortCriteria::Age, SortCriteria::Age);
202        assert_eq!(SortCriteria::Name, SortCriteria::Name);
203        assert_eq!(SortCriteria::Type, SortCriteria::Type);
204
205        assert_ne!(SortCriteria::Size, SortCriteria::Age);
206        assert_ne!(SortCriteria::Name, SortCriteria::Type);
207    }
208
209    #[test]
210    fn test_sort_criteria_copy() {
211        let original = SortCriteria::Size;
212        let copied = original;
213        assert_eq!(original, copied);
214    }
215
216    #[test]
217    fn test_sort_options_creation() {
218        let sort_opts = SortOptions {
219            criteria: Some(SortCriteria::Size),
220            reverse: false,
221        };
222        assert_eq!(sort_opts.criteria, Some(SortCriteria::Size));
223        assert!(!sort_opts.reverse);
224    }
225
226    #[test]
227    fn test_sort_options_none_criteria() {
228        let sort_opts = SortOptions {
229            criteria: None,
230            reverse: false,
231        };
232        assert!(sort_opts.criteria.is_none());
233    }
234
235    #[test]
236    fn test_sort_options_clone() {
237        let original = SortOptions {
238            criteria: Some(SortCriteria::Age),
239            reverse: true,
240        };
241        let cloned = original.clone();
242
243        assert_eq!(original.criteria, cloned.criteria);
244        assert_eq!(original.reverse, cloned.reverse);
245    }
246}