How Superfile’s Process Bar Displays File Operation Progress
Superfile renders real-time file operation progress by maintaining a Process struct for each task, computing a percentage from completed items, and drawing a gradient-coloured bar via the Bubble Tea progress.Model component.
Superfile is an open-source terminal file manager that surfaces live feedback for copy, move, paste, and delete actions through a dedicated process bar UI component. The implementation ties together a structured process model, file-operation handlers, and Bubble Tea rendering logic to produce a smooth, theme-aware progress indicator directly in the terminal.
Process Bar Architecture
At the core of superfile's progress reporting is the Process struct defined in src/internal/ui/processbar/process.go. This struct tracks everything Bubble Tea needs to animate and colour each bar.
The Process Struct
Each running operation is represented by a Process value with the following fields:
ID,CurrentFile, andOperationstore basic metadata about the task.Progressholds aprogress.Modelfromcharm.land/bubbles/v2/progressthat draws the actual bar.State,Total,Done, andDoneTimetrack execution state and completion metrics.
When an operation starts, NewProcess initializes the progress model using the active UI theme:
prog := progress.New(
progress.WithColors(
lipgloss.Color(common.Theme.GradientColor[0]),
lipgloss.Color(common.Theme.GradientColor[1]),
),
progress.WithScaled(true),
)
prog.PercentageStyle = common.FooterStyle
The WithColors option applies a two-stop gradient from the theme, and WithScaled(true) ensures the bar stretches to fit the terminal width.
Updating File Operation Progress in Real Time
Superfile updates the process bar while iterating over files in src/internal/handle_file_operations.go. During each step of a copy, move, or delete loop, the application increments counters and refreshes the percentage.
The typical lifecycle begins with NewProcess:
// Starting a copy operation (simplified)
proc := processbar.NewProcess(reqID, srcPath, processbar.Copy, totalFiles)
m.processes[reqID] = proc
Inside the file loop, the code performs three actions for every item:
- Sets
process.CurrentFileto the file currently being handled. - Increments
process.Doneto reflect another completed item. - Recalculates the percentage and pushes it to the progress model:
// Inside the copy loop
proc.CurrentFile = file.Name()
proc.Done++
proc.Progress.SetPercent(float64(proc.Done) / float64(proc.Total))
When the operation finishes, the State field switches to Successful, Cancelled, or Failed. The terminal icon updates accordingly via ProcessState.Icon() in src/internal/ui/processbar/process.go.
Rendering the Process Bar UI
The process bar rendering pipeline lives in src/internal/ui/processbar/model.go, while update messages are propagated through src/internal/ui/processbar/model_update.go. Bubble Tea calls the model's View() method to repaint active processes on every frame.
View Assembly
For each active Process, the renderer:
- Calls
process.GetDisplayName()to build a textual description combining the operation verb, current file name, and a state icon. - Invokes
process.Progress.ViewAs(percent)to generate the bar string. - Concatenates the display name and bar, respecting
progressBarRightPadding = 3fromsrc/internal/ui/processbar/const.goso the status icon remains visible.
A simplified version of the loop looks like this:
// Rendering a single process (inside model.go)
func (m *Model) View() string {
for _, p := range m.activeProcesses {
pct := float64(p.Done) / float64(p.Total)
line := fmt.Sprintf("%s %s",
p.GetDisplayName(),
p.Progress.ViewAs(pct),
)
// …append line to output buffer…
}
return buffer.String()
}
The result is a live line such as:
📂 Copy file.txt ────────────────────── 45%
As Done approaches Total, the gradient bar expands to 100 % and the leading icon flips to a checkmark for success or a cross for failure.
Summary
- Superfile defines every file task as a
Processstruct insrc/internal/ui/processbar/process.go, pairing operation metadata with a Bubble Teaprogress.Model. NewProcessconfigures a gradient, width-scaled bar using theme colours fromcommon.Theme.GradientColor.- File loops in
src/internal/handle_file_operations.goadvanceDone, refreshCurrentFile, and callSetPercentto update the bar in real time. src/internal/ui/processbar/model.gocomposites each line withGetDisplayName()andViewAs, whileconst.goreserves right-hand padding for status icons.
Frequently Asked Questions
How does superfile calculate the process bar percentage?
Superfile divides the number of completed items by the total item count. In src/internal/handle_file_operations.go, it computes float64(process.Done) / float64(process.Total) and passes the result to process.Progress.SetPercent.
What library draws the progress bar in superfile?
The bar is rendered by progress.Model from the charm.land/bubbles/v2/progress package. Superfile wraps this model inside its own Process struct located in src/internal/ui/processbar/process.go.
Can the process bar colours be customized?
Yes. During initialization in process.go, NewProcess feeds common.Theme.GradientColor[0] and common.Theme.GradientColor[1] into progress.WithColors. Changing the theme therefore changes the gradient applied to every process bar.
Where does superfile store active process state during rendering?
Active processes are held in the model within src/internal/ui/processbar/model.go. The View() method iterates over m.activeProcesses, calling GetDisplayName() and ViewAs to produce the final terminal output on every Bubble Tea frame.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →