aboutsummaryrefslogtreecommitdiffstats
path: root/commands/account/query.go
blob: da8a8c0667e0c80d7b094b786ed96c7800d78a5d (plain) (blame)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package account

import (
	"errors"
	"strings"
	"time"

	"git.sr.ht/~rjarry/aerc/app"
	"git.sr.ht/~rjarry/aerc/commands"
	"git.sr.ht/~rjarry/aerc/worker/types"
)

type Query struct {
	Account string `opt:"-a" complete:"CompleteAccount"`
	Name    string `opt:"-n"`
	Force   bool   `opt:"-f"`
	Query   string `opt:"..." complete:"CompleteNotmuch"`
}

func init() {
	commands.Register(Query{})
}

func (Query) Description() string {
	return "Create a virtual folder using the specified notmuch query."
}

func (Query) Context() commands.CommandContext {
	return commands.MESSAGE_LIST
}

func (Query) Aliases() []string {
	return []string{"query"}
}

func (Query) CompleteAccount(arg string) []string {
	return commands.FilterList(app.AccountNames(), arg, commands.QuoteSpace)
}

func (q Query) Execute([]string) error {
	var acct *app.AccountView

	if q.Account == "" {
		acct = app.SelectedAccount()
		if acct == nil {
			return errors.New("No account selected")
		}
	} else {
		var err error
		acct, err = app.Account(q.Account)
		if err != nil {
			return err
		}
	}

	if acct.AccountConfig().Backend != "notmuch" {
		return errors.New(":query is only available for notmuch accounts")
	}

	finalize := func(msg types.WorkerMessage) {
		handleDirOpenResponse(acct, msg)
	}

	name := q.Name
	if name == "" {
		name = q.Query
	}
	acct.Directories().Open(name, q.Query, 0*time.Second, finalize, q.Force)
	return nil
}

func (*Query) CompleteNotmuch(arg string) []string {
	return handleNotmuchComplete(arg)
}

var notmuch_search_terms = []string{
	"from:",
	"to:",
	"tag:",
	"date:",
	"attachment:",
	"mimetype:",
	"subject:",
	"body:",
	"id:",
	"thread:",
	"folder:",
	"path:",
}

func handleNotmuchComplete(arg string) []string {
	prefixes := []string{"from:", "to:"}
	for _, prefix := range prefixes {
		if strings.HasPrefix(arg, prefix) {
			arg = strings.TrimPrefix(arg, prefix)
			return commands.FilterList(
				commands.GetAddress(arg), arg,
				func(v string) string { return prefix + v },
			)
		}
	}

	prefixes = []string{"tag:"}
	for _, prefix := range prefixes {
		if strings.HasPrefix(arg, prefix) {
			arg = strings.TrimPrefix(arg, prefix)
			return commands.FilterList(
				commands.GetLabels(arg), arg,
				func(v string) string { return prefix + v },
			)
		}
	}

	prefixes = []string{"path:", "folder:"}
	dbPath := strings.TrimPrefix(app.SelectedAccount().AccountConfig().Source, "notmuch://")
	for _, prefix := range prefixes {
		if strings.HasPrefix(arg, prefix) {
			arg = strings.TrimPrefix(arg, prefix)
			return commands.FilterList(
				commands.CompletePath(dbPath+arg, true), arg,
				func(v string) string { return prefix + strings.TrimPrefix(v, dbPath) },
			)
		}
	}

	return commands.FilterList(notmuch_search_terms, arg, nil)
}