diff options
Diffstat (limited to 'commands/account/search.go')
-rw-r--r-- | commands/account/search.go | 114 |
1 files changed, 110 insertions, 4 deletions
diff --git a/commands/account/search.go b/commands/account/search.go index 7b98d98b..bb5617c0 100644 --- a/commands/account/search.go +++ b/commands/account/search.go @@ -2,18 +2,35 @@ package account import ( "errors" + "fmt" + "net/textproto" "strings" + "time" "git.sr.ht/~rjarry/aerc/app" "git.sr.ht/~rjarry/aerc/commands" + "git.sr.ht/~rjarry/aerc/lib/parse" "git.sr.ht/~rjarry/aerc/lib/state" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" + "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" ) type SearchFilter struct { - Unused struct{} `opt:"-"` + Read bool `opt:"-r" action:"ParseRead"` + Unread bool `opt:"-u" action:"ParseUnread"` + Body bool `opt:"-b"` + All bool `opt:"-a"` + Headers textproto.MIMEHeader `opt:"-H" action:"ParseHeader" metavar:"<header>:<value>"` + WithFlags models.Flags `opt:"-x" action:"ParseFlag"` + WithoutFlags models.Flags `opt:"-X" action:"ParseNotFlag"` + To []string `opt:"-t" action:"ParseTo"` + From []string `opt:"-f" action:"ParseFrom"` + Cc []string `opt:"-c" action:"ParseCc"` + StartDate time.Time `opt:"-d" action:"ParseDate"` + EndDate time.Time + Terms string `opt:"..." required:"false"` } func init() { @@ -49,7 +66,82 @@ func (SearchFilter) Complete(args []string) []string { return nil } -func (SearchFilter) Execute(args []string) error { +func (s *SearchFilter) ParseRead(arg string) error { + s.WithFlags |= models.SeenFlag + s.WithoutFlags &^= models.SeenFlag + return nil +} + +func (s *SearchFilter) ParseUnread(arg string) error { + s.WithFlags &^= models.SeenFlag + s.WithoutFlags |= models.SeenFlag + return nil +} + +var flagValues = map[string]models.Flags{ + "seen": models.SeenFlag, + "answered": models.AnsweredFlag, + "flagged": models.FlaggedFlag, +} + +func (s *SearchFilter) ParseFlag(arg string) error { + f, ok := flagValues[strings.ToLower(arg)] + if !ok { + return fmt.Errorf("%q unknown flag", arg) + } + s.WithFlags |= f + s.WithoutFlags &^= f + return nil +} + +func (s *SearchFilter) ParseNotFlag(arg string) error { + f, ok := flagValues[strings.ToLower(arg)] + if !ok { + return fmt.Errorf("%q unknown flag", arg) + } + s.WithFlags &^= f + s.WithoutFlags |= f + return nil +} + +func (s *SearchFilter) ParseHeader(arg string) error { + name, value, hasColon := strings.Cut(arg, ":") + if !hasColon { + return fmt.Errorf("%q invalid syntax", arg) + } + if s.Headers == nil { + s.Headers = make(textproto.MIMEHeader) + } + s.Headers.Add(name, strings.TrimSpace(value)) + return nil +} + +func (s *SearchFilter) ParseTo(arg string) error { + s.To = append(s.To, arg) + return nil +} + +func (s *SearchFilter) ParseFrom(arg string) error { + s.From = append(s.From, arg) + return nil +} + +func (s *SearchFilter) ParseCc(arg string) error { + s.Cc = append(s.Cc, arg) + return nil +} + +func (s *SearchFilter) ParseDate(arg string) error { + start, end, err := parse.DateRange(arg) + if err != nil { + return err + } + s.StartDate = start + s.EndDate = end + return nil +} + +func (s SearchFilter) Execute(args []string) error { acct := app.SelectedAccount() if acct == nil { return errors.New("No account selected") @@ -59,12 +151,26 @@ func (SearchFilter) Execute(args []string) error { return errors.New("Cannot perform action. Messages still loading") } + criteria := types.SearchCriteria{ + WithFlags: s.WithFlags, + WithoutFlags: s.WithoutFlags, + From: s.From, + To: s.To, + Cc: s.Cc, + Headers: s.Headers, + StartDate: s.StartDate, + EndDate: s.EndDate, + SearchBody: s.Body, + SearchAll: s.All, + Terms: s.Terms, + } + if args[0] == "filter" { if len(args[1:]) == 0 { return Clear{}.Execute([]string{"clear"}) } acct.SetStatus(state.FilterActivity("Filtering..."), state.Search("")) - store.SetFilter(args[1:]) + store.SetFilter(&criteria) cb := func(msg types.WorkerMessage) { if _, ok := msg.(*types.Done); ok { acct.SetStatus(state.FilterResult(strings.Join(args, " "))) @@ -81,7 +187,7 @@ func (SearchFilter) Execute(args []string) error { // TODO: Remove when stores have multiple OnUpdate handlers ui.Invalidate() } - store.Search(args, cb) + store.Search(&criteria, cb) } return nil } |