|
| 1 | +# PR Review: Add Visual Mode Multi-file Selection for snacks.explorer |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +This PR adds visual mode multi-file selection support for snacks.explorer, bringing it to feature parity with other supported file explorers (oil.nvim, nvim-tree, neo-tree). The implementation is clean, follows existing patterns, and includes comprehensive test coverage. |
| 6 | + |
| 7 | +## Strengths |
| 8 | + |
| 9 | +### 1. **Consistent Implementation Pattern** |
| 10 | + |
| 11 | +The implementation follows the established pattern used by other file explorers in the codebase. The author properly: |
| 12 | + |
| 13 | +- Added optional parameters to `_get_snacks_explorer_selection(visual_start, visual_end)` |
| 14 | +- Used the same visual range handling approach as oil.nvim |
| 15 | +- Maintained backwards compatibility by keeping parameters optional |
| 16 | + |
| 17 | +### 2. **Comprehensive Test Coverage** |
| 18 | + |
| 19 | +The test suite is thorough and covers: |
| 20 | + |
| 21 | +- Basic visual mode selection |
| 22 | +- Edge cases (nil items, empty paths, missing indices) |
| 23 | +- Different item structure variations (file vs path fields) |
| 24 | +- Proper filtering of invalid entries |
| 25 | + |
| 26 | +### 3. **Proper Error Handling** |
| 27 | + |
| 28 | +The implementation correctly handles edge cases: |
| 29 | + |
| 30 | +- Checks for nil returns from `row2idx()` and `get()` |
| 31 | +- Filters out empty file paths |
| 32 | +- Falls back gracefully when visual mode isn't active |
| 33 | + |
| 34 | +### 4. **Documentation Updates** |
| 35 | + |
| 36 | +The author remembered to update both README.md and dev-config.lua to mention snacks.explorer support. |
| 37 | + |
| 38 | +## Areas for Improvement |
| 39 | + |
| 40 | +### 1. **File Type Consistency** |
| 41 | + |
| 42 | +In the keybinding configuration, the filetype is listed as `"snacks_picker_list"`: |
| 43 | + |
| 44 | +```lua |
| 45 | +ft = { "NvimTree", "neo-tree", "oil", "snacks_picker_list" }, |
| 46 | +``` |
| 47 | + |
| 48 | +While this is correct, it might be worth adding a comment explaining why this filetype differs from the others (which use their plugin names directly). This would help future contributors understand the naming convention. |
| 49 | + |
| 50 | +### 2. **Depth/Root Protection Missing** |
| 51 | + |
| 52 | +Other file explorer implementations have protection against selecting root-level files: |
| 53 | + |
| 54 | +- nvim-tree: `if not string.match(mark.absolute_path, "^/[^/]*$") then` |
| 55 | +- neo-tree: `if depth > 1 then` |
| 56 | + |
| 57 | +The snacks.explorer implementation doesn't have similar protection. While this might be intentional (snacks.explorer might handle this internally), it's worth considering for consistency. |
| 58 | + |
| 59 | +### 3. **Directory Handling** |
| 60 | + |
| 61 | +The oil.nvim implementation has special handling for directories (ensures they end with `/`): |
| 62 | + |
| 63 | +```lua |
| 64 | +elseif entry.type == "directory" then |
| 65 | + table.insert(files, full_path:match("/$") and full_path or full_path .. "/") |
| 66 | +``` |
| 67 | + |
| 68 | +The snacks.explorer implementation doesn't distinguish between files and directories. This might be fine if snacks.explorer handles this internally, but it's worth verifying. |
| 69 | + |
| 70 | +### 4. **Code Duplication** |
| 71 | + |
| 72 | +There's some duplication in how file paths are extracted: |
| 73 | + |
| 74 | +```lua |
| 75 | +local file_path = item.file or item.path or (item.item and item.item.file) or (item.item and item.item.path) |
| 76 | +``` |
| 77 | + |
| 78 | +This pattern appears three times in the function. Consider extracting it to a local helper function: |
| 79 | + |
| 80 | +```lua |
| 81 | +local function extract_file_path(item) |
| 82 | + return item.file or item.path or (item.item and item.item.file) or (item.item and item.item.path) |
| 83 | +end |
| 84 | +``` |
| 85 | + |
| 86 | +## Minor Issues |
| 87 | + |
| 88 | +### 1. **Untracked Test File** |
| 89 | + |
| 90 | +The git status shows `tests/unit/snacks_explorer_spec.lua` as untracked (`??`). This file should be added to the commit since it contains the tests for this feature. |
| 91 | + |
| 92 | +### 2. **Snacks.nvim Directory** |
| 93 | + |
| 94 | +There's an entire `snacks.nvim` directory in the project root that appears to be untracked. This looks like a cloned repository and should probably be added to `.gitignore` if it's being used for local testing. |
| 95 | + |
| 96 | +## Code Quality |
| 97 | + |
| 98 | +The code quality is excellent: |
| 99 | + |
| 100 | +- Follows Lua idioms and project conventions |
| 101 | +- Proper use of pcall for error handling |
| 102 | +- Clear variable names and good code organization |
| 103 | +- Comprehensive documentation in comments |
| 104 | + |
| 105 | +## Testing Recommendations |
| 106 | + |
| 107 | +Before merging, please verify: |
| 108 | + |
| 109 | +1. The visual selection works correctly with actual snacks.explorer usage (not just unit tests) |
| 110 | +2. Directory selection behaves as expected |
| 111 | +3. The feature works with both single and multiple file selections |
| 112 | +4. Performance with large file lists in visual mode |
| 113 | + |
| 114 | +## Conclusion |
| 115 | + |
| 116 | +This is a well-implemented feature that properly extends the existing functionality to support snacks.explorer. The code follows established patterns, includes good test coverage, and maintains backwards compatibility. With the minor improvements suggested above (particularly ensuring the test file is committed), this PR is ready for merge. |
| 117 | + |
| 118 | +The implementation shows good understanding of both the codebase architecture and the snacks.explorer API. The author has done a commendable job of maintaining consistency with existing file explorer integrations while adapting to snacks.explorer's unique picker-based architecture. |
| 119 | + |
| 120 | +## Recommended Actions |
| 121 | + |
| 122 | +1. **Required**: Add `tests/unit/snacks_explorer_spec.lua` to the commit |
| 123 | +2. **Recommended**: Consider adding root/depth protection if applicable |
| 124 | +3. **Optional**: Extract the file path resolution logic to reduce duplication |
| 125 | +4. **Optional**: Add `.gitignore` entry for the snacks.nvim directory if it's for testing |
0 commit comments