diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-11-15 21:24:49 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-12-02 22:59:23 +0100 |
commit | ff101bda430dda18e6f150ce6915891139ecccd9 (patch) | |
tree | df7906c7c5379307522ddc21634660fc99f02b2d /worker/lib/search.go | |
parent | 23a05d17ac1d23466ff73efa19576d43d06efe4b (diff) | |
download | aerc-ff101bda430dda18e6f150ce6915891139ecccd9.tar.gz |
search: handle date ranges in search/filter query
Handle date ranges in the filter and search commands for searching and
filtering based on the Date: header. Implement a flag (-d) that accepts
a date range <start[..end]> where the start date is included in the
range but the end date is not, i.e. [start,end).
The start or end date can be omitted: "start", "start..", "..end", or
"start..end" are all valid inputs.
An example filter query would look like this: :filter -d 2022-11-09..
The dates should be in the YYYY-MM-DD format.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'worker/lib/search.go')
-rw-r--r-- | worker/lib/search.go | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/worker/lib/search.go b/worker/lib/search.go index fe1ec114..c09feff6 100644 --- a/worker/lib/search.go +++ b/worker/lib/search.go @@ -4,10 +4,12 @@ import ( "io" "net/textproto" "strings" + "time" "unicode" "git.sr.ht/~sircmpwn/getopt" + "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" ) @@ -18,12 +20,14 @@ type searchCriteria struct { WithFlags []models.Flag WithoutFlags []models.Flag + + startDate, endDate time.Time } func GetSearchCriteria(args []string) (*searchCriteria, error) { criteria := &searchCriteria{Header: make(textproto.MIMEHeader)} - opts, optind, err := getopt.Getopts(args, "rux:X:bat:H:f:c:") + opts, optind, err := getopt.Getopts(args, "rux:X:bat:H:f:c:d:") if err != nil { return nil, err } @@ -49,8 +53,18 @@ func GetSearchCriteria(args []string) (*searchCriteria, error) { criteria.Header.Add("Cc", opt.Value) case 'b': body = true - case 'a': - text = true + case 'd': + start, end, err := ParseDateRange(opt.Value) + if err != nil { + log.Errorf("failed to parse start date: %v", err) + continue + } + if !start.IsZero() { + criteria.startDate = start + } + if !end.IsZero() { + criteria.endDate = end + } } } switch { @@ -116,7 +130,7 @@ func searchMessage(message RawMessage, criteria *searchCriteria, return false, err } } - if parts&HEADER > 0 { + if parts&HEADER > 0 || parts&DATE > 0 { header, err = MessageInfo(message) if err != nil { return false, err @@ -188,6 +202,22 @@ func searchMessage(message RawMessage, criteria *searchCriteria, } } } + if parts&DATE > 0 { + if date, err := header.RFC822Headers.Date(); err != nil { + log.Errorf("Failed to get date from header: %v", err) + } else { + if !criteria.startDate.IsZero() { + if date.Before(criteria.startDate) { + return false, nil + } + } + if !criteria.endDate.IsZero() { + if date.After(criteria.endDate) { + return false, nil + } + } + } + } return true, nil } @@ -227,6 +257,7 @@ const NONE MsgParts = 0 const ( FLAGS MsgParts = 1 << iota HEADER + DATE BODY ALL ) @@ -238,6 +269,9 @@ func getRequiredParts(criteria *searchCriteria) MsgParts { if len(criteria.Header) > 0 { required |= HEADER } + if !criteria.startDate.IsZero() || !criteria.endDate.IsZero() { + required |= DATE + } if criteria.Body != nil && len(criteria.Body) > 0 { required |= BODY } |