From 270c226d8443c779374ee46631c4f385126b9a81 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 13 May 2026 19:32:59 +0300 Subject: 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 --- internal/tui/dashboard/files.go | 34 ++-------------------------------- internal/tui/dashboard/processes.go | 18 +----------------- internal/tui/dashboard/sort.go | 34 ++++++++++++++++++++++++++++++++++ internal/tui/dashboard/syscalls.go | 18 +----------------- 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 { -- cgit v1.2.3