1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 "~"
}
|