about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTobias Wölfel <tobias.woelfel@mailbox.org>2020-07-24 10:36:19 +0200
committerReto Brunner <reto@labrat.space>2020-07-25 08:08:08 +0200
commit494bd674a98bc9f2889acad0fda3ff4c77c641b5 (patch)
treefb9ec5313689de1e48211607adc71c1ae23b72a9
parent126c9437e8bd6374a432a8af6cfe3e6d5227dcc2 (diff)
downloadaerc-494bd674a98bc9f2889acad0fda3ff4c77c641b5.tar.gz
Add flag based search options
Provide search and filter with the option to specify more flag based
conditions.
Use '-x <flag>' to search for messages with a flag (seen, answered,
flagged) and '-X <flag>' to search for messages without a flag.
-rw-r--r--doc/aerc-search.1.scd36
-rw-r--r--worker/imap/search.go25
-rw-r--r--worker/maildir/search.go19
3 files changed, 76 insertions, 4 deletions
diff --git a/doc/aerc-search.1.scd b/doc/aerc-search.1.scd
index 8c5861a..b90a934 100644
--- a/doc/aerc-search.1.scd
+++ b/doc/aerc-search.1.scd
@@ -2,7 +2,7 @@ aerc-search(1)
 
 # IMAP
 
-*search* [-ruba] [-f <from>] [-t <to>] [-c <cc>] [terms...]
+*search* [-ruba] [-x <flag>] [-X <flag>] [-f <from>] [-t <to>] [-c <cc>] [terms...]
 	Searches the current folder for messages matching the given set of
 	conditions.
 
@@ -14,6 +14,22 @@ aerc-search(1)
 
 	*-u*: Search for unread messages
 
+	*-x <flag>*, *-X <flag>*: Restrict search to messages with or without <flag>
+
+	Use *-x* to search for messages with the flag set.
+	Use *-X* to search for messages without the flag set.
+
+	Possible values are:
+
+	Seen
+		Read messages
+
+	Answered
+		Replied messages
+
+	Flagged
+		Flagged messages
+
 	*-b*: Search in the body of the messages
 
 	*-a*: Search in the entire text of the messages
@@ -26,7 +42,7 @@ aerc-search(1)
 
 # MAILDIR
 
-*search* [-ruba] [-f <from>] [-t <to>] [-c <cc>] [terms...]
+*search* [-ruba] [-x <flag>] [-X <flag>] [-f <from>] [-t <to>] [-c <cc>] [terms...]
 	Searches the current folder for messages matching the given set of
 	conditions.
 
@@ -38,6 +54,22 @@ aerc-search(1)
 
 	*-u*: Search for unread messages
 
+	*-x <flag>*, *-X <flag>*: Restrict search to messages with or without <flag>
+
+	Use *-x* to search for messages with the flag set.
+	Use *-X* to search for messages without the flag set.
+
+	Possible values are:
+
+	Seen
+		Read messages
+
+	Answered
+		Replied messages
+
+	Flagged
+		Flagged messages
+
 	*-b*: Search in the body of the messages
 
 	*-a*: Search in the entire text of the messages
diff --git a/worker/imap/search.go b/worker/imap/search.go
index 42e155b..f866b1c 100644
--- a/worker/imap/search.go
+++ b/worker/imap/search.go
@@ -1,6 +1,9 @@
 package imap
 
 import (
+	"errors"
+	"strings"
+
 	"github.com/emersion/go-imap"
 
 	"git.sr.ht/~sircmpwn/getopt"
@@ -9,7 +12,7 @@ import (
 func parseSearch(args []string) (*imap.SearchCriteria, error) {
 	criteria := imap.NewSearchCriteria()
 
-	opts, optind, err := getopt.Getopts(args, "rubat:H:f:c:")
+	opts, optind, err := getopt.Getopts(args, "rubax:X:t:H:f:c:")
 	if err != nil {
 		return nil, err
 	}
@@ -21,6 +24,14 @@ func parseSearch(args []string) (*imap.SearchCriteria, error) {
 			criteria.WithFlags = append(criteria.WithFlags, imap.SeenFlag)
 		case 'u':
 			criteria.WithoutFlags = append(criteria.WithoutFlags, imap.SeenFlag)
+		case 'x':
+			if f, err := getParsedFlag(opt.Value); err == nil {
+				criteria.WithFlags = append(criteria.WithFlags, f)
+			}
+		case 'X':
+			if f, err := getParsedFlag(opt.Value); err == nil {
+				criteria.WithoutFlags = append(criteria.WithoutFlags, f)
+			}
 		case 'H':
 			// TODO
 		case 'f':
@@ -46,3 +57,15 @@ func parseSearch(args []string) (*imap.SearchCriteria, error) {
 	}
 	return criteria, nil
 }
+
+func getParsedFlag(name string) (string, error) {
+	switch strings.ToLower(name) {
+	case "seen":
+		return imap.SeenFlag, nil
+	case "flagged":
+		return imap.FlaggedFlag, nil
+	case "answered":
+		return imap.AnsweredFlag, nil
+	}
+	return imap.FlaggedFlag, errors.New("Flag not suppored")
+}
diff --git a/worker/maildir/search.go b/worker/maildir/search.go
index f658c02..005f6fa 100644
--- a/worker/maildir/search.go
+++ b/worker/maildir/search.go
@@ -29,7 +29,7 @@ func newSearchCriteria() *searchCriteria {
 func parseSearch(args []string) (*searchCriteria, error) {
 	criteria := newSearchCriteria()
 
-	opts, optind, err := getopt.Getopts(args, "rubat:H:f:c:")
+	opts, optind, err := getopt.Getopts(args, "rux:X:bat:H:f:c:")
 	if err != nil {
 		return nil, err
 	}
@@ -41,6 +41,10 @@ func parseSearch(args []string) (*searchCriteria, error) {
 			criteria.WithFlags = append(criteria.WithFlags, maildir.FlagSeen)
 		case 'u':
 			criteria.WithoutFlags = append(criteria.WithoutFlags, maildir.FlagSeen)
+		case 'x':
+			criteria.WithFlags = append(criteria.WithFlags, getParsedFlag(opt.Value))
+		case 'X':
+			criteria.WithoutFlags = append(criteria.WithoutFlags, getParsedFlag(opt.Value))
 		case 'H':
 			// TODO
 		case 'f':
@@ -67,6 +71,19 @@ func parseSearch(args []string) (*searchCriteria, error) {
 	return criteria, nil
 }
 
+func getParsedFlag(name string) maildir.Flag {
+	var f maildir.Flag
+	switch strings.ToLower(name) {
+	case "seen":
+		f = maildir.FlagSeen
+	case "answered":
+		f = maildir.FlagReplied
+	case "flagged":
+		f = maildir.FlagFlagged
+	}
+	return f
+}
+
 func (w *Worker) search(criteria *searchCriteria) ([]uint32, error) {
 	requiredParts := getRequiredParts(criteria)
 	w.worker.Logger.Printf("Required parts bitmask for search: %b", requiredParts)