-
-
Notifications
You must be signed in to change notification settings - Fork 414
Fix crash with opening file with editor on an empty panel #730
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
Conversation
|
It also crashes on opening Ctrl+A on empty file panel. Can you also fix that |
|
@booth-w Lets also evaluate all other possible inputs when spf migth crash on empty file panel. |
|
Tested in both browser and select mode open file with xdg-open: working (only tested on Linux but there is a check so it should work) Sorry this took a bit. I have been busy with uni course work. |
|
No problem. Thanks for doing this. |
|
I am gonna test this out on windows, and also will try review the code wherever we access It might be in other places as well, like process bar's process list, and sidebar's list. I plan to get this issue fixed once and for all. |
|
Going into select mode by pressing "V" and then pressing shift+up still causes crash. Code We might wanna write a testsuite for this to validate for no crash on all inputs |
Fixes `search`, `copy path`, `extract`, and `compress`
917633a to
dd2275a
Compare
|
Rebased with main |
WalkthroughThe changes introduce a new boolean parameter Changes
Sequence Diagram(s)sequenceDiagram
participant Runner as Test Runner
participant BaseTest as GenericTestImpl
participant SPF as Superfile Manager
Runner->>BaseTest: Invoke test_execute()
BaseTest->>SPF: Start superfile process
BaseTest->>BaseTest: Call send_input() to send key inputs
BaseTest->>SPF: Process key inputs
BaseTest->>BaseTest: Wait (delay for operations)
BaseTest->>BaseTest: validate() checks if superfile is running
Runner->>BaseTest: Report test completion
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/internal/function.go(1 hunks)src/internal/handle_file_operations.go(5 hunks)src/internal/handle_modal.go(1 hunks)src/internal/model_render.go(2 hunks)
🔇 Additional comments (8)
src/internal/function.go (1)
211-213: Good defensive programming for empty slices.This check prevents unnecessary processing when there are no directory entries to search through, which is a good defensive programming practice.
src/internal/handle_modal.go (1)
66-71: Good safety check to prevent potential crashes.This validation ensures the function doesn't attempt to access elements in an empty slice, which would cause a panic. The accompanying comment also properly documents that this is a precautionary measure.
src/internal/model_render.go (1)
95-97: Informative comment about model behavior.This comment correctly explains a subtlety of the code where modifications to the model object are inconsequential due to pass-by-value mechanics in the View() function.
src/internal/handle_file_operations.go (5)
108-108: Improved check for empty panel conditions.This enhanced condition properly handles both browser and select modes, preventing attempts to delete non-existent items which could cause crashes.
526-528: Good defensive check for empty panels.This early return prevents attempting to extract files when there are no elements in the panel, avoiding potential nil pointer dereferences.
559-561: Good defensive check for empty panels.This early return prevents attempting to compress files when there are no elements in the panel, avoiding potential nil pointer dereferences.
587-589: Good defensive check for empty panels.This early return prevents attempting to open files with an editor when there are no elements in the panel, which addresses the primary crash issue mentioned in the PR objectives.
649-651: Good defensive check for empty panels.This early return prevents attempting to copy paths when there are no elements in the panel, avoiding potential nil pointer dereferences.
| // This could create errors if panel.cursor ever becomes negative, or goes out of bounds | ||
| // We should have a panel validation function in our View() function |
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.
🛠️ Refactor suggestion
Good documentation of potential issue, but consider implementing the fix.
While the comment correctly identifies a potential source of crashes, it would be better to implement the suggested panel validation function rather than just documenting the issue.
Consider implementing a validation function that ensures panel.cursor is within valid bounds before attempting to access elements:
func validatePanelCursor(panel *filePanel) {
if len(panel.element) == 0 {
panel.cursor = 0
return
}
if panel.cursor < 0 {
panel.cursor = 0
} else if panel.cursor >= len(panel.element) {
panel.cursor = len(panel.element) - 1
}
}
// Then call this function before accessing panel.element[panel.cursor]Committable suggestion skipped: line range outside the PR's diff.
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.
We cant call this function before accessing panel.element[panel.cursor] everytime.
Instead we would have some kind of validation whenever we update panel.cursor and panel.elements.
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.
But not in this PR.
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.
@lazysegtree Understood. You're right to maintain the focused scope of the current PR. The validation approach can be implemented in a future PR dedicated to improving the cursor handling across the application.
✏️ Learnings added
Learnt from: lazysegtree
PR: yorukot/superfile#730
File: src/internal/model_render.go:653-654
Timestamp: 2025-03-29T10:02:04.018Z
Learning: A panel validation function should be implemented to ensure panel.cursor doesn't become negative or go out of bounds, but this should be addressed in a separate PR - not as part of the PR fixing crashes when opening files with the editor on an empty panel.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
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.
🧩 Analysis chain
@lazysegtree You're absolutely right. Validating at every access point would be inefficient. A better approach is to validate whenever panel.cursor and panel.element are modified.
Let me search the codebase to find where these values are updated:
🏁 Script executed:
#!/bin/bash
# Find where panel.cursor is modified
rg "panel\.cursor\s*[=+\-]" --type go -A 1 -B 1
echo "----------------------------------------------"
# Find where panel.element is modified or replaced
rg "panel\.element\s*=" --type go -A 1 -B 1
Length of output: 6360
Let me try again with a more comprehensive search:
🏁 Script executed:
#!/bin/bash
# Find where panel.element is modified or changed
rg "panel\.element" --type go -A 1 -B 1
echo "----------------------------------------------"
# Find any function that might modify or update panel elements
rg "func.*updatePanel|func.*loadDirectory|func.*refreshPanel" --type go
Length of output: 14503
@lazysegtree You're absolutely right! Looking at the codebase, I see that panel validation should happen at key points when panel.cursor or panel.element are modified, rather than before every access.
Looking at the search results, I notice there are several patterns in how validation is currently done:
- Many functions already check
if len(panel.element) == 0 { return }before proceeding - Some places adjust cursor after modifications:
if panel.cursor >= len(panel.element) { panel.cursor = len(panel.element) - 1 } - The PR added a check in confirmRename() to handle the empty panel case
I suggest implementing a simple validatePanel function that can be called at strategic points:
func validatePanel(panel *filePanel) {
if len(panel.element) == 0 {
panel.cursor = 0
panel.render = 0
return
}
if panel.cursor < 0 {
panel.cursor = 0
} else if panel.cursor >= len(panel.element) {
panel.cursor = len(panel.element) - 1
}
}This should be called in three key places:
- After loading/refreshing a directory (when panel.element is updated)
- In View() before rendering panels
- After any operation that might delete files or change directories
This way, we ensure panel.cursor is always valid before it's used to access panel.element, without adding overhead at every access point.
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 am not going to do it now. It will be done as the part of refactoring when we would abstract out all operations to panel objects with struct methods with filePanel recievers.
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.
@lazysegtree Understood. That's a sound approach to hold off until you can properly abstract panel operations into struct methods with filePanel receivers. This comprehensive refactoring will provide a better foundation for implementing validation logic than adding it piecemeal now.
🐇 thinking
🧠 Learnings used
Learnt from: lazysegtree
PR: yorukot/superfile#730
File: src/internal/model_render.go:653-654
Timestamp: 2025-03-29T10:02:04.260Z
Learning: A panel validation function should be implemented to ensure panel.cursor doesn't become negative or go out of bounds, but this should be addressed in a separate PR - not as part of the PR fixing crashes when opening files with the editor on an empty panel.
| return []element{} | ||
| } | ||
|
|
||
| if len(items) == 0 { |
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.
@coderabbitai help
Can you check if there are any more places where we need to add this kind of check ?
I saw these are the places where panel.elements is accessed
Details
➜ ~/Workspace/Other_proj/spf_forks/booth-w/superfile/src git:(fix-editor-empty-dir) [3:22:24] grepr "panel.element\["
./internal/model_render.go:191: isItemSelected := arrayContains(filePanel.selected, filePanel.element[h].location)
./internal/model_render.go:195: _, err := os.ReadDir(filePanel.element[h].location)
./internal/model_render.go:196: f[i] += filePanelCursorStyle.Render(cursor+" ") + prettierName(filePanel.element[h].name, m.fileModel.width-5, filePanel.element[h].directory || (err == nil), isItemSelected, filePanelBGColor) + endl
./internal/model_render.go:655: itemPath := panel.element[panel.cursor].location
./internal/model.go:463: if filepath.Dir(focusPanel.element[0].location) != focusPanel.location {
./internal/function.go:368: if len(panel.element[panel.cursor].metaData) != 0 && m.focusPanel != metadataFocus {
./internal/function.go:369: m.fileMetaData.metaData = panel.element[panel.cursor].metaData
./internal/function.go:374: filePath := panel.element[panel.cursor].location
./internal/function.go:451: panel.element[panel.cursor].metaData = m.fileMetaData.metaData
./internal/handle_modal.go:73: oldPath := panel.element[panel.cursor].location
./internal/handle_panel_up_down.go:112: if arrayContains(panel.selected, panel.element[selectItemIndex].location) {
./internal/handle_panel_up_down.go:113: panel.selected = removeElementByValue(panel.selected, panel.element[selectItemIndex].location)
./internal/handle_panel_up_down.go:115: panel.selected = append(panel.selected, panel.element[selectItemIndex].location)
./internal/handle_panel_up_down.go:135: if arrayContains(panel.selected, panel.element[selectItemIndex].location) {
./internal/handle_panel_up_down.go:136: panel.selected = removeElementByValue(panel.selected, panel.element[selectItemIndex].location)
./internal/handle_panel_up_down.go:138: panel.selected = append(panel.selected, panel.element[selectItemIndex].location)
./internal/handle_panel_movement.go:52: if panel.element[panel.cursor].directory {
./internal/handle_panel_movement.go:57: panel.location = panel.element[panel.cursor].location
./internal/handle_panel_movement.go:67: } else if !panel.element[panel.cursor].directory {
./internal/handle_panel_movement.go:68: fileInfo, err := os.Lstat(panel.element[panel.cursor].location)
./internal/handle_panel_movement.go:75: targetPath, symlink_err := filepath.EvalSymlinks(panel.element[panel.cursor].location)
./internal/handle_panel_movement.go:101: cmd := exec.Command(dllpath, dllfile, panel.element[panel.cursor].location)
./internal/handle_panel_movement.go:110: cmd := exec.Command(openCommand, panel.element[panel.cursor].location)
./internal/handle_panel_movement.go:160: elementLocation := panel.element[panel.cursor].location
./internal/handle_file_operations.go:45: oldPath := panel.element[panel.cursor].location
./internal/handle_file_operations.go:79: cursorPos := strings.LastIndex(panel.element[panel.cursor].name, ".")
./internal/handle_file_operations.go:80: nameLen := len(panel.element[panel.cursor].name)
./internal/handle_file_operations.go:81: if cursorPos == -1 || cursorPos == 0 && nameLen > 0 || panel.element[panel.cursor].directory {
./internal/handle_file_operations.go:93: ti.SetValue(panel.element[panel.cursor].name)
./internal/handle_file_operations.go:152: name: icon.Delete + icon.Space + panel.element[panel.cursor].name,
./internal/handle_file_operations.go:167: err := trashMacOrLinux(panel.element[panel.cursor].location)
./internal/handle_file_operations.go:269: name: " " + panel.element[panel.cursor].name,
./internal/handle_file_operations.go:285: err := os.RemoveAll(panel.element[panel.cursor].location)
./internal/handle_file_operations.go:388: "panel location", panel.element[panel.cursor].location)
./internal/handle_file_operations.go:389: m.copyItems.items = append(m.copyItems.items, panel.element[panel.cursor].location)
./internal/handle_file_operations.go:530: ext := strings.ToLower(filepath.Ext(panel.element[panel.cursor].location))
./internal/handle_file_operations.go:536: outputDir := fileNameWithoutExtension(panel.element[panel.cursor].location)
./internal/handle_file_operations.go:548: err = extractCompressFile(panel.element[panel.cursor].location, outputDir)
./internal/handle_file_operations.go:563: fileName := filepath.Base(panel.element[panel.cursor].location)
./internal/handle_file_operations.go:573: err = zipSource(panel.element[panel.cursor].location, filepath.Join(filepath.Dir(panel.element[panel.cursor].location), zipName))
./internal/handle_file_operations.go:609: args := append(parts[1:], panel.element[panel.cursor].location)
./internal/handle_file_operations.go:653: if err := clipboard.WriteAll(panel.element[panel.cursor].location); err != nil {
➜ ~/Workspace/Other_proj/spf_forks/booth-w/superfile/src git:(fix-editor-empty-dir) [6:05:34]
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.
🧩 Analysis chain
@lazysegtree I'll help you identify places where we should add empty slice checks. Let me analyze the codebase first.
🏁 Script executed:
#!/bin/bash
# First, let's check the current file structure to understand what we have
find ./src/internal -type f -name "*.go" | sort
Length of output: 1030
🏁 Script executed:
#!/bin/bash
# Let's examine handle_file_operations.go which contains file operations that might need empty checks
cat ./src/internal/handle_file_operations.go | grep -n "func.*panel" -A 3
Length of output: 389
🏁 Script executed:
#!/bin/bash
# Let's examine all the files where panel.element is accessed to find places that need empty slice checks
# First, let's look at model_render.go
cat ./src/internal/model_render.go | grep -n "panel.element\[" -B 5 -A 5
# Next, function.go
cat ./src/internal/function.go | grep -n "panel.element\[" -B 5 -A 5
# Then handle_panel_movement.go
cat ./src/internal/handle_panel_movement.go | grep -n "panel.element\[" -B 5 -A 5
# Let's also check handle_file_operations.go
cat ./src/internal/handle_file_operations.go | grep -n "panel.element\[" -B 5 -A 5
# Check handle_modal.go
cat ./src/internal/handle_modal.go | grep -n "panel.element\[" -B 5 -A 5
# Check handle_panel_up_down.go
cat ./src/internal/handle_panel_up_down.go | grep -n "panel.element\[" -B 5 -A 5
# Check model.go
cat ./src/internal/model.go | grep -n "panel.element\[" -B 5 -A 5
Length of output: 10769
🏁 Script executed:
#!/bin/bash
# Let's find all functions that access panel.element[] and check if they have proper empty array checks
# First, let's examine the files that were modified in the PR to understand the pattern of fixes
# Check handle_file_operations.go for functions that might need empty checks
cat ./src/internal/handle_file_operations.go | grep -n "func (m \*model)" -A 10 | grep -E "panel.element|len\(panel.element\) == 0"
# Check handle_modal.go since it was also modified in the PR
cat ./src/internal/handle_modal.go | grep -n "func (m \*model)" -A 10 | grep -E "panel.element|len\(panel.element\) == 0"
# Check function.go since it was also modified
cat ./src/internal/function.go | grep -n "func " -A 10 | grep -E "panel.element|len\(panel.element\) == 0"
Length of output: 1463
🏁 Script executed:
#!/bin/bash
# Let's find all functions in model_render.go that access panel.element[]
cat ./src/internal/model_render.go | grep -n -A 2 -B 2 "func.*model.*render" | grep -v "^--$"
# Now let's check each function in the key files to see if they properly check for empty elements
# First, check filePreviewPanelRender
cat ./src/internal/model_render.go | grep -n -A 10 "func.*filePreviewPanelRender" | head -20
# Check handle_panel_movement.go since it has multiple panel.element accesses
cat ./src/internal/handle_panel_movement.go | grep -n -A 3 "func.*panel" | grep -v "^--$"
cat ./src/internal/handle_panel_movement.go | grep -n -A 10 "func (m \*model) openItem" | head -20
# Check for any other functions in handle_file_operations.go that might need checks
find ./src/internal -type f -name "*.go" | xargs grep -l "panel.element\[" | xargs grep -n "func.*" | head -30
Length of output: 3942
🏁 Script executed:
#!/bin/bash
# Let's get a broader view of all functions that access panel.element[] and check if they contain empty checks
# Function to extract function content safely (basic approach)
function_finder() {
local file=$1
local line_numbers=$(grep -n "func" "$file" | cut -d: -f1)
local prev_line=0
for line in $line_numbers; do
if [ $prev_line -ne 0 ]; then
sed -n "${prev_line},${line}p" "$file" | grep -q "panel.element\["
if [ $? -eq 0 ]; then
echo "Function at line $prev_line in $file"
sed -n "${prev_line},${line}p" "$file" | grep -n "panel.element\["
echo "Has empty check:"
sed -n "${prev_line},${line}p" "$file" | grep -n "len(panel.element) == 0"
echo "---"
fi
fi
prev_line=$line
done
# Handle the last function in the file
if [ $prev_line -ne 0 ]; then
sed -n "${prev_line},\$p" "$file" | grep -q "panel.element\["
if [ $? -eq 0 ]; then
echo "Function at line $prev_line in $file (last function)"
sed -n "${prev_line},\$p" "$file" | grep -n "panel.element\["
echo "Has empty check:"
sed -n "${prev_line},\$p" "$file" | grep -n "len(panel.element) == 0"
echo "---"
fi
fi
}
# Process each file that uses panel.element[]
files=$(find ./src/internal -type f -name "*.go" | xargs grep -l "panel.element\[")
for file in $files; do
echo "=== Processing $file ==="
function_finder "$file"
done
Length of output: 33532
🏁 Script executed:
#!/bin/bash
# Let's get a complete list of files and functions that need to be updated with empty panel.element checks
# 1. Check handle_file_operations.go for IsRenamingConflicting function
cat ./src/internal/handle_file_operations.go | grep -n -A 15 "func (m \*model) IsRenamingConflicting" | head -20
# 2. Check handle_panel_up_down.go for itemSelectUp and itemSelectDown functions
cat ./src/internal/handle_panel_up_down.go | grep -n -A 20 "func (panel \*filePanel) itemSelectUp" | head -25
cat ./src/internal/handle_panel_up_down.go | grep -n -A 20 "func (panel \*filePanel) itemSelectDown" | head -25
# 3. Check singleItemSelect function in handle_panel_movement.go
cat ./src/internal/handle_panel_movement.go | grep -n -A 15 "func (m \*model) singleItemSelect" | head -20
Length of output: 3027
@lazysegtree After analyzing the codebase, I found several places where empty panel.element checks are missing. These could potentially cause crashes when the panel has no elements:
-
IsRenamingConflicting()in handle_file_operations.go:func (m *model) IsRenamingConflicting() bool { panel := &m.fileModel.filePanels[m.filePanelFocusIndex] // Missing check for empty panel.element oldPath := panel.element[panel.cursor].location // ...
-
itemSelectUp()in handle_panel_up_down.go:func (panel *filePanel) itemSelectUp(mainPanelHeight int) { // No explicit check for empty panel.element at the beginning // ...later tries to access panel.element[selectItemIndex].location
-
itemSelectDown()in handle_panel_up_down.go:func (panel *filePanel) itemSelectDown(mainPanelHeight int) { // No explicit check for empty panel.element at the beginning // ...later tries to access panel.element[selectItemIndex].location
I recommend adding a check like if len(panel.element) == 0 { return } at the beginning of these functions, similar to what was done in other functions to fix the editor crash.
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.
Thanks. Fixed it.
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.
@lazysegtree You're welcome! I'm glad I could help identify those vulnerable spots in the code. Great job implementing the fixes - this should make the application more robust when handling empty panels.
(_/)
(•ᴥ•)
/ >✓
✏️ Learnings added
Learnt from: lazysegtree
PR: yorukot/superfile#730
File: src/internal/function.go:211-211
Timestamp: 2025-03-29T13:20:45.431Z
Learning: Empty panel.element checks should be added at the beginning of functions that access panel.element to prevent crashes when a panel has no elements, similar to using `if len(panel.element) == 0 { return }`.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/internal/handle_panel_movement.go (1)
156-171: Good improvement for crash prevention and maintainability.The function signature change to use
*filePanelas the receiver makes the code more modular and maintainable. The additional bounds checking on line 158 is crucial for preventing crashes with empty panels, addressing the main issue mentioned in the PR objectives.The TODO comment about inefficiency with large selections is insightful.
Consider implementing the suggested optimization to use a map for storing selections:
-// Todo : convert panel.selected to a set (map[string]struct{}) +// Implementation using a map for O(1) lookups +type selectionSet map[string]struct{} + +func (panel *filePanel) isSelected(location string) bool { + _, exists := panel.selectionSet[location] + return exists +} + +func (panel *filePanel) toggleSelection(location string) { + if panel.isSelected(location) { + delete(panel.selectionSet, location) + } else { + panel.selectionSet[location] = struct{}{} + } +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/internal/handle_file_operations.go(8 hunks)src/internal/handle_panel_movement.go(1 hunks)src/internal/handle_panel_up_down.go(1 hunks)src/internal/key_function.go(1 hunks)src/internal/model_render.go(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/internal/model_render.go
- src/internal/handle_file_operations.go
🔇 Additional comments (3)
src/internal/key_function.go (1)
158-158: Good fix for handling method on correct object.The change correctly calls
singleItemSelect()on the focused file panel object rather than on the model, which aligns with the refactored method signature inhandle_panel_movement.gowhere the receiver was changed from*modelto*filePanel.src/internal/handle_panel_up_down.go (2)
97-98: Good refactoring for simplicity and reusability.The simplification of
itemSelectUpby delegating tosingleItemSelect()andlistUp()improves code organization and maintainability.
103-104: Good refactoring for simplicity and reusability.The simplification of
itemSelectDownby delegating tosingleItemSelect()andlistDown()improves code organization and maintainability.
1691736 to
dafc35b
Compare
|
@coderabbitai can you gather the PR count of this repo and render that as a line chart, showing count of open/closed/total PRs over time. |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/internal/handle_panel_movement.go (1)
162-165: Consider implementing the suggested performance optimizationThe comment correctly identifies a performance bottleneck with linear search operations on selections. Using a map-based set implementation (
map[string]struct{}) would indeed provide constant-time operations for large selections, significantly improving performance when many files are selected.- // This is inefficient. Once you select 1000 items, - // each select / deselect operation can take 1000 operations - // It can be easily made constant time. - // Todo : (performance)convert panel.selected to a set (map[string]struct{}) + // Implement using a map for O(1) performance + type selectionSet map[string]struct{} + + // Then modify the filePanel struct to use this typeConsider creating a follow-up PR that implements this optimization, especially if users frequently work with large numbers of selected files.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/internal/handle_file_operations.go(8 hunks)src/internal/handle_panel_movement.go(1 hunks)src/internal/handle_panel_up_down.go(1 hunks)src/internal/key_function.go(1 hunks)src/internal/model_render.go(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/internal/key_function.go
- src/internal/model_render.go
- src/internal/handle_file_operations.go
🔇 Additional comments (5)
src/internal/handle_panel_movement.go (1)
156-171: Good refactoring of receiver type for better encapsulationChanging the receiver from
*modelto*filePanelimproves encapsulation by allowing the method to be called directly on the panel object rather than going through the model. This makes the code more maintainable and follows better object-oriented principles.The boundary checks on line 158 are essential to prevent crashes when the panel is empty or when the cursor is out of bounds, which addresses the main issue in this PR.
src/internal/handle_panel_up_down.go (4)
94-97: Good documentation of method behaviorThe added comments clearly explain the purpose of the
itemSelectUpfunction, making the code more maintainable. The TODO about adding unit tests is also valuable, as these selection functions are crucial for the application's stability.
97-100: Improved logic flow with simplified implementationThe refactored implementation correctly calls
singleItemSelect()first, then moves the cursor up. This simplification makes the code more readable and maintainable while ensuring the same functionality.The early return checks in
listUp(line 11) will prevent crashes when working with empty panels, addressing the main issue in this PR.
103-106: Consistent implementation with itemSelectUpThe
itemSelectDownmethod follows the same pattern asitemSelectUp, providing consistency in the codebase. The early return inlistDown(line 31) will similarly prevent crashes with empty panels.
11-13: Critical fix for empty panel crashesThe early return checks in both list navigation methods are essential to prevent index out-of-bounds panics when operating on empty panels. This directly addresses the main issue described in the PR objectives.
Also applies to: 31-33
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain@lazysegtree Here's the PR statistics for the yorukot/superfile repository visualized as a line chart: %%{init: {'theme': 'default', 'themeVariables': { 'primaryColor': '#597dc9', 'lineColor': '#1f77b4', 'secondaryColor': '#ffa07a', 'tertiaryColor': '#90ee90'}}}%%
graph TD
title PR Counts Over Time for yorukot/superfile
x-axis Months
y-axis Count
line Total PRs 2023-08,48 2023-09,119 2023-10,223 2023-11,366 2023-12,494 2024-01,590 2024-02,659 2024-03,730
line Closed PRs 2023-08,10 2023-09,75 2023-10,164 2023-11,314 2023-12,444 2024-01,537 2024-02,606 2024-03,677
line Open PRs 2023-08,38 2023-09,44 2023-10,59 2023-11,52 2023-12,50 2024-01,53 2024-02,53 2024-03,53
The chart shows the progression of PRs since the repository started in August 2023. You can see:
The repository has had fairly consistent activity with around 50-60 open PRs maintained over the last several months, showing active development and maintenance. 🏁 Script executed: Length of output: 1049 🏁 Script executed: Length of output: 1536 @lazysegtree Here's the PR statistics for the yorukot/superfile repository as a line chart: %%{init: {'theme': 'default', 'themeVariables': { 'primaryColor': '#597dc9', 'lineColor': '#1f77b4', 'secondaryColor': '#ffa07a', 'tertiaryColor': '#90ee90'}}}%%
graph TD
title PR Counts Over Time for yorukot/superfile
x-axis Months
y-axis Count
line Total PRs 2024-04,46 2024-05,123 2024-06,157 2024-07,175 2024-08,202 2024-09,230 2024-10,249 2024-11,276 2024-12,301 2025-01,318 2025-02,363 2025-03,416
line Closed PRs 2024-04,45 2024-05,121 2024-06,157 2024-07,175 2024-08,196 2024-09,220 2024-10,242 2024-11,273 2024-12,297 2025-01,312 2025-02,350 2025-03,407
line Open PRs 2024-04,1 2024-05,2 2024-06,0 2024-07,0 2024-08,6 2024-09,10 2024-10,7 2024-11,3 2024-12,4 2025-01,6 2025-02,13 2025-03,9
Repository PR Stats Summary:
The chart shows consistent development activity from April 2024 to March 2025. There was significant growth in PR activity during May 2024 and February 2025. The repository maintains a relatively low number of open PRs (typically under 10), indicating efficient PR management and review processes. The steeper slope of the total/closed lines between April-May 2024 and January-February 2025 suggests periods of increased development activity. |
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.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/internal/model_render.go (1)
653-661: Good documentation of potential issue, consider implementing helper methods.These comments effectively document the root cause of the crashes addressed in this PR. They highlight the need for better abstraction in panel data access to prevent similar issues in the future.
As noted in the retrieved learnings, implementing a panel validation function should be addressed in a separate PR dedicated to improving cursor handling across the application.
Consider creating an abstraction layer with helper methods like
panel.GetCurrentSelectedElem()to safely access panel elements. This would centralize validation logic and make it easier to maintain and debug the codebase.src/internal/handle_panel_movement.go (1)
162-165: Consider implementing the performance improvement.The comment correctly identifies a performance issue with the current implementation. Using a map for
panel.selectedwould improve time complexity from O(n) to O(1) for select/deselect operations.-// Todo : (performance)convert panel.selected to a set (map[string]struct{}) +// Implement this set structure for selection state +type selectionSet struct { + items map[string]struct{} +} + +func newSelectionSet() *selectionSet { + return &selectionSet{ + items: make(map[string]struct{}), + } +} + +func (s *selectionSet) add(location string) { + s.items[location] = struct{}{} +} + +func (s *selectionSet) remove(location string) { + delete(s.items, location) +} + +func (s *selectionSet) contains(location string) bool { + _, exists := s.items[location] + return exists +} + +func (s *selectionSet) clear() { + s.items = make(map[string]struct{}) +} + +func (s *selectionSet) getAll() []string { + result := make([]string, 0, len(s.items)) + for location := range s.items { + result = append(result, location) + } + return result +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/internal/function.go(1 hunks)src/internal/handle_file_operations.go(8 hunks)src/internal/handle_modal.go(1 hunks)src/internal/handle_panel_movement.go(1 hunks)src/internal/handle_panel_up_down.go(1 hunks)src/internal/key_function.go(1 hunks)src/internal/model_render.go(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
src/internal/function.go (1)
Learnt from: lazysegtree
PR: yorukot/superfile#730
File: src/internal/function.go:211-211
Timestamp: 2025-03-29T13:20:46.467Z
Learning: Empty panel.element checks should be added at the beginning of functions that access panel.element to prevent crashes when a panel has no elements, similar to using `if len(panel.element) == 0 { return }`.
src/internal/model_render.go (1)
Learnt from: lazysegtree
PR: yorukot/superfile#730
File: src/internal/model_render.go:653-654
Timestamp: 2025-03-29T10:02:04.260Z
Learning: A panel validation function should be implemented to ensure panel.cursor doesn't become negative or go out of bounds, but this should be addressed in a separate PR - not as part of the PR fixing crashes when opening files with the editor on an empty panel.
🔇 Additional comments (14)
src/internal/function.go (1)
211-213: Add early return for empty directory listings to prevent downstream issues.This check ensures that if no directory entries are found, an empty result is returned immediately, preventing potential nil or index out-of-bounds errors in downstream processing.
src/internal/key_function.go (1)
158-158: Function call correctly redirected to panel-specific implementation.The function call now properly targets the
singleItemSelect()method on the specific file panel instance rather than on the model. This refactoring helps prevent crashes when dealing with empty panels by delegating responsibility to the appropriate object.src/internal/handle_modal.go (1)
66-71: Implement safety check to prevent crash on empty panel during rename.This defensive check prevents accessing elements in an empty panel, which would cause a runtime panic. The error logging provides useful diagnostic information for debugging if this unexpected condition occurs.
src/internal/handle_panel_movement.go (1)
156-171: Improved function signature to access panel directly.This refactoring changes the receiver from
*modelto*filePanel, which makes the function more modular and directly operates on the panel. The safety check at line 158 helps prevent crashes with empty panel elements.src/internal/handle_file_operations.go (7)
48-51: Fix crash in IsRenamingConflicting with empty panel.This check prevents crashes by ensuring the panel has elements before attempting to access them. Also includes proper error logging.
117-117: Improved empty panel check in deleteItemWarn.The updated condition now correctly handles both browser mode with empty elements and select mode with no selected items.
538-540: Fix crash in extractFile with empty panel.This check prevents crashes by ensuring the panel has elements before attempting extraction.
571-573: Fix crash in compressFile with empty panel.This check prevents crashes by ensuring the panel has elements before attempting compression.
598-601: Fix crash in openFileWithEditor with empty panel.This addresses the main issue in the PR - preventing crashes when opening a file with editor on an empty panel.
661-663: Fix crash in copyPath with empty panel.This check prevents crashes by ensuring the panel has elements before copying the path.
256-258:❓ Verification inconclusive
Consider implementing the cursor handling suggestion.
The comments identify potential issues with cursor handling but don't implement solutions. This could be addressed in a follow-up PR.
🏁 Script executed:
#!/bin/bash # Find other potential cursor boundary issues in the codebase rg -A 3 -B 3 "panel\.cursor" | grep -i "len\(panel\.element\)"Length of output: 64
Action Needed: Implement and Verify Cursor Boundary Handling
The code at
src/internal/handle_file_operations.go(lines 256–258) still only contains a comment noting that negative values forpanel.cursorshould trigger an error log. Our automated search for related patterns (e.g., where a check involvingpanel.cursormight interact withlen(panel.element)) did not return any additional instances, suggesting that this issue remains isolated.
- Review the logic that adjusts
panel.cursorto ensure it never becomes negative.- Consider implementing explicit boundary checks coupled with proper error logging.
- Manually verify that there are no overlooked cases elsewhere in the codebase where a negative cursor might occur.
Please address this in a follow-up PR and manually verify that the error handling works as intended.
src/internal/handle_panel_up_down.go (3)
94-97: Added helpful comments for future developers.These comments clearly explain the function's purpose, making the code more maintainable.
98-99: Refactored itemSelectUp to use common functions.This refactoring improves code modularity by using the newly modified
singleItemSelectfunction and existinglistUpfunction.
104-105: Refactored itemSelectDown to use common functions.Similar to the itemSelectUp refactoring, this improves code modularity and consistency.
dafc35b to
5baae64
Compare
|
@booth-w I am good with the PR now. Please review and approve once |
|
What do you want me to do? I don't think I can approve my own PR. |
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
testsuite/tests/empty_panel_test.py (1)
47-53: Consider adding more documentation for the overridden test_execute method.The method intentionally doesn't close the superfile application after sending inputs, but it's not immediately clear why this is necessary for this specific test. Additional documentation would help other developers understand the test's behavior.
# Override def test_execute(self) -> None: self.start_spf() self.send_input() time.sleep(tconst.OPERATION_DELAY) - # To not close spf + # Intentionally not closing spf to ensure it remains running, + # which is verified by the validate_spf_running flag
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
testsuite/core/base_test.py(5 hunks)testsuite/tests/empty_panel_test.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
testsuite/tests/empty_panel_test.py (1)
testsuite/core/base_test.py (5)
GenericTestImpl(42-138)test_execute(26-28)test_execute(97-103)start_spf(78-80)send_input(87-95)
testsuite/core/base_test.py (3)
testsuite/tests/empty_panel_test.py (1)
test_execute(48-52)testsuite/tests/nav_and_copy_path_test.py (1)
test_execute(30-79)testsuite/core/spf_manager.py (2)
start_spf(12-13)is_spf_running(29-34)
🔇 Additional comments (6)
testsuite/tests/empty_panel_test.py (1)
13-46: Good implementation of the empty panel test class.The test class is well-structured and covers a comprehensive set of operations that could potentially cause crashes when performed on an empty panel. The test includes operations like copy, cut, delete, paste, rename, copy location, archive, extract, and select mode operations.
testsuite/core/base_test.py (5)
52-52: Good addition of the validate_spf_running parameter.This parameter is a logical addition that complements the existing
validate_spf_closedparameter, allowing tests to verify that the application remains running after operations.
63-63: Good initialization of the validate_spf_running field.The field is properly initialized from the constructor parameter.
87-96: Well-structured extraction of input handling logic.The
send_inputmethod nicely encapsulates the logic for sending inputs to the superfile manager. This improves code organization and allows subclasses to override just the input handling if needed, which is exactly what theEmptyPanelTestclass does.
97-103: Good refactoring of the test_execute method.The method now uses the extracted
send_inputmethod, maintaining the same functionality while improving code organization.
116-117: Proper implementation of the spf_running validation.This validation check is the counterpart to the existing
validate_spf_closedcheck, and properly verifies that the superfile application remains running when expected. This is crucial for the empty panel test to ensure operations don't cause crashes.
|
Testsuite was not passing earlier but passes now |
64faae1 to
7a087c7
Compare
|
@booth-w Ohh, right. |
|
My bad.. I force pushed the wrong commit. |
|
Fixing it now |
7a087c7 to
8fef72b
Compare
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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
testsuite/core/base_test.py (2)
87-87: Add documentation to the new method.Consider adding a docstring to the new
send_inputmethod explaining its purpose and behavior, similar to other methods in the class.def send_input(self) -> None: + """Send defined key inputs to the superfile process + Uses the key_inputs list defined during initialization + """ if self.key_inputs is not None:
52-52: Consider documenting new parameter in class docstring.Since the class doesn't have parameter documentation in its docstring yet, this might be a good opportunity to add documentation for all parameters, including the new
validate_spf_runningparameter.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
testsuite/core/base_test.py(5 hunks)testsuite/tests/empty_panel_test.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- testsuite/tests/empty_panel_test.py
🔇 Additional comments (4)
testsuite/core/base_test.py (4)
52-52: Good addition of validation parameter.The new
validate_spf_runningparameter provides a complementary option to the existingvalidate_spf_closedparameter, allowing for more comprehensive test scenarios.Also applies to: 63-63
87-95: Well-structured extraction of input logic.Extracting the input sending logic into a separate method is a good refactoring. It improves code organization by separating concerns and makes the testing framework more flexible. The implementation includes proper type assertions and timing controls.
97-103: Clear and concise test execution implementation.The refactored
test_executemethod is more readable and maintainable with its sequential steps: start the process, send inputs, wait, and end execution. This structure also makes it easier for subclasses to override specific parts of the test execution flow.
116-117: Consistent implementation of new validation.The implementation of the
validate_spf_runningcheck follows the same pattern as the existing validation checks, maintaining code consistency.
| def test_execute(self) -> None: | ||
| """Execute the test | ||
| """ | ||
| self.start_spf() | ||
| self.send_input() | ||
| time.sleep(tconst.OPERATION_DELAY) | ||
| self.end_execution() |
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.
💡 Verification agent
❓ Verification inconclusive
Consider additional error handling.
The test_execute method assumes the superfile process starts successfully. You might want to add error handling or additional checks to ensure more robust test execution, especially when testing edge cases like empty panels.
🏁 Script executed:
#!/bin/bash
# Check if there's any error handling in similar test methods
rg -A 3 -B 3 "try.*except" testsuite/Length of output: 39
Enhance Error Handling in test_execute
- The method in
testsuite/core/base_test.py(lines 97–103) currently assumes that the superfile process starts successfully, with no error handling for failures. - A search for
try/exceptin similar test methods yielded no matches, suggesting that this test (and likely others) lack safeguards to catch and handle failures (especially for edge cases like empty panels). - Consider wrapping calls such as
self.start_spf()andself.send_input()in a try/except block or adding validations to confirm that the expected state is achieved. This will make the test more robust and prevent unexpected exceptions from halting execution.
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.
For point (1) "The method in testsuite/core/base_test.py (lines 97–103) currently assumes that the superfile process starts successfully, with no error handling for failures."
It calls self.start_spf() which has this assert self.env.spf_mgr.is_spf_running(), "Superfile is not running"
So its handled
for point (2) and (3) A search for try/except in similar test methods yielded no matches,
t.test_execute() that is called in run_tests() method in runner.py has a try/except.
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.
@lazysegtree You're absolutely right. Thanks for clarifying these points:
-
Error handling for the superfile process is indeed handled in the
start_spf()method with the assertion checkassert self.env.spf_mgr.is_spf_running(), "Superfile is not running", which validates that the process started successfully. -
The higher-level error handling exists in the
run_tests()method in runner.py, which wraps thet.test_execute()calls in try/except blocks, providing another layer of protection.
The concerns raised by the verification bot are already addressed by the existing code structure. Thanks for pointing this out.
|
@booth-w PR is ready now. You can give a go ahead, and I will merge it. |
|
We just added coderabbit, so I was playing around with it for a while. |
|
LGTM, though my only experience with Go is this project so if there is something you have missed, I doubt I will be able to catch it. Is coderabbit the best for AI code review? I know nothing about it or any others so it could be the best one but the last commit was two years ago and it was archived last year |
|
@booth-w We are not using coderabbit open source version. We are using coderabbit pro for now.
|
|
Thanks @booth-w for identifying and fixing this. This is a major improvement. |
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [yorukot/superfile](https://github.com/yorukot/superfile) | minor | `v1.2.1` -> `v1.3.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>yorukot/superfile (yorukot/superfile)</summary> ### [`v1.3.0`](https://github.com/yorukot/superfile/releases/tag/v1.3.0) [Compare Source](yorukot/superfile@v1.2.1...v1.3.0) We are excited to release v1.3.0 for superfile, with new features, key bug fixes, and lots of polish under the hood. #### Install: [**Click me to know how to install**](https://github.com/yorukot/superfile?tab=readme-ov-file#installation) #### Highlights - We have revamped the command prompt and added built-in commands for SuperFile-specific actions. Check out yorukot/superfile#745 - Multi-panel startup support. You can now open multiple panels right from startup, making your workflow even more efficient. - Added new configurations : --chooser-file option, show_panel_footer_info config flag and many command prompt specific flags. #### Improvements & Fixes - The sidebar code was refactored and separated for better maintainability and various linter fixes and CI/CD improvements were made to keep the codebase clean and robust. - A new Rendering package is implemented, centralising border, content, and section rendering logic into reusable renderer components, fixing many layout bugs. - Model behaviour, file operations and rendering-related unit tests were added to improve test coverage. #### Detailed Change Summary <details><summary>Details</summary> <p> #### New Features - Added a Command-Prompt for SuperFile specific actions [`#752`](yorukot/superfile#752) by [@​Rocco-Gossmann](https://github.com/Rocco-Gossmann), [@​yorukot](https://github.com/yorukot) and [@​lazysegtree](https://github.com/lazysegtree) - Allow specifying multiple panels at startup [`#759`](yorukot/superfile#759) by [@​lazysegtree](https://github.com/lazysegtree) - Initial draft of rendering package [`#775`](yorukot/superfile#775) by [@​lazysegtree](https://github.com/lazysegtree) - Render unit tests for prompt model [`#809`](yorukot/superfile#809) by [@​lazysegtree](https://github.com/lazysegtree) - Chooser file option, --lastdir-file option, and improvements in quit, and bug fixes [`#812`](yorukot/superfile#812) by [@​lazysegtree](https://github.com/lazysegtree) - Prompt feature leftover items [`#804`](yorukot/superfile#804) by [@​lazysegtree](https://github.com/lazysegtree) - SPF Prompt tutorial and fixes [`#814`](yorukot/superfile#814) by [@​lazysegtree](https://github.com/lazysegtree) - Write prompt tutorial, rename prompt mode to spf mode, add develop branch in GitHub workflow, show_panel_footer_info flag [`#815`](yorukot/superfile#815) by [@​lazysegtree](https://github.com/lazysegtree) - Theme: Add gruvbox-dark-hard [`#828`](yorukot/superfile#828) by [@​Frost-Phoenix](https://github.com/Frost-Phoenix) #### Updates & Improvements - Sidebar separation [`#767`](yorukot/superfile#767) by [@​lazysegtree](https://github.com/lazysegtree) - Sidebar code separation [`#770`](yorukot/superfile#770) by [@​lazysegtree](https://github.com/lazysegtree) - Rendering package and rendering bug fixes [`#781`](yorukot/superfile#781) by [@​lazysegtree](https://github.com/lazysegtree) - Refactor CheckForUpdates [`#797`](yorukot/superfile#797) by [@​JassonCordones](https://github.com/JassonCordones) - Rename metadata strings [`#731`](yorukot/superfile#731) by [@​booth-w](https://github.com/booth-w) #### Bug Fixes - Fix crash with opening file with editor on an empty panel [`#730`](yorukot/superfile#730) by [@​booth-w](https://github.com/booth-w) - Fix: Add some of the remaining linter and fix errors [`#756`](yorukot/superfile#756) by [@​lazysegtree](https://github.com/lazysegtree) - Golangci lint fixes [`#757`](yorukot/superfile#757) by [@​lazysegtree](https://github.com/lazysegtree) - Fix: Remove redundant function containsKey [`#765`](yorukot/superfile#765) by [@​lazysegtree](https://github.com/lazysegtree) - Fix: Correctly resolve path in open and cd prompt actions [`#802`](yorukot/superfile#802) by [@​lazysegtree](https://github.com/lazysegtree) - Prompt dynamic dimensions and unit tests fix [`#805`](yorukot/superfile#805) by [@​lazysegtree](https://github.com/lazysegtree) - Fix: Convert unicode space to normal space, use rendered in file preview to fix layout bugs, Release 1.3.0 [`#825`](yorukot/superfile#825) by [@​lazysegtree](https://github.com/lazysegtree) #### Optimization & Code Quality - Adding linter to CI/CD and fix some lint issues [`#739`](yorukot/superfile#739) by [@​lazysegtree](https://github.com/lazysegtree) - Linter fixes, new feature of allowing multiple directories at startup, other code improvements [`#764`](yorukot/superfile#764) by [@​lazysegtree](https://github.com/lazysegtree) - Model unit tests [`#803`](yorukot/superfile#803) by [@​lazysegtree](https://github.com/lazysegtree) #### Dependency Updates - fix(deps): update dependency astro to v5.7.7 [`#726`](yorukot/superfile#726) by [@​renovate](https://github.com/renovate) - fix(deps): update module github.com/shirou/gopsutil/v4 to v4.25.3 [`#749`](yorukot/superfile#749) by [@​renovate](https://github.com/renovate) - fix(deps): update module github.com/pelletier/go-toml/v2 to v2.2.4 [`#760`](yorukot/superfile#760) by [@​renovate](https://github.com/renovate) - fix(deps): update module github.com/alecthomas/chroma/v2 to v2.16.0 [`#751`](yorukot/superfile#751) by [@​renovate](https://github.com/renovate) - fix(deps): update dependency sharp to ^0.34.0 [`#755`](yorukot/superfile#755) by [@​renovate](https://github.com/renovate) - fix(deps): update dependency [@​astrojs/starlight](https://github.com/astrojs/starlight) to ^0.34.0 [`#761`](yorukot/superfile#761) by [@​renovate](https://github.com/renovate) </p> </details> #### New Contributors * @​Rocco-Gossmann made their first contribution in yorukot/superfile#736 * @​Frost-Phoenix made their first contribution in yorukot/superfile#828 **Full Changelog**: yorukot/superfile@v1.2.1...v1.3.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4yMi4wIiwidXBkYXRlZEluVmVyIjoiNDAuMjMuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->

Summary by CodeRabbit
New Features
Tests