summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-13 19:32:59 +0300
committerPaul Buetow <paul@buetow.org>2026-05-13 19:32:59 +0300
commit270c226d8443c779374ee46631c4f385126b9a81 (patch)
tree9a1d613d5ea5d6227103cbf71283e9149420a22d
parentd585f83e1c3757e1a1edf2802abfa6171b5234f3 (diff)
extract generic sortedWithState helper to deduplicate tab sort logic
Four near-identical sorted-rows functions (sortedFileSnapshots, sortedDirSnapshots, sortedSyscallSnapshots, sortedProcessTableRows) each repeated the same guard-clone-sort-tiebreak-apply pattern. Replace them with a single generic sortedWithState[T,K] in sort.go that accepts per-tab byKey and tiebreak comparators as parameters. Remove now-unused slices imports from syscalls.go and processes.go. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--internal/tui/dashboard/files.go34
-rw-r--r--internal/tui/dashboard/processes.go18
-rw-r--r--internal/tui/dashboard/sort.go34
-rw-r--r--internal/tui/dashboard/syscalls.go18
4 files changed, 38 insertions, 66 deletions
diff --git a/internal/tui/dashboard/files.go b/internal/tui/dashboard/files.go
index 3b85a73..d74ea29 100644
--- a/internal/tui/dashboard/files.go
+++ b/internal/tui/dashboard/files.go
@@ -177,41 +177,11 @@ func fileDirColumns(width int) []common.TableColumn {
}
func sortedFileSnapshots(rows []statsengine.FileSnapshot, sortState tableSortState[fileSortKey]) []statsengine.FileSnapshot {
- if len(rows) == 0 {
- return nil
- }
- if !sortState.active {
- return rows
- }
-
- sorted := slices.Clone(rows)
- slices.SortFunc(sorted, func(left, right statsengine.FileSnapshot) int {
- cmp := compareFileBySort(left, right, sortState.key)
- if cmp == 0 {
- cmp = compareFileDefault(left, right)
- }
- return sortState.apply(cmp)
- })
- return sorted
+ return sortedWithState(rows, sortState, compareFileBySort, compareFileDefault)
}
func sortedDirSnapshots(rows []DirSnapshot, sortState tableSortState[fileDirSortKey]) []DirSnapshot {
- if len(rows) == 0 {
- return nil
- }
- if !sortState.active {
- return rows
- }
-
- sorted := slices.Clone(rows)
- slices.SortFunc(sorted, func(left, right DirSnapshot) int {
- cmp := compareDirBySort(left, right, sortState.key)
- if cmp == 0 {
- cmp = compareDirDefault(left, right)
- }
- return sortState.apply(cmp)
- })
- return sorted
+ return sortedWithState(rows, sortState, compareDirBySort, compareDirDefault)
}
func compareFileBySort(left, right statsengine.FileSnapshot, key fileSortKey) int {
diff --git a/internal/tui/dashboard/processes.go b/internal/tui/dashboard/processes.go
index f4eedec..5481843 100644
--- a/internal/tui/dashboard/processes.go
+++ b/internal/tui/dashboard/processes.go
@@ -2,7 +2,6 @@ package dashboard
import (
"fmt"
- "slices"
"strconv"
"strings"
@@ -63,22 +62,7 @@ func processColumns() []common.TableColumn {
}
func sortedProcessTableRows(rows []statsengine.ProcessSnapshot, sortState tableSortState[processSortKey]) []statsengine.ProcessSnapshot {
- if len(rows) == 0 {
- return nil
- }
- if !sortState.active {
- return rows
- }
-
- sorted := slices.Clone(rows)
- slices.SortFunc(sorted, func(left, right statsengine.ProcessSnapshot) int {
- cmp := compareProcessBySort(left, right, sortState.key)
- if cmp == 0 {
- cmp = compareProcessDefault(left, right)
- }
- return sortState.apply(cmp)
- })
- return sorted
+ return sortedWithState(rows, sortState, compareProcessBySort, compareProcessDefault)
}
func compareProcessBySort(left, right statsengine.ProcessSnapshot, key processSortKey) int {
diff --git a/internal/tui/dashboard/sort.go b/internal/tui/dashboard/sort.go
index 399d0c5..718746a 100644
--- a/internal/tui/dashboard/sort.go
+++ b/internal/tui/dashboard/sort.go
@@ -1,5 +1,7 @@
package dashboard
+import "slices"
+
type tableSortState[K comparable] struct {
active bool
key K
@@ -74,3 +76,35 @@ func compareStringAsc(left, right string) int {
return 0
}
}
+
+// sortedWithState is the shared sort helper for all sortable dashboard tables.
+// It avoids four near-identical functions (files, dirs, syscalls, processes)
+// that each guard on empty/inactive, clone the slice, sort with a key
+// comparator, fall back to a tiebreaker, and apply the reverse flag.
+//
+// - rows – the input slice (not modified; nil is returned when empty)
+// - sortState – carries the active flag, selected key, and reverse flag
+// - byKey – per-key comparator for the active sort column
+// - tiebreak – stable fallback comparator used when byKey returns 0
+func sortedWithState[T any, K comparable](
+ rows []T,
+ sortState tableSortState[K],
+ byKey func(left, right T, key K) int,
+ tiebreak func(left, right T) int,
+) []T {
+ if len(rows) == 0 {
+ return nil
+ }
+ if !sortState.active {
+ return rows
+ }
+ sorted := slices.Clone(rows)
+ slices.SortFunc(sorted, func(left, right T) int {
+ cmp := byKey(left, right, sortState.key)
+ if cmp == 0 {
+ cmp = tiebreak(left, right)
+ }
+ return sortState.apply(cmp)
+ })
+ return sorted
+}
diff --git a/internal/tui/dashboard/syscalls.go b/internal/tui/dashboard/syscalls.go
index 3b64b12..90f40ca 100644
--- a/internal/tui/dashboard/syscalls.go
+++ b/internal/tui/dashboard/syscalls.go
@@ -2,7 +2,6 @@ package dashboard
import (
"fmt"
- "slices"
"strconv"
"time"
@@ -96,22 +95,7 @@ func syscallColumns(width int) []common.TableColumn {
}
func sortedSyscallSnapshots(rows []statsengine.SyscallSnapshot, sortState tableSortState[syscallSortKey]) []statsengine.SyscallSnapshot {
- if len(rows) == 0 {
- return nil
- }
- if !sortState.active {
- return rows
- }
-
- sorted := slices.Clone(rows)
- slices.SortFunc(sorted, func(left, right statsengine.SyscallSnapshot) int {
- cmp := compareSyscallBySort(left, right, sortState.key)
- if cmp == 0 {
- cmp = compareSyscallDefault(left, right)
- }
- return sortState.apply(cmp)
- })
- return sorted
+ return sortedWithState(rows, sortState, compareSyscallBySort, compareSyscallDefault)
}
func compareSyscallBySort(left, right statsengine.SyscallSnapshot, key syscallSortKey) int {