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
54/// Configuration for project filtering criteria.
55///
56/// This struct contains the filtering options used to determine which projects
57/// should be considered for cleanup based on size and modification time.
58#[derive(Clone)]
59pub struct FilterOptions {
60    /// Minimum size threshold for build directories
61    pub keep_size: String,
62
63    /// Minimum age in days for projects to be considered
64    pub keep_days: u32,
65}
66
67/// Enumeration of supported sorting criteria for project output.
68///
69/// This enum determines how projects are ordered in the output.
70/// Each variant has a natural default direction:
71/// - `Size`: largest first (descending)
72/// - `Age`: oldest first (ascending)
73/// - `Name`: alphabetical (ascending)
74/// - `Type`: grouped by type name alphabetically
75#[derive(Clone, Copy, PartialEq, Eq, Debug, ValueEnum)]
76pub enum SortCriteria {
77    /// Sort by build artifacts size (largest first by default)
78    Size,
79
80    /// Sort by build artifacts modification time (oldest first by default)
81    Age,
82
83    /// Sort by project name alphabetically (A-Z by default)
84    Name,
85
86    /// Sort by project type name alphabetically
87    Type,
88}
89
90/// Configuration for project sorting behavior.
91///
92/// Controls how the list of projects is ordered before display or processing.
93/// When `criteria` is `None`, projects are displayed in scan order.
94#[derive(Clone)]
95pub struct SortOptions {
96    /// The sorting criterion to apply, or `None` to preserve scan order
97    pub criteria: Option<SortCriteria>,
98
99    /// Whether to reverse the sort order
100    pub reverse: bool,
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_project_filter_equality() {
109        assert_eq!(ProjectFilter::All, ProjectFilter::All);
110        assert_eq!(ProjectFilter::Rust, ProjectFilter::Rust);
111        assert_eq!(ProjectFilter::Node, ProjectFilter::Node);
112        assert_eq!(ProjectFilter::Python, ProjectFilter::Python);
113        assert_eq!(ProjectFilter::Go, ProjectFilter::Go);
114        assert_eq!(ProjectFilter::Java, ProjectFilter::Java);
115        assert_eq!(ProjectFilter::Cpp, ProjectFilter::Cpp);
116        assert_eq!(ProjectFilter::Swift, ProjectFilter::Swift);
117        assert_eq!(ProjectFilter::DotNet, ProjectFilter::DotNet);
118        assert_eq!(ProjectFilter::Ruby, ProjectFilter::Ruby);
119        assert_eq!(ProjectFilter::Elixir, ProjectFilter::Elixir);
120        assert_eq!(ProjectFilter::Deno, ProjectFilter::Deno);
121
122        assert_ne!(ProjectFilter::All, ProjectFilter::Rust);
123        assert_ne!(ProjectFilter::Rust, ProjectFilter::Node);
124        assert_ne!(ProjectFilter::Node, ProjectFilter::Python);
125        assert_ne!(ProjectFilter::Python, ProjectFilter::Go);
126        assert_ne!(ProjectFilter::Go, ProjectFilter::Java);
127        assert_ne!(ProjectFilter::Java, ProjectFilter::Cpp);
128        assert_ne!(ProjectFilter::Cpp, ProjectFilter::Swift);
129        assert_ne!(ProjectFilter::Swift, ProjectFilter::DotNet);
130        assert_ne!(ProjectFilter::DotNet, ProjectFilter::Ruby);
131        assert_ne!(ProjectFilter::Ruby, ProjectFilter::Elixir);
132        assert_ne!(ProjectFilter::Elixir, ProjectFilter::Deno);
133    }
134
135    #[test]
136    fn test_project_filter_copy() {
137        let original = ProjectFilter::Rust;
138        let copied = original;
139
140        assert_eq!(original, copied);
141    }
142
143    #[test]
144    fn test_project_filter_default() {
145        let default_filter = ProjectFilter::default();
146        assert_eq!(default_filter, ProjectFilter::All);
147    }
148
149    #[test]
150    fn test_filter_options_creation() {
151        let filter_opts = FilterOptions {
152            keep_size: "100MB".to_string(),
153            keep_days: 30,
154        };
155
156        assert_eq!(filter_opts.keep_size, "100MB");
157        assert_eq!(filter_opts.keep_days, 30);
158    }
159
160    #[test]
161    fn test_filter_options_clone() {
162        let original = FilterOptions {
163            keep_size: "100MB".to_string(),
164            keep_days: 30,
165        };
166        let cloned = original.clone();
167
168        assert_eq!(original.keep_size, cloned.keep_size);
169        assert_eq!(original.keep_days, cloned.keep_days);
170    }
171
172    #[test]
173    fn test_sort_criteria_equality() {
174        assert_eq!(SortCriteria::Size, SortCriteria::Size);
175        assert_eq!(SortCriteria::Age, SortCriteria::Age);
176        assert_eq!(SortCriteria::Name, SortCriteria::Name);
177        assert_eq!(SortCriteria::Type, SortCriteria::Type);
178
179        assert_ne!(SortCriteria::Size, SortCriteria::Age);
180        assert_ne!(SortCriteria::Name, SortCriteria::Type);
181    }
182
183    #[test]
184    fn test_sort_criteria_copy() {
185        let original = SortCriteria::Size;
186        let copied = original;
187        assert_eq!(original, copied);
188    }
189
190    #[test]
191    fn test_sort_options_creation() {
192        let sort_opts = SortOptions {
193            criteria: Some(SortCriteria::Size),
194            reverse: false,
195        };
196        assert_eq!(sort_opts.criteria, Some(SortCriteria::Size));
197        assert!(!sort_opts.reverse);
198    }
199
200    #[test]
201    fn test_sort_options_none_criteria() {
202        let sort_opts = SortOptions {
203            criteria: None,
204            reverse: false,
205        };
206        assert!(sort_opts.criteria.is_none());
207    }
208
209    #[test]
210    fn test_sort_options_clone() {
211        let original = SortOptions {
212            criteria: Some(SortCriteria::Age),
213            reverse: true,
214        };
215        let cloned = original.clone();
216
217        assert_eq!(original.criteria, cloned.criteria);
218        assert_eq!(original.reverse, cloned.reverse);
219    }
220}