|
1 | 1 | // SPDX-License-Identifier: Apache-2.0 |
2 | 2 | // SPDX-FileCopyrightText: Copyright the Vortex contributors |
3 | 3 |
|
| 4 | +use fuzzy_matcher::FuzzyMatcher; |
| 5 | +use fuzzy_matcher::skim::SkimMatcherV2; |
4 | 6 | use humansize::{DECIMAL, make_format}; |
| 7 | +use itertools::Itertools; |
5 | 8 | use ratatui::buffer::Buffer; |
6 | 9 | use ratatui::layout::{Constraint, Direction, Layout, Rect}; |
7 | 10 | use ratatui::style::{Color, Style, Stylize}; |
@@ -218,44 +221,71 @@ fn render_children_list(app: &mut AppState, area: Rect, buf: &mut Buffer) { |
218 | 221 | let layout = app.cursor.layout(); |
219 | 222 |
|
220 | 223 | if layout.nchildren() > 0 { |
221 | | - let filter: Vec<bool> = layout |
222 | | - .child_names() |
223 | | - .map(|name| { |
224 | | - if search_filter.is_empty() { |
225 | | - true |
226 | | - } else { |
227 | | - name.contains(&search_filter) |
228 | | - } |
229 | | - }) |
230 | | - .collect(); |
231 | | - |
232 | | - let list_items: Vec<String> = layout |
233 | | - .child_names() |
234 | | - .zip(filter.iter()) |
235 | | - .filter_map(|(name, keep)| keep.then_some(name.to_string())) |
236 | | - .collect(); |
| 224 | + if search_filter.is_empty() { |
| 225 | + // No search filter, show all items |
| 226 | + let list_items = layout |
| 227 | + .child_names() |
| 228 | + .map(|name| name.to_string()) |
| 229 | + .collect_vec(); |
| 230 | + |
| 231 | + app.filter = None; |
| 232 | + render_child_list_items(app, area, buf, list_items); |
| 233 | + } else { |
| 234 | + // Use fuzzy matching to rank and filter results |
| 235 | + let matcher = SkimMatcherV2::default(); |
| 236 | + |
| 237 | + // Collect scored matches |
| 238 | + let mut scored_matches = layout |
| 239 | + .child_names() |
| 240 | + .enumerate() |
| 241 | + .filter_map(|(idx, name)| { |
| 242 | + matcher |
| 243 | + .fuzzy_match(&name, &search_filter) |
| 244 | + .map(|score| (idx, name.to_string(), score)) |
| 245 | + }) |
| 246 | + .collect_vec(); |
| 247 | + |
| 248 | + // Sort by score (higher is better) |
| 249 | + scored_matches.sort_by(|a, b| b.2.cmp(&a.2)); |
| 250 | + |
| 251 | + // Create filter based on fuzzy matches |
| 252 | + let mut filter = vec![false; layout.nchildren()]; |
| 253 | + let list_items = scored_matches |
| 254 | + .iter() |
| 255 | + .map(|(idx, name, _score)| { |
| 256 | + filter[*idx] = true; |
| 257 | + name.clone() |
| 258 | + }) |
| 259 | + .collect_vec(); |
237 | 260 |
|
238 | | - if !app.search_filter.is_empty() { |
239 | 261 | app.filter = Some(filter); |
| 262 | + render_child_list_items(app, area, buf, list_items); |
240 | 263 | } |
| 264 | + } |
| 265 | +} |
241 | 266 |
|
242 | | - let container = Block::new() |
243 | | - .title("Child Layouts") |
244 | | - .borders(Borders::ALL) |
245 | | - .border_type(BorderType::Rounded) |
246 | | - .border_style(Style::default().fg(Color::DarkGray)); |
| 267 | +fn render_child_list_items( |
| 268 | + app: &mut AppState, |
| 269 | + area: Rect, |
| 270 | + buf: &mut Buffer, |
| 271 | + list_items: Vec<String>, |
| 272 | +) { |
| 273 | + let container = Block::new() |
| 274 | + .title("Child Layouts") |
| 275 | + .borders(Borders::ALL) |
| 276 | + .border_type(BorderType::Rounded) |
| 277 | + .border_style(Style::default().fg(Color::DarkGray)); |
247 | 278 |
|
248 | | - let inner_area = container.inner(area); |
| 279 | + let inner_area = container.inner(area); |
249 | 280 |
|
250 | | - container.render(area, buf); |
| 281 | + container.render(area, buf); |
251 | 282 |
|
252 | | - // Render the List view. |
253 | | - // TODO: add state so we can scroll |
254 | | - StatefulWidget::render( |
255 | | - List::new(list_items).highlight_style(Style::default().black().on_white().bold()), |
256 | | - inner_area, |
257 | | - buf, |
258 | | - &mut app.layouts_list_state, |
259 | | - ); |
260 | | - } |
| 283 | + // Render the List view. |
| 284 | + // TODO: add state so we can scroll |
| 285 | + StatefulWidget::render( |
| 286 | + List::new(list_items).highlight_style(Style::default().black().on_white().bold()), |
| 287 | + inner_area, |
| 288 | + buf, |
| 289 | + &mut app.layouts_list_state, |
| 290 | + ); |
261 | 291 | } |
0 commit comments