diff options
Diffstat (limited to 'gui/internal/model/sort.go')
| -rw-r--r-- | gui/internal/model/sort.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/gui/internal/model/sort.go b/gui/internal/model/sort.go new file mode 100644 index 0000000..9968a08 --- /dev/null +++ b/gui/internal/model/sort.go @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package model + +import ( + "sort" + "strings" +) + +// The orders a plan can be read in. "default" is the order krino planned +// the directory in, which is the order the files were scanned; the rest are +// what a column is worth sorting by (his request, 2026-09-17). +const ( + SortDefault = "default" + SortName = "name" + SortSize = "size" + SortAge = "age" + SortAction = "action" + SortRule = "rule" +) + +// SortOrders are the choices, in the order they are offered. +var SortOrders = []string{SortDefault, SortName, SortSize, SortAge, SortAction, SortRule} + +// SortLabels say which way each order runs, for the picker and its help. +var SortLabels = map[string]string{ + SortDefault: "as scanned", + SortName: "name, A to Z", + SortSize: "size, largest first", + SortAge: "age, oldest first", + SortAction: "action, A to Z", + SortRule: "rule, A to Z", +} + +// IsSortOrder reports whether s names one of them. +func IsSortOrder(s string) bool { + for _, o := range SortOrders { + if o == s { + return true + } + } + return false +} + +// Sorted puts the rows named by shown in the order asked for, leaving the +// plan itself alone: only the reading order changes. Ties keep the plan's +// own order, so the list never shuffles between two files that compare the +// same. +func (t *PlanTab) Sorted(shown []int, by string) []int { + out := append([]int(nil), shown...) + if by == SortDefault || by == "" || !IsSortOrder(by) { + return out + } + less := func(a, b int) bool { + x, y := t.Rows[a], t.Rows[b] + switch by { + case SortName: + return strings.ToLower(x.Rel) < strings.ToLower(y.Rel) + case SortSize: + return x.Size > y.Size + case SortAge: + // Oldest first: the files an (age > ...) rule is about. + return x.ModTime.Before(y.ModTime) + case SortAction: + return firstAction(x) < firstAction(y) + case SortRule: + return strings.ToLower(x.Rule) < strings.ToLower(y.Rule) + } + return false + } + sort.SliceStable(out, func(i, j int) bool { return less(out[i], out[j]) }) + return out +} + +// firstAction is what a row does, for sorting; a row that does nothing +// sorts after the ones that do. +func firstAction(r Row) string { + for _, s := range r.Steps { + if s.Skip == "" { + return s.Kind.String() + } + } + return "~" +} |
