lint: apply new formatting rules
Run `make fmt`. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
21dcd440f8
commit
aaf0a0c656
78 changed files with 288 additions and 285 deletions
|
@ -4,9 +4,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var AccountCommands *commands.Commands
|
||||||
AccountCommands *commands.Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd commands.Command) {
|
func register(cmd commands.Command) {
|
||||||
if AccountCommands == nil {
|
if AccountCommands == nil {
|
||||||
|
|
|
@ -9,9 +9,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var history map[string]string
|
||||||
history map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
type ChangeFolder struct{}
|
type ChangeFolder struct{}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,7 @@ import (
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var previousDir string
|
||||||
previousDir string
|
|
||||||
)
|
|
||||||
|
|
||||||
type ChangeDirectory struct{}
|
type ChangeDirectory struct{}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ComposeCommands *commands.Commands
|
||||||
ComposeCommands *commands.Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd commands.Command) {
|
func register(cmd commands.Command) {
|
||||||
if ComposeCommands == nil {
|
if ComposeCommands == nil {
|
||||||
|
|
|
@ -12,17 +12,15 @@ import (
|
||||||
|
|
||||||
type Header struct{}
|
type Header struct{}
|
||||||
|
|
||||||
var (
|
var headers = []string{
|
||||||
headers = []string{
|
"From",
|
||||||
"From",
|
"To",
|
||||||
"To",
|
"Cc",
|
||||||
"Cc",
|
"Bcc",
|
||||||
"Bcc",
|
"Subject",
|
||||||
"Subject",
|
"Comments",
|
||||||
"Comments",
|
"Keywords",
|
||||||
"Keywords",
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
register(Header{})
|
register(Header{})
|
||||||
|
@ -50,9 +48,7 @@ func (Header) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
return errors.New("command parsing failed")
|
return errors.New("command parsing failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var force bool = false
|
||||||
force bool = false
|
|
||||||
)
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch opt.Option {
|
switch opt.Option {
|
||||||
case 'f':
|
case 'f':
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
var copyBuf bytes.Buffer // for the Sent folder content if CopyTo is set
|
var copyBuf bytes.Buffer // for the Sent folder content if CopyTo is set
|
||||||
|
|
||||||
failCh := make(chan error)
|
failCh := make(chan error)
|
||||||
//writer
|
// writer
|
||||||
go func() {
|
go func() {
|
||||||
defer logging.PanicHandler()
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
failCh <- sender.Close()
|
failCh <- sender.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//cleanup + copy to sent
|
// cleanup + copy to sent
|
||||||
go func() {
|
go func() {
|
||||||
defer logging.PanicHandler()
|
defer logging.PanicHandler()
|
||||||
|
|
||||||
|
@ -431,7 +431,8 @@ func connectSmtps(host string) (*smtp.Client, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyToSent(worker *types.Worker, dest string,
|
func copyToSent(worker *types.Worker, dest string,
|
||||||
n int, msg io.Reader) <-chan error {
|
n int, msg io.Reader,
|
||||||
|
) <-chan error {
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
worker.PostAction(&types.AppendMessage{
|
worker.PostAction(&types.AppendMessage{
|
||||||
Destination: dest,
|
Destination: dest,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
var (
|
var GlobalCommands *Commands
|
||||||
GlobalCommands *Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd Command) {
|
func register(cmd Command) {
|
||||||
if GlobalCommands == nil {
|
if GlobalCommands == nil {
|
||||||
|
|
|
@ -86,7 +86,8 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
for dir, uids := range uidMap {
|
for dir, uids := range uidMap {
|
||||||
store.Move(uids, dir, true, func(
|
store.Move(uids, dir, true, func(
|
||||||
msg types.WorkerMessage) {
|
msg types.WorkerMessage,
|
||||||
|
) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Done:
|
case *types.Done:
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
@ -111,7 +112,8 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupBy(msgs []*models.MessageInfo,
|
func groupBy(msgs []*models.MessageInfo,
|
||||||
grouper func(*models.MessageInfo) string) map[string][]uint32 {
|
grouper func(*models.MessageInfo) string,
|
||||||
|
) map[string][]uint32 {
|
||||||
m := make(map[string][]uint32)
|
m := make(map[string][]uint32)
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
group := grouper(msg)
|
group := grouper(msg)
|
||||||
|
|
|
@ -34,9 +34,7 @@ func (Copy) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
var createParents bool
|
||||||
createParents bool
|
|
||||||
)
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch opt.Option {
|
switch opt.Option {
|
||||||
case 'p':
|
case 'p':
|
||||||
|
@ -54,8 +52,8 @@ func (Copy) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
store.Copy(uids, strings.Join(args[optind:], " "),
|
store.Copy(uids, strings.Join(args[optind:], " "),
|
||||||
createParents, func(
|
createParents, func(
|
||||||
msg types.WorkerMessage) {
|
msg types.WorkerMessage,
|
||||||
|
) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Done:
|
case *types.Done:
|
||||||
aerc.PushStatus("Messages copied.", 10*time.Second)
|
aerc.PushStatus("Messages copied.", 10*time.Second)
|
||||||
|
|
|
@ -42,7 +42,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//caution, can be nil
|
// caution, can be nil
|
||||||
next := findNextNonDeleted(uids, store)
|
next := findNextNonDeleted(uids, store)
|
||||||
store.ClearVisualMark()
|
store.ClearVisualMark()
|
||||||
store.Delete(uids, func(msg types.WorkerMessage) {
|
store.Delete(uids, func(msg types.WorkerMessage) {
|
||||||
|
|
|
@ -28,7 +28,6 @@ func (invite) Complete(aerc *widgets.Aerc, args []string) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (invite) Execute(aerc *widgets.Aerc, args []string) error {
|
func (invite) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
acct := aerc.SelectedAccount()
|
acct := aerc.SelectedAccount()
|
||||||
if acct == nil {
|
if acct == nil {
|
||||||
return errors.New("no account selected")
|
return errors.New("no account selected")
|
||||||
|
@ -90,9 +89,7 @@ func (invite) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var to []*mail.Address
|
||||||
to []*mail.Address
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(msg.Envelope.ReplyTo) != 0 {
|
if len(msg.Envelope.ReplyTo) != 0 {
|
||||||
to = msg.Envelope.ReplyTo
|
to = msg.Envelope.ReplyTo
|
||||||
|
|
|
@ -52,8 +52,8 @@ func (ModifyLabels) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store.ModifyLabels(uids, add, remove, func(
|
store.ModifyLabels(uids, add, remove, func(
|
||||||
msg types.WorkerMessage) {
|
msg types.WorkerMessage,
|
||||||
|
) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Done:
|
case *types.Done:
|
||||||
aerc.PushStatus("labels updated", 10*time.Second)
|
aerc.PushStatus("labels updated", 10*time.Second)
|
||||||
|
|
|
@ -34,9 +34,7 @@ func (Move) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
var createParents bool
|
||||||
createParents bool
|
|
||||||
)
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch opt.Option {
|
switch opt.Option {
|
||||||
case 'p':
|
case 'p':
|
||||||
|
@ -61,8 +59,8 @@ func (Move) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
findNextNonDeleted(uids, store)
|
findNextNonDeleted(uids, store)
|
||||||
joinedArgs := strings.Join(args[optind:], " ")
|
joinedArgs := strings.Join(args[optind:], " ")
|
||||||
store.Move(uids, joinedArgs, createParents, func(
|
store.Move(uids, joinedArgs, createParents, func(
|
||||||
msg types.WorkerMessage) {
|
msg types.WorkerMessage,
|
||||||
|
) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Done:
|
case *types.Done:
|
||||||
aerc.PushStatus("Message moved to "+joinedArgs, 10*time.Second)
|
aerc.PushStatus("Message moved to "+joinedArgs, 10*time.Second)
|
||||||
|
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var MessageCommands *commands.Commands
|
||||||
MessageCommands *commands.Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd commands.Command) {
|
func register(cmd commands.Command) {
|
||||||
if MessageCommands == nil {
|
if MessageCommands == nil {
|
||||||
|
|
|
@ -36,7 +36,6 @@ func (FlagMsg) Complete(aerc *widgets.Aerc, args []string) []string {
|
||||||
// If this was called as 'read' or 'unread', it has the same effect as
|
// If this was called as 'read' or 'unread', it has the same effect as
|
||||||
// 'flag' or 'unflag', respectively, but the 'Seen' flag is affected.
|
// 'flag' or 'unflag', respectively, but the 'Seen' flag is affected.
|
||||||
func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error {
|
func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
// The flag to change
|
// The flag to change
|
||||||
var flag models.Flag
|
var flag models.Flag
|
||||||
// User-readable name of the flag to change
|
// User-readable name of the flag to change
|
||||||
|
@ -184,7 +183,8 @@ func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
func submitFlagChange(aerc *widgets.Aerc, store *lib.MessageStore,
|
func submitFlagChange(aerc *widgets.Aerc, store *lib.MessageStore,
|
||||||
uids []uint32, flag models.Flag, newState bool,
|
uids []uint32, flag models.Flag, newState bool,
|
||||||
wg *sync.WaitGroup, success *bool) {
|
wg *sync.WaitGroup, success *bool,
|
||||||
|
) {
|
||||||
store.Flag(uids, flag, newState, func(msg types.WorkerMessage) {
|
store.Flag(uids, flag, newState, func(msg types.WorkerMessage) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
|
|
|
@ -136,7 +136,6 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
)
|
)
|
||||||
aerc.AddDialog(confirm)
|
aerc.AddDialog(confirm)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,9 +211,7 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -146,7 +146,7 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
to = append(to, envTos...)
|
to = append(to, envTos...)
|
||||||
|
|
||||||
for _, addr := range msg.Envelope.Cc {
|
for _, addr := range msg.Envelope.Cc {
|
||||||
//dedupe stuff from the to/from headers
|
// dedupe stuff from the to/from headers
|
||||||
if recSet.Contains(addr) {
|
if recSet.Contains(addr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -259,8 +259,8 @@ func (s addrSet) Contains(a *mail.Address) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
//setReferencesHeader adds the references header to target based on parent
|
// setReferencesHeader adds the references header to target based on parent
|
||||||
//according to RFC2822
|
// according to RFC2822
|
||||||
func setReferencesHeader(target, parent *mail.Header) error {
|
func setReferencesHeader(target, parent *mail.Header) error {
|
||||||
refs, err := parent.MsgIDList("references")
|
refs, err := parent.MsgIDList("references")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -285,7 +285,8 @@ func setReferencesHeader(target, parent *mail.Header) error {
|
||||||
|
|
||||||
// addMimeType adds the proper mime type of the part to the originalMail struct
|
// addMimeType adds the proper mime type of the part to the originalMail struct
|
||||||
func addMimeType(msg *models.MessageInfo, part []int,
|
func addMimeType(msg *models.MessageInfo, part []int,
|
||||||
orig *models.OriginalMail) error {
|
orig *models.OriginalMail,
|
||||||
|
) error {
|
||||||
// caution, :forward uses the code as well, keep that in mind when modifying
|
// caution, :forward uses the code as well, keep that in mind when modifying
|
||||||
bs, err := msg.BodyStructure.PartAtIndex(part)
|
bs, err := msg.BodyStructure.PartAtIndex(part)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -18,10 +18,12 @@ func TestParseUnsubscribe(t *testing.T) {
|
||||||
{"<https://example.com> is a URL", []string{
|
{"<https://example.com> is a URL", []string{
|
||||||
"https://example.com",
|
"https://example.com",
|
||||||
}},
|
}},
|
||||||
{"<mailto:user@host?subject=unsubscribe>, <https://example.com>",
|
{
|
||||||
|
"<mailto:user@host?subject=unsubscribe>, <https://example.com>",
|
||||||
[]string{
|
[]string{
|
||||||
"mailto:user@host?subject=unsubscribe", "https://example.com",
|
"mailto:user@host?subject=unsubscribe", "https://example.com",
|
||||||
}},
|
},
|
||||||
|
},
|
||||||
{"<>, <https://example> ", []string{
|
{"<>, <https://example> ", []string{
|
||||||
"", "https://example",
|
"", "https://example",
|
||||||
}},
|
}},
|
||||||
|
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var MessageViewCommands *commands.Commands
|
||||||
MessageViewCommands *commands.Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd commands.Command) {
|
func register(cmd commands.Command) {
|
||||||
if MessageViewCommands == nil {
|
if MessageViewCommands == nil {
|
||||||
|
|
|
@ -129,7 +129,6 @@ func savePart(
|
||||||
aerc *widgets.Aerc,
|
aerc *widgets.Aerc,
|
||||||
params *saveParams,
|
params *saveParams,
|
||||||
) error {
|
) error {
|
||||||
|
|
||||||
if params.trailingSlash || isDirExists(path) {
|
if params.trailingSlash || isDirExists(path) {
|
||||||
filename := generateFilename(pi.Part)
|
filename := generateFilename(pi.Part)
|
||||||
path = filepath.Join(path, filename)
|
path = filepath.Join(path, filename)
|
||||||
|
@ -137,7 +136,7 @@ func savePart(
|
||||||
|
|
||||||
dir := filepath.Dir(path)
|
dir := filepath.Dir(path)
|
||||||
if params.createDirs && dir != "" {
|
if params.createDirs && dir != "" {
|
||||||
err := os.MkdirAll(dir, 0755)
|
err := os.MkdirAll(dir, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -177,7 +176,7 @@ func savePart(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//isDir returns true if path is a directory and exists
|
// isDir returns true if path is a directory and exists
|
||||||
func isDirExists(path string) bool {
|
func isDirExists(path string) bool {
|
||||||
pathinfo, err := os.Stat(path)
|
pathinfo, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -189,14 +188,14 @@ func isDirExists(path string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//pathExists returns true if path exists
|
// pathExists returns true if path exists
|
||||||
func pathExists(path string) bool {
|
func pathExists(path string) bool {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
|
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//isAbsPath returns true if path given is anchored to / or . or ~
|
// isAbsPath returns true if path given is anchored to / or . or ~
|
||||||
func isAbsPath(path string) bool {
|
func isAbsPath(path string) bool {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -2,8 +2,9 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.sr.ht/~rjarry/aerc/widgets"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Prompt struct{}
|
type Prompt struct{}
|
||||||
|
|
|
@ -21,7 +21,6 @@ func init() {
|
||||||
|
|
||||||
func (Set) Aliases() []string {
|
func (Set) Aliases() []string {
|
||||||
return []string{"set"}
|
return []string{"set"}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Set) Complete(aerc *widgets.Aerc, args []string) []string {
|
func (Set) Complete(aerc *widgets.Aerc, args []string) []string {
|
||||||
|
@ -48,7 +47,6 @@ func SetCore(aerc *widgets.Aerc, args []string) error {
|
||||||
new_file := ini.Empty()
|
new_file := ini.Empty()
|
||||||
|
|
||||||
section, err := new_file.NewSection(category)
|
section, err := new_file.NewSection(category)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/commands"
|
"git.sr.ht/~rjarry/aerc/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var TerminalCommands *commands.Commands
|
||||||
TerminalCommands *commands.Commands
|
|
||||||
)
|
|
||||||
|
|
||||||
func register(cmd commands.Command) {
|
func register(cmd commands.Command) {
|
||||||
if TerminalCommands == nil {
|
if TerminalCommands == nil {
|
||||||
|
|
|
@ -56,8 +56,8 @@ func MergeBindings(bindings ...*KeyBindings) *KeyBindings {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config AercConfig) MergeContextualBinds(baseBinds *KeyBindings,
|
func (config AercConfig) MergeContextualBinds(baseBinds *KeyBindings,
|
||||||
contextType ContextType, reg string, bindCtx string) *KeyBindings {
|
contextType ContextType, reg string, bindCtx string,
|
||||||
|
) *KeyBindings {
|
||||||
bindings := baseBinds
|
bindings := baseBinds
|
||||||
for _, contextualBind := range config.ContextualBinds {
|
for _, contextualBind := range config.ContextualBinds {
|
||||||
if contextualBind.ContextType != contextType {
|
if contextualBind.ContextType != contextType {
|
||||||
|
@ -83,8 +83,8 @@ func (bindings *KeyBindings) Add(binding *Binding) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bindings *KeyBindings) GetBinding(
|
func (bindings *KeyBindings) GetBinding(
|
||||||
input []KeyStroke) (BindingSearchResult, []KeyStroke) {
|
input []KeyStroke,
|
||||||
|
) (BindingSearchResult, []KeyStroke) {
|
||||||
incomplete := false
|
incomplete := false
|
||||||
// TODO: This could probably be a sorted list to speed things up
|
// TODO: This could probably be a sorted list to speed things up
|
||||||
// TODO: Deal with bindings that share a prefix
|
// TODO: Deal with bindings that share a prefix
|
||||||
|
@ -165,9 +165,7 @@ func FormatKeyStrokes(keystrokes []KeyStroke) string {
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var keyNames map[string]KeyStroke
|
||||||
keyNames map[string]KeyStroke
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseKeyStrokes(keystrokes string) ([]KeyStroke, error) {
|
func ParseKeyStrokes(keystrokes string) ([]KeyStroke, error) {
|
||||||
var strokes []KeyStroke
|
var strokes []KeyStroke
|
||||||
|
|
|
@ -398,7 +398,7 @@ var searchDirs = buildDefaultDirs()
|
||||||
func installTemplate(root, name string) error {
|
func installTemplate(root, name string) error {
|
||||||
var err error
|
var err error
|
||||||
if _, err = os.Stat(root); os.IsNotExist(err) {
|
if _, err = os.Stat(root); os.IsNotExist(err) {
|
||||||
err = os.MkdirAll(root, 0755)
|
err = os.MkdirAll(root, 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ func installTemplate(root, name string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(path.Join(root, name), data, 0644)
|
err = ioutil.WriteFile(path.Join(root, name), data, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -527,10 +527,9 @@ func (config *AercConfig) LoadConfig(file *ini.File) error {
|
||||||
if err := validateBorderChars(uiSection, &uiSubConfig); err != nil {
|
if err := validateBorderChars(uiSection, &uiSubConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
contextualUi :=
|
contextualUi := UIConfigContext{
|
||||||
UIConfigContext{
|
UiConfig: uiSubConfig,
|
||||||
UiConfig: uiSubConfig,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var index int
|
var index int
|
||||||
if strings.Contains(sectionName, "~") {
|
if strings.Contains(sectionName, "~") {
|
||||||
|
@ -922,7 +921,6 @@ func LoadBindingSection(sec *ini.Section) (*KeyBindings, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup **KeyBindings) error {
|
func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup **KeyBindings) error {
|
||||||
|
|
||||||
if sec, err := binds.GetSection(baseName); err == nil {
|
if sec, err := binds.GetSection(baseName); err == nil {
|
||||||
binds, err := LoadBindingSection(sec)
|
binds, err := LoadBindingSection(sec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -947,11 +945,10 @@ func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
contextualBind :=
|
contextualBind := BindingConfigContext{
|
||||||
BindingConfigContext{
|
Bindings: binds,
|
||||||
Bindings: binds,
|
BindContext: baseName,
|
||||||
BindContext: baseName,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var index int
|
var index int
|
||||||
if strings.Contains(sectionName, "=") {
|
if strings.Contains(sectionName, "=") {
|
||||||
|
@ -1006,7 +1003,7 @@ func checkConfigPerms(filename string) error {
|
||||||
|
|
||||||
perms := info.Mode().Perm()
|
perms := info.Mode().Perm()
|
||||||
// group or others have read access
|
// group or others have read access
|
||||||
if perms&044 != 0 {
|
if perms&0o44 != 0 {
|
||||||
fmt.Fprintf(os.Stderr, "The file %v has too open permissions.\n", filename)
|
fmt.Fprintf(os.Stderr, "The file %v has too open permissions.\n", filename)
|
||||||
fmt.Fprintln(os.Stderr, "This is a security issue (it contains passwords).")
|
fmt.Fprintln(os.Stderr, "This is a security issue (it contains passwords).")
|
||||||
fmt.Fprintf(os.Stderr, "To fix it, run `chmod 600 %v`\n", filename)
|
fmt.Fprintf(os.Stderr, "To fix it, run `chmod 600 %v`\n", filename)
|
||||||
|
@ -1035,7 +1032,8 @@ func (ui *UIConfig) loadStyleSet(styleSetDirs []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config AercConfig) mergeContextualUi(baseUi UIConfig,
|
func (config AercConfig) mergeContextualUi(baseUi UIConfig,
|
||||||
contextType ContextType, s string) UIConfig {
|
contextType ContextType, s string,
|
||||||
|
) UIConfig {
|
||||||
for _, contextualUi := range config.ContextualUis {
|
for _, contextualUi := range config.ContextualUis {
|
||||||
if contextualUi.ContextType != contextType {
|
if contextualUi.ContextType != contextType {
|
||||||
continue
|
continue
|
||||||
|
@ -1078,7 +1076,8 @@ func (uiConfig UIConfig) GetStyleSelected(so StyleObject) tcell.Style {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uiConfig UIConfig) GetComposedStyle(base StyleObject,
|
func (uiConfig UIConfig) GetComposedStyle(base StyleObject,
|
||||||
styles []StyleObject) tcell.Style {
|
styles []StyleObject,
|
||||||
|
) tcell.Style {
|
||||||
return uiConfig.style.Compose(base, styles)
|
return uiConfig.style.Compose(base, styles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,8 @@ func (ss StyleSet) Compose(so StyleObject, sos []StyleObject) tcell.Style {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss StyleSet) ComposeSelected(so StyleObject,
|
func (ss StyleSet) ComposeSelected(so StyleObject,
|
||||||
sos []StyleObject) tcell.Style {
|
sos []StyleObject,
|
||||||
|
) tcell.Style {
|
||||||
base := *ss.selected[so]
|
base := *ss.selected[so]
|
||||||
styles := make([]*Style, len(sos))
|
styles := make([]*Style, len(sos))
|
||||||
for i, so := range sos {
|
for i, so := range sos {
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (trig *TriggersConfig) ExecTrigger(triggerCmd string,
|
func (trig *TriggersConfig) ExecTrigger(triggerCmd string,
|
||||||
triggerFmt func(string) (string, error)) error {
|
triggerFmt func(string) (string, error),
|
||||||
|
) error {
|
||||||
if len(triggerCmd) == 0 {
|
if len(triggerCmd) == 0 {
|
||||||
return errors.New("Trigger command empty")
|
return errors.New("Trigger command empty")
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ func (trig *TriggersConfig) ExecTrigger(triggerCmd string,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (trig *TriggersConfig) ExecNewEmail(account *AccountConfig,
|
func (trig *TriggersConfig) ExecNewEmail(account *AccountConfig,
|
||||||
conf *AercConfig, msg *models.MessageInfo) {
|
conf *AercConfig, msg *models.MessageInfo,
|
||||||
|
) {
|
||||||
err := trig.ExecTrigger(trig.NewEmail,
|
err := trig.ExecTrigger(trig.NewEmail,
|
||||||
func(part string) (string, error) {
|
func(part string) (string, error) {
|
||||||
formatstr, args, err := format.ParseMessageFormat(
|
formatstr, args, err := format.ParseMessageFormat(
|
||||||
|
@ -45,7 +46,8 @@ func (trig *TriggersConfig) ExecNewEmail(account *AccountConfig,
|
||||||
format.Ctx{
|
format.Ctx{
|
||||||
FromAddress: account.From,
|
FromAddress: account.From,
|
||||||
AccountName: account.Name,
|
AccountName: account.Name,
|
||||||
MsgInfo: msg},
|
MsgInfo: msg,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -26,7 +26,6 @@ func (cr *Reply) AddOrganizer(o string) {
|
||||||
|
|
||||||
// CreateReply parses a ics request and return a ics reply (RFC 2446, Section 3.2.3)
|
// CreateReply parses a ics request and return a ics reply (RFC 2446, Section 3.2.3)
|
||||||
func CreateReply(reader io.Reader, from *mail.Address, partstat string) (*Reply, error) {
|
func CreateReply(reader io.Reader, from *mail.Address, partstat string) (*Reply, error) {
|
||||||
|
|
||||||
cr := Reply{
|
cr := Reply{
|
||||||
MimeType: "text/calendar",
|
MimeType: "text/calendar",
|
||||||
Params: map[string]string{
|
Params: map[string]string{
|
||||||
|
|
|
@ -37,7 +37,6 @@ func (m *Mail) ImportKeys(r io.Reader) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mail) Encrypt(buf *bytes.Buffer, rcpts []string, signer string, decryptKeys openpgp.PromptFunction, header *mail.Header) (io.WriteCloser, error) {
|
func (m *Mail) Encrypt(buf *bytes.Buffer, rcpts []string, signer string, decryptKeys openpgp.PromptFunction, header *mail.Header) (io.WriteCloser, error) {
|
||||||
|
|
||||||
return Encrypt(buf, header.Header.Header, rcpts, signer)
|
return Encrypt(buf, header.Header.Header, rcpts, signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// Encrypt runs gpg --encrypt [--sign] -r [recipient]. The default is to have
|
// Encrypt runs gpg --encrypt [--sign] -r [recipient]. The default is to have
|
||||||
// --trust-model always set
|
// --trust-model always set
|
||||||
func Encrypt(r io.Reader, to []string, from string) ([]byte, error) {
|
func Encrypt(r io.Reader, to []string, from string) ([]byte, error) {
|
||||||
//TODO probably shouldn't have --trust-model always a default
|
// TODO probably shouldn't have --trust-model always a default
|
||||||
args := []string{
|
args := []string{
|
||||||
"--armor",
|
"--armor",
|
||||||
"--trust-model", "always",
|
"--trust-model", "always",
|
||||||
|
|
|
@ -31,10 +31,10 @@ var (
|
||||||
|
|
||||||
func (m *Mail) Init() error {
|
func (m *Mail) Init() error {
|
||||||
logging.Infof("Initializing PGP keyring")
|
logging.Infof("Initializing PGP keyring")
|
||||||
os.MkdirAll(path.Join(xdg.DataHome(), "aerc"), 0700)
|
os.MkdirAll(path.Join(xdg.DataHome(), "aerc"), 0o700)
|
||||||
|
|
||||||
lockpath := path.Join(xdg.DataHome(), "aerc", "keyring.lock")
|
lockpath := path.Join(xdg.DataHome(), "aerc", "keyring.lock")
|
||||||
lockfile, err := os.OpenFile(lockpath, os.O_CREATE|os.O_EXCL, 0600)
|
lockfile, err := os.OpenFile(lockpath, os.O_CREATE|os.O_EXCL, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Consider connecting to main process over IPC socket
|
// TODO: Consider connecting to main process over IPC socket
|
||||||
locked = false
|
locked = false
|
||||||
|
@ -149,7 +149,7 @@ func (m *Mail) ImportKeys(r io.Reader) error {
|
||||||
Keyring = append(Keyring, keys...)
|
Keyring = append(Keyring, keys...)
|
||||||
if locked {
|
if locked {
|
||||||
keypath := path.Join(xdg.DataHome(), "aerc", "keyring.asc")
|
keypath := path.Join(xdg.DataHome(), "aerc", "keyring.asc")
|
||||||
keyfile, err := os.OpenFile(keypath, os.O_CREATE|os.O_APPEND, 0600)
|
keyfile, err := os.OpenFile(keypath, os.O_CREATE|os.O_APPEND, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,8 @@ type Ctx struct {
|
||||||
|
|
||||||
func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string,
|
func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string,
|
||||||
thisWeekTimeFmt string, thisYearTimeFmt string, ctx Ctx) (
|
thisWeekTimeFmt string, thisYearTimeFmt string, ctx Ctx) (
|
||||||
string, []interface{}, error) {
|
string, []interface{}, error,
|
||||||
|
) {
|
||||||
retval := make([]byte, 0, len(format))
|
retval := make([]byte, 0, len(format))
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
|
|
||||||
|
@ -289,10 +290,10 @@ func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string,
|
||||||
}
|
}
|
||||||
case 'Z':
|
case 'Z':
|
||||||
// calculate all flags
|
// calculate all flags
|
||||||
var readReplyFlag = ""
|
readReplyFlag := ""
|
||||||
var delFlag = ""
|
delFlag := ""
|
||||||
var flaggedFlag = ""
|
flaggedFlag := ""
|
||||||
var markedFlag = ""
|
markedFlag := ""
|
||||||
seen := false
|
seen := false
|
||||||
recent := false
|
recent := false
|
||||||
answered := false
|
answered := false
|
||||||
|
@ -390,7 +391,8 @@ handle_end_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
func dummyIfZeroDate(date time.Time, format string, todayFormat string,
|
func dummyIfZeroDate(date time.Time, format string, todayFormat string,
|
||||||
thisWeekFormat string, thisYearFormat string) string {
|
thisWeekFormat string, thisYearFormat string,
|
||||||
|
) string {
|
||||||
if date.IsZero() {
|
if date.IsZero() {
|
||||||
return strings.Repeat("?", len(format))
|
return strings.Repeat("?", len(format))
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,10 +62,12 @@ type MessageStoreView struct {
|
||||||
|
|
||||||
func NewMessageStoreView(messageInfo *models.MessageInfo,
|
func NewMessageStoreView(messageInfo *models.MessageInfo,
|
||||||
store *MessageStore, pgp crypto.Provider, decryptKeys openpgp.PromptFunction,
|
store *MessageStore, pgp crypto.Provider, decryptKeys openpgp.PromptFunction,
|
||||||
cb func(MessageView, error)) {
|
cb func(MessageView, error),
|
||||||
|
) {
|
||||||
msv := &MessageStoreView{messageInfo, store,
|
msv := &MessageStoreView{
|
||||||
nil, nil, messageInfo.BodyStructure}
|
messageInfo, store,
|
||||||
|
nil, nil, messageInfo.BodyStructure,
|
||||||
|
}
|
||||||
|
|
||||||
if usePGP(messageInfo.BodyStructure) {
|
if usePGP(messageInfo.BodyStructure) {
|
||||||
store.FetchFull([]uint32{messageInfo.Uid}, func(fm *types.FullMessage) {
|
store.FetchFull([]uint32{messageInfo.Uid}, func(fm *types.FullMessage) {
|
||||||
|
@ -117,7 +119,6 @@ func (msv *MessageStoreView) MessageDetails() *models.MessageDetails {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msv *MessageStoreView) FetchBodyPart(part []int, cb func(io.Reader)) {
|
func (msv *MessageStoreView) FetchBodyPart(part []int, cb func(io.Reader)) {
|
||||||
|
|
||||||
if msv.message == nil {
|
if msv.message == nil {
|
||||||
msv.messageStore.FetchBodyPart(msv.messageInfo.Uid, part, cb)
|
msv.messageStore.FetchBodyPart(msv.messageInfo.Uid, part, cb)
|
||||||
return
|
return
|
||||||
|
|
|
@ -27,7 +27,7 @@ type MessageStore struct {
|
||||||
bodyCallbacks map[uint32][]func(*types.FullMessage)
|
bodyCallbacks map[uint32][]func(*types.FullMessage)
|
||||||
headerCallbacks map[uint32][]func(*types.MessageInfo)
|
headerCallbacks map[uint32][]func(*types.MessageInfo)
|
||||||
|
|
||||||
//marking
|
// marking
|
||||||
marked map[uint32]struct{}
|
marked map[uint32]struct{}
|
||||||
lastMarked map[uint32]struct{}
|
lastMarked map[uint32]struct{}
|
||||||
visualStartUid uint32
|
visualStartUid uint32
|
||||||
|
@ -68,8 +68,8 @@ func NewMessageStore(worker *types.Worker,
|
||||||
defaultSortCriteria []*types.SortCriterion,
|
defaultSortCriteria []*types.SortCriterion,
|
||||||
thread bool, clientThreads bool, clientThreadsDelay time.Duration,
|
thread bool, clientThreads bool, clientThreadsDelay time.Duration,
|
||||||
triggerNewEmail func(*models.MessageInfo),
|
triggerNewEmail func(*models.MessageInfo),
|
||||||
triggerDirectoryChange func()) *MessageStore {
|
triggerDirectoryChange func(),
|
||||||
|
) *MessageStore {
|
||||||
if !dirInfo.Caps.Thread {
|
if !dirInfo.Caps.Thread {
|
||||||
clientThreads = true
|
clientThreads = true
|
||||||
}
|
}
|
||||||
|
@ -102,8 +102,8 @@ func NewMessageStore(worker *types.Worker,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) FetchHeaders(uids []uint32,
|
func (store *MessageStore) FetchHeaders(uids []uint32,
|
||||||
cb func(*types.MessageInfo)) {
|
cb func(*types.MessageInfo),
|
||||||
|
) {
|
||||||
// TODO: this could be optimized by pre-allocating toFetch and trimming it
|
// TODO: this could be optimized by pre-allocating toFetch and trimming it
|
||||||
// at the end. In practice we expect to get most messages back in one frame.
|
// at the end. In practice we expect to get most messages back in one frame.
|
||||||
var toFetch []uint32
|
var toFetch []uint32
|
||||||
|
@ -166,7 +166,6 @@ func (store *MessageStore) FetchFull(uids []uint32, cb func(*types.FullMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) FetchBodyPart(uid uint32, part []int, cb func(io.Reader)) {
|
func (store *MessageStore) FetchBodyPart(uid uint32, part []int, cb func(io.Reader)) {
|
||||||
|
|
||||||
store.worker.PostAction(&types.FetchMessageBodyPart{
|
store.worker.PostAction(&types.FetchMessageBodyPart{
|
||||||
Uid: uid,
|
Uid: uid,
|
||||||
Part: part,
|
Part: part,
|
||||||
|
@ -399,7 +398,6 @@ func (store *MessageStore) runThreadBuilder() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store.threadBuilderDebounce = time.AfterFunc(store.threadBuilderDelay, func() {
|
store.threadBuilderDebounce = time.AfterFunc(store.threadBuilderDelay, func() {
|
||||||
|
|
||||||
// temporarily deactiviate the selector in the message list by
|
// temporarily deactiviate the selector in the message list by
|
||||||
// setting SelectedUid to the MagicUid
|
// setting SelectedUid to the MagicUid
|
||||||
oldUid := store.SelectedUid()
|
oldUid := store.SelectedUid()
|
||||||
|
@ -436,8 +434,8 @@ func (store *MessageStore) runThreadBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Delete(uids []uint32,
|
func (store *MessageStore) Delete(uids []uint32,
|
||||||
cb func(msg types.WorkerMessage)) {
|
cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
for _, uid := range uids {
|
for _, uid := range uids {
|
||||||
store.Deleted[uid] = nil
|
store.Deleted[uid] = nil
|
||||||
}
|
}
|
||||||
|
@ -461,8 +459,8 @@ func (store *MessageStore) revertDeleted(uids []uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Copy(uids []uint32, dest string, createDest bool,
|
func (store *MessageStore) Copy(uids []uint32, dest string, createDest bool,
|
||||||
cb func(msg types.WorkerMessage)) {
|
cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
if createDest {
|
if createDest {
|
||||||
store.worker.PostAction(&types.CreateDirectory{
|
store.worker.PostAction(&types.CreateDirectory{
|
||||||
Directory: dest,
|
Directory: dest,
|
||||||
|
@ -477,8 +475,8 @@ func (store *MessageStore) Copy(uids []uint32, dest string, createDest bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Move(uids []uint32, dest string, createDest bool,
|
func (store *MessageStore) Move(uids []uint32, dest string, createDest bool,
|
||||||
cb func(msg types.WorkerMessage)) {
|
cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
for _, uid := range uids {
|
for _, uid := range uids {
|
||||||
store.Deleted[uid] = nil
|
store.Deleted[uid] = nil
|
||||||
}
|
}
|
||||||
|
@ -505,8 +503,8 @@ func (store *MessageStore) Move(uids []uint32, dest string, createDest bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Flag(uids []uint32, flag models.Flag,
|
func (store *MessageStore) Flag(uids []uint32, flag models.Flag,
|
||||||
enable bool, cb func(msg types.WorkerMessage)) {
|
enable bool, cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
store.worker.PostAction(&types.FlagMessages{
|
store.worker.PostAction(&types.FlagMessages{
|
||||||
Enable: enable,
|
Enable: enable,
|
||||||
Flag: flag,
|
Flag: flag,
|
||||||
|
@ -515,8 +513,8 @@ func (store *MessageStore) Flag(uids []uint32, flag models.Flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Answered(uids []uint32, answered bool,
|
func (store *MessageStore) Answered(uids []uint32, answered bool,
|
||||||
cb func(msg types.WorkerMessage)) {
|
cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
store.worker.PostAction(&types.AnsweredMessages{
|
store.worker.PostAction(&types.AnsweredMessages{
|
||||||
Answered: answered,
|
Answered: answered,
|
||||||
Uids: uids,
|
Uids: uids,
|
||||||
|
@ -524,7 +522,6 @@ func (store *MessageStore) Answered(uids []uint32, answered bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Uids() []uint32 {
|
func (store *MessageStore) Uids() []uint32 {
|
||||||
|
|
||||||
if store.ThreadedView() && store.builder != nil {
|
if store.ThreadedView() && store.builder != nil {
|
||||||
if uids := store.builder.Uids(); len(uids) > 0 {
|
if uids := store.builder.Uids(); len(uids) > 0 {
|
||||||
return uids
|
return uids
|
||||||
|
@ -608,13 +605,13 @@ func (store *MessageStore) checkMark() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//IsMarked checks whether a MessageInfo has been marked
|
// IsMarked checks whether a MessageInfo has been marked
|
||||||
func (store *MessageStore) IsMarked(uid uint32) bool {
|
func (store *MessageStore) IsMarked(uid uint32) bool {
|
||||||
_, marked := store.marked[uid]
|
_, marked := store.marked[uid]
|
||||||
return marked
|
return marked
|
||||||
}
|
}
|
||||||
|
|
||||||
//ToggleVisualMark enters or leaves the visual marking mode
|
// ToggleVisualMark enters or leaves the visual marking mode
|
||||||
func (store *MessageStore) ToggleVisualMark() {
|
func (store *MessageStore) ToggleVisualMark() {
|
||||||
store.visualMarkMode = !store.visualMarkMode
|
store.visualMarkMode = !store.visualMarkMode
|
||||||
switch store.visualMarkMode {
|
switch store.visualMarkMode {
|
||||||
|
@ -629,7 +626,7 @@ func (store *MessageStore) ToggleVisualMark() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ClearVisualMark leaves the visual marking mode and resets any marking
|
// ClearVisualMark leaves the visual marking mode and resets any marking
|
||||||
func (store *MessageStore) ClearVisualMark() {
|
func (store *MessageStore) ClearVisualMark() {
|
||||||
store.resetMark()
|
store.resetMark()
|
||||||
store.visualMarkMode = false
|
store.visualMarkMode = false
|
||||||
|
@ -793,7 +790,8 @@ func (store *MessageStore) PrevResult() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) ModifyLabels(uids []uint32, add, remove []string,
|
func (store *MessageStore) ModifyLabels(uids []uint32, add, remove []string,
|
||||||
cb func(msg types.WorkerMessage)) {
|
cb func(msg types.WorkerMessage),
|
||||||
|
) {
|
||||||
store.worker.PostAction(&types.ModifyLabels{
|
store.worker.PostAction(&types.ModifyLabels{
|
||||||
Uids: uids,
|
Uids: uids,
|
||||||
Add: add,
|
Add: add,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package lib
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/emersion/go-imap/client"
|
"github.com/emersion/go-imap/client"
|
||||||
"github.com/emersion/go-sasl"
|
"github.com/emersion/go-sasl"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
|
@ -29,7 +29,6 @@ func NewXDGOpen(filename string) *xdgOpen {
|
||||||
errCh: errch,
|
errCh: errch,
|
||||||
args: []string{filename},
|
args: []string{filename},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetArgs sets additional arguments to the open command prior to the filename
|
// SetArgs sets additional arguments to the open command prior to the filename
|
||||||
|
|
|
@ -8,8 +8,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var submatch = `(https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,10}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))`
|
var (
|
||||||
var httpRe = regexp.MustCompile("\"" + submatch + "\"" + "|" + "\\(" + submatch + "\\)" + "|" + "<" + submatch + ">" + "|" + submatch)
|
submatch = `(https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,10}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))`
|
||||||
|
httpRe = regexp.MustCompile("\"" + submatch + "\"" + "|" + "\\(" + submatch + "\\)" + "|" + "<" + submatch + ">" + "|" + submatch)
|
||||||
|
)
|
||||||
|
|
||||||
// HttpLinks searches a reader for a http link and returns a copy of the
|
// HttpLinks searches a reader for a http link and returns a copy of the
|
||||||
// reader and a slice with links.
|
// reader and a slice with links.
|
||||||
|
@ -36,7 +38,7 @@ func HttpLinks(r io.Reader) (io.Reader, []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
results := []string{}
|
results := []string{}
|
||||||
for link, _ := range linkMap {
|
for link := range linkMap {
|
||||||
results = append(results, link)
|
results = append(results, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,11 @@ type folderState struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewState(name string, multipleAccts bool, conf config.StatuslineConfig) *State {
|
func NewState(name string, multipleAccts bool, conf config.StatuslineConfig) *State {
|
||||||
return &State{separator: conf.Separator,
|
return &State{
|
||||||
renderer: newRenderer(conf.RenderFormat, conf.DisplayMode),
|
separator: conf.Separator,
|
||||||
acct: &accountState{Name: name, Multiple: multipleAccts},
|
renderer: newRenderer(conf.RenderFormat, conf.DisplayMode),
|
||||||
fldr: make(map[string]*folderState),
|
acct: &accountState{Name: name, Multiple: multipleAccts},
|
||||||
|
fldr: make(map[string]*folderState),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,27 +8,26 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLib_FindAllNonMultipart(t *testing.T) {
|
func TestLib_FindAllNonMultipart(t *testing.T) {
|
||||||
|
|
||||||
testStructure := &models.BodyStructure{
|
testStructure := &models.BodyStructure{
|
||||||
MIMEType: "multipart",
|
MIMEType: "multipart",
|
||||||
Parts: []*models.BodyStructure{
|
Parts: []*models.BodyStructure{
|
||||||
&models.BodyStructure{},
|
{},
|
||||||
&models.BodyStructure{
|
{
|
||||||
MIMEType: "multipart",
|
MIMEType: "multipart",
|
||||||
Parts: []*models.BodyStructure{
|
Parts: []*models.BodyStructure{
|
||||||
&models.BodyStructure{},
|
{},
|
||||||
&models.BodyStructure{},
|
{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&models.BodyStructure{},
|
{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := [][]int{
|
expected := [][]int{
|
||||||
[]int{1},
|
{1},
|
||||||
[]int{2, 1},
|
{2, 1},
|
||||||
[]int{2, 2},
|
{2, 2},
|
||||||
[]int{3},
|
{3},
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := lib.FindAllNonMultipart(testStructure, nil, nil)
|
parts := lib.FindAllNonMultipart(testStructure, nil, nil)
|
||||||
|
@ -42,5 +41,4 @@ func TestLib_FindAllNonMultipart(t *testing.T) {
|
||||||
t.Errorf("incorrect values; expected: %v, got: %v", expected[i], parts[i])
|
t.Errorf("incorrect values; expected: %v, got: %v", expected[i], parts[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
|
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
//SetVersion initializes the aerc version displayed in template functions
|
// SetVersion initializes the aerc version displayed in template functions
|
||||||
func SetVersion(v string) {
|
func SetVersion(v string) {
|
||||||
version = v
|
version = v
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ func findTemplate(templateName string, templateDirs []string) (string, error) {
|
||||||
"Can't find template %q in any of %v ", templateName, templateDirs)
|
"Can't find template %q in any of %v ", templateName, templateDirs)
|
||||||
}
|
}
|
||||||
|
|
||||||
//DummyData provides dummy data to test template validity
|
// DummyData provides dummy data to test template validity
|
||||||
func DummyData() interface{} {
|
func DummyData() interface{} {
|
||||||
from := &mail.Address{
|
from := &mail.Address{
|
||||||
Name: "John Doe",
|
Name: "John Doe",
|
||||||
|
|
|
@ -22,7 +22,8 @@ type Bordered struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBordered(
|
func NewBordered(
|
||||||
content Drawable, borders uint, uiConfig *config.UIConfig) *Bordered {
|
content Drawable, borders uint, uiConfig *config.UIConfig,
|
||||||
|
) *Bordered {
|
||||||
b := &Bordered{
|
b := &Bordered{
|
||||||
borders: borders,
|
borders: borders,
|
||||||
content: content,
|
content: content,
|
||||||
|
|
|
@ -63,7 +63,8 @@ func (ctx *Context) SetCell(x, y int, ch rune, style tcell.Style) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *Context) Printf(x, y int, style tcell.Style,
|
func (ctx *Context) Printf(x, y int, style tcell.Style,
|
||||||
format string, a ...interface{}) int {
|
format string, a ...interface{},
|
||||||
|
) int {
|
||||||
width, height := ctx.viewport.Size()
|
width, height := ctx.viewport.Size()
|
||||||
|
|
||||||
if x >= width || y >= height {
|
if x >= width || y >= height {
|
||||||
|
|
|
@ -36,8 +36,10 @@ type Tab struct {
|
||||||
uiConf *config.UIConfig
|
uiConf *config.UIConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type TabStrip Tabs
|
type (
|
||||||
type TabContent Tabs
|
TabStrip Tabs
|
||||||
|
TabContent Tabs
|
||||||
|
)
|
||||||
|
|
||||||
func NewTabs(uiConf *config.UIConfig) *Tabs {
|
func NewTabs(uiConf *config.UIConfig) *Tabs {
|
||||||
tabs := &Tabs{}
|
tabs := &Tabs{}
|
||||||
|
|
|
@ -59,7 +59,8 @@ func (ti *TextInput) Prompt(prompt string) *TextInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ti *TextInput) TabComplete(
|
func (ti *TextInput) TabComplete(
|
||||||
tabcomplete func(s string) ([]string, string), d time.Duration) *TextInput {
|
tabcomplete func(s string) ([]string, string), d time.Duration,
|
||||||
|
) *TextInput {
|
||||||
ti.tabcomplete = tabcomplete
|
ti.tabcomplete = tabcomplete
|
||||||
ti.completeDelay = d
|
ti.completeDelay = d
|
||||||
return ti
|
return ti
|
||||||
|
|
|
@ -19,7 +19,6 @@ type UI struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Initialize(content DrawableInteractive) (*UI, error) {
|
func Initialize(content DrawableInteractive) (*UI, error) {
|
||||||
|
|
||||||
screen, err := tcell.NewScreen()
|
screen, err := tcell.NewScreen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -142,7 +142,7 @@ type BodyStructure struct {
|
||||||
DispositionParams map[string]string
|
DispositionParams map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
//PartAtIndex returns the BodyStructure at the requested index
|
// PartAtIndex returns the BodyStructure at the requested index
|
||||||
func (bs *BodyStructure) PartAtIndex(index []int) (*BodyStructure, error) {
|
func (bs *BodyStructure) PartAtIndex(index []int) (*BodyStructure, error) {
|
||||||
if len(index) == 0 {
|
if len(index) == 0 {
|
||||||
return bs, nil
|
return bs, nil
|
||||||
|
|
|
@ -506,7 +506,7 @@ func (wizard *AccountWizard) finish(tutorial bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !wizard.temporary {
|
if !wizard.temporary {
|
||||||
f, err := os.OpenFile(accountsConf, os.O_WRONLY|os.O_CREATE, 0600)
|
f, err := os.OpenFile(accountsConf, os.O_WRONLY|os.O_CREATE, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wizard.errorFor(nil, err)
|
wizard.errorFor(nil, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -51,7 +51,8 @@ type Choice struct {
|
||||||
func NewAerc(conf *config.AercConfig,
|
func NewAerc(conf *config.AercConfig,
|
||||||
crypto crypto.Provider, cmd func(cmd []string) error,
|
crypto crypto.Provider, cmd func(cmd []string) error,
|
||||||
complete func(cmd string) []string, cmdHistory lib.History,
|
complete func(cmd string) []string, cmdHistory lib.History,
|
||||||
deferLoop chan struct{}) *Aerc {
|
deferLoop chan struct{},
|
||||||
|
) *Aerc {
|
||||||
tabs := ui.NewTabs(&conf.Ui)
|
tabs := ui.NewTabs(&conf.Ui)
|
||||||
|
|
||||||
statusbar := ui.NewStack(conf.Ui)
|
statusbar := ui.NewStack(conf.Ui)
|
||||||
|
|
|
@ -65,8 +65,8 @@ type Composer struct {
|
||||||
|
|
||||||
func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
|
func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
|
||||||
acctConfig *config.AccountConfig, worker *types.Worker, template string,
|
acctConfig *config.AccountConfig, worker *types.Worker, template string,
|
||||||
h *mail.Header, orig models.OriginalMail) (*Composer, error) {
|
h *mail.Header, orig models.OriginalMail,
|
||||||
|
) (*Composer, error) {
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = new(mail.Header)
|
h = new(mail.Header)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,6 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
|
||||||
}
|
}
|
||||||
if fl != nil {
|
if fl != nil {
|
||||||
h.SetAddressList("from", fl)
|
h.SetAddressList("from", fl)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +133,6 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) {
|
func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) {
|
||||||
|
|
||||||
c.layout = aerc.conf.Compose.HeaderLayout
|
c.layout = aerc.conf.Compose.HeaderLayout
|
||||||
c.editors = make(map[string]*headerEditor)
|
c.editors = make(map[string]*headerEditor)
|
||||||
c.focusable = make([]ui.MouseableDrawableInteractive, 0)
|
c.focusable = make([]ui.MouseableDrawableInteractive, 0)
|
||||||
|
@ -540,7 +538,7 @@ func (c *Composer) Worker() *types.Worker {
|
||||||
return c.worker
|
return c.worker
|
||||||
}
|
}
|
||||||
|
|
||||||
//PrepareHeader finalizes the header, adding the value from the editors
|
// PrepareHeader finalizes the header, adding the value from the editors
|
||||||
func (c *Composer) PrepareHeader() (*mail.Header, error) {
|
func (c *Composer) PrepareHeader() (*mail.Header, error) {
|
||||||
for _, editor := range c.editors {
|
for _, editor := range c.editors {
|
||||||
editor.storeValue()
|
editor.storeValue()
|
||||||
|
@ -594,7 +592,7 @@ func getRecipientsEmail(c *Composer) ([]string, error) {
|
||||||
|
|
||||||
// return email addresses as string slice
|
// return email addresses as string slice
|
||||||
results := []string{}
|
results := []string{}
|
||||||
for email, _ := range rcpts {
|
for email := range rcpts {
|
||||||
results = append(results, email)
|
results = append(results, email)
|
||||||
}
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
|
@ -933,7 +931,8 @@ type headerEditor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHeaderEditor(name string, h *mail.Header,
|
func newHeaderEditor(name string, h *mail.Header,
|
||||||
uiConfig *config.UIConfig) *headerEditor {
|
uiConfig *config.UIConfig,
|
||||||
|
) *headerEditor {
|
||||||
he := &headerEditor{
|
he := &headerEditor{
|
||||||
input: ui.NewTextInput("", uiConfig),
|
input: ui.NewTextInput("", uiConfig),
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -944,8 +943,8 @@ func newHeaderEditor(name string, h *mail.Header,
|
||||||
return he
|
return he
|
||||||
}
|
}
|
||||||
|
|
||||||
//extractHumanHeaderValue extracts the human readable string for key from the
|
// extractHumanHeaderValue extracts the human readable string for key from the
|
||||||
//header. If a parsing error occurs the raw value is returned
|
// header. If a parsing error occurs the raw value is returned
|
||||||
func extractHumanHeaderValue(key string, h *mail.Header) string {
|
func extractHumanHeaderValue(key string, h *mail.Header) string {
|
||||||
var val string
|
var val string
|
||||||
var err error
|
var err error
|
||||||
|
@ -964,16 +963,16 @@ func extractHumanHeaderValue(key string, h *mail.Header) string {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
//loadValue loads the value of he.name form the underlying header
|
// loadValue loads the value of he.name form the underlying header
|
||||||
//the value is decoded and meant for human consumption.
|
// the value is decoded and meant for human consumption.
|
||||||
//decoding issues are ignored and return their raw values
|
// decoding issues are ignored and return their raw values
|
||||||
func (he *headerEditor) loadValue() {
|
func (he *headerEditor) loadValue() {
|
||||||
he.input.Set(extractHumanHeaderValue(he.name, he.header))
|
he.input.Set(extractHumanHeaderValue(he.name, he.header))
|
||||||
he.input.Invalidate()
|
he.input.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
//storeValue writes the current state back to the underlying header.
|
// storeValue writes the current state back to the underlying header.
|
||||||
//errors are ignored
|
// errors are ignored
|
||||||
func (he *headerEditor) storeValue() {
|
func (he *headerEditor) storeValue() {
|
||||||
val := he.input.String()
|
val := he.input.String()
|
||||||
switch strings.ToLower(he.name) {
|
switch strings.ToLower(he.name) {
|
||||||
|
@ -996,8 +995,8 @@ func (he *headerEditor) storeValue() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//setValue overwrites the current value of the header editor and flushes it
|
// setValue overwrites the current value of the header editor and flushes it
|
||||||
//to the underlying header
|
// to the underlying header
|
||||||
func (he *headerEditor) setValue(val string) {
|
func (he *headerEditor) setValue(val string) {
|
||||||
he.input.Set(val)
|
he.input.Set(val)
|
||||||
he.storeValue()
|
he.storeValue()
|
||||||
|
|
|
@ -119,7 +119,6 @@ func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) {
|
||||||
var dirs []string
|
var dirs []string
|
||||||
dirlist.worker.PostAction(
|
dirlist.worker.PostAction(
|
||||||
&types.ListDirectories{}, func(msg types.WorkerMessage) {
|
&types.ListDirectories{}, func(msg types.WorkerMessage) {
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Directory:
|
case *types.Directory:
|
||||||
dirs = append(dirs, msg.Dir.Name)
|
dirs = append(dirs, msg.Dir.Name)
|
||||||
|
|
|
@ -383,7 +383,7 @@ func buildTree(node *types.Thread, stree [][]string, defaultUid uint32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys := make([]string, 0)
|
keys := make([]string, 0)
|
||||||
for key, _ := range m {
|
for key := range m {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
|
@ -20,8 +20,8 @@ type ExLine struct {
|
||||||
|
|
||||||
func NewExLine(conf *config.AercConfig, cmd string, commit func(cmd string), finish func(),
|
func NewExLine(conf *config.AercConfig, cmd string, commit func(cmd string), finish func(),
|
||||||
tabcomplete func(cmd string) ([]string, string),
|
tabcomplete func(cmd string) ([]string, string),
|
||||||
cmdHistory lib.History) *ExLine {
|
cmdHistory lib.History,
|
||||||
|
) *ExLine {
|
||||||
input := ui.NewTextInput("", &conf.Ui).Prompt(":").Set(cmd)
|
input := ui.NewTextInput("", &conf.Ui).Prompt(":").Set(cmd)
|
||||||
if conf.Ui.CompletionPopovers {
|
if conf.Ui.CompletionPopovers {
|
||||||
input.TabComplete(tabcomplete, conf.Ui.CompletionDelay)
|
input.TabComplete(tabcomplete, conf.Ui.CompletionDelay)
|
||||||
|
@ -41,8 +41,8 @@ func NewExLine(conf *config.AercConfig, cmd string, commit func(cmd string), fin
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPrompt(conf *config.AercConfig, prompt string, commit func(text string),
|
func NewPrompt(conf *config.AercConfig, prompt string, commit func(text string),
|
||||||
tabcomplete func(cmd string) ([]string, string)) *ExLine {
|
tabcomplete func(cmd string) ([]string, string),
|
||||||
|
) *ExLine {
|
||||||
input := ui.NewTextInput("", &conf.Ui).Prompt(prompt)
|
input := ui.NewTextInput("", &conf.Ui).Prompt(prompt)
|
||||||
if conf.Ui.CompletionPopovers {
|
if conf.Ui.CompletionPopovers {
|
||||||
input.TabComplete(tabcomplete, conf.Ui.CompletionDelay)
|
input.TabComplete(tabcomplete, conf.Ui.CompletionDelay)
|
||||||
|
|
|
@ -19,7 +19,8 @@ type GetPasswd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGetPasswd(title string, prompt string, conf *config.AercConfig,
|
func NewGetPasswd(title string, prompt string, conf *config.AercConfig,
|
||||||
cb func(string, error)) *GetPasswd {
|
cb func(string, error),
|
||||||
|
) *GetPasswd {
|
||||||
getpasswd := &GetPasswd{
|
getpasswd := &GetPasswd{
|
||||||
callback: cb,
|
callback: cb,
|
||||||
title: title,
|
title: title,
|
||||||
|
|
|
@ -102,7 +102,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
|
||||||
}
|
}
|
||||||
counter--
|
counter--
|
||||||
if counter > len(store.Uids())-1-ml.Scroll() {
|
if counter > len(store.Uids())-1-ml.Scroll() {
|
||||||
//skip messages which are higher than the viewport
|
// skip messages which are higher than the viewport
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
msg := store.Messages[t.Uid]
|
msg := store.Messages[t.Uid]
|
||||||
|
|
|
@ -52,8 +52,8 @@ type PartSwitcher struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageViewer(acct *AccountView,
|
func NewMessageViewer(acct *AccountView,
|
||||||
conf *config.AercConfig, msg lib.MessageView) *MessageViewer {
|
conf *config.AercConfig, msg lib.MessageView,
|
||||||
|
) *MessageViewer {
|
||||||
hf := HeaderLayoutFilter{
|
hf := HeaderLayoutFilter{
|
||||||
layout: HeaderLayout(conf.Viewer.HeaderLayout),
|
layout: HeaderLayout(conf.Viewer.HeaderLayout),
|
||||||
keep: func(msg *models.MessageInfo, header string) bool {
|
keep: func(msg *models.MessageInfo, header string) bool {
|
||||||
|
@ -178,8 +178,8 @@ func fmtHeader(msg *models.MessageInfo, header string, timefmt string) string {
|
||||||
|
|
||||||
func enumerateParts(acct *AccountView, conf *config.AercConfig,
|
func enumerateParts(acct *AccountView, conf *config.AercConfig,
|
||||||
msg lib.MessageView, body *models.BodyStructure,
|
msg lib.MessageView, body *models.BodyStructure,
|
||||||
index []int) ([]*PartViewer, error) {
|
index []int,
|
||||||
|
) ([]*PartViewer, error) {
|
||||||
var parts []*PartViewer
|
var parts []*PartViewer
|
||||||
for i, part := range body.Parts {
|
for i, part := range body.Parts {
|
||||||
curindex := append(index, i+1)
|
curindex := append(index, i+1)
|
||||||
|
@ -205,8 +205,8 @@ func enumerateParts(acct *AccountView, conf *config.AercConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSwitcher(acct *AccountView, switcher *PartSwitcher,
|
func createSwitcher(acct *AccountView, switcher *PartSwitcher,
|
||||||
conf *config.AercConfig, msg lib.MessageView) error {
|
conf *config.AercConfig, msg lib.MessageView,
|
||||||
|
) error {
|
||||||
var err error
|
var err error
|
||||||
switcher.selected = -1
|
switcher.selected = -1
|
||||||
switcher.showHeaders = conf.Viewer.ShowHeaders
|
switcher.showHeaders = conf.Viewer.ShowHeaders
|
||||||
|
@ -530,8 +530,8 @@ type PartViewer struct {
|
||||||
|
|
||||||
func NewPartViewer(acct *AccountView, conf *config.AercConfig,
|
func NewPartViewer(acct *AccountView, conf *config.AercConfig,
|
||||||
msg lib.MessageView, part *models.BodyStructure,
|
msg lib.MessageView, part *models.BodyStructure,
|
||||||
index []int) (*PartViewer, error) {
|
index []int,
|
||||||
|
) (*PartViewer, error) {
|
||||||
var (
|
var (
|
||||||
filter *exec.Cmd
|
filter *exec.Cmd
|
||||||
pager *exec.Cmd
|
pager *exec.Cmd
|
||||||
|
@ -634,7 +634,7 @@ func (pv *PartViewer) attemptCopy() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pv.filter != nil {
|
if pv.filter != nil {
|
||||||
pv.copyFilterOutToPager() //delayed until we write to the sink
|
pv.copyFilterOutToPager() // delayed until we write to the sink
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer logging.PanicHandler()
|
defer logging.PanicHandler()
|
||||||
|
|
|
@ -64,5 +64,4 @@ func (s *Scrollable) EnsureScroll(selectingIdx int) {
|
||||||
if s.scroll > maxScroll {
|
if s.scroll > maxScroll {
|
||||||
s.scroll = maxScroll
|
s.scroll = maxScroll
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,8 @@ type SelectorDialog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSelectorDialog(title string, prompt string, options []string, focus int,
|
func NewSelectorDialog(title string, prompt string, options []string, focus int,
|
||||||
uiConfig *config.UIConfig, cb func(string, error)) *SelectorDialog {
|
uiConfig *config.UIConfig, cb func(string, error),
|
||||||
|
) *SelectorDialog {
|
||||||
sd := &SelectorDialog{
|
sd := &SelectorDialog{
|
||||||
callback: cb,
|
callback: cb,
|
||||||
title: title,
|
title: title,
|
||||||
|
|
|
@ -82,8 +82,7 @@ func init() {
|
||||||
keyMap[tcell.KeyPgUp] = directKey(vterm.KeyPageUp)
|
keyMap[tcell.KeyPgUp] = directKey(vterm.KeyPageUp)
|
||||||
keyMap[tcell.KeyPgDn] = directKey(vterm.KeyPageDown)
|
keyMap[tcell.KeyPgDn] = directKey(vterm.KeyPageDown)
|
||||||
for i := 0; i < 64; i++ {
|
for i := 0; i < 64; i++ {
|
||||||
keyMap[tcell.Key(int(tcell.KeyF1)+i)] =
|
keyMap[tcell.Key(int(tcell.KeyF1)+i)] = directKey(vterm.Key(int(vterm.KeyFunction0) + i + 1))
|
||||||
directKey(vterm.Key(int(vterm.KeyFunction0) + i + 1))
|
|
||||||
}
|
}
|
||||||
keyMap[tcell.KeyTAB] = directKey(vterm.KeyTab)
|
keyMap[tcell.KeyTAB] = directKey(vterm.KeyTab)
|
||||||
keyMap[tcell.KeyESC] = directKey(vterm.KeyEscape)
|
keyMap[tcell.KeyESC] = directKey(vterm.KeyEscape)
|
||||||
|
@ -302,7 +301,6 @@ func (term *Terminal) Draw(ctx *ui.Context) {
|
||||||
term.damageMutex.Lock()
|
term.damageMutex.Lock()
|
||||||
for _, rect := range term.damage {
|
for _, rect := range term.damage {
|
||||||
for x := rect.StartCol(); x < rect.EndCol() && x < ctx.Width(); x += 1 {
|
for x := rect.StartCol(); x < rect.EndCol() && x < ctx.Width(); x += 1 {
|
||||||
|
|
||||||
for y := rect.StartRow(); y < rect.EndRow() && y < ctx.Height(); y += 1 {
|
for y := rect.StartRow(); y < rect.EndRow() && y < ctx.Height(); y += 1 {
|
||||||
|
|
||||||
coords := coords{x, y}
|
coords := coords{x, y}
|
||||||
|
@ -472,8 +470,8 @@ func (term *Terminal) onDamage(rect *vterm.Rect) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (term *Terminal) onMoveCursor(old *vterm.Pos,
|
func (term *Terminal) onMoveCursor(old *vterm.Pos,
|
||||||
pos *vterm.Pos, visible bool) int {
|
pos *vterm.Pos, visible bool,
|
||||||
|
) int {
|
||||||
rows, cols, _ := pty.Getsize(term.pty)
|
rows, cols, _ := pty.Getsize(term.pty)
|
||||||
if pos.Row() >= rows || pos.Col() >= cols {
|
if pos.Row() >= rows || pos.Col() >= cols {
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
// selects the default inbox. If no error is returned, the imap client will be
|
// selects the default inbox. If no error is returned, the imap client will be
|
||||||
// in the imap.SelectedState.
|
// in the imap.SelectedState.
|
||||||
func (w *IMAPWorker) connect() (*client.Client, error) {
|
func (w *IMAPWorker) connect() (*client.Client, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
conn *net.TCPConn
|
conn *net.TCPConn
|
||||||
err error
|
err error
|
||||||
|
@ -98,8 +97,7 @@ func (w *IMAPWorker) connect() (*client.Client, error) {
|
||||||
// but a valid connection is eventually returned, ensure that it is properly
|
// but a valid connection is eventually returned, ensure that it is properly
|
||||||
// closed.
|
// closed.
|
||||||
func newTCPConn(addr string, timeout time.Duration) (*net.TCPConn, error) {
|
func newTCPConn(addr string, timeout time.Duration) (*net.TCPConn, error) {
|
||||||
|
errTCPTimeout := fmt.Errorf("tcp connection timeout")
|
||||||
var errTCPTimeout = fmt.Errorf("tcp connection timeout")
|
|
||||||
|
|
||||||
type tcpConn struct {
|
type tcpConn struct {
|
||||||
conn *net.TCPConn
|
conn *net.TCPConn
|
||||||
|
|
|
@ -16,7 +16,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleFetchMessageHeaders(
|
func (imapw *IMAPWorker) handleFetchMessageHeaders(
|
||||||
msg *types.FetchMessageHeaders) {
|
msg *types.FetchMessageHeaders,
|
||||||
|
) {
|
||||||
toFetch := msg.Uids
|
toFetch := msg.Uids
|
||||||
if imapw.config.cacheEnabled && imapw.cache != nil {
|
if imapw.config.cacheEnabled && imapw.cache != nil {
|
||||||
toFetch = imapw.getCachedHeaders(msg)
|
toFetch = imapw.getCachedHeaders(msg)
|
||||||
|
@ -76,8 +77,8 @@ func (imapw *IMAPWorker) handleFetchMessageHeaders(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleFetchMessageBodyPart(
|
func (imapw *IMAPWorker) handleFetchMessageBodyPart(
|
||||||
msg *types.FetchMessageBodyPart) {
|
msg *types.FetchMessageBodyPart,
|
||||||
|
) {
|
||||||
logging.Infof("Fetching message %d part: %v", msg.Uid, msg.Part)
|
logging.Infof("Fetching message %d part: %v", msg.Uid, msg.Part)
|
||||||
|
|
||||||
var partHeaderSection imap.BodySectionName
|
var partHeaderSection imap.BodySectionName
|
||||||
|
@ -146,8 +147,8 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleFetchFullMessages(
|
func (imapw *IMAPWorker) handleFetchFullMessages(
|
||||||
msg *types.FetchFullMessages) {
|
msg *types.FetchFullMessages,
|
||||||
|
) {
|
||||||
logging.Infof("Fetching full messages: %v", msg.Uids)
|
logging.Infof("Fetching full messages: %v", msg.Uids)
|
||||||
section := &imap.BodySectionName{}
|
section := &imap.BodySectionName{}
|
||||||
items := []imap.FetchItem{
|
items := []imap.FetchItem{
|
||||||
|
@ -205,8 +206,8 @@ func (imapw *IMAPWorker) handleFetchMessageFlags(msg *types.FetchMessageFlags) {
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleFetchMessages(
|
func (imapw *IMAPWorker) handleFetchMessages(
|
||||||
msg types.WorkerMessage, uids []uint32, items []imap.FetchItem,
|
msg types.WorkerMessage, uids []uint32, items []imap.FetchItem,
|
||||||
procFunc func(*imap.Message) error) {
|
procFunc func(*imap.Message) error,
|
||||||
|
) {
|
||||||
messages := make(chan *imap.Message)
|
messages := make(chan *imap.Message)
|
||||||
done := make(chan error)
|
done := make(chan error)
|
||||||
|
|
||||||
|
|
|
@ -79,5 +79,4 @@ func (imapw *IMAPWorker) handleSearchDirectory(msg *types.SearchDirectory) {
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
Uids: uids,
|
Uids: uids,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ func (imapw *IMAPWorker) handleAppendMessage(msg *types.AppendMessage) {
|
||||||
Reader: msg.Reader,
|
Reader: msg.Reader,
|
||||||
Length: msg.Length,
|
Length: msg.Length,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|
||||||
imapw.worker.PostMessage(&types.Error{
|
imapw.worker.PostMessage(&types.Error{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
Error: err,
|
Error: err,
|
||||||
|
|
|
@ -140,7 +140,8 @@ func (o *observer) DelayedReconnect() error {
|
||||||
func (o *observer) emit(errMsg string) {
|
func (o *observer) emit(errMsg string) {
|
||||||
o.log("disconnect done->")
|
o.log("disconnect done->")
|
||||||
o.worker.PostMessage(&types.Done{
|
o.worker.PostMessage(&types.Done{
|
||||||
Message: types.RespondTo(&types.Disconnect{})}, nil)
|
Message: types.RespondTo(&types.Disconnect{}),
|
||||||
|
}, nil)
|
||||||
o.log("connection error->")
|
o.log("connection error->")
|
||||||
o.worker.PostMessage(&types.ConnError{
|
o.worker.PostMessage(&types.ConnError{
|
||||||
Error: fmt.Errorf(errMsg),
|
Error: fmt.Errorf(errMsg),
|
||||||
|
|
|
@ -25,8 +25,8 @@ func (imapw *IMAPWorker) handleOpenDirectory(msg *types.OpenDirectory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleFetchDirectoryContents(
|
func (imapw *IMAPWorker) handleFetchDirectoryContents(
|
||||||
msg *types.FetchDirectoryContents) {
|
msg *types.FetchDirectoryContents,
|
||||||
|
) {
|
||||||
logging.Infof("Fetching UID list")
|
logging.Infof("Fetching UID list")
|
||||||
|
|
||||||
searchCriteria, err := parseSearch(msg.FilterCriteria)
|
searchCriteria, err := parseSearch(msg.FilterCriteria)
|
||||||
|
@ -88,7 +88,8 @@ var sortFieldMap sortFieldMapT = sortFieldMapT{
|
||||||
}
|
}
|
||||||
|
|
||||||
func translateSortCriterions(
|
func translateSortCriterions(
|
||||||
cs []*types.SortCriterion) []sortthread.SortCriterion {
|
cs []*types.SortCriterion,
|
||||||
|
) []sortthread.SortCriterion {
|
||||||
result := make([]sortthread.SortCriterion, 0, len(cs))
|
result := make([]sortthread.SortCriterion, 0, len(cs))
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
if f, ok := sortFieldMap[c.Field]; ok {
|
if f, ok := sortFieldMap[c.Field]; ok {
|
||||||
|
@ -99,7 +100,8 @@ func translateSortCriterions(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imapw *IMAPWorker) handleDirectoryThreaded(
|
func (imapw *IMAPWorker) handleDirectoryThreaded(
|
||||||
msg *types.FetchDirectoryThreaded) {
|
msg *types.FetchDirectoryThreaded,
|
||||||
|
) {
|
||||||
logging.Infof("Fetching threaded UID list")
|
logging.Infof("Fetching threaded UID list")
|
||||||
|
|
||||||
searchCriteria, err := parseSearch(msg.FilterCriteria)
|
searchCriteria, err := parseSearch(msg.FilterCriteria)
|
||||||
|
|
|
@ -46,7 +46,7 @@ func FetchEntityPartReader(e *message.Entity, index []int) (io.Reader, error) {
|
||||||
return nil, fmt.Errorf("FetchEntityPartReader: unexpected code reached")
|
return nil, fmt.Errorf("FetchEntityPartReader: unexpected code reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: the UI doesn't seem to like readers which aren't buffers
|
// TODO: the UI doesn't seem to like readers which aren't buffers
|
||||||
func bufReader(e *message.Entity) (io.Reader, error) {
|
func bufReader(e *message.Entity) (io.Reader, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if _, err := io.Copy(&buf, e.Body); err != nil {
|
if _, err := io.Copy(&buf, e.Body); err != nil {
|
||||||
|
@ -157,7 +157,7 @@ func parseEnvelope(h *mail.Header) (*models.Envelope, error) {
|
||||||
}
|
}
|
||||||
msgID, err := h.MessageID()
|
msgID, err := h.MessageID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//proper parsing failed, so fall back to whatever is there
|
// proper parsing failed, so fall back to whatever is there
|
||||||
msgID, err = h.Text("message-id")
|
msgID, err = h.Text("message-id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -97,8 +97,8 @@ func Search(messages []RawMessage, criteria *searchCriteria) ([]uint32, error) {
|
||||||
// searchMessage executes the search criteria for the given RawMessage,
|
// searchMessage executes the search criteria for the given RawMessage,
|
||||||
// returns true if search succeeded
|
// returns true if search succeeded
|
||||||
func searchMessage(message RawMessage, criteria *searchCriteria,
|
func searchMessage(message RawMessage, criteria *searchCriteria,
|
||||||
parts MsgParts) (bool, error) {
|
parts MsgParts,
|
||||||
|
) (bool, error) {
|
||||||
// setup parts of the message to use in the search
|
// setup parts of the message to use in the search
|
||||||
// this is so that we try to minimise reading unnecessary parts
|
// this is so that we try to minimise reading unnecessary parts
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -10,7 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Sort(messageInfos []*models.MessageInfo,
|
func Sort(messageInfos []*models.MessageInfo,
|
||||||
criteria []*types.SortCriterion) ([]uint32, error) {
|
criteria []*types.SortCriterion,
|
||||||
|
) ([]uint32, error) {
|
||||||
// loop through in reverse to ensure we sort by non-primary fields first
|
// loop through in reverse to ensure we sort by non-primary fields first
|
||||||
for i := len(criteria) - 1; i >= 0; i-- {
|
for i := len(criteria) - 1; i >= 0; i-- {
|
||||||
criterion := criteria[i]
|
criterion := criteria[i]
|
||||||
|
@ -62,7 +63,8 @@ func Sort(messageInfos []*models.MessageInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
||||||
getValue func(*models.MessageInfo) []*mail.Address) {
|
getValue func(*models.MessageInfo) []*mail.Address,
|
||||||
|
) {
|
||||||
sortSlice(criterion, messageInfos, func(i, j int) bool {
|
sortSlice(criterion, messageInfos, func(i, j int) bool {
|
||||||
addressI, addressJ := getValue(messageInfos[i]), getValue(messageInfos[j])
|
addressI, addressJ := getValue(messageInfos[i]), getValue(messageInfos[j])
|
||||||
var firstI, firstJ *mail.Address
|
var firstI, firstJ *mail.Address
|
||||||
|
@ -92,7 +94,8 @@ func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCrit
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
||||||
testFlag models.Flag) {
|
testFlag models.Flag,
|
||||||
|
) {
|
||||||
var slice []*boolStore
|
var slice []*boolStore
|
||||||
for _, msgInfo := range messageInfos {
|
for _, msgInfo := range messageInfos {
|
||||||
flagPresent := false
|
flagPresent := false
|
||||||
|
@ -116,7 +119,8 @@ func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterio
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
|
||||||
getValue func(*models.MessageInfo) string) {
|
getValue func(*models.MessageInfo) string,
|
||||||
|
) {
|
||||||
var slice []*lexiStore
|
var slice []*lexiStore
|
||||||
for _, msgInfo := range messageInfos {
|
for _, msgInfo := range messageInfos {
|
||||||
slice = append(slice, &lexiStore{
|
slice = append(slice, &lexiStore{
|
||||||
|
|
|
@ -35,8 +35,10 @@ func NewContainer(dir string, maildirpp bool) (*Container, error) {
|
||||||
if !s.IsDir() {
|
if !s.IsDir() {
|
||||||
return nil, fmt.Errorf("Given maildir '%s' not a directory", dir)
|
return nil, fmt.Errorf("Given maildir '%s' not a directory", dir)
|
||||||
}
|
}
|
||||||
return &Container{dir: dir, uids: uidstore.NewStore(),
|
return &Container{
|
||||||
recentUIDS: make(map[uint32]struct{}), maildirpp: maildirpp}, nil
|
dir: dir, uids: uidstore.NewStore(),
|
||||||
|
recentUIDS: make(map[uint32]struct{}), maildirpp: maildirpp,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListFolders returns a list of maildir folders in the container
|
// ListFolders returns a list of maildir folders in the container
|
||||||
|
@ -183,7 +185,8 @@ func (c *Container) DeleteAll(d maildir.Dir, uids []uint32) ([]uint32, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) CopyAll(
|
func (c *Container) CopyAll(
|
||||||
dest maildir.Dir, src maildir.Dir, uids []uint32) error {
|
dest maildir.Dir, src maildir.Dir, uids []uint32,
|
||||||
|
) error {
|
||||||
for _, uid := range uids {
|
for _, uid := range uids {
|
||||||
if err := c.copyMessage(dest, src, uid); err != nil {
|
if err := c.copyMessage(dest, src, uid); err != nil {
|
||||||
return fmt.Errorf("could not copy message %d: %v", uid, err)
|
return fmt.Errorf("could not copy message %d: %v", uid, err)
|
||||||
|
@ -193,7 +196,8 @@ func (c *Container) CopyAll(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) copyMessage(
|
func (c *Container) copyMessage(
|
||||||
dest maildir.Dir, src maildir.Dir, uid uint32) error {
|
dest maildir.Dir, src maildir.Dir, uid uint32,
|
||||||
|
) error {
|
||||||
key, ok := c.uids.GetKey(uid)
|
key, ok := c.uids.GetKey(uid)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("could not find key for message id %d", uid)
|
return fmt.Errorf("could not find key for message id %d", uid)
|
||||||
|
|
|
@ -111,7 +111,8 @@ func (w *Worker) search(criteria *searchCriteria) ([]uint32, error) {
|
||||||
|
|
||||||
// Execute the search criteria for the given key, returns true if search succeeded
|
// Execute the search criteria for the given key, returns true if search succeeded
|
||||||
func (w *Worker) searchKey(key uint32, criteria *searchCriteria,
|
func (w *Worker) searchKey(key uint32, criteria *searchCriteria,
|
||||||
parts MsgParts) (bool, error) {
|
parts MsgParts,
|
||||||
|
) (bool, error) {
|
||||||
message, err := w.c.Message(*w.selected, key)
|
message, err := w.c.Message(*w.selected, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -406,7 +406,8 @@ func (w *Worker) handleOpenDirectory(msg *types.OpenDirectory) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) handleFetchDirectoryContents(
|
func (w *Worker) handleFetchDirectoryContents(
|
||||||
msg *types.FetchDirectoryContents) error {
|
msg *types.FetchDirectoryContents,
|
||||||
|
) error {
|
||||||
var (
|
var (
|
||||||
uids []uint32
|
uids []uint32
|
||||||
err error
|
err error
|
||||||
|
@ -482,7 +483,8 @@ func (w *Worker) handleRemoveDirectory(msg *types.RemoveDirectory) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) handleFetchMessageHeaders(
|
func (w *Worker) handleFetchMessageHeaders(
|
||||||
msg *types.FetchMessageHeaders) error {
|
msg *types.FetchMessageHeaders,
|
||||||
|
) error {
|
||||||
for _, uid := range msg.Uids {
|
for _, uid := range msg.Uids {
|
||||||
info, err := w.msgInfoFromUid(uid)
|
info, err := w.msgInfoFromUid(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -500,8 +502,8 @@ func (w *Worker) handleFetchMessageHeaders(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) handleFetchMessageBodyPart(
|
func (w *Worker) handleFetchMessageBodyPart(
|
||||||
msg *types.FetchMessageBodyPart) error {
|
msg *types.FetchMessageBodyPart,
|
||||||
|
) error {
|
||||||
// get reader
|
// get reader
|
||||||
m, err := w.c.Message(*w.selected, msg.Uid)
|
m, err := w.c.Message(*w.selected, msg.Uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func createMailboxContainer(path string) (*mailboxContainer, error) {
|
func createMailboxContainer(path string) (*mailboxContainer, error) {
|
||||||
|
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -99,7 +99,8 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
w.folder = w.data.Create(w.name)
|
w.folder = w.data.Create(w.name)
|
||||||
w.worker.PostMessage(&types.Done{
|
w.worker.PostMessage(&types.Done{
|
||||||
Message: types.RespondTo(&types.CreateDirectory{})}, nil)
|
Message: types.RespondTo(&types.CreateDirectory{}),
|
||||||
|
}, nil)
|
||||||
}
|
}
|
||||||
w.worker.PostMessage(&types.DirectoryInfo{
|
w.worker.PostMessage(&types.DirectoryInfo{
|
||||||
Info: w.data.DirectoryInfo(msg.Directory),
|
Info: w.data.DirectoryInfo(msg.Directory),
|
||||||
|
@ -338,7 +339,8 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
folder = w.data.Create(msg.Destination)
|
folder = w.data.Create(msg.Destination)
|
||||||
w.worker.PostMessage(&types.Done{
|
w.worker.PostMessage(&types.Done{
|
||||||
Message: types.RespondTo(&types.CreateDirectory{})}, nil)
|
Message: types.RespondTo(&types.CreateDirectory{}),
|
||||||
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := folder.Append(msg.Reader, msg.Flags); err != nil {
|
if err := folder.Append(msg.Reader, msg.Flags); err != nil {
|
||||||
|
|
|
@ -61,9 +61,9 @@ func (db *DB) connect(writable bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//withConnection calls callback on the DB object, cleaning up upon return.
|
// withConnection calls callback on the DB object, cleaning up upon return.
|
||||||
//the error returned is from the connection attempt, if not successful,
|
// the error returned is from the connection attempt, if not successful,
|
||||||
//or from the callback otherwise.
|
// or from the callback otherwise.
|
||||||
func (db *DB) withConnection(writable bool, cb func(*notmuch.DB) error) error {
|
func (db *DB) withConnection(writable bool, cb func(*notmuch.DB) error) error {
|
||||||
too_old := time.Now().After(db.lastOpenTime.Add(MAX_DB_AGE))
|
too_old := time.Now().After(db.lastOpenTime.Add(MAX_DB_AGE))
|
||||||
if db.db == nil || writable || too_old {
|
if db.db == nil || writable || too_old {
|
||||||
|
@ -104,8 +104,8 @@ func (db *DB) ListTags() ([]string, error) {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//getQuery returns a query based on the provided query string.
|
// getQuery returns a query based on the provided query string.
|
||||||
//It also configures the query as specified on the worker
|
// It also configures the query as specified on the worker
|
||||||
func (db *DB) newQuery(ndb *notmuch.DB, query string) (*notmuch.Query, error) {
|
func (db *DB) newQuery(ndb *notmuch.DB, query string) (*notmuch.Query, error) {
|
||||||
q := ndb.NewQuery(query)
|
q := ndb.NewQuery(query)
|
||||||
q.SetExcludeScheme(notmuch.EXCLUDE_ALL)
|
q.SetExcludeScheme(notmuch.EXCLUDE_ALL)
|
||||||
|
@ -225,7 +225,8 @@ func (db *DB) MsgTags(key string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) msgModify(key string,
|
func (db *DB) msgModify(key string,
|
||||||
cb func(*notmuch.Message) error) error {
|
cb func(*notmuch.Message) error,
|
||||||
|
) error {
|
||||||
err := db.withConnection(true, func(ndb *notmuch.DB) error {
|
err := db.withConnection(true, func(ndb *notmuch.DB) error {
|
||||||
msg, err := ndb.FindMessage(key)
|
msg, err := ndb.FindMessage(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -281,7 +282,8 @@ func (db *DB) KeyFromUid(uid uint32) (string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) enumerateThread(nt *notmuch.Threads,
|
func (db *DB) enumerateThread(nt *notmuch.Threads,
|
||||||
valid map[string]struct{}) ([]*types.Thread, error) {
|
valid map[string]struct{},
|
||||||
|
) ([]*types.Thread, error) {
|
||||||
var res []*types.Thread
|
var res []*types.Thread
|
||||||
var thread *notmuch.Thread
|
var thread *notmuch.Thread
|
||||||
for nt.Next(&thread) {
|
for nt.Next(&thread) {
|
||||||
|
@ -292,7 +294,8 @@ func (db *DB) enumerateThread(nt *notmuch.Threads,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) makeThread(parent *types.Thread, msgs *notmuch.Messages,
|
func (db *DB) makeThread(parent *types.Thread, msgs *notmuch.Messages,
|
||||||
valid map[string]struct{}) *types.Thread {
|
valid map[string]struct{},
|
||||||
|
) *types.Thread {
|
||||||
var lastSibling *types.Thread
|
var lastSibling *types.Thread
|
||||||
var msg *notmuch.Message
|
var msg *notmuch.Message
|
||||||
for msgs.Next(&msg) {
|
for msgs.Next(&msg) {
|
||||||
|
|
|
@ -160,16 +160,16 @@ func (m *Message) Filename() (string, error) {
|
||||||
return m.db.MsgFilename(m.key)
|
return m.db.MsgFilename(m.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddTag adds a single tag.
|
// AddTag adds a single tag.
|
||||||
//Consider using *Message.ModifyTags for multiple additions / removals
|
// Consider using *Message.ModifyTags for multiple additions / removals
|
||||||
//instead of looping over a tag array
|
// instead of looping over a tag array
|
||||||
func (m *Message) AddTag(tag string) error {
|
func (m *Message) AddTag(tag string) error {
|
||||||
return m.ModifyTags([]string{tag}, nil)
|
return m.ModifyTags([]string{tag}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//RemoveTag removes a single tag.
|
// RemoveTag removes a single tag.
|
||||||
//Consider using *Message.ModifyTags for multiple additions / removals
|
// Consider using *Message.ModifyTags for multiple additions / removals
|
||||||
//instead of looping over a tag array
|
// instead of looping over a tag array
|
||||||
func (m *Message) RemoveTag(tag string) error {
|
func (m *Message) RemoveTag(tag string) error {
|
||||||
return m.ModifyTags(nil, []string{tag})
|
return m.ModifyTags(nil, []string{tag})
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,10 @@ type worker struct {
|
||||||
// NewWorker creates a new notmuch worker with the provided worker.
|
// NewWorker creates a new notmuch worker with the provided worker.
|
||||||
func NewWorker(w *types.Worker) (types.Backend, error) {
|
func NewWorker(w *types.Worker) (types.Backend, error) {
|
||||||
events := make(chan eventType, 20)
|
events := make(chan eventType, 20)
|
||||||
return &worker{w: w,
|
return &worker{
|
||||||
nmEvents: events}, nil
|
w: w,
|
||||||
|
nmEvents: events,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run starts the worker's message handling loop.
|
// Run starts the worker's message handling loop.
|
||||||
|
@ -92,6 +94,7 @@ func (w *worker) err(msg types.WorkerMessage, err error) {
|
||||||
Error: err,
|
Error: err,
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) handleMessage(msg types.WorkerMessage) error {
|
func (w *worker) handleMessage(msg types.WorkerMessage) error {
|
||||||
if w.setupErr != nil {
|
if w.setupErr != nil {
|
||||||
// only configure can recover from a config error, bail for everything else
|
// only configure can recover from a config error, bail for everything else
|
||||||
|
@ -211,12 +214,14 @@ func (w *worker) handleListDirectories(msg *types.ListDirectories) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) gatherDirectoryInfo(name string, query string) (
|
func (w *worker) gatherDirectoryInfo(name string, query string) (
|
||||||
*types.DirectoryInfo, error) {
|
*types.DirectoryInfo, error,
|
||||||
|
) {
|
||||||
return w.buildDirInfo(name, query, false)
|
return w.buildDirInfo(name, query, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) buildDirInfo(name string, query string, skipSort bool) (
|
func (w *worker) buildDirInfo(name string, query string, skipSort bool) (
|
||||||
*types.DirectoryInfo, error) {
|
*types.DirectoryInfo, error,
|
||||||
|
) {
|
||||||
count, err := w.db.QueryCountMessages(query)
|
count, err := w.db.QueryCountMessages(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -254,8 +259,8 @@ func (w *worker) emitDirectoryInfo(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//queryFromName either returns the friendly ID if aliased or the name itself
|
// queryFromName either returns the friendly ID if aliased or the name itself
|
||||||
//assuming it to be the query
|
// assuming it to be the query
|
||||||
func (w *worker) queryFromName(name string) string {
|
func (w *worker) queryFromName(name string) string {
|
||||||
// try the friendly name first, if that fails assume it's a query
|
// try the friendly name first, if that fails assume it's a query
|
||||||
q, ok := w.nameQueryMap[name]
|
q, ok := w.nameQueryMap[name]
|
||||||
|
@ -281,7 +286,8 @@ func (w *worker) handleOpenDirectory(msg *types.OpenDirectory) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) handleFetchDirectoryContents(
|
func (w *worker) handleFetchDirectoryContents(
|
||||||
msg *types.FetchDirectoryContents) error {
|
msg *types.FetchDirectoryContents,
|
||||||
|
) error {
|
||||||
w.currentSortCriteria = msg.SortCriteria
|
w.currentSortCriteria = msg.SortCriteria
|
||||||
err := w.emitDirectoryContents(msg)
|
err := w.emitDirectoryContents(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -292,7 +298,8 @@ func (w *worker) handleFetchDirectoryContents(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) handleFetchDirectoryThreaded(
|
func (w *worker) handleFetchDirectoryThreaded(
|
||||||
msg *types.FetchDirectoryThreaded) error {
|
msg *types.FetchDirectoryThreaded,
|
||||||
|
) error {
|
||||||
// w.currentSortCriteria = msg.SortCriteria
|
// w.currentSortCriteria = msg.SortCriteria
|
||||||
err := w.emitDirectoryThreaded(msg)
|
err := w.emitDirectoryThreaded(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -303,7 +310,8 @@ func (w *worker) handleFetchDirectoryThreaded(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) handleFetchMessageHeaders(
|
func (w *worker) handleFetchMessageHeaders(
|
||||||
msg *types.FetchMessageHeaders) error {
|
msg *types.FetchMessageHeaders,
|
||||||
|
) error {
|
||||||
for _, uid := range msg.Uids {
|
for _, uid := range msg.Uids {
|
||||||
m, err := w.msgFromUid(uid)
|
m, err := w.msgFromUid(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -350,8 +358,8 @@ func (w *worker) msgFromUid(uid uint32) (*Message, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) handleFetchMessageBodyPart(
|
func (w *worker) handleFetchMessageBodyPart(
|
||||||
msg *types.FetchMessageBodyPart) error {
|
msg *types.FetchMessageBodyPart,
|
||||||
|
) error {
|
||||||
m, err := w.msgFromUid(msg.Uid)
|
m, err := w.msgFromUid(msg.Uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Errorf("could not get message %d: %v", msg.Uid, err)
|
logging.Errorf("could not get message %d: %v", msg.Uid, err)
|
||||||
|
@ -542,7 +550,8 @@ func (w *worker) loadQueryMap(acctConfig *config.AccountConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) loadExcludeTags(
|
func (w *worker) loadExcludeTags(
|
||||||
acctConfig *config.AccountConfig) []string {
|
acctConfig *config.AccountConfig,
|
||||||
|
) []string {
|
||||||
raw, ok := acctConfig.Params["exclude-tags"]
|
raw, ok := acctConfig.Params["exclude-tags"]
|
||||||
if !ok {
|
if !ok {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
@ -598,7 +607,8 @@ func (w *worker) emitDirectoryThreaded(parent types.WorkerMessage) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) emitMessageInfo(m *Message,
|
func (w *worker) emitMessageInfo(m *Message,
|
||||||
parent types.WorkerMessage) error {
|
parent types.WorkerMessage,
|
||||||
|
) error {
|
||||||
info, err := m.MessageInfo()
|
info, err := m.MessageInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get MessageInfo: %v", err)
|
return fmt.Errorf("could not get MessageInfo: %v", err)
|
||||||
|
@ -620,7 +630,8 @@ func (w *worker) emitLabelList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) sort(uids []uint32,
|
func (w *worker) sort(uids []uint32,
|
||||||
criteria []*types.SortCriterion) ([]uint32, error) {
|
criteria []*types.SortCriterion,
|
||||||
|
) ([]uint32, error) {
|
||||||
if len(criteria) == 0 {
|
if len(criteria) == 0 {
|
||||||
return uids, nil
|
return uids, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ var ErrSkipThread = errors.New("skip this Thread")
|
||||||
|
|
||||||
type NewThreadWalkFn func(t *Thread, level int, currentErr error) error
|
type NewThreadWalkFn func(t *Thread, level int, currentErr error) error
|
||||||
|
|
||||||
//Implement interface to be able to sort threads by newest (max UID)
|
// Implement interface to be able to sort threads by newest (max UID)
|
||||||
type ByUID []*Thread
|
type ByUID []*Thread
|
||||||
|
|
||||||
func getMaxUID(thread *Thread) uint32 {
|
func getMaxUID(thread *Thread) uint32 {
|
||||||
|
@ -113,9 +113,11 @@ func getMaxUID(thread *Thread) uint32 {
|
||||||
func (s ByUID) Len() int {
|
func (s ByUID) Len() int {
|
||||||
return len(s)
|
return len(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ByUID) Swap(i, j int) {
|
func (s ByUID) Swap(i, j int) {
|
||||||
s[i], s[j] = s[j], s[i]
|
s[i], s[j] = s[j], s[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ByUID) Less(i, j int) bool {
|
func (s ByUID) Less(i, j int) bool {
|
||||||
maxUID_i := getMaxUID(s[i])
|
maxUID_i := getMaxUID(s[i])
|
||||||
maxUID_j := getMaxUID(s[j])
|
maxUID_j := getMaxUID(s[j])
|
||||||
|
|
|
@ -85,7 +85,7 @@ func TestNewWalk(t *testing.T) {
|
||||||
prefix = append(prefix, " ")
|
prefix = append(prefix, " ")
|
||||||
}
|
}
|
||||||
} else if lvl < lastLevel {
|
} else if lvl < lastLevel {
|
||||||
//ascended, need to trim the prefix layers
|
// ascended, need to trim the prefix layers
|
||||||
diff := lastLevel - lvl
|
diff := lastLevel - lvl
|
||||||
prefix = prefix[:len(prefix)-diff]
|
prefix = prefix[:len(prefix)-diff]
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ func (worker *Worker) setId(msg WorkerMessage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (worker *Worker) PostAction(msg WorkerMessage, cb func(msg WorkerMessage)) {
|
func (worker *Worker) PostAction(msg WorkerMessage, cb func(msg WorkerMessage)) {
|
||||||
|
|
||||||
worker.setId(msg)
|
worker.setId(msg)
|
||||||
|
|
||||||
if resp := msg.InResponseTo(); resp != nil {
|
if resp := msg.InResponseTo(); resp != nil {
|
||||||
|
@ -52,8 +51,8 @@ func (worker *Worker) PostAction(msg WorkerMessage, cb func(msg WorkerMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (worker *Worker) PostMessage(msg WorkerMessage,
|
func (worker *Worker) PostMessage(msg WorkerMessage,
|
||||||
cb func(msg WorkerMessage)) {
|
cb func(msg WorkerMessage),
|
||||||
|
) {
|
||||||
worker.setId(msg)
|
worker.setId(msg)
|
||||||
|
|
||||||
if resp := msg.InResponseTo(); resp != nil {
|
if resp := msg.InResponseTo(); resp != nil {
|
||||||
|
|
Loading…
Reference in a new issue