From d653a60418d3a8d66eb188b0bba88a06a05ef4c4 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 21 Nov 2019 22:25:19 +0100 Subject: [PATCH] Add `--sort` parameter for `termine yarpnarp` --- termine/yarpnarp.go | 106 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 20 deletions(-) diff --git a/termine/yarpnarp.go b/termine/yarpnarp.go index 3e8d074..6dd4188 100644 --- a/termine/yarpnarp.go +++ b/termine/yarpnarp.go @@ -5,22 +5,47 @@ import ( "fmt" "os" "sort" + "strings" "text/tabwriter" "time" "github.com/nnev/website/data" ) +type OrderPriority = uint8 + +const ( + Asc OrderPriority = iota + Desc +) + +type ZusageOrderBy = uint8 + +const ( + ZusageByNick ZusageOrderBy = iota + ZusageByKommt + ZusageByKommentar + ZusageByRegistered +) + +type ZusageOrder struct { + by ZusageOrderBy + priority OrderPriority +} + var cmdYarpNarp = &Command{ UsageLine: "yarpnarp", Short: "Zeige Zu- und Absagen für den Stammtisch", Long: `Zeigt die Zu- und Absagen für den Stammtisch an`, - Flag: flag.NewFlagSet("clear", flag.ExitOnError), + Flag: flag.NewFlagSet("yarpnarp", flag.ExitOnError), NeedsDB: true, RegenWebsite: false, } +var sortOrder string + func init() { + cmdYarpNarp.Flag.StringVar(&sortOrder, "sort", "-kommt,+registered", "Bestimmt die Sortierreihenfolge") cmdYarpNarp.Run = RunYarpNarp } @@ -34,24 +59,32 @@ func (z Zusagen) Swap(i, j int) { z[i], z[j] = z[j], z[i] } -func (z Zusagen) Less(i, j int) bool { - if z[i].Kommt && !z[j].Kommt { - return true - } else if z[j].Kommt && !z[i].Kommt { - return false - } - - // If one or both registered fields are NULL, just treat them as the zero - // time (so they sort before all other values) - if z[i].Registered.Time.Before(z[j].Registered.Time) { - return true - } else if z[j].Registered.Time.Before(z[i].Registered.Time) { - return false - } - - // If one or both nick fields are NULL, just tream them as the empty string - if z[i].Nick.String < z[j].Nick.String { - return true +func (z Zusagen) Less(i, j int, key []ZusageOrder) bool { + for _, order := range key { + i_, j_ := i, j + if order.priority == Desc { + i_, j_ = j, i + } + switch order.by { + case ZusageByKommentar: + if z[i_].Kommentar < z[j_].Kommentar { + return true + } + case ZusageByKommt: + if !z[i_].Kommt && z[j_].Kommt { + return true + } + case ZusageByNick: + if z[i_].Nick.String < z[j_].Nick.String { + return true + } + case ZusageByRegistered: + if z[i_].Registered.Time.Before(z[j_].Registered.Time) { + return true + } + default: + panic("Invalid ZusageOrderBy field") + } } return false @@ -75,6 +108,36 @@ func formatBool(b bool) string { return "Nein" } +func parseSortOrder(s string) []ZusageOrder { + elements := strings.Split(s, ",") + result := make([]ZusageOrder, len(elements)) + for i, element := range elements { + result[i].priority = Asc + + if element[0] == '-' { + result[i].priority = Desc + } + if element[0] == '+' || element[0] == '-' { + element = element[1:] + } + + switch element { + case "nick": + result[i].by = ZusageByNick + case "kommentar": + result[i].by = ZusageByKommentar + case "kommt": + result[i].by = ZusageByKommt + case "registered": + result[i].by = ZusageByRegistered + default: + // FIXME: Probably not panic, because it is an expected error. + panic("Invalid sort order element") + } + } + return result +} + func maybeTruncate(s string, width int, truncate bool) string { if !truncate { return s @@ -101,7 +164,10 @@ func RunYarpNarp() error { return err } - sort.Sort(zusagen) + order := parseSortOrder(sortOrder) + sort.Slice(zusagen, func(i, j int) bool { + return zusagen.Less(i, j, order) + }) width, trunc := TermWidth()