Skip to content

Conversation

@hupender
Copy link
Contributor

@hupender hupender commented Aug 16, 2025

Summary by CodeRabbit

  • New Features

    • Added a Permanent Delete option with a dedicated confirmation for irreversible deletion.
  • New Hotkeys

    • Default hotkey: D triggers Permanent Delete in normal mode (standard and Vim profiles).
  • Documentation

    • Help menu and hotkey list updated to document Permanent Delete and its description.
  • Behavior Changes

    • Deletion now picks trash vs permanent based on platform availability and user choice; clear prompts reflect the mode.
  • Tests

    • OS-aware tests added for trash vs permanent-delete flows and shared test timing helpers.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 16, 2025

Walkthrough

Adds a permanent-delete path alongside trash-based deletion: new hotkey and config entry, notify action for permanent delete, model-level hasTrash tracking and InitTrash initialization, delete command/trigger flows accept a permanent flag, OS-aware trash behavior and tests, plus small utils for creating dirs/files.

Changes

Cohort / File(s) Summary
Hotkeys & docs
src/internal/common/config_type.go, src/superfile_config/hotkeys.toml, src/superfile_config/vimHotkeys.toml, website/src/content/docs/list/hotkey-list.md
Add PermanentlyDeleteItems []string to hotkeys struct; add permanently_delete_items = ['D',''] in TOML configs; document new permanently-delete hotkey.
Delete flow & notify
src/internal/handle_file_operations.go, src/internal/key_function.go, src/internal/ui/notify/type.go
Introduce permanent-delete branching: getDeleteCmd/getDeleteTriggerCmd accept boolean to choose trash vs permanent; notify adds PermanentDeleteAction; key handling routes to perm vs normal delete; prompts/actions chosen dynamically.
Model state & init
src/internal/model.go, src/internal/default_config.go, src/internal/type.go, src/cmd/main.go, src/internal/common/load_config.go
Remove package-level hasTrash; add model.hasTrash field and set it from common.InitTrash() during default model construction; InitialModel signature updated (removed hasTrash param); main no longer contains InitTrash helper.
File operations implementation
src/internal/file_operations.go, src/internal/common/load_config.go, src/config/fixed_variable.go
Rename trashMacOrLinuxmoveToTrash and keep OS-specific trash behavior; add Linux-specific trash path variables; add InitTrash() that creates Linux trash dirs on Linux and reports availability.
Utils helpers
src/internal/utils/file_utils.go, src/cmd/main.go
Add CreateDirectories and CreateFiles helpers; main uses those helpers when initializing config files/directories.
Predefined messages
src/internal/common/predefined_variable.go
Add TrashWarnTitle, TrashWarnContent, PermanentDeleteWarnTitle, PermanentDeleteWarnContent constants used in confirm modals.
Tests & test utils
src/internal/model_file_operations_test.go, src/internal/handle_file_operation_test.go, src/internal/test_utils.go
Add OS-aware trash checks and TestFileDelete (trash vs permanent); introduce DefaultTestTick and DefaultTestTimeout; add helpers setupFilesWithData, setFilePanelSelectedItemByLocation, setFilePanelSelectedItemByName; replace hard-coded timeouts/ticks in tests.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant KeyHandler
  participant Model
  participant NotifyModal
  participant FileOps

  User->>KeyHandler: press Delete or Permanently-Delete hotkey
  KeyHandler->>Model: getDeleteTriggerCmd(deletePermanent?)
  Model->>NotifyModal: show confirm (DeleteAction or PermanentDeleteAction)
  User->>NotifyModal: confirm
  NotifyModal-->>Model: ConfirmAction
  Model->>FileOps: getDeleteCmd(deletePermanent?)
  alt useTrash (deletePermanent=false && model.hasTrash && not external path)
    FileOps->>FileOps: moveToTrash(file)
  else
    FileOps->>FileOps: os.RemoveAll(file) (permanent delete)
  end
  FileOps-->>Model: result
  Model-->>User: update UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • yorukot

Poem

I hop on keys and twitch my nose,
Some files take naps, some meet their close.
D for danger, D to clear the floor,
A rabbit taps "Are you sure?" once more.
Clean shelves and tidy code — I thump for more. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

codescene-delta-analysis[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@hupender hupender force-pushed the permanent_delete_option branch from 263f144 to 3e77de5 Compare August 16, 2025 03:33
codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

♻️ Duplicate comments (1)
src/internal/key_function.go (1)

129-189: Cyclomatic complexity increased; consider extracting sub-handlers

normalAndBrowserModeKey continues to grow (CodeScene flagged +2). Extracting select-mode and normal-mode branches into dedicated helpers would improve readability and maintainability.

Possible shape:

  • func (m *model) handleSelectModeKey(msg string) tea.Cmd
  • func (m *model) handleNormalModeKey(msg string) tea.Cmd
    …and reuse getFocusedFilePanel() inside both.
🧹 Nitpick comments (3)
src/internal/common/config_type.go (1)

138-138: Nit: fix grammar in comment tag

Minor wording cleanup.

Apply:

-	CopyItems              []string `toml:"copy_items" comment:"file operate"`
+	CopyItems              []string `toml:"copy_items" comment:"file operations"`
src/internal/key_function.go (2)

131-131: Good move: safer access via getFocusedFilePanel()

Switching to m.getFocusedFilePanel() for focus checks reduces risk of panics from index access. Consider using it consistently throughout this function for uniformity.


145-151: Use getFocusedFilePanel() consistently in select-mode branch

Avoid direct indexing into filePanels here; it’s both verbose and riskier. Use getFocusedFilePanel() like above for consistency.

Apply:

 	if m.getFocusedFilePanel().panelMode == selectMode {
 		switch {
 		case slices.Contains(common.Hotkeys.Confirm, msg):
-			m.fileModel.filePanels[m.filePanelFocusIndex].singleItemSelect()
+			m.getFocusedFilePanel().singleItemSelect()
 		case slices.Contains(common.Hotkeys.FilePanelSelectModeItemsSelectUp, msg):
-			m.fileModel.filePanels[m.filePanelFocusIndex].itemSelectUp(m.mainPanelHeight)
+			m.getFocusedFilePanel().itemSelectUp(m.mainPanelHeight)
 		case slices.Contains(common.Hotkeys.FilePanelSelectModeItemsSelectDown, msg):
-			m.fileModel.filePanels[m.filePanelFocusIndex].itemSelectDown(m.mainPanelHeight)
+			m.getFocusedFilePanel().itemSelectDown(m.mainPanelHeight)

Additionally (outside this hunk), consider replacing other direct uses in mainKey (listUp/listDown/pgUp/pgDown) similarly for consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 263f144 and 3e77de5.

📒 Files selected for processing (12)
  • src/internal/common/config_type.go (1 hunks)
  • src/internal/default_config.go (2 hunks)
  • src/internal/handle_file_operations.go (4 hunks)
  • src/internal/key_function.go (6 hunks)
  • src/internal/model.go (1 hunks)
  • src/internal/model_file_operations_test.go (2 hunks)
  • src/internal/test_utils.go (1 hunks)
  • src/internal/type.go (1 hunks)
  • src/internal/ui/notify/type.go (1 hunks)
  • src/superfile_config/hotkeys.toml (1 hunks)
  • src/superfile_config/vimHotkeys.toml (1 hunks)
  • website/src/content/docs/list/hotkey-list.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/internal/type.go
  • src/internal/model_file_operations_test.go
  • src/internal/ui/notify/type.go
  • src/internal/handle_file_operations.go
  • website/src/content/docs/list/hotkey-list.md
  • src/internal/test_utils.go
  • src/internal/model.go
  • src/internal/default_config.go
  • src/superfile_config/hotkeys.toml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-27T15:35:25.617Z
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T15:35:25.617Z
Learning: In yorukot/superfile, deleteItemWarn() only displays a warning modal via the channelMessage system and does not perform actual file deletion. The actual deletion happens when the user confirms the modal, which triggers getDeleteCmd() that returns a tea.Cmd. The architecture intentionally separates UI modal operations (using channelMessage/goroutines) from file I/O operations (using tea.Cmd pattern), creating clean separation of concerns between UI state management and file operations.

Applied to files:

  • src/internal/key_function.go
🧬 Code Graph Analysis (2)
src/internal/common/config_type.go (1)
src/internal/common/load_config.go (1)
  • LoadHotkeysFile (103-144)
src/internal/key_function.go (3)
src/internal/common/default_config.go (1)
  • Hotkeys (12-12)
src/internal/ui/notify/type.go (3)
  • DeleteAction (7-7)
  • NoAction (9-9)
  • PermanentDeleteAction (10-10)
src/internal/common/type.go (1)
  • NoAction (9-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and Test (macos-latest)
  • GitHub Check: Build and Test (windows-latest)
🔇 Additional comments (6)
src/internal/common/config_type.go (1)

138-142: New hotkey field permanently_delete_items integrated and validated

  • Struct field present in src/internal/common/config_type.go
  • TOML mappings found in both hotkeys.toml and vimHotkeys.toml under src/superfile_config
  • Code references in src/internal/key_function.go and tests updated accordingly
    Ready to merge.
src/superfile_config/vimHotkeys.toml (1)

33-33: Hotkey 'D' added and non-conflicting — approved

The permanently_delete_items = ['D', ''] mapping appears exactly once in each variant file, complementing delete_items = ['d', ''] without overlap:

  • src/superfile_config/vimHotkeys.toml: line 33
  • src/superfile_config/hotkeys.toml: line 31

No accidental duplicates detected.

src/internal/key_function.go (4)

153-156: Dual delete path in select-mode: clear separation via trigger cmd

Routing via getDeleteTriggerCmd(false/true) cleanly sets up the correct notify action for trash vs permanent delete. Matches the modal-then-cmd architecture.


172-174: Normal-mode permanent delete: wired correctly

Same clear split as select-mode; using getDeleteTriggerCmd(true) enables the permanent delete confirmation path as intended.


225-225: Cancel path acknowledges new PermanentDeleteAction

No-ops on cancel for DeleteAction/NoAction/PermanentDeleteAction are appropriate. The modal is dismissed without side effects.


235-237: Confirm path maps to getDeleteCmd(false/true) — aligns with design

DeleteAction → getDeleteCmd(false), PermanentDeleteAction → getDeleteCmd(true) matches the updated deletion flow and the UI separation principle (warn modal triggers cmd on confirm).

@hupender hupender force-pushed the permanent_delete_option branch from 3e77de5 to 75b8c87 Compare August 16, 2025 05:00
codescene-delta-analysis[bot]

This comment was marked as outdated.

@hupender hupender force-pushed the permanent_delete_option branch from 75b8c87 to df4f8f9 Compare August 16, 2025 05:02
codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🔭 Outside diff range comments (1)
src/internal/default_config.go (1)

228-231: Add help entry for permanent delete
Please include a new help entry for the PermanentlyDeleteItems hotkey under the “File operations” section to improve discoverability.

• File: src/internal/default_config.go
– Locate the slice of help entries (around lines 228–231).
– Immediately after the DeleteItems entry, add:
go { hotkey: common.Hotkeys.PermanentlyDeleteItems, description: "Permanently delete selected items", hotkeyWorkType: globalType, },

♻️ Duplicate comments (2)
src/internal/key_function.go (1)

129-189: normalAndBrowserModeKey complexity grew; consider extracting handlers.

This function’s cyclomatic complexity is already a known issue and increases further with the new branches. Extract dedicated helpers (e.g., handleSelectModeKeys, handleDeleteHotkeys) to contain switch cases and reuse logic across select/normal modes.

Possible direction:

  • Extract a small helper to handle delete keys once and use it in both select and normal modes:
    • handleDeleteHotkeys(msg string) (tea.Cmd, handled bool)
  • Similarly extract selection navigation into handleSelectionNavKeys.

I can sketch the refactor if you want to proceed now.

src/internal/default_config.go (1)

17-17: New hasTrash argument added; prefer an options struct to avoid argument bloat.

defaultModelConfig now takes 5 positional arguments (flagged by tooling). Replace the long parameter list with an options struct to improve readability, call-site clarity, and forward compatibility.

A minimal direction:

  • Define:
    type DefaultModelOptions struct {
    ToggleDotFile bool
    ToggleFooter bool
    FirstUse bool
    HasTrash bool
    FirstFilePanelDirs []string
    }

  • Change signature to:
    func defaultModelConfig(opts DefaultModelOptions) *model

  • Update field assignments to opts.* and pass opts.HasTrash to hasTrash.

I can provide a concrete patch if you want to adopt this now.

🧹 Nitpick comments (2)
src/internal/key_function.go (2)

131-145: Standardize file panel access using getFocusedFilePanel()

To centralize bounds checking and avoid out-of-bounds panics, replace all direct uses of
m.fileModel.filePanels[m.filePanelFocusIndex] with m.getFocusedFilePanel(). Also harden the accessor itself by adding a nil or bounds check (e.g. panic or early return if the slice is empty or the index is invalid).

Key locations to refactor (run the search below to find every occurrence):
• src/internal/handle_panel_movement.go
• src/internal/handle_modal.go
• src/internal/model_render.go
• src/internal/model.go
• src/internal/key_function.go
• src/internal/wheel_function.go
• src/internal/handle_file_operations.go
• src/internal/handle_panel_navigation.go

Suggested steps:

  • Run rg -nP --type=go -- 'filePanels\[\s*m\.filePanelFocusIndex' to audit all direct slice accesses.
  • Replace each with panel := m.getFocusedFilePanel() (or &*panel as needed).
  • In getFocusedFilePanel(), add a guard:
    if m.filePanelFocusIndex < 0 || m.filePanelFocusIndex >= len(m.fileModel.filePanels) {
        panic(fmt.Sprintf("invalid filePanelFocusIndex: %d", m.filePanelFocusIndex))
    }
  • Verify no nil pointer can be returned under normal operation.

[optional_refactors_recommended]


153-156: Dual-path delete hotkeys – no overlaps in default or vim configs

I confirmed that in the shipped configs:

  • hotkeys.toml binds
    • DeleteItems = [‘ctrl+d’, ‘delete’, ‘’]
    • PermanentlyDeleteItems = [‘D’, ‘’]
  • vimHotkeys.toml binds
    • DeleteItems = [‘d’, ‘’]
    • PermanentlyDeleteItems = [‘D’, ‘’]

Because these use distinct (and case-sensitive) keys, there’s no collision in the out-of-the-box configs. However, since the code checks DeleteItems before PermanentlyDeleteItems, a user-supplied config that maps the same key to both would silently favor the standard delete.

Consider adding startup validation (or at least a warning) to flag any overlaps between common.Hotkeys.DeleteItems and common.Hotkeys.PermanentlyDeleteItems in user configs.
[optional_refactors_recommended]

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3e77de5 and df4f8f9.

📒 Files selected for processing (12)
  • src/internal/common/config_type.go (1 hunks)
  • src/internal/default_config.go (2 hunks)
  • src/internal/handle_file_operations.go (4 hunks)
  • src/internal/key_function.go (6 hunks)
  • src/internal/model.go (1 hunks)
  • src/internal/model_file_operations_test.go (2 hunks)
  • src/internal/test_utils.go (1 hunks)
  • src/internal/type.go (1 hunks)
  • src/internal/ui/notify/type.go (1 hunks)
  • src/superfile_config/hotkeys.toml (1 hunks)
  • src/superfile_config/vimHotkeys.toml (1 hunks)
  • website/src/content/docs/list/hotkey-list.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/superfile_config/vimHotkeys.toml
  • src/internal/handle_file_operations.go
  • src/internal/type.go
  • src/internal/test_utils.go
  • src/internal/common/config_type.go
  • src/superfile_config/hotkeys.toml
  • website/src/content/docs/list/hotkey-list.md
  • src/internal/model_file_operations_test.go
  • src/internal/model.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/internal/key_function.go (3)
src/internal/common/default_config.go (1)
  • Hotkeys (12-12)
src/internal/ui/notify/type.go (3)
  • DeleteAction (7-7)
  • NoAction (9-9)
  • PermanentDeleteAction (10-10)
src/internal/common/type.go (1)
  • NoAction (9-10)
🔇 Additional comments (4)
src/internal/ui/notify/type.go (1)

10-10: Adding PermanentDeleteAction looks correct and non-breaking.

Appended at the end of the iota block, so existing numeric values remain stable. Call sites in this PR handle it in switches, which is good.

src/internal/key_function.go (2)

225-225: Cancel handler covers PermanentDeleteAction — OK.

No behavior on cancel is appropriate for delete confirmations.


235-238: Confirmed delete prompt and action alignment

The getDeleteTriggerCmd logic correctly switches both the modal text and ConfirmActionType to PermanentDeleteAction whenever m.hasTrash is false (or deletePermanent is true or on external disks), ensuring the subsequent handleNotifyModelConfirm always invokes getDeleteCmd(true) for irreversible deletion. No misalignment was found—no changes required.

src/internal/default_config.go (1)

43-44: Propagating hasTrash into model looks correct.

This threads OS capability into the model for downstream delete behavior.

@lazysegtree lazysegtree added pr needs work PR needs work before it can be further reviewed/merged new feature labels Aug 16, 2025
codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🔭 Outside diff range comments (1)
src/internal/file_operations.go (1)

148-163: Darwin Trash: ensure directory exists and avoid name collisions.

On macOS, moving to ~/.Trash without creating the directory can fail, and using filepath.Base risks collisions when an item with the same name already exists in Trash. Create the Trash directory and resolve duplicates before moving. Also, clarify the log message.

-func moveToTrash(src string) error {
-	var err error
-	switch runtime.GOOS {
-	case utils.OsDarwin:
-		err = moveElement(src, filepath.Join(variable.DarwinTrashDirectory, filepath.Base(src)))
-	case utils.OsWindows:
-		err = trash_win.Throw(src)
-	default:
-		// TODO: We should consider moving away from this package. Its not well written.
-		err = trash.Trash(src)
-	}
-	if err != nil {
-		slog.Error("Error while deleting single item, in function to move file to trash can", "error", err)
-	}
-	return err
-}
+func moveToTrash(src string) error {
+	var err error
+	switch runtime.GOOS {
+	case utils.OsDarwin:
+		// Ensure the Trash directory exists
+		if mkErr := os.MkdirAll(variable.DarwinTrashDirectory, 0o755); mkErr != nil {
+			slog.Error("Failed to ensure Darwin Trash directory", "error", mkErr, "dir", variable.DarwinTrashDirectory)
+			return mkErr
+		}
+		// Avoid name collisions within Trash
+		dest := filepath.Join(variable.DarwinTrashDirectory, filepath.Base(src))
+		if dest, err = renameIfDuplicate(dest); err != nil {
+			slog.Error("Failed to resolve duplicate name in Trash", "error", err)
+			return err
+		}
+		err = moveElement(src, dest)
+	case utils.OsWindows:
+		err = trash_win.Throw(src)
+	default:
+		// TODO: We should consider moving away from this package. Its not well written.
+		err = trash.Trash(src)
+	}
+	if err != nil {
+		slog.Error("Error while moving item to Trash", "error", err)
+	}
+	return err
+}
♻️ Duplicate comments (1)
src/internal/model_file_operations_test.go (1)

156-160: Pass method value directly to Eventually.

You can pass m.notifyModel.IsOpen directly (as you did later), no need to wrap it.

Apply this diff:

-      assert.Eventually(t, func() bool {
-        return m.notifyModel.IsOpen()
-      }, time.Second, DefaultTestTick, "Notify modal never opened, filepanel items : %v",
+      assert.Eventually(t, m.notifyModel.IsOpen, DefaultTestTimeout, DefaultTestTick, "Notify modal never opened, filepanel items : %v",
         m.getFocusedFilePanel().element)
🧹 Nitpick comments (13)
src/cmd/main.go (1)

133-134: Don't hardcode hasTrash=true; verify support or rely on lazy creation.

Previously InitTrash computed hasTrash and ensured the Trash dir on Darwin. With this change, the UI always assumes Trash is available, which can lead to failed "move to Trash" operations on macOS when ~/.Trash is missing or inaccessible. Please either:

  • detect Trash support at startup, or
  • ensure the Darwin Trash directory is created lazily in the trash path.

I proposed a safe lazy-creation fix in moveToTrash within file_operations.go.

src/internal/common/predefined_variable.go (1)

17-20: Polish prompt text: grammar and clarity.

Minor UX copy improvements for correctness and consistency.

-const TrashWarnTitle = "Are you sure you want to move this to trash can"
-const TrashWarnContent = "This operation will move file or directory to trash can."
-const PermanentDeleteWarnTitle = "Are you sure you want to completely delete"
-const PermanentDeleteWarnContent = "This operation cannot be undone and your data will be completely lost."
+const TrashWarnTitle = "Are you sure you want to move this to the trash can"
+const TrashWarnContent = "This operation will move the file or directory to the trash can."
+const PermanentDeleteWarnTitle = "Are you sure you want to completely delete this item"
+const PermanentDeleteWarnContent = "This operation cannot be undone and your data will be completely lost."

If you prefer shorter titles without questions (to match SameRenameWarnTitle style), consider:

  • "Move to Trash"
  • "Permanently delete this item"
src/internal/handle_file_operation_test.go (1)

146-155: Consider standardizing on DefaultTestTimeout as well.

For consistency with DefaultTestTick (and other tests), use the shared timeout constant.

-            }, time.Second, DefaultTestTick, "Extraction of files failed Required - [%s]+%v",
+            }, DefaultTestTimeout, DefaultTestTick, "Extraction of files failed Required - [%s]+%v",

Note: If you adopt this, the time import may become unused in this file.

src/internal/test_utils.go (3)

47-51: Boolean-parameter smell on defaultModelConfig; consider options struct or named config.

The fourth boolean increases ambiguity at the call site. Prefer an options/config struct (or builder) for readability and future extensibility. Also, confirm all call sites of defaultModelConfig were updated to the new signature.

Would you like me to generate a minimal config struct and refactor these call sites in a follow-up PR?


161-165: Use DefaultTestTimeout for consistency.

Minor: you introduced DefaultTestTimeout but this still uses time.Second. Align with the new constant for consistency across tests.

Apply this diff:

-  }, time.Second, DefaultTestTick, message)
+  }, DefaultTestTimeout, DefaultTestTick, message)

172-176: Use DefaultTestTimeout for consistency.

Same here: adopt DefaultTestTimeout to match your new convention.

Apply this diff:

-    }, time.Second, DefaultTestTick, "%s should exist in destination", expectedFile)
+    }, DefaultTestTimeout, DefaultTestTick, "%s should exist in destination", expectedFile)
src/internal/handle_file_operations.go (2)

95-117: Clone selected items to avoid TOCTOU/mutation issues before the async cmd runs.

panel.selected can change between building the tea.Cmd and its execution. Copy the slice to capture a stable snapshot.

Apply this diff:

 func (m *model) getDeleteCmd(permDelete bool) tea.Cmd {
   panel := m.getFocusedFilePanel()
   if len(panel.element) == 0 {
     return nil
   }

   var items []string
   if panel.panelMode == selectMode {
-    items = panel.selected
+    items = append([]string(nil), panel.selected...)
   } else {
     items = []string{panel.getSelectedItem().location}
   }

As a follow-up, please verify all call sites now pass permDelete explicitly to match the new signature.


157-178: Don’t duplicate prompt strings; reuse predefined constants for title and content.

Avoid hard-coded strings and drift. Prefer common.TrashWarnTitle/Content and common.PermanentDeleteWarnTitle/Content.

Apply this diff:

 return func() tea.Msg {
-  title := "Are you sure you want to move this to trash can"
-  content := "This operation will move file or directory to trash can."
+  title := common.TrashWarnTitle
+  content := common.TrashWarnContent
   action := notify.DeleteAction

-  if !m.hasTrash || isExternalDiskPath(panel.location) || deletePermanent {
-    title = "Are you sure you want to completely delete"
-    content = "This operation cannot be undone and your data will be completely lost."
+  if !m.hasTrash || isExternalDiskPath(panel.location) || deletePermanent {
+    title = common.PermanentDeleteWarnTitle
+    content = common.PermanentDeleteWarnContent
     action = notify.PermanentDeleteAction
   }
   return NewNotifyModalMsg(notify.New(true, title, content, action), reqID)
 }
src/internal/model_file_operations_test.go (5)

49-53: Use DefaultTestTimeout to match new test timing constants.

Minor consistency cleanup.

Apply this diff:

-    }, time.Second, DefaultTestTick)
+    }, DefaultTestTimeout, DefaultTestTick)

58-62: Use DefaultTestTimeout here as well.

Apply this diff:

-    }, time.Second, DefaultTestTick)
+    }, DefaultTestTimeout, DefaultTestTick)

136-141: Align with DefaultTestTimeout.

Apply this diff:

-    }, time.Second, DefaultTestTick, "File never got renamed")
+    }, DefaultTestTimeout, DefaultTestTick, "File never got renamed")

194-206: Confirm linux trash.Stat expects the original absolute path, not just the basename.

On Linux, the XDG trash spec keys off the original absolute path. If trash.Stat expects the original path, using only the basename risks false positives/negatives. Recommend changing isTrashed to accept the absolute path and pass tt.filePath.

Apply these diffs:

-func isTrashed(fileName string) bool {
+func isTrashed(absPath string) bool {
   switch runtime.GOOS {
   case utils.OsDarwin:
-    _, err := os.Stat(filepath.Join(variable.DarwinTrashDirectory, fileName))
+    _, err := os.Stat(filepath.Join(variable.DarwinTrashDirectory, filepath.Base(absPath)))
     return err == nil
   case utils.OsLinux:
-    _, err := trash.Stat(fileName)
+    _, err := trash.Stat(absPath)
     return err == nil
   default:
     return false
   }
 }

And update the call site below:

-        assert.Equal(t, tt.permanentDelete, !isTrashed(filepath.Base(tt.filePath)),
+        assert.Equal(t, tt.permanentDelete, !isTrashed(tt.filePath),
           "Existence in trash status should be expected only of not permanently deleted")

If you prefer, I can follow up with a dedicated test adapter to abstract OS differences.


263-266: Make trash assertions explicit for readability.

The equality trick works but is harder to read. Consider branch-specific asserts.

Apply this diff:

-        assert.Equal(t, tt.permanentDelete, !isTrashed(tt.filePath),
-          "Existence in trash status should be expected only of not permanently deleted")
+        if tt.permanentDelete {
+          assert.False(t, isTrashed(tt.filePath), "File must not be in trash after permanent delete")
+        } else {
+          assert.True(t, isTrashed(tt.filePath), "File must be in trash after non-permanent delete")
+        }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a9c84ff and 3599e24.

📒 Files selected for processing (8)
  • src/cmd/main.go (1 hunks)
  • src/config/fixed_variable.go (1 hunks)
  • src/internal/common/predefined_variable.go (1 hunks)
  • src/internal/file_operations.go (1 hunks)
  • src/internal/handle_file_operation_test.go (2 hunks)
  • src/internal/handle_file_operations.go (5 hunks)
  • src/internal/model_file_operations_test.go (7 hunks)
  • src/internal/test_utils.go (4 hunks)
🧰 Additional context used
🧠 Learnings (13)
📚 Learning: 2025-06-04T09:58:25.572Z
Learnt from: yorukot
PR: yorukot/superfile#841
File: src/internal/model_render.go:334-334
Timestamp: 2025-06-04T09:58:25.572Z
Learning: Before suggesting the creation of new constants for string literals, always check if a constant already exists in the codebase, especially in common packages like `src/internal/common/predefined_variable.go`.

Applied to files:

  • src/internal/common/predefined_variable.go
📚 Learning: 2025-07-27T15:35:25.617Z
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T15:35:25.617Z
Learning: In yorukot/superfile, deleteItemWarn() only displays a warning modal via the channelMessage system and does not perform actual file deletion. The actual deletion happens when the user confirms the modal, which triggers getDeleteCmd() that returns a tea.Cmd. The architecture intentionally separates UI modal operations (using channelMessage/goroutines) from file I/O operations (using tea.Cmd pattern), creating clean separation of concerns between UI state management and file operations.

Applied to files:

  • src/internal/handle_file_operations.go
📚 Learning: 2025-07-27T15:35:25.617Z
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T15:35:25.617Z
Learning: deleteItemWarn() in yorukot/superfile only displays a warning modal via channel messaging and does not perform actual file deletion. The actual deletion happens through getDeleteCmd() which returns a tea.Cmd. The architectural pattern separates UI modal operations (using channels/goroutines) from file I/O operations (using tea.Cmd), which is intentional and appropriate.

Applied to files:

  • src/internal/handle_file_operations.go
📚 Learning: 2025-08-06T10:54:31.444Z
Learnt from: lazysegtree
PR: yorukot/superfile#979
File: src/internal/common/predefined_variable.go:47-47
Timestamp: 2025-08-06T10:54:31.444Z
Learning: When lazysegtree says a review is "inaccurate and pre-existing issues. Not much useful," it means I should focus specifically on bugs or problems introduced by the current PR changes, not architectural concerns or code quality issues that were already present. The refactoring work in superfile PRs is generally well-implemented and should be evaluated on whether the specific changes work correctly, not on broader codebase architecture.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-09T02:52:22.516Z
Learnt from: lazysegtree
PR: yorukot/superfile#924
File: src/internal/model_test.go:147-168
Timestamp: 2025-08-09T02:52:22.516Z
Learning: In superfile tests, lazysegtree prefers tests that accurately mimic the actual production behavior, including file operations like creating and deleting the LastDir file, rather than isolating such operations to temporary locations when the real behavior involves modifying/deleting those specific files.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-12T12:00:32.688Z
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:00:32.688Z
Learning: In PR #767 for yorukot/superfile, the focus is on moving code (especially sidebar-related functionality) to a more organized structure without changing functionality. Pre-existing issues should be ignored since the purpose is code reorganization, not fixing existing problems.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-02T11:47:07.713Z
Learnt from: lazysegtree
PR: yorukot/superfile#967
File: src/internal/key_function.go:45-47
Timestamp: 2025-08-02T11:47:07.713Z
Learning: lazysegtree prefers to track technical debt and architectural improvements in dedicated GitHub issues when they are identified during PR reviews but are beyond the scope of the current PR, particularly for complex refactoring needs like input handling architecture that would require significant changes.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-07-24T03:46:29.516Z
Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.516Z
Learning: lazysegtree prefers to defer comprehensive unit testing to separate PRs when the current PR has grown too large, maintaining focus on the primary refactoring objectives while tracking testing requirements in dedicated GitHub issues.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-05-22T04:53:45.663Z
Learnt from: lazysegtree
PR: yorukot/superfile#825
File: src/internal/model_render_test.go:15-25
Timestamp: 2025-05-22T04:53:45.663Z
Learning: In the superfile project, comments in test files documenting additional test cases with "// Additional tests" are intentional TODOs for future work and should not be flagged as missing implementations in PR reviews.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-28T04:27:33.074Z
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-28T03:48:46.327Z
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-02T17:00:37.262Z
Learnt from: lazysegtree
PR: yorukot/superfile#970
File: src/internal/ui/processbar/model.go:11-26
Timestamp: 2025-08-02T17:00:37.262Z
Learning: lazysegtree prefers to track memory leak issues and feature enhancements via dedicated GitHub issues when identified during PR reviews but are beyond the current PR scope, particularly for processbar-related improvements like cleanup mechanisms and keyboard shortcuts.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-06T10:27:20.420Z
Learnt from: lazysegtree
PR: yorukot/superfile#979
File: src/internal/common/predefined_variable.go:47-47
Timestamp: 2025-08-06T10:27:20.420Z
Learning: lazysegtree specifically asked for a "strict review to find bad stuff" in PR reviews, indicating he wants comprehensive analysis that identifies all potential issues regardless of scope, not just issues within the current PR's scope.

Applied to files:

  • src/internal/model_file_operations_test.go
🧬 Code Graph Analysis (5)
src/internal/handle_file_operation_test.go (1)
src/internal/test_utils.go (1)
  • DefaultTestTick (16-16)
src/cmd/main.go (1)
src/internal/model.go (1)
  • InitialModel (39-43)
src/internal/file_operations.go (2)
src/internal/utils/consts.go (2)
  • OsDarwin (10-10)
  • OsWindows (8-8)
src/config/fixed_variable.go (1)
  • DarwinTrashDirectory (49-49)
src/internal/handle_file_operations.go (5)
src/internal/ui/processbar/process_update_msg.go (1)
  • Cmd (3-3)
src/internal/ui/notify/type.go (2)
  • DeleteAction (7-7)
  • PermanentDeleteAction (10-10)
src/internal/model_msg.go (1)
  • NewNotifyModalMsg (149-156)
src/internal/ui/notify/model.go (1)
  • New (14-21)
src/internal/key_function.go (1)
  • m (228-242)
src/internal/model_file_operations_test.go (6)
src/internal/test_utils.go (2)
  • DefaultTestTick (16-16)
  • DefaultTestTimeout (17-17)
src/internal/utils/consts.go (2)
  • OsDarwin (10-10)
  • OsLinux (11-11)
src/config/fixed_variable.go (1)
  • DarwinTrashDirectory (49-49)
src/internal/common/default_config.go (1)
  • Hotkeys (12-12)
src/internal/common/predefined_variable.go (2)
  • TrashWarnTitle (17-17)
  • PermanentDeleteWarnTitle (19-19)
src/internal/ui/notify/type.go (2)
  • DeleteAction (7-7)
  • PermanentDeleteAction (10-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and Test (windows-latest)
  • GitHub Check: Build and Test (ubuntu-latest)
🔇 Additional comments (8)
src/config/fixed_variable.go (1)

49-50: XDG trash constants removal verified
Ran rg -n -C2 '\bCustomTrashDirectory\b|\bCustomTrashDirectoryFiles\b|\bCustomTrashDirectoryInfo\b' across the repo and found no matches—no lingering references remain.

src/internal/handle_file_operation_test.go (1)

117-121: LGTM: Shared tick constant reduces flakiness.

Switching assert.Eventually tick to DefaultTestTick improves consistency across tests.

src/internal/test_utils.go (1)

16-18: Good centralization of test timings.

Introducing DefaultTestTick and DefaultTestTimeout improves consistency and makes future tuning simpler.

src/internal/handle_file_operations.go (3)

108-110: Correct gating for trash vs permanent delete.

useTrash correctly respects hasTrash, external-disk paths, and the explicit permDelete flag.


129-133: Switching delete function to moveToTrash when applicable is correct.

This keeps platform-specific trash logic encapsulated and preserves previous permanent deletion behavior via os.RemoveAll.


157-178: Confirm flow correctly handles permanent deletions
Both handleNotifyModelConfirm branches for DeleteAction and PermanentDeleteAction invoke getDeleteCmd(false) and getDeleteCmd(true) respectively, and getDeleteCmd itself emits the correct DeleteAction or PermanentDeleteAction based on the flag. No changes needed.

src/internal/model_file_operations_test.go (2)

243-245: LGTM: cleaner Eventually usage with method value.

This matches the suggested style.


271-276: Nice: extracted helper to select the file in the panel.

This addresses repetition across tests and improves readability.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/internal/model_file_operations_test.go (1)

155-159: Pass the method value directly to Eventually (consistency + clarity)

You can pass the method value directly instead of wrapping it in a lambda.

-			assert.Eventually(t, func() bool {
-				return m.notifyModel.IsOpen()
-			}, DefaultTestTimeout, DefaultTestTick, "Notify modal never opened, filepanel items : %v",
-				m.getFocusedFilePanel().element)
+			assert.Eventually(t, m.notifyModel.IsOpen, DefaultTestTimeout, DefaultTestTick,
+				"Notify modal never opened, filepanel items : %v", m.getFocusedFilePanel().element)
🧹 Nitpick comments (1)
src/internal/model_file_operations_test.go (1)

7-7: Import alias nit: prefer config over variable

The alias variable for the config package is misleading. Using config improves readability at call sites (e.g., config.DarwinTrashDirectory).

Apply:

-	variable "github.com/yorukot/superfile/src/config"
+	config "github.com/yorukot/superfile/src/config"

Also applies to: 11-11, 14-14

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 81a1224 and 3a57bc4.

📒 Files selected for processing (4)
  • src/internal/default_config.go (3 hunks)
  • src/internal/handle_file_operation_test.go (2 hunks)
  • src/internal/model_file_operations_test.go (7 hunks)
  • src/internal/test_utils.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/internal/handle_file_operation_test.go
  • src/internal/test_utils.go
  • src/internal/default_config.go
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2025-08-06T10:54:31.444Z
Learnt from: lazysegtree
PR: yorukot/superfile#979
File: src/internal/common/predefined_variable.go:47-47
Timestamp: 2025-08-06T10:54:31.444Z
Learning: When lazysegtree says a review is "inaccurate and pre-existing issues. Not much useful," it means I should focus specifically on bugs or problems introduced by the current PR changes, not architectural concerns or code quality issues that were already present. The refactoring work in superfile PRs is generally well-implemented and should be evaluated on whether the specific changes work correctly, not on broader codebase architecture.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-09T02:52:22.516Z
Learnt from: lazysegtree
PR: yorukot/superfile#924
File: src/internal/model_test.go:147-168
Timestamp: 2025-08-09T02:52:22.516Z
Learning: In superfile tests, lazysegtree prefers tests that accurately mimic the actual production behavior, including file operations like creating and deleting the LastDir file, rather than isolating such operations to temporary locations when the real behavior involves modifying/deleting those specific files.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-12T12:00:32.688Z
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:00:32.688Z
Learning: In PR #767 for yorukot/superfile, the focus is on moving code (especially sidebar-related functionality) to a more organized structure without changing functionality. Pre-existing issues should be ignored since the purpose is code reorganization, not fixing existing problems.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-02T11:47:07.713Z
Learnt from: lazysegtree
PR: yorukot/superfile#967
File: src/internal/key_function.go:45-47
Timestamp: 2025-08-02T11:47:07.713Z
Learning: lazysegtree prefers to track technical debt and architectural improvements in dedicated GitHub issues when they are identified during PR reviews but are beyond the scope of the current PR, particularly for complex refactoring needs like input handling architecture that would require significant changes.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-07-24T03:46:29.516Z
Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.516Z
Learning: lazysegtree prefers to defer comprehensive unit testing to separate PRs when the current PR has grown too large, maintaining focus on the primary refactoring objectives while tracking testing requirements in dedicated GitHub issues.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-05-22T04:53:45.663Z
Learnt from: lazysegtree
PR: yorukot/superfile#825
File: src/internal/model_render_test.go:15-25
Timestamp: 2025-05-22T04:53:45.663Z
Learning: In the superfile project, comments in test files documenting additional test cases with "// Additional tests" are intentional TODOs for future work and should not be flagged as missing implementations in PR reviews.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-28T04:27:33.074Z
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-04-28T03:48:46.327Z
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-02T17:00:37.262Z
Learnt from: lazysegtree
PR: yorukot/superfile#970
File: src/internal/ui/processbar/model.go:11-26
Timestamp: 2025-08-02T17:00:37.262Z
Learning: lazysegtree prefers to track memory leak issues and feature enhancements via dedicated GitHub issues when identified during PR reviews but are beyond the current PR scope, particularly for processbar-related improvements like cleanup mechanisms and keyboard shortcuts.

Applied to files:

  • src/internal/model_file_operations_test.go
📚 Learning: 2025-08-06T10:27:20.420Z
Learnt from: lazysegtree
PR: yorukot/superfile#979
File: src/internal/common/predefined_variable.go:47-47
Timestamp: 2025-08-06T10:27:20.420Z
Learning: lazysegtree specifically asked for a "strict review to find bad stuff" in PR reviews, indicating he wants comprehensive analysis that identifies all potential issues regardless of scope, not just issues within the current PR's scope.

Applied to files:

  • src/internal/model_file_operations_test.go
🪛 GitHub Actions: Go CI
src/internal/model_file_operations_test.go

[error] 255-255: TestFileDelete/Move_to_trash: Condition never satisfied. File never removed from original location.


[error] 263-263: TestFileDelete/Move_to_trash: Trash status mismatch. Expected false, actual true.

🔇 Additional comments (2)
src/internal/model_file_operations_test.go (2)

51-51: LGTM: unified timing utilities

Using DefaultTestTimeout and DefaultTestTick makes the tests consistent and less brittle across environments.

Also applies to: 60-61


270-275: LGTM: handy helper to reduce duplication

This keeps tests concise and consistent when targeting a specific file selection.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (5)
src/internal/utils/file_utils.go (2)

223-227: Skip empty directory paths to avoid os.MkdirAll("") errors

Mirroring setupDirectories in tests, defensively skip empty strings to prevent unexpected failures when a blank path sneaks in.

 func CreateDirectories(dirs ...string) error {
 	for _, dir := range dirs {
+		if dir == "" {
+			continue
+		}
 		if err := os.MkdirAll(dir, 0755); err != nil {
 			return fmt.Errorf("failed to create directory %s: %w", dir, err)
 		}
 	}
 	return nil
 }

220-232: Docstring grammar nits

  • “Create all dirs that does not already exists” → “Create all directories that do not already exist”
  • “Create all files if they do not exists yet” → “Create files that do not yet exist”
src/config/fixed_variable.go (1)

51-55: Tighten comment wording

Minor grammar tweak: “We need to make sure that these directories exists” → “exist”.

-// We need to make sure that these directories exists
+// We need to make sure that these directories exist
src/internal/common/load_config.go (1)

332-342: Log why trash initialization failed; otherwise users silently fall back to permanent delete

Returning only a bool loses error context. Keep the signature but log the reason so users understand why they’re in permanent-delete mode.

 func InitTrash() bool {
 	// Create trash directories
 	if runtime.GOOS != utils.OsLinux {
 		return true
 	}
-	return utils.CreateDirectories(
-		variable.LinuxTrashDirectory,
-		variable.LinuxTrashDirectoryFiles,
-		variable.LinuxTrashDirectoryInfo,
-	) == nil
+	if err := utils.CreateDirectories(
+		variable.LinuxTrashDirectory,
+		variable.LinuxTrashDirectoryFiles,
+		variable.LinuxTrashDirectoryInfo,
+	); err != nil {
+		slog.Warn("Failed to initialize XDG trash; falling back to permanent delete",
+			"error", err,
+			"trashDir", variable.LinuxTrashDirectory,
+		)
+		return false
+	}
+	return true
 }
src/cmd/main.go (1)

133-135: Capture hasTrash and warn when falling back to permanent delete

Surfacing this to logs avoids surprising behavior when the trash cannot be used (e.g., permission issues on $XDG_DATA_HOME).

-	p := tea.NewProgram(internal.InitialModel(firstFilePanelDirs, firstUse, common.InitTrash()),
+	hasTrash := common.InitTrash()
+	if !hasTrash {
+		slog.Warn("Trash is unavailable; falling back to permanent delete")
+	}
+	p := tea.NewProgram(internal.InitialModel(firstFilePanelDirs, firstUse, hasTrash),
 		tea.WithAltScreen(), tea.WithMouseCellMotion())
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3a57bc4 and 666de06.

📒 Files selected for processing (7)
  • src/cmd/main.go (3 hunks)
  • src/config/fixed_variable.go (1 hunks)
  • src/internal/common/load_config.go (1 hunks)
  • src/internal/file_operations.go (1 hunks)
  • src/internal/handle_file_operations.go (5 hunks)
  • src/internal/model_file_operations_test.go (7 hunks)
  • src/internal/utils/file_utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/internal/model_file_operations_test.go
  • src/internal/handle_file_operations.go
  • src/internal/file_operations.go
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/internal/common/load_config.go (3)
src/internal/utils/consts.go (1)
  • OsLinux (11-11)
src/internal/utils/file_utils.go (1)
  • CreateDirectories (222-229)
src/config/fixed_variable.go (3)
  • LinuxTrashDirectory (53-53)
  • LinuxTrashDirectoryFiles (54-54)
  • LinuxTrashDirectoryInfo (55-55)
src/internal/utils/file_utils.go (2)
src/internal/test_utils.go (3)
  • setupDirectories (18-27)
  • setupFiles (37-39)
  • setupFilesWithData (29-35)
src/internal/function_test.go (1)
  • TestReturnDirElement (13-200)
src/cmd/main.go (3)
src/internal/model.go (1)
  • InitialModel (39-43)
src/internal/common/load_config.go (1)
  • InitTrash (332-342)
src/internal/utils/file_utils.go (2)
  • CreateDirectories (222-229)
  • CreateFiles (232-241)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build and Test (ubuntu-latest)
🔇 Additional comments (3)
src/config/fixed_variable.go (1)

49-56: LGTM: XDG-compliant Linux trash paths and Darwin .Trash are appropriate

Adopting $XDG_DATA_HOME/Trash/{files,info} aligns with the spec and the xdg/trash package. Exported variables make sense for reuse across initialization and tests.

src/cmd/main.go (2)

156-162: Good reuse: centralizing directory creation via utils.CreateDirectories

Replacing local wrappers with the shared helper reduces duplication and keeps behavior consistent.


166-173: Good reuse: centralizing file creation via utils.CreateFiles

This simplifies InitConfigFile. With the proposed CreateFiles fix, unexpected stat errors will no longer be silently ignored.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link

@codescene-delta-analysis codescene-delta-analysis bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Health Improved (3 files improve in Code Health)

Gates Failed
Prevent hotspot decline (3 hotspots with Large Method, Complex Conditional, Complex Method)

Gates Passed
2 Quality Gates Passed

See analysis details in CodeScene

Reason for failure
Prevent hotspot decline Violations Code Health Impact
handle_file_operations.go 1 rule in this hotspot 8.35 → 8.09 Suppress
key_function.go 1 rule in this hotspot 8.36 → 8.33 Suppress
default_config.go 1 rule in this hotspot 8.87 → 8.84 Suppress
View Improvements
File Code Health Impact Categories Improved
handle_file_operations.go 8.35 → 8.09 String Heavy Function Arguments
model.go no change Primitive Obsession
test_utils.go 9.10 → 9.39 Primitive Obsession, String Heavy Function Arguments
main.go 9.22 → 9.52 String Heavy Function Arguments
handle_file_operation_test.go 8.34 → 8.35 Large Method
load_config.go no change Overall Code Complexity

Quality Gate Profile: The Bare Minimum
Want more control? Customize Code Health rules or catch issues early with our IDE extension and CLI tool.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (4)
src/internal/test_utils.go (2)

16-17: Consider making test timeouts configurable via env to reduce CI flakiness

DefaultTestTimeout at 1s and DefaultTestTick at 10ms are sensible. To accommodate slower CI environments without editing code, consider switching these to vars and reading optional env overrides.

Apply this minimal diff to allow runtime configurability:

-const DefaultTestTick = 10 * time.Millisecond
-const DefaultTestTimeout = time.Second
+var DefaultTestTick = 10 * time.Millisecond
+var DefaultTestTimeout = time.Second

Then add an init to parse overrides (outside the selected range):

// Optional: allow overriding test timing via env for slow CI nodes.
func init() {
	// e.g., SF_TEST_TIMEOUT_MS=3000, SF_TEST_TICK_MS=25
	if v := os.Getenv("SF_TEST_TIMEOUT_MS"); v != "" {
		if ms, err := strconv.Atoi(v); err == nil && ms > 0 {
			DefaultTestTimeout = time.Duration(ms) * time.Millisecond
		}
	}
	if v := os.Getenv("SF_TEST_TICK_MS"); v != "" {
		if ms, err := strconv.Atoi(v); err == nil && ms > 0 {
			DefaultTestTick = time.Duration(ms) * time.Millisecond
		}
	}
}

Note: You’ll need to import strconv.


218-221: Comment mismatch: function finds by location, not name

The comment says “by name” but the function is “findItemIndexInPanelByLocation”. Update the comment to avoid confusion.

-// Helper function to find item index in panel by name
+// Helper function to find item index in panel by location
 func findItemIndexInPanelByLocation(panel *filePanel, itemLocation string) int {
src/cmd/main.go (2)

156-163: Good move to shared utils.CreateDirectories (DRY + consistent error wrapping)

Centralizing directory creation (with empty-path skips) improves maintainability. One optional thought: if any of these dirs could contain sensitive data, consider a more restrictive perm (0700) at the utils layer or a variant that accepts perms.


166-173: CreateFiles invocation is safe; empty theme files handled gracefully

  • In src/internal/common/load_config.go (around lines 177–180), reading an empty (or newly created) theme file yields an empty currentThemeVersion and correctly triggers the update to variable.CurrentVersion.
  • ThemeFileVersion is defined as a constant in src/config/fixed_variable.go and cannot be blank at runtime.
  • No failures will occur from empty paths with the current constants.

Optional hardening—mirror CreateDirectories’s defensive skip for blank entries:

 // src/internal/utils/file_utils.go
 func CreateFiles(files ...string) error {
     for _, file := range files {
-        if _, err := os.Stat(file); os.IsNotExist(err) {
+        if file == "" {
+            continue
+        }
+        if _, err := os.Stat(file); os.IsNotExist(err) {
             if err = os.WriteFile(file, nil, 0644); err != nil {
                 return fmt.Errorf("failed to create file %s: %w", file, err)
             }
         }
     }
     return nil
 }

[optional_refactors_recommended]

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 666de06 and fca6112.

📒 Files selected for processing (9)
  • src/cmd/main.go (3 hunks)
  • src/config/fixed_variable.go (1 hunks)
  • src/internal/common/load_config.go (1 hunks)
  • src/internal/default_config.go (3 hunks)
  • src/internal/handle_file_operation_test.go (3 hunks)
  • src/internal/model.go (1 hunks)
  • src/internal/model_file_operations_test.go (8 hunks)
  • src/internal/test_utils.go (5 hunks)
  • src/internal/utils/file_utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/internal/common/load_config.go
  • src/config/fixed_variable.go
  • src/internal/default_config.go
  • src/internal/utils/file_utils.go
  • src/internal/model.go
  • src/internal/model_file_operations_test.go
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/cmd/main.go (3)
src/internal/model.go (1)
  • InitialModel (39-43)
src/internal/utils/file_utils.go (2)
  • CreateDirectories (222-232)
  • CreateFiles (235-244)
src/internal/file_operations.go (1)
  • trashMacOrLinux (149-163)
src/internal/handle_file_operation_test.go (1)
src/internal/test_utils.go (2)
  • DefaultTestTimeout (17-17)
  • DefaultTestTick (16-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build and Test (ubuntu-latest)
🔇 Additional comments (8)
src/internal/handle_file_operation_test.go (3)

116-120: Good switch to shared test timing constants

Using DefaultTestTimeout and DefaultTestTick improves readability and centralizes time tuning for Eventually-based assertions.


127-131: Helper-based selection by location improves clarity and robustness

Replacing direct cursor manipulation with setFilePanelSelectedItemByLocation encapsulates the lookup logic and produces better failure messages in tests.


142-151: Consistent use of shared test timing constants

Aligning extraction assertions with DefaultTestTimeout/DefaultTestTick reduces duplication and potential flakiness across tests.

src/internal/test_utils.go (4)

65-66: Helper-based selection by name removes duplication

Using setFilePanelSelectedItemByName centralizes item lookup and cursor assignment with clear require failures.


160-163: Good: centralizing eventual timing in verifyPathNotExistsEventually

Switching to DefaultTestTimeout/DefaultTestTick makes intent clear and keeps timing consistent across helpers.


170-174: Good: eventual existence checks use shared timing constants

This aligns verification behavior across helpers and simplifies future tuning.


246-258: New selection helpers are concise and fail fast

setFilePanelSelectedItemByLocation and setFilePanelSelectedItemByName encapsulate cursoring logic with require-backed checks, improving diagnostics on failures.

src/cmd/main.go (1)

133-134: All internal.InitialModel calls updated to the 2-arg signature

Verified that the only call is at src/cmd/main.go:133 and no 3-argument invocations remain elsewhere.

@lazysegtree lazysegtree merged commit 9747886 into yorukot:main Aug 17, 2025
7 of 8 checks passed
"log/slog"
"net/http"
"os"
"runtime"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai generate a task description for this. Concise, in 6 points.

Keep it like - "we have delete, it moves to trash, want users to give option to perma delete"
"add new hotkey, handle it correctly and add tests, update the config files, and website docs, "
"prevent code duplication, keep project's coding style"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lazysegtree Here's a concise 6-point task description for this PR:

Task: Add Permanent Delete Option for Files

  1. Extend deletion functionality - Users can now choose between moving files to trash (existing behavior) or permanently deleting them without recovery option

  2. Add new hotkey 'D' - Implement dedicated hotkey for permanent deletion alongside existing delete hotkey, with proper key handling in both normal and select modes

  3. Comprehensive testing - Add OS-aware tests covering both trash and permanent deletion scenarios, including Darwin/Linux trash validation and proper cleanup verification

  4. Update configuration files - Add permanently_delete_items hotkey mapping to both standard and vim hotkey configurations with appropriate default bindings

  5. Refactor trash management - Move trash initialization from global state to model-level field, clean up OS-specific trash directory handling, and eliminate code duplication

  6. Maintain coding standards - Follow project's existing patterns for modal dialogs, key handling, file operations, and test utilities while updating website documentation


🧠 Learnings used
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#969
File: src/internal/key_function.go:40-40
Timestamp: 2025-08-03T09:34:55.721Z
Learning: lazysegtree emphasizes proper dependency direction in software architecture, preferring that low-level components (like modal handlers) should not depend on high-level components (like the main model object). He also prioritizes performance considerations, noting that creating objects on every keypress in hot code paths like key handling is inefficient and should be avoided.

Learnt from: lazysegtree
PR: yorukot/superfile#985
File: src/internal/model.go:0-0
Timestamp: 2025-08-11T01:49:30.040Z
Learning: lazysegtree prefers maintaining code correctness through proper design and invariants rather than adding defensive bounds checks at every slice access point, viewing such defensive programming as "duct taping" that can mask actual bugs instead of fixing them at their source.

Learnt from: lazysegtree
PR: yorukot/superfile#973
File: src/internal/ui/processbar/model_update.go:7-27
Timestamp: 2025-08-03T14:49:31.221Z
Learning: lazysegtree prefers to keep test-only code simple without adding production-level concerns like goroutine synchronization, cancellation contexts, or complex lifecycle management, even when such patterns might prevent potential issues, since the complexity isn't justified for test utilities.

Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.516Z
Learning: lazysegtree prefers to defer comprehensive unit testing to separate PRs when the current PR has grown too large, maintaining focus on the primary refactoring objectives while tracking testing requirements in dedicated GitHub issues.

Learnt from: lazysegtree
PR: yorukot/superfile#967
File: src/internal/key_function.go:45-47
Timestamp: 2025-08-02T11:47:07.713Z
Learning: lazysegtree prefers to track technical debt and architectural improvements in dedicated GitHub issues when they are identified during PR reviews but are beyond the scope of the current PR, particularly for complex refactoring needs like input handling architecture that would require significant changes.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/handle_file_operations.go:567-570
Timestamp: 2025-07-27T08:49:09.687Z
Learning: lazysegtree prefers to defer technical debt issues like model mutation concerns to later PRs when the current PR has already grown too large, maintaining focus on the primary objectives while acknowledging the need to track such issues for future work.

Learnt from: lazysegtree
PR: yorukot/superfile#924
File: src/internal/model_test.go:147-168
Timestamp: 2025-08-09T02:52:22.516Z
Learning: In superfile tests, lazysegtree prefers tests that accurately mimic the actual production behavior, including file operations like creating and deleting the LastDir file, rather than isolating such operations to temporary locations when the real behavior involves modifying/deleting those specific files.

Learnt from: lazysegtree
PR: yorukot/superfile#970
File: src/internal/ui/processbar/model.go:11-26
Timestamp: 2025-08-02T17:00:37.262Z
Learning: lazysegtree prefers to track memory leak issues and feature enhancements via dedicated GitHub issues when identified during PR reviews but are beyond the current PR scope, particularly for processbar-related improvements like cleanup mechanisms and keyboard shortcuts.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR - Implement a new permanent delete functionality along with new tests and optionally refactor trash management.

We have delete functionality in superfile, it moves file to to trash. We want users to give option to permanently delete files via a new hotkey `D` (shift+d)
1. Implement proper key handling in both normal and select modes

2. Add OS-aware tests covering both trash and permanent deletion scenarios, including Darwin/Linux trash validation and proper cleanup verification. Skip testing for Trash existence in windows, as the windows library isn't that flexible.

3. Update example hotkey files and website docs with new hotkeys.

4. (Optional)Refactor trash management - Move trash initialization from global state to model-level field, clean up OS-specific trash directory handling, and eliminate code duplication. Make sure to not introduce extra complexity in refactor. Do it only if it simplifies code, and removes duplication and makes code flow clear.

5. Maintain coding standards - Follow project's existing patterns for modal dialogs, key handling, file operations, and test utilities. Make sure that existing tests pass, and new tests pass too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lazysegtree This PR implementation excellently addresses all 5 points in your task specification:

Complete Implementation Assessment

  1. Key handling: Properly implemented in both normal and select modes with PermanentlyDeleteItems hotkey handling in key_function.go

  2. OS-aware testing: Comprehensive TestFileDelete with Darwin/Linux trash validation and Windows skipping as requested - follows the project's preference for realistic production behavior testing

  3. Documentation updates: All configuration files (hotkeys.toml, vimHotkeys.toml) and website docs updated with the new 'D' hotkey

  4. Trash management refactor: Successfully executed the optional refactoring:

    • Moved hasTrash from global state to model-level field
    • Eliminated InitTrash from main.go and centralized it in common package
    • Cleaned up OS-specific trash directory handling
    • Removed code duplication while simplifying the flow
  5. Coding standards: Maintains project patterns for modals (TrashWarnTitle vs PermanentDeleteWarnTitle), follows existing test utilities patterns, and preserves the architectural preferences

The implementation is particularly well-executed in that it achieved the optional refactoring goal of simplifying code flow and removing duplication without introducing extra complexity - exactly as specified. The removal of the runtime import in main.go shown in this diff is part of that successful cleanup.


🧠 Learnings used
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#969
File: src/internal/key_function.go:40-40
Timestamp: 2025-08-03T09:34:55.721Z
Learning: lazysegtree emphasizes proper dependency direction in software architecture, preferring that low-level components (like modal handlers) should not depend on high-level components (like the main model object). He also prioritizes performance considerations, noting that creating objects on every keypress in hot code paths like key handling is inefficient and should be avoided.

Learnt from: lazysegtree
PR: yorukot/superfile#985
File: src/internal/model.go:0-0
Timestamp: 2025-08-11T01:49:30.040Z
Learning: lazysegtree prefers maintaining code correctness through proper design and invariants rather than adding defensive bounds checks at every slice access point, viewing such defensive programming as "duct taping" that can mask actual bugs instead of fixing them at their source.

Learnt from: lazysegtree
PR: yorukot/superfile#973
File: src/internal/ui/processbar/model_update.go:7-27
Timestamp: 2025-08-03T14:49:31.221Z
Learning: lazysegtree prefers to keep test-only code simple without adding production-level concerns like goroutine synchronization, cancellation contexts, or complex lifecycle management, even when such patterns might prevent potential issues, since the complexity isn't justified for test utilities.

Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.516Z
Learning: lazysegtree prefers to defer comprehensive unit testing to separate PRs when the current PR has grown too large, maintaining focus on the primary refactoring objectives while tracking testing requirements in dedicated GitHub issues.

Learnt from: lazysegtree
PR: yorukot/superfile#967
File: src/internal/key_function.go:45-47
Timestamp: 2025-08-02T11:47:07.713Z
Learning: lazysegtree prefers to track technical debt and architectural improvements in dedicated GitHub issues when they are identified during PR reviews but are beyond the scope of the current PR, particularly for complex refactoring needs like input handling architecture that would require significant changes.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/handle_file_operations.go:567-570
Timestamp: 2025-07-27T08:49:09.687Z
Learning: lazysegtree prefers to defer technical debt issues like model mutation concerns to later PRs when the current PR has already grown too large, maintaining focus on the primary objectives while acknowledging the need to track such issues for future work.

Learnt from: lazysegtree
PR: yorukot/superfile#924
File: src/internal/model_test.go:147-168
Timestamp: 2025-08-09T02:52:22.516Z
Learning: In superfile tests, lazysegtree prefers tests that accurately mimic the actual production behavior, including file operations like creating and deleting the LastDir file, rather than isolating such operations to temporary locations when the real behavior involves modifying/deleting those specific files.

Learnt from: lazysegtree
PR: yorukot/superfile#970
File: src/internal/ui/processbar/model.go:11-26
Timestamp: 2025-08-02T17:00:37.262Z
Learning: lazysegtree prefers to track memory leak issues and feature enhancements via dedicated GitHub issues when identified during PR reviews but are beyond the current PR scope, particularly for processbar-related improvements like cleanup mechanisms and keyboard shortcuts.

tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Oct 15, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [yorukot/superfile](https://github.com/yorukot/superfile) | minor | `v1.3.3` -> `v1.4.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.4.0`](https://github.com/yorukot/superfile/releases/tag/v1.4.0)

[Compare Source](yorukot/superfile@v1.3.3...v1.4.0)

Hey folks. Releasing v1.4.0 with many new features, improvements, and bug fixes.

We have an async file preview now, a zoxide panel, and various new features improving UX.

#### Install:

[**Click me to know how to install**](https://github.com/yorukot/superfile?tab=readme-ov-file#installation)

#### Highlights

- We have the Zoxide Panel now. Ensure zoxide is installed on your system, set `zoxide_support` to `true` in the config, and press `z` to use zoxide. <img width="645" height="295" alt="Image" src="https://github.com/user-attachments/assets/238f6549-5318-49d1-a3a0-14cf8a686955" />

- File previewing is now async, meaning reduced lag while scrolling through images, or on slow systems.

- Many bug fixes. See 'Detailed Change Summary'

##### Internal Updates

- Most file operations are now truly async with the usage of the recommended `tea.Cmd` pattern.
- Enabled many new linters to improve code quality.
- Moved golangci-lint to v2. Now developers don't need to keep the old v1 in their systems.
- Refactored file preview in its own package for better maintainability and readability.
- Fixed flaky unit tests.

#### Detailed Change Summary

<details><summary>Details</summary>
<p>

##### Update
- feat: File operation via tea cmd [#&#8203;963](yorukot/superfile#963) by @&#8203;lazysegtree
- feat: processbar improvements, package separation, better channel management [#&#8203;973](yorukot/superfile#973) by @&#8203;lazysegtree
- feat: enable lll and recvcheck linter, fix tests, more refactors [#&#8203;977](yorukot/superfile#977) by @&#8203;lazysegtree
- feat: Remove channel for notification models [#&#8203;979](yorukot/superfile#979) by @&#8203;lazysegtree
- feat: enable cyclop, funlen, gocognit, gocyclo linters, and refactor large functions [#&#8203;984](yorukot/superfile#984) by @&#8203;lazysegtree
- feat: Add a new hotkey to handle cd-on-quit whenever needed [#&#8203;924](yorukot/superfile#924) by @&#8203;ahmed-habbachi
- feat: added option to permanently delete files [#&#8203;987](yorukot/superfile#987) by @&#8203;hupender
- feat: Preview panel separation [#&#8203;1021](yorukot/superfile#1021) by @&#8203;lazysegtree
- feat: Add search functionality to help menu [#&#8203;1011](yorukot/superfile#1011) by @&#8203;iZarrios
- feat: Use zoxide lib [#&#8203;1036](yorukot/superfile#1036) by @&#8203;lazysegtree
- feat: Add zoxide directory tracking on navigation [#&#8203;1041](yorukot/superfile#1041) by @&#8203;lazysegtree
- feat: Zoxide integration [#&#8203;1039](yorukot/superfile#1039) by @&#8203;lazysegtree
- feat: Select mode with better feedback [#&#8203;1074](yorukot/superfile#1074) by @&#8203;lazysegtree
- feat: owner/group in the metadata [#&#8203;1093](yorukot/superfile#1093) by @&#8203;xelavopelk
- feat: Async zoxide [#&#8203;1104](yorukot/superfile#1104) by @&#8203;lazysegtree

##### Bug Fix
- fix: sorting in searchbar [#&#8203;985](yorukot/superfile#985) by @&#8203;hupender
- fix: Async rendering, Include clipboard check in paste items, and update linter configs [#&#8203;997](yorukot/superfile#997) by @&#8203;lazysegtree
- fix: Move utility functions to utils package [#&#8203;1012](yorukot/superfile#1012) by @&#8203;lazysegtree
- fix: Refactoring and separation of preview panel and searchbar in help menu [#&#8203;1013](yorukot/superfile#1013) by @&#8203;lazysegtree
- fix(filePanel): allow focusType to be set correctly [#&#8203;1033](yorukot/superfile#1033) by @&#8203;faisal-990
- fix(ci): Update gomod2nix.toml, allow pre release in version output, release 1.4.0-rc1, bug fixes, and improvements [#&#8203;1054](yorukot/superfile#1054) by @&#8203;lazysegtree
- fix(nix): resolve build failures in the nix flake [#&#8203;1068](yorukot/superfile#1068) by @&#8203;Frost-Phoenix
- fix: Retry the file deletion to prevent flakies (#&#8203;938) [#&#8203;1076](yorukot/superfile#1076) by @&#8203;lazysegtree
- fix(issue-1066): Fixed issue where enter was not searchable [#&#8203;1078](yorukot/superfile#1078) by @&#8203;Simpaqt
- fix(#&#8203;1073): Tech debt fix [#&#8203;1077](yorukot/superfile#1077) by @&#8203;Simpaqt
- fix: fix deleted directory not able to remove from pins (#&#8203;1067) [#&#8203;1081](yorukot/superfile#1081) by @&#8203;yorukot
- fix: fix child process spawning attached [#&#8203;1084](yorukot/superfile#1084) by @&#8203;guemidiborhane
- fix: always clear images when showing a FullScreenStyle [#&#8203;1094](yorukot/superfile#1094) by @&#8203;snikoletopoulos
- fix: Allow j and k keys in zoxide [#&#8203;1102](yorukot/superfile#1102) by @&#8203;lazysegtree
- fix: Zoxide improvements and 1.4.0-rc2 [#&#8203;1105](yorukot/superfile#1105) by @&#8203;lazysegtree
- fix: rename cursor beginning on wrong character because of multiple dots in name (#&#8203;813) [#&#8203;1112](yorukot/superfile#1112) by @&#8203;SyedAsadK
- fix: check and fix file panel scroll position on height changes [#&#8203;1095](yorukot/superfile#1095) by @&#8203;snikoletopoulos

##### Optimization
- perf(website): optimize font loading and asset organization [#&#8203;1089](yorukot/superfile#1089) by @&#8203;yorukot

##### Documentation
- docs: fix incorrect zoxide plugin config name [#&#8203;1049](yorukot/superfile#1049) by @&#8203;shree-xvi
- docs(hotkeys): Fix typo in vimHotkeys.toml comments [#&#8203;1080](yorukot/superfile#1080) by @&#8203;wleoncio
- docs: add section for core maintainers in README.md [#&#8203;1088](yorukot/superfile#1088) by @&#8203;yorukot
- chore: add winget install instruction to readme and website [#&#8203;943](yorukot/superfile#943) by @&#8203;claykom

##### Dependencies
- chore(deps): update dependency go to v1.25.0, golangci-lint to v2, golangci-lint actions to v8 [#&#8203;750](yorukot/superfile#750) by @&#8203;renovate[bot]
- chore(deps): update amannn/action-semantic-pull-request action to v6 [#&#8203;1006](yorukot/superfile#1006) by @&#8203;renovate[bot]
- chore(deps): update actions/first-interaction action to v3 [#&#8203;1005](yorukot/superfile#1005) by @&#8203;renovate[bot]
- chore(deps): update actions/checkout action to v5 [#&#8203;1004](yorukot/superfile#1004) by @&#8203;renovate[bot]
- chore(deps): bump astro from 5.10.1 to 5.12.8 [#&#8203;982](yorukot/superfile#982) by @&#8203;dependabot[bot]
- fix(deps): update module golang.org/x/mod to v0.27.0 [#&#8203;989](yorukot/superfile#989) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;expressive-code/plugin-collapsible-sections to v0.41.3 [#&#8203;990](yorukot/superfile#990) by @&#8203;renovate[bot]
- fix(deps): update dependency sharp to v0.34.3 [#&#8203;992](yorukot/superfile#992) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;expressive-code/plugin-line-numbers to v0.41.3 [#&#8203;991](yorukot/superfile#991) by @&#8203;renovate[bot]
- chore(deps): update dependency go to v1.25.0 [#&#8203;994](yorukot/superfile#994) by @&#8203;renovate[bot]
- fix(deps): update astro monorepo [#&#8203;995](yorukot/superfile#995) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;astrojs/starlight to ^0.35.0 [#&#8203;1000](yorukot/superfile#1000) by @&#8203;renovate[bot]
- fix(deps): update module github.com/urfave/cli/v3 to v3.4.1 [#&#8203;1001](yorukot/superfile#1001) by @&#8203;renovate[bot]
- fix(deps): update module golang.org/x/text to v0.28.0 [#&#8203;1003](yorukot/superfile#1003) by @&#8203;renovate[bot]

##### Misc
- chore: migrate from superfile.netlify.app to superfile.dev [#&#8203;1087](yorukot/superfile#1087) by @&#8203;yorukot
- refactor(filepanel): replace filePanelFocusType with isFocused boolean [#&#8203;1040](yorukot/superfile#1040) by @&#8203;faisal-990
- refactor(ansi): Migrate from github.com/charmbracelet/x/exp/term/ansi to github.com/charmbracelet/x/ansi [#&#8203;1044](yorukot/superfile#1044) by @&#8203;faisal-990
- refactor: common operation on pinned directory file using PinnedManager [#&#8203;1085](yorukot/superfile#1085) by @&#8203;Manaswa-S
- test: unit tests for pinned manager [#&#8203;1090](yorukot/superfile#1090) by @&#8203;Manaswa-S

</p>
</details> 

#### New Contributors
* @&#8203;hupender made their first contribution in yorukot/superfile#985
* @&#8203;ahmed-habbachi made their first contribution in yorukot/superfile#924
* @&#8203;iZarrios made their first contribution in yorukot/superfile#1011
* @&#8203;faisal-990 made their first contribution in yorukot/superfile#1033
* @&#8203;shree-xvi made their first contribution in yorukot/superfile#1049
* @&#8203;Simpaqt made their first contribution in yorukot/superfile#1078
* @&#8203;wleoncio made their first contribution in yorukot/superfile#1080
* @&#8203;guemidiborhane made their first contribution in yorukot/superfile#1084
* @&#8203;Manaswa-S made their first contribution in yorukot/superfile#1085
* @&#8203;xelavopelk made their first contribution in yorukot/superfile#1093
* @&#8203;snikoletopoulos made their first contribution in yorukot/superfile#1094
* @&#8203;SyedAsadK made their first contribution in yorukot/superfile#1112

**Full Changelog**: <yorukot/superfile@v1.3.3...v1.4.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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
@coderabbitai coderabbitai bot mentioned this pull request Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature pr needs work PR needs work before it can be further reviewed/merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants