~sircmpwn/aerc

Fix a couple of issues with the style patch. v3 PROPOSED

Kalyan Sriram: 1
 Fix a couple of issues with the style patch.

 33 files changed, 73 insertions(+), 137 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/aerc/patches/11759/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH v3] Fix a couple of issues with the style patch. Export this patch

To Reto and anyone else looking at this:
Thanks a lot for taking a look at my patch. This is my first mailing
list patch, and I'm new to aerc source, so thanks for understanding.

I implemented the changes requested by Reto, namely
* Formatting and typo fixes
* Removed the styleset hardcoding
* Hardcode expiry duration for PushError and PushSuccess
* Other formatting

Take a look at the commit message and diffs for more details.

Keep in mind that what I said in an earlier email is no longer true; you
MUST run `make install` for aerc to continue working as it will expect a
default styleset in the install location.
---
 commands/account/mkdir.go            |  2 +-
 commands/account/view.go             |  3 +--
 commands/compose/attach.go           |  9 +++----
 commands/compose/detach.go           |  3 +--
 commands/compose/postpone.go         |  6 ++---
 commands/compose/send.go             |  4 +--
 commands/exec.go                     |  4 +--
 commands/msg/archive.go              |  2 +-
 commands/msg/copy.go                 |  2 +-
 commands/msg/delete.go               |  6 ++---
 commands/msg/forward.go              |  3 +--
 commands/msg/modify-labels.go        |  2 +-
 commands/msg/move.go                 |  2 +-
 commands/msg/pipe.go                 |  6 ++---
 commands/msg/read.go                 |  2 +-
 commands/msg/recall.go               |  3 +--
 commands/msg/reply.go                |  3 +--
 commands/msgview/next.go             |  4 +--
 commands/msgview/open.go             |  6 ++---
 commands/msgview/save.go             |  2 +-
 commands/term.go                     |  3 +--
 commands/util.go                     |  4 +--
 config/config.go                     | 19 ++------------
 config/style.go                      | 37 ----------------------------
 widgets/account-wizard.go            |  7 +++---
 widgets/account.go                   |  5 ++--
 widgets/aerc.go                      | 16 ++++++------
 widgets/compose.go                   |  5 ++--
 widgets/getpasswd.go                 |  3 ++-
 widgets/msglist.go                   |  3 +--
 widgets/{selecter.go => selector.go} | 22 ++++++++---------
 widgets/status.go                    |  8 +++---
 widgets/tabhost.go                   |  4 +--
 33 files changed, 73 insertions(+), 137 deletions(-)
 rename widgets/{selecter.go => selector.go} (75%)
diff --git a/commands/account/mkdir.go b/commands/account/mkdir.go
index f99fc01..9d16063 100644
--- a/commands/account/mkdir.go
+++ b/commands/account/mkdir.go
@@ -40,7 +40,7 @@ func (MakeDir) Execute(aerc *widgets.Aerc, args []string) error {
			aerc.PushStatus("Directory created.", 10*time.Second)
			acct.Directories().Select(name)
		case *types.Error:
			aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
			aerc.PushError(" "+msg.Error.Error())
		}
	})
	return nil
diff --git a/commands/account/view.go b/commands/account/view.go
index d4653be..b421666 100644
--- a/commands/account/view.go
+++ b/commands/account/view.go
@@ -2,7 +2,6 @@ package account

import (
	"errors"
	"time"

	"git.sr.ht/~sircmpwn/aerc/lib"
	"git.sr.ht/~sircmpwn/aerc/widgets"
@@ -42,7 +41,7 @@ func (ViewMessage) Execute(aerc *widgets.Aerc, args []string) error {
	lib.NewMessageStoreView(msg, store, aerc.DecryptKeys,
		func(view lib.MessageView, err error) {
			if err != nil {
				aerc.PushError(err.Error(), 10*time.Second)
				aerc.PushError(err.Error())
				return
			}
			viewer := widgets.NewMessageViewer(acct, aerc.Config(), view)
diff --git a/commands/compose/attach.go b/commands/compose/attach.go
index 6b8d72f..294f1b1 100644
--- a/commands/compose/attach.go
+++ b/commands/compose/attach.go
@@ -4,7 +4,6 @@ import (
	"fmt"
	"os"
	"strings"
	"time"

	"git.sr.ht/~sircmpwn/aerc/commands"
	"git.sr.ht/~sircmpwn/aerc/widgets"
@@ -35,23 +34,23 @@ func (Attach) Execute(aerc *widgets.Aerc, args []string) error {

	path, err := homedir.Expand(path)
	if err != nil {
		aerc.PushError(" "+err.Error(), 10*time.Second)
		aerc.PushError(" "+err.Error())
		return err
	}

	pathinfo, err := os.Stat(path)
	if err != nil {
		aerc.PushError(" "+err.Error(), 10*time.Second)
		aerc.PushError(" "+err.Error())
		return err
	} else if pathinfo.IsDir() {
		aerc.PushError("Attachment must be a file, not a directory", 10*time.Second)
		aerc.PushError("Attachment must be a file, not a directory")
		return nil
	}

	composer, _ := aerc.SelectedTab().(*widgets.Composer)
	composer.AddAttachment(path)

	aerc.PushSuccess(fmt.Sprintf("Attached %s", pathinfo.Name()), 10*time.Second)
	aerc.PushSuccess(fmt.Sprintf("Attached %s", pathinfo.Name()))

	return nil
}
diff --git a/commands/compose/detach.go b/commands/compose/detach.go
index 8bc0e88..b48159d 100644
--- a/commands/compose/detach.go
+++ b/commands/compose/detach.go
@@ -3,7 +3,6 @@ package compose
import (
	"fmt"
	"strings"
	"time"

	"git.sr.ht/~sircmpwn/aerc/widgets"
)
@@ -43,7 +42,7 @@ func (Detach) Execute(aerc *widgets.Aerc, args []string) error {
		return err
	}

	aerc.PushSuccess(fmt.Sprintf("Detached %s", path), 10*time.Second)
	aerc.PushSuccess(fmt.Sprintf("Detached %s", path))

	return nil
}
diff --git a/commands/compose/postpone.go b/commands/compose/postpone.go
index 90b6134..bdf3d48 100644
--- a/commands/compose/postpone.go
+++ b/commands/compose/postpone.go
@@ -63,7 +63,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
	go func() {
		errStr := <-errChan
		if errStr != "" {
			aerc.PushError(" "+errStr, 10*time.Second)
			aerc.PushError(" "+errStr)
			return
		}

@@ -71,7 +71,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
		ctr := datacounter.NewWriterCounter(ioutil.Discard)
		err = composer.WriteMessage(header, ctr)
		if err != nil {
			aerc.PushError(errors.Wrap(err, "WriteMessage").Error(), 10*time.Second)
			aerc.PushError(errors.Wrap(err, "WriteMessage").Error())
			composer.Close()
			return
		}
@@ -90,7 +90,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
				r.Close()
				composer.Close()
			case *types.Error:
				aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
				aerc.PushError(" "+msg.Error.Error())
				r.Close()
				composer.Close()
			}
diff --git a/commands/compose/send.go b/commands/compose/send.go
index cbcc876..1177371 100644
--- a/commands/compose/send.go
+++ b/commands/compose/send.go
@@ -224,7 +224,7 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
		aerc.PushStatus("Sending...", 10*time.Second)
		nbytes, err := sendAsync()
		if err != nil {
			aerc.PushError(" " + err.Error(), 10*time.Second)
			aerc.PushError(" " + err.Error())
			return
		}
		if config.CopyTo != "" {
@@ -245,7 +245,7 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error {
					composer.SetSent()
					composer.Close()
				case *types.Error:
					aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
					aerc.PushError(" "+msg.Error.Error())
					r.Close()
					composer.Close()
				}
diff --git a/commands/exec.go b/commands/exec.go
index 0a5470d..3dafe49 100644
--- a/commands/exec.go
+++ b/commands/exec.go
@@ -31,12 +31,12 @@ func (ExecCmd) Execute(aerc *widgets.Aerc, args []string) error {
	go func() {
		err := cmd.Run()
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		} else {
			if cmd.ProcessState.ExitCode() != 0 {
				aerc.PushError(fmt.Sprintf(
					"%s: completed with status %d", args[0],
					cmd.ProcessState.ExitCode()), 10*time.Second)
					cmd.ProcessState.ExitCode()))
			} else {
				aerc.PushStatus(fmt.Sprintf(
					"%s: completed with status %d", args[0],
diff --git a/commands/msg/archive.go b/commands/msg/archive.go
index 8d42308..1018fd7 100644
--- a/commands/msg/archive.go
+++ b/commands/msg/archive.go
@@ -86,7 +86,7 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
			case *types.Done:
				wg.Done()
			case *types.Error:
				aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
				aerc.PushError(" "+msg.Error.Error())
				success = false
				wg.Done()
			}
diff --git a/commands/msg/copy.go b/commands/msg/copy.go
index e822c5c..49614f4 100644
--- a/commands/msg/copy.go
+++ b/commands/msg/copy.go
@@ -60,7 +60,7 @@ func (Copy) Execute(aerc *widgets.Aerc, args []string) error {
			case *types.Done:
				aerc.PushStatus("Messages copied.", 10*time.Second)
			case *types.Error:
				aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
				aerc.PushError(" "+msg.Error.Error())
			}
		})
	return nil
diff --git a/commands/msg/delete.go b/commands/msg/delete.go
index 26f0df8..6eb35eb 100644
--- a/commands/msg/delete.go
+++ b/commands/msg/delete.go
@@ -47,10 +47,10 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
		case *types.Done:
			aerc.PushStatus("Messages deleted.", 10*time.Second)
		case *types.Error:
			aerc.PushError(" " + msg.Error.Error(), 10*time.Second)
			aerc.PushError(" " + msg.Error.Error())
		case *types.Unsupported:
			// notmuch doesn't support it, we want the user to know
			aerc.PushError(" error, unsupported for this worker", 10*time.Second)
			aerc.PushError(" error, unsupported for this worker")
		}
	})

@@ -71,7 +71,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
			lib.NewMessageStoreView(next, store, aerc.DecryptKeys,
				func(view lib.MessageView, err error) {
					if err != nil {
						aerc.PushError(err.Error(), 10*time.Second)
						aerc.PushError(err.Error())
						return
					}
					nextMv := widgets.NewMessageViewer(acct, aerc.Config(), view)
diff --git a/commands/msg/forward.go b/commands/msg/forward.go
index 61e3a24..ab55877 100644
--- a/commands/msg/forward.go
+++ b/commands/msg/forward.go
@@ -9,7 +9,6 @@ import (
	"os"
	"path"
	"strings"
	"time"

	"git.sr.ht/~sircmpwn/aerc/models"
	"git.sr.ht/~sircmpwn/aerc/widgets"
@@ -84,7 +83,7 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
		composer, err := widgets.NewComposer(aerc, acct, aerc.Config(), acct.AccountConfig(),
			acct.Worker(), template, defaults, original)
		if err != nil {
			aerc.PushError("Error: "+err.Error(), 10*time.Second)
			aerc.PushError("Error: "+err.Error())
			return nil, err
		}

diff --git a/commands/msg/modify-labels.go b/commands/msg/modify-labels.go
index d74aece..d68a895 100644
--- a/commands/msg/modify-labels.go
+++ b/commands/msg/modify-labels.go
@@ -58,7 +58,7 @@ func (ModifyLabels) Execute(aerc *widgets.Aerc, args []string) error {
		case *types.Done:
			aerc.PushStatus("labels updated", 10*time.Second)
		case *types.Error:
			aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
			aerc.PushError(" "+msg.Error.Error())
		}
	})
	return nil
diff --git a/commands/msg/move.go b/commands/msg/move.go
index 1a8f949..820217e 100644
--- a/commands/msg/move.go
+++ b/commands/msg/move.go
@@ -71,7 +71,7 @@ func (Move) Execute(aerc *widgets.Aerc, args []string) error {
		case *types.Done:
			aerc.PushStatus("Message moved to "+joinedArgs, 10*time.Second)
		case *types.Error:
			aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
			aerc.PushError(" "+msg.Error.Error())
		}
	})
	return nil
diff --git a/commands/msg/pipe.go b/commands/msg/pipe.go
index 5a0b120..2bc6b62 100644
--- a/commands/msg/pipe.go
+++ b/commands/msg/pipe.go
@@ -75,7 +75,7 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
	doTerm := func(reader io.Reader, name string) {
		term, err := commands.QuickTerm(aerc, cmd, reader)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
			return
		}
		aerc.NewTab(term, name)
@@ -93,12 +93,12 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
		}()
		err = ecmd.Run()
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		} else {
			if ecmd.ProcessState.ExitCode() != 0 {
				aerc.PushError(fmt.Sprintf(
					"%s: completed with status %d", cmd[0],
					ecmd.ProcessState.ExitCode()), 10*time.Second)
					ecmd.ProcessState.ExitCode()))
			} else {
				aerc.PushStatus(fmt.Sprintf(
					"%s: completed with status %d", cmd[0],
diff --git a/commands/msg/read.go b/commands/msg/read.go
index a0b68bc..21d7673 100644
--- a/commands/msg/read.go
+++ b/commands/msg/read.go
@@ -187,7 +187,7 @@ func submitFlagChange(aerc *widgets.Aerc, store *lib.MessageStore,
		case *types.Done:
			wg.Done()
		case *types.Error:
			aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
			aerc.PushError(" "+msg.Error.Error())
			*success = false
			wg.Done()
		}
diff --git a/commands/msg/recall.go b/commands/msg/recall.go
index 6c5e973..f24b5df 100644
--- a/commands/msg/recall.go
+++ b/commands/msg/recall.go
@@ -2,7 +2,6 @@ package msg

import (
	"io"
	"time"

	"github.com/emersion/go-message"
	_ "github.com/emersion/go-message/charset"
@@ -92,7 +91,7 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
			}, func(msg types.WorkerMessage) {
				switch msg := msg.(type) {
				case *types.Error:
					aerc.PushError(" "+msg.Error.Error(), 10*time.Second)
					aerc.PushError(" "+msg.Error.Error())
					composer.Close()
				}
			})
diff --git a/commands/msg/reply.go b/commands/msg/reply.go
index 1655052..3340b2f 100644
--- a/commands/msg/reply.go
+++ b/commands/msg/reply.go
@@ -7,7 +7,6 @@ import (
	"io"
	gomail "net/mail"
	"strings"
	"time"

	"git.sr.ht/~sircmpwn/getopt"

@@ -140,7 +139,7 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
		composer, err := widgets.NewComposer(aerc, acct, aerc.Config(),
			acct.AccountConfig(), acct.Worker(), template, defaults, original)
		if err != nil {
			aerc.PushError("Error: "+err.Error(), 10*time.Second)
			aerc.PushError("Error: "+err.Error())
			return err
		}

diff --git a/commands/msgview/next.go b/commands/msgview/next.go
index f9fb3d7..978cf10 100644
--- a/commands/msgview/next.go
+++ b/commands/msgview/next.go
@@ -1,8 +1,6 @@
package msgview

import (
	"time"

	"git.sr.ht/~sircmpwn/aerc/commands/account"
	"git.sr.ht/~sircmpwn/aerc/lib"
	"git.sr.ht/~sircmpwn/aerc/widgets"
@@ -42,7 +40,7 @@ func (NextPrevMsg) Execute(aerc *widgets.Aerc, args []string) error {
	lib.NewMessageStoreView(nextMsg, store, aerc.DecryptKeys,
		func(view lib.MessageView, err error) {
			if err != nil {
				aerc.PushError(err.Error(), 10*time.Second)
				aerc.PushError(err.Error())
				return
			}
			nextMv := widgets.NewMessageViewer(acct, aerc.Config(), view)
diff --git a/commands/msgview/open.go b/commands/msgview/open.go
index b4dfab7..c681f86 100644
--- a/commands/msgview/open.go
+++ b/commands/msgview/open.go
@@ -49,19 +49,19 @@ func (Open) Execute(aerc *widgets.Aerc, args []string) error {

		tmpFile, err := ioutil.TempFile(os.TempDir(), "aerc-*"+extension)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
			return
		}
		defer tmpFile.Close()

		_, err = io.Copy(tmpFile, reader)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
			return
		}

		lib.OpenFile(tmpFile.Name(), func(err error) {
			aerc.PushError(" " + err.Error(), 10*time.Second)
			aerc.PushError(" " + err.Error())
		})

		aerc.PushStatus("Opened", 10*time.Second)
diff --git a/commands/msgview/save.go b/commands/msgview/save.go
index ea1b8f3..ef6bba8 100644
--- a/commands/msgview/save.go
+++ b/commands/msgview/save.go
@@ -128,7 +128,7 @@ func (Save) Execute(aerc *widgets.Aerc, args []string) error {
	go func() {
		err := <-ch
		if err != nil {
			aerc.PushError(fmt.Sprintf("Save failed: %v", err), 10*time.Second)
			aerc.PushError(fmt.Sprintf("Save failed: %v", err))
			return
		}
		aerc.PushStatus("Saved to "+path, 10*time.Second)
diff --git a/commands/term.go b/commands/term.go
index 9023285..c75fda5 100644
--- a/commands/term.go
+++ b/commands/term.go
@@ -2,7 +2,6 @@ package commands

import (
	"os/exec"
	"time"

	"github.com/riywo/loginshell"

@@ -47,7 +46,7 @@ func TermCore(aerc *widgets.Aerc, args []string) error {
	term.OnClose = func(err error) {
		aerc.RemoveTab(term)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
	}
	return nil
diff --git a/commands/util.go b/commands/util.go
index 7c7b6ab..011f419 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -32,7 +32,7 @@ func QuickTerm(aerc *widgets.Aerc, args []string, stdin io.Reader) (*widgets.Ter

	term.OnClose = func(err error) {
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
			// remove the tab on error, otherwise it gets stuck
			aerc.RemoveTab(term)
		} else {
@@ -56,7 +56,7 @@ func QuickTerm(aerc *widgets.Aerc, args []string, stdin io.Reader) (*widgets.Ter

		err := <-status
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
	}

diff --git a/config/config.go b/config/config.go
index 0ccf350..7cd0964 100644
--- a/config/config.go
+++ b/config/config.go
@@ -45,7 +45,7 @@ type UIConfig struct {
	NextMessageOnDelete bool          `ini:"next-message-on-delete"`
	CompletionDelay     time.Duration `ini:"completion-delay"`
	CompletionPopovers  bool          `ini:"completion-popovers"`
	StyleSetDirs        []string      `ini:"stylesets-dirs", delim:":"`
	StyleSetDirs        []string      `ini:"stylesets-dirs" delim:":"`
	StyleSetName        string        `ini:"styleset-name"`
	style               StyleSet
}
@@ -340,11 +340,6 @@ func (config *AercConfig) LoadConfig(file *ini.File) error {
		if err := ui.MapTo(&config.Ui); err != nil {
			return err
		}

		stylesetsDirs := ui.Key("stylesets-dirs").String()
		if stylesetsDirs != "" {
			config.Ui.StyleSetDirs = strings.Split(stylesetsDirs, ":")
		}
	}
	for _, sectionName := range file.SectionStrings() {
		if !strings.Contains(sectionName, "ui:") {
@@ -359,10 +354,6 @@ func (config *AercConfig) LoadConfig(file *ini.File) error {
		if err := uiSection.MapTo(&uiSubConfig); err != nil {
			return err
		}
		stylesetsDirs := uiSection.Key("stylesets-dirs").String()
		if stylesetsDirs != "" {
			uiSubConfig.StyleSetDirs = strings.Split(stylesetsDirs, ":")
		}
		contextualUi :=
			UIConfigContext{
				UiConfig: uiSubConfig,
@@ -650,13 +641,7 @@ func (ui *UIConfig) loadStyleSet(styleSetDirs []string) error {
	ui.style = NewStyleSet()
    err := ui.style.LoadStyleSet(ui.StyleSetName, styleSetDirs)
    if err != nil {
        fmt.Errorf("Error while parsing styleset \"%s\": %s", ui.StyleSetName, err)
        fmt.Printf("Loading default styles")

        err = ui.style.LoadDefaultStyleSet()
        if err != nil {
            return fmt.Errorf("Error while loading default styleset: %s", err)
        }
        return fmt.Errorf("Unable to load default styleset: %s", err)
    }

	return nil
diff --git a/config/style.go b/config/style.go
index dfedf35..7fbc1b1 100644
--- a/config/style.go
+++ b/config/style.go
@@ -95,34 +95,6 @@ type Style struct {
	Reverse   bool
}

var StyleDefaults = []byte(`
*.default=true
*.selected.reverse=toggle

title.reverse=true
header.bold=true

*error.bold=true
error.fg=red
warning.fg=yello
success.fg=green

statusline*.default=true
statusline_default.reverse=true
statusline_error.fg=red
statusline_error.reverse=true

msglist_unread.bold=true

completion_pill.reverse=true

tab.reverse=true
border.reverse=true

selector_focused.reverse=true
selector_chooser.bold=true
`)

func (s Style) Get() tcell.Style {
	return tcell.StyleDefault.
		Foreground(s.Fg).
@@ -386,15 +358,6 @@ func (ss *StyleSet) LoadStyleSet(stylesetName string, stylesetDirs []string) err
    return ss.ParseStyleSet(file)
}

func (ss *StyleSet) LoadDefaultStyleSet() error {
    file, err := ini.Load(StyleDefaults);
    if err != nil {
        return err
    }

    return ss.ParseStyleSet(file)
}

func fnmatchToRegex(pattern string) string {
	n := len(pattern)
	var regex strings.Builder
diff --git a/widgets/account-wizard.go b/widgets/account-wizard.go
index 1921f06..4d25cae 100644
--- a/widgets/account-wizard.go
+++ b/widgets/account-wizard.go
@@ -10,7 +10,6 @@ import (
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/gdamore/tcell"
	"github.com/go-ini/ini"
@@ -429,7 +428,7 @@ func (wizard *AccountWizard) ConfigureTemporaryAccount(temporary bool) {

func (wizard *AccountWizard) errorFor(d ui.Interactive, err error) {
	if d == nil {
		wizard.aerc.PushError(" "+err.Error(), 10*time.Second)
		wizard.aerc.PushError(" "+err.Error())
		wizard.Invalidate()
		return
	}
@@ -444,7 +443,7 @@ func (wizard *AccountWizard) errorFor(d ui.Interactive, err error) {
				wizard.step = step
				wizard.focus = focus
				wizard.Focus(true)
				wizard.aerc.PushError(" "+err.Error(), 10*time.Second)
				wizard.aerc.PushError(" "+err.Error())
				wizard.Invalidate()
				return
			}
@@ -555,7 +554,7 @@ func (wizard *AccountWizard) finish(tutorial bool) {
		term.OnClose = func(err error) {
			wizard.aerc.RemoveTab(term)
			if err != nil {
				wizard.aerc.PushError(" "+err.Error(), 10*time.Second)
				wizard.aerc.PushError(" "+err.Error())
			}
		}
	}
diff --git a/widgets/account.go b/widgets/account.go
index 6567638..8d89eef 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -4,7 +4,6 @@ import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/gdamore/tcell"

@@ -273,7 +272,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
		acct.labels = msg.Labels
	case *types.Error:
		acct.logger.Printf("%v", msg.Error)
		acct.aerc.PushError(fmt.Sprintf("%v", msg.Error), 10*time.Second)
		acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
	}
}

@@ -283,7 +282,7 @@ func (acct *AccountView) getSortCriteria() []*types.SortCriterion {
	}
	criteria, err := sort.GetSortCriteria(acct.UiConfig().Sort)
	if err != nil {
		acct.aerc.PushError(" ui.sort: "+err.Error(), 10*time.Second)
		acct.aerc.PushError(" ui.sort: "+err.Error())
		return nil
	}
	return criteria
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 367335d..ac532ac 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -390,12 +390,12 @@ func (aerc *Aerc) PushStatus(text string, expiry time.Duration) *StatusMessage {
	return aerc.statusline.Push(text, expiry)
}

func (aerc *Aerc) PushError(text string, expiry time.Duration) *StatusMessage {
	return aerc.statusline.PushError(text, expiry)
func (aerc *Aerc) PushError(text string) *StatusMessage {
	return aerc.statusline.PushError(text)
}

func (aerc *Aerc) PushSuccess(text string, expiry time.Duration) *StatusMessage {
	return aerc.statusline.PushSuccess(text, expiry)
func (aerc *Aerc) PushSuccess(text string) *StatusMessage {
	return aerc.statusline.PushSuccess(text)
}

func (aerc *Aerc) focus(item ui.Interactive) {
@@ -424,11 +424,11 @@ func (aerc *Aerc) BeginExCommand(cmd string) {
	exline := NewExLine(aerc.conf, cmd, func(cmd string) {
		parts, err := shlex.Split(cmd)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
		err = aerc.cmd(parts)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
		// only add to history if this is an unsimulated command,
		// ie one not executed from a keybinding
@@ -452,7 +452,7 @@ func (aerc *Aerc) RegisterPrompt(prompt string, cmd []string) {
		}
		err := aerc.cmd(cmd)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
	}, func(cmd string) []string {
		return nil // TODO: completions
@@ -479,7 +479,7 @@ func (aerc *Aerc) RegisterChoices(choices []Choice) {
		}
		err := aerc.cmd(cmd)
		if err != nil {
			aerc.PushError(" "+err.Error(), 10*time.Second)
			aerc.PushError(" "+err.Error())
		}
	}, func(cmd string) []string {
		return nil // TODO: completions
diff --git a/widgets/compose.go b/widgets/compose.go
index 39e40cd..03c9175 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -73,7 +73,7 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
	templateData := templates.ParseTemplateData(defaults, original)
	cmpl := completer.New(conf.Compose.AddressBookCmd, func(err error) {
		aerc.PushError(
			fmt.Sprintf("could not complete header: %v", err), 10*time.Second)
			fmt.Sprintf("could not complete header: %v", err))
		worker.Logger.Printf("could not complete header: %v", err)
	}, aerc.Logger())
	layout, editors, focusable := buildComposeHeader(aerc, cmpl, defaults)
@@ -261,8 +261,7 @@ func (c *Composer) readSignatureFromFile() []byte {
	signature, err := ioutil.ReadFile(sigFile)
	if err != nil {
		c.aerc.PushError(
			fmt.Sprintf(" Error loading signature from file: %v", sigFile),
			10*time.Second)
			fmt.Sprintf(" Error loading signature from file: %v", sigFile))
		return nil
	}
	return signature
diff --git a/widgets/getpasswd.go b/widgets/getpasswd.go
index b3ea9e0..5a47094 100644
--- a/widgets/getpasswd.go
+++ b/widgets/getpasswd.go
@@ -18,7 +18,8 @@ type GetPasswd struct {
	conf     *config.AercConfig
}

func NewGetPasswd(title string, prompt string, conf *config.AercConfig, cb func(string, error)) *GetPasswd {
func NewGetPasswd(title string, prompt string, conf *config.AercConfig,
    cb func(string, error)) *GetPasswd {
	getpasswd := &GetPasswd{
		callback: cb,
		title:    title,
diff --git a/widgets/msglist.go b/widgets/msglist.go
index a98e79c..e38dd9e 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -4,7 +4,6 @@ import (
	"fmt"
	"log"
	"math"
	"time"

	"github.com/gdamore/tcell"
	"github.com/mattn/go-runewidth"
@@ -222,7 +221,7 @@ func (ml *MessageList) MouseEvent(localX int, localY int, event tcell.Event) {
				lib.NewMessageStoreView(msg, store, ml.aerc.DecryptKeys,
					func(view lib.MessageView, err error) {
						if err != nil {
							ml.aerc.PushError(err.Error(), 10*time.Second)
							ml.aerc.PushError(err.Error())
							return
						}
						viewer := NewMessageViewer(acct, ml.aerc.Config(), view)
diff --git a/widgets/selecter.go b/widgets/selector.go
similarity index 75%
rename from widgets/selecter.go
rename to widgets/selector.go
index d68a8cc..d19d38f 100644
--- a/widgets/selecter.go
+++ b/widgets/selector.go
@@ -7,7 +7,7 @@ import (
	"git.sr.ht/~sircmpwn/aerc/lib/ui"
)

type Selecter struct {
type Selector struct {
	ui.Invalidatable
	chooser  bool
	focused  bool
@@ -19,24 +19,24 @@ type Selecter struct {
	onSelect func(option string)
}

func NewSelecter(options []string, focus int, uiConfig config.UIConfig) *Selecter {
	return &Selecter{
func NewSelector(options []string, focus int, uiConfig config.UIConfig) *Selector {
	return &Selector{
		focus:    focus,
		options:  options,
		uiConfig: uiConfig,
	}
}

func (sel *Selecter) Chooser(chooser bool) *Selecter {
func (sel *Selector) Chooser(chooser bool) *Selector {
	sel.chooser = chooser
	return sel
}

func (sel *Selecter) Invalidate() {
func (sel *Selector) Invalidate() {
	sel.DoInvalidate(sel)
}

func (sel *Selecter) Draw(ctx *ui.Context) {
func (sel *Selector) Draw(ctx *ui.Context) {
	ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ',
		sel.uiConfig.GetStyle(config.STYLE_SELECTOR_DEFAULT))
	x := 2
@@ -54,26 +54,26 @@ func (sel *Selecter) Draw(ctx *ui.Context) {
	}
}

func (sel *Selecter) OnChoose(fn func(option string)) *Selecter {
func (sel *Selector) OnChoose(fn func(option string)) *Selector {
	sel.onChoose = fn
	return sel
}

func (sel *Selecter) OnSelect(fn func(option string)) *Selecter {
func (sel *Selector) OnSelect(fn func(option string)) *Selector {
	sel.onSelect = fn
	return sel
}

func (sel *Selecter) Selected() string {
func (sel *Selector) Selected() string {
	return sel.options[sel.focus]
}

func (sel *Selecter) Focus(focus bool) {
func (sel *Selector) Focus(focus bool) {
	sel.focused = focus
	sel.Invalidate()
}

func (sel *Selecter) Event(event tcell.Event) bool {
func (sel *Selector) Event(event tcell.Event) bool {
	switch event := event.(type) {
	case *tcell.EventKey:
		switch event.Key() {
diff --git a/widgets/status.go b/widgets/status.go
index e3272fe..122ca5f 100644
--- a/widgets/status.go
+++ b/widgets/status.go
@@ -91,14 +91,14 @@ func (status *StatusLine) Push(text string, expiry time.Duration) *StatusMessage
	return msg
}

func (status *StatusLine) PushError(text string, expiry time.Duration) *StatusMessage {
	msg := status.Push(text, expiry)
func (status *StatusLine) PushError(text string) *StatusMessage {
	msg := status.Push(text, 10*time.Second)
	msg.Color(status.uiConfig.GetStyle(config.STYLE_STATUSLINE_ERROR))
	return msg
}

func (status *StatusLine) PushSuccess(text string, expiry time.Duration) *StatusMessage {
	msg := status.Push(text, expiry)
func (status *StatusLine) PushSuccess(text string) *StatusMessage {
	msg := status.Push(text, 10*time.Second)
	msg.Color(status.uiConfig.GetStyle(config.STYLE_STATUSLINE_SUCCESS))
	return msg
}
diff --git a/widgets/tabhost.go b/widgets/tabhost.go
index 1322a0a..28c9be0 100644
--- a/widgets/tabhost.go
+++ b/widgets/tabhost.go
@@ -9,7 +9,7 @@ type TabHost interface {
	SetStatus(status string) *StatusMessage
	SetError(err string) *StatusMessage
	PushStatus(text string, expiry time.Duration) *StatusMessage
	PushError(text string, expiry time.Duration) *StatusMessage
	PushSuccess(text string, expiry time.Duration) *StatusMessage
	PushError(text string) *StatusMessage
	PushSuccess(text string) *StatusMessage
	Beep()
}
-- 
2.27.0

Thanks,
Kalyan
Quick comment regarding the structure of a patch via email:

The mail subject becomes the commit message (without "[.*]"), so make sure
that this makes sense.