1use super::data::EntryData;
4use crate::models::EntryType;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum EntryFilter {
9 All,
11 Aliases,
13 Functions,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum GroupMode {
20 None,
22 Aliases,
24 Functions,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum SortOrder {
31 Ascending,
33 Descending,
35}
36
37#[derive(Debug, Clone)]
39pub struct FilterState {
40 filter: EntryFilter,
42 group_mode: GroupMode,
44 sort_order: SortOrder,
46}
47
48impl Default for FilterState {
49 fn default() -> Self {
50 Self {
51 filter: EntryFilter::All,
52 group_mode: GroupMode::Aliases, sort_order: SortOrder::Ascending, }
55 }
56}
57
58impl FilterState {
59 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn filter(&self) -> EntryFilter {
66 self.filter
67 }
68
69 pub fn group_mode(&self) -> GroupMode {
71 self.group_mode
72 }
73
74 pub fn sort_order(&self) -> SortOrder {
76 self.sort_order
77 }
78
79 pub fn cycle_filter(&mut self) {
81 self.filter = match self.filter {
82 EntryFilter::All => EntryFilter::Aliases,
83 EntryFilter::Aliases => EntryFilter::Functions,
84 EntryFilter::Functions => EntryFilter::All,
85 };
86 }
87
88 pub fn cycle_filter_backward(&mut self) {
90 self.filter = match self.filter {
91 EntryFilter::All => EntryFilter::Functions,
92 EntryFilter::Functions => EntryFilter::Aliases,
93 EntryFilter::Aliases => EntryFilter::All,
94 };
95 }
96
97 pub fn set_filter(
99 &mut self,
100 filter: EntryFilter,
101 ) {
102 self.filter = filter;
103 }
104
105 pub fn cycle_group_mode(&mut self) {
107 self.group_mode = match self.group_mode {
108 GroupMode::None => GroupMode::Aliases,
109 GroupMode::Aliases => GroupMode::Functions,
110 GroupMode::Functions => GroupMode::None,
111 };
112 }
113
114 pub fn cycle_group_mode_backward(&mut self) {
116 self.group_mode = match self.group_mode {
117 GroupMode::None => GroupMode::Functions,
118 GroupMode::Functions => GroupMode::Aliases,
119 GroupMode::Aliases => GroupMode::None,
120 };
121 }
122
123 pub fn toggle_sort_order(&mut self) {
125 self.sort_order = match self.sort_order {
126 SortOrder::Ascending => SortOrder::Descending,
127 SortOrder::Descending => SortOrder::Ascending,
128 };
129 }
130
131 pub fn update_visible_entries(
133 &self,
134 data: &mut EntryData,
135 search_query: &str,
136 ) {
137 let query = search_query.to_lowercase();
138
139 *data.visible_indices_mut() = data
141 .entries()
142 .iter()
143 .enumerate()
144 .filter(|(_, entry)| self.matches_filter(entry))
145 .filter(|(_, entry)| self.matches_search(entry, &query))
146 .map(|(idx, _)| idx)
147 .collect();
148
149 self.apply_grouping_and_sorting(data);
151 }
152
153 fn matches_filter(
155 &self,
156 entry: &crate::models::AliasEntry,
157 ) -> bool {
158 match self.filter {
159 EntryFilter::All => true,
160 EntryFilter::Aliases => entry.entry_type == EntryType::Alias,
161 EntryFilter::Functions => entry.entry_type == EntryType::Function,
162 }
163 }
164
165 fn matches_search(
167 &self,
168 entry: &crate::models::AliasEntry,
169 query: &str,
170 ) -> bool {
171 if query.is_empty() {
172 return true;
173 }
174 let name_match = entry.name.to_lowercase().contains(query);
176 let value_match = entry.value.to_lowercase().contains(query);
177 let comment_match = entry
178 .comments
179 .as_ref()
180 .map(|comments| comments.iter().any(|c| c.to_lowercase().contains(query)))
181 .unwrap_or(false);
182 name_match || value_match || comment_match
183 }
184
185 fn apply_grouping_and_sorting(
187 &self,
188 data: &mut EntryData,
189 ) {
190 let sort_order = self.sort_order;
191
192 match self.group_mode {
193 GroupMode::None => {
194 data.sort_visible_indices(|entry_a, entry_b| match sort_order {
196 SortOrder::Ascending => entry_a.name.cmp(&entry_b.name),
197 SortOrder::Descending => entry_b.name.cmp(&entry_a.name),
198 });
199 },
200 GroupMode::Aliases => {
201 data.sort_visible_indices(|entry_a, entry_b| {
203 match (entry_a.entry_type, entry_b.entry_type) {
205 (EntryType::Alias, EntryType::Function) => std::cmp::Ordering::Less,
206 (EntryType::Function, EntryType::Alias) => std::cmp::Ordering::Greater,
207 _ => {
208 match sort_order {
210 SortOrder::Ascending => entry_a.name.cmp(&entry_b.name),
211 SortOrder::Descending => entry_b.name.cmp(&entry_a.name),
212 }
213 },
214 }
215 });
216 },
217 GroupMode::Functions => {
218 data.sort_visible_indices(|entry_a, entry_b| {
220 match (entry_a.entry_type, entry_b.entry_type) {
222 (EntryType::Function, EntryType::Alias) => std::cmp::Ordering::Less,
223 (EntryType::Alias, EntryType::Function) => std::cmp::Ordering::Greater,
224 _ => {
225 match sort_order {
227 SortOrder::Ascending => entry_a.name.cmp(&entry_b.name),
228 SortOrder::Descending => entry_b.name.cmp(&entry_a.name),
229 }
230 },
231 }
232 });
233 },
234 }
235 }
236}
237
238#[cfg(test)]
239#[path = "filter_tests.rs"]
240mod filter_tests;