How Superfile's Selection Mode Works for Batch File Operations

Superfile's selection mode uses a map-based state tracker with an incrementing order counter to enable deterministic multi-file selection for batch copy, move, and delete operations.

Superfile, the terminal-based file manager by yorukot, implements a robust selection mode that transforms single-item navigation into powerful batch file operations. Understanding this mechanism reveals how the tool maintains selection order while providing visual feedback for bulk actions.

Selection State Architecture

The selection system resides in src/internal/ui/filepanel/utils.go and centers on two core properties within the filepanel model:

  • selected: A map[string]int storing absolute file paths as keys and incrementing integers representing selection order as values
  • selectOrderCounter: An integer that increments with each new selection to establish deterministic "first-selected" semantics

This design allows Superfile to track not just what is selected, but when it was selected.

Core Selection Functions

Adding selections uses SetSelected, which increments the counter and records the location:

func (m *Model) SetSelected(location string) {
    m.selectOrderCounter++
    m.selected[location] = m.selectOrderCounter
}

Removing selections uses SetUnSelected with existence checking:

func (m * Model) SetUnSelected(location string) {
    if m.CheckSelected(location) {
        delete(m.selected, location)
    }
}

Toggle behavior is handled by ToggleSelected, which calls either SetUnSelected or SetSelected depending on current state.

Selection Queries

The model provides several accessors for batch operations:

  • SelectedCount(): Returns the total number of selected items
  • GetSelectedLocations(): Returns an unordered slice of paths
  • GetFirstSelectedLocation(): Walks the map to find the entry with the smallest order value (the initial selection)
  • GetSelectedLocationsSortedAsVisible(): Returns paths ordered according to their visual position in the panel

Entering Selection Mode

Users activate selection mode through key bindings defined in the UI layer. When active, pressing Space invokes SingleItemSelect at src/internal/ui/filepanel/utils.go lines 117-122:

func (m *Model) SingleItemSelect() {
    if !m.EmptyOrInvalid() {
        m.ToggleSelected(m.GetFocusedItem().Location)
    }
}

This toggles the current cursor location in the selected map. The mode state itself is managed by the surrounding Panel struct, which determines whether navigation commands affect the cursor position only or also update the selection set.

Executing Batch File Operations

When users trigger batch commands (copy, move, delete), the handler retrieves selections using GetSelectedLocationsSortedAsVisible. This ensures operations process files in visual order—critical for hierarchical moves or ordered processing:

selected := panel.GetSelectedLocationsSortedAsVisible()
if len(selected) == 0 {
    // Fallback: operate on the focused item only
    selected = []string{panel.GetFocusedItem().Location}
}

The operation iterates over this slice, performing filesystem actions on each path. Because GetSelectedLocationsSortedAsVisible walks the visible element list (m.element) and filters for selected items, the order matches exactly what the user sees on screen.

Practical Implementation Example

To implement a batch move operation using Superfile's selection API:

func batchMove(panel *filepanel.Model, dest string) error {
    srcs := panel.GetSelectedLocationsSortedAsVisible()
    if len(srcs) == 0 {
        // No explicit selection → operate on the focused item
        srcs = []string{panel.GetFocusedItem().Location}
    }

    for _, src := range srcs {
        if err := fs.Move(src, filepath.Join(dest, filepath.Base(src))); err != nil {
            return err
        }
    }
    panel.ResetSelected() // Clear selections post-operation
    return nil
}

Resetting and Clearing Selections

After completing batch operations or when reinitializing panels, ResetSelected clears the state:

func (m *Model) ResetSelected() {
    m.selectOrderCounter = 0
    m.selected = make(map[string]int)
}

This function appears at src/internal/ui/filepanel/utils.go lines 28-31 and ensures deterministic behavior by zeroing the counter and reinitializing the map.

The test suite in src/internal/ui/filepanel/selection_test.go (lines 9-55) validates this lifecycle, covering add, remove, multi-select, and reset operations.

Summary

  • Superfile tracks selections using a map[string]int where keys are absolute paths and values are incrementing order integers
  • SetSelected and ToggleSelected in src/internal/ui/filepanel/utils.go manage the selection state with automatic ordering
  • SingleItemSelect connects the Space key to toggle the current cursor location in the selection set
  • GetSelectedLocationsSortedAsVisible ensures batch operations process files in visual order as displayed to the user
  • ResetSelected clears the map and counter after operations complete or when panels refresh

Frequently Asked Questions

How does Superfile remember which file was selected first?

Superfile uses the selectOrderCounter integer that increments each time SetSelected adds a new item. The GetFirstSelectedLocation function walks the selected map to find the entry with the smallest order value, providing deterministic access to the initial selection regardless of map iteration order.

What happens if I run a batch operation without selecting any files?

The command handler checks len(selected) and falls back to the currently focused item. If GetSelectedLocationsSortedAsVisible returns an empty slice, the code uses panel.GetFocusedItem().Location as the sole target, ensuring operations always have valid targets.

Why does Superfile sort selected locations by visible order rather than selection order?

While the selected map tracks selection order via integers, GetSelectedLocationsSortedAsVisible returns paths ordered by their position in the visible file list. This design ensures that batch operations like move or copy progress through the directory in the same sequence the user sees, preventing confusion when operating on hierarchies or large directories.

Where are selection mode tests located in the Superfile repository?

The selection lifecycle tests reside in src/internal/ui/filepanel/selection_test.go, covering the complete functionality from SetSelected through ResetSelected. These tests verify that the order counter increments correctly, toggles remove entries properly, and bulk selections work as expected.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →