-
Notifications
You must be signed in to change notification settings - Fork 50
feat: add configurable sibling file prioritization with performance optimizations #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add configurable sibling file prioritization with performance optimizations #25
Conversation
Implement Jaro-Winkler string similarity algorithm for enhanced file prioritization. Add optimized scoring functions that gate expensive similarity calculations behind distance checks to maintain performance while improving relevance of file suggestions. - Add strsim dependency for Jaro-Winkler similarity calculations - Implement optimized path distance and filename similarity functions - Add CurrentFileData struct to cache frequently accessed path components - Gate similarity bonus calculations behind MAX_DISTANCE_FOR_SIMILARITY_BONUS
Introduce same_dir_preference configuration option to control how strongly the file picker prioritizes files near the current file. This allows users to customize the balance between relevance and broader search results. - Add config_utils.lua with preference validation and parameter mapping - Integrate scoring configuration into main setup function - Map user preference (0.0-1.0) to internal scoring parameters - Add validation with helpful error messages for invalid ranges
Connect the new scoring system to the file picker interface and preview functionality. Optimize scoring operations by pre-computing current file data and passing it to the scoring context for better performance. - Update file picker to use optimized scoring with CurrentFileData - Integrate scoring parameters from configuration into picker context - Add tracing for scoring performance monitoring - Export new scoring functions from Rust library
Add comprehensive documentation for the new same_dir_preference configuration option. Update both README and Vim help documentation to explain how users can control file prioritization behavior. - Document scoring.same_dir_preference configuration option - Add usage examples and recommended values (0.0-1.0 range) - Update Vim help documentation with new configuration - Add performance monitoring traces for scoring operations
Resolve merge conflicts between feat/optimize-sibling-prioritization and main - Merged documentation in doc/fff.nvim.txt with enhanced configuration structure - Fixed UI buffer management conflicts in picker_ui.lua - Integrated sibling file prioritization features with main branch updates - Resolved Rust backend conflicts preserving enhanced scoring system - Updated test file to use new API with sibling prioritization parameters - Ensured all code compiles successfully with release build
|
wow this is huge and makes a lot of sense, I'll give a proper review for this feature tomorrow! Thanks for a huge addition |
- Apply consistent Rust formatting with proper line breaks and indentation - Organize imports following standard Rust conventions - Fix comment spacing in Lua configuration files - Improve code readability without changing functionality
sQVe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👋🏼
I think this project has great potential, and it feels very snappy 👏🏼. I'm currently using snacks.nvim with a custom multi picker, which provides basic proximity handling for the active buffer.
This is really essential when working within large monorepos, and projects that is very structure / name oriented - like TypeScript & Next.js etc.
Do note that I'm very novice when it comes to Rust, so be thorough and kind. I'm more than happy to make whatever changes you feel are necessary to get this in! ❤️
| let max_typos = if query.len() <= 4 { | ||
| 0 | ||
| } else { | ||
| (query.len() as u16 / 5).clamp(1, 3) | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found the previous max_typos value to be too permissive, which was problematic when scoring against proximity. I primarily work within a large TypeScript monorepo, and when typing Page it didn't filter out any items.
This change should hopefully be a bit more adaptive. I wouldn't be surprised if we would need to tweak this though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should probably make it configurable as well while allowing typos starting from the very start. I make typos even in 4 lines and I find it absolutely useful to have them
| similarity_threshold: f64, | ||
| ) -> i32 { | ||
| use std::path::Path; | ||
| use strsim::jaro_winkler; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Jaro Winkler is a good choice since:
- Prefix bias: Gives higher scores to strings that share common prefixes, which aligns with how developers typically name related files (e.g.,
user.rs,user_test.rs,user_service.rs) - Typo tolerance: Handles minor typos and variations gracefully, which is important for fuzzy file finding
- Performance: It's computationally efficient compared to algorithms like Levenshtein.
- Score range: Returns normalized scores between 0.0 and 1.0, making it easy to set meaningful thresholds
| directory_distance_penalty = -8, -- Balanced penalty for different directories | ||
| filename_similarity_bonus_max = math.floor(50 * preference), -- Moderate sibling bonus (35 with default 0.7) | ||
| filename_similarity_threshold = 0.5, -- Good relevance/performance balance | ||
| max_search_directory_levels = math.floor(1 + 3 * preference), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got these defaults by forcing multiple AI models to reach a consensus on what they believed was the optimal values. I then manually tested and iterated multiple times, feeding the results to the models.
With that said, we should really see these values as an initial best guess. My gut feeling is that we will lower these values rather than raising them in the future.
dmtrKovalenko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not getting your review fast enough. I'll spend a few days working with this version to see how it feels and will get back to you. Thank you very much this is an amazing contribution!
|
|
||
| let results = picker.fuzzy_search(&query, max_results, max_threads, current_file.as_ref()); | ||
| let distance_penalty = distance_penalty.unwrap_or(-8); | ||
| let relation_bonus_max = relation_bonus_max.unwrap_or(35); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should give a default dardcoded bonusws or penalties
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this should be configurable instead, or solved in some other way?
|
@dmtrKovalenko No need to rush ❤️ I understand if you want to make sure this feels right and that you might want to get the basics right in the picker - before adding further tweaks. I prefer having a picker that solves proximity, open buffers, and fuzzy finding - but that might not be the goal of this project. |
|
It actually is I am really grateful for your input I just want to double check that it doesn't break the existing flows and maybe tweak/make configurabel the scoring impact. We are going to merge this PR anyway |
Summary
Enhance the fuzzy file picker with sibling file prioritization that considers your current context. When editing a file, the picker now prioritizes related files (similar names, nearby directories) while maintaining performance through optimized scoring algorithms.
This helps with common workflows where you need to quickly navigate between related files (e.g.,
user.tsanduser.test.ts, or files in the same feature directory) by making the most relevant results appear first.Key Changes
scoring.same_dir_preferenceoption (0.0-1.0) to control prioritization strengthConfiguration
Users can now control file prioritization behavior:
Performance
MAX_DISTANCE_FOR_SIMILARITY_BONUSdirectory levels (default: 2)CurrentFileDatastructTest Plan
same_dir_preferencevalues