package widgets import ( "bufio" "bytes" "fmt" "io" "io/ioutil" "mime" "net/http" "net/textproto" "os" "os/exec" "path/filepath" "strings" "time" "github.com/ProtonMail/go-crypto/openpgp" "github.com/emersion/go-message/mail" "github.com/emersion/go-pgpmail" "github.com/gdamore/tcell/v2" "github.com/mattn/go-runewidth" "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "git.sr.ht/~rjarry/aerc/completer" "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/lib/templates" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" ) type Composer struct { editors map[string]*headerEditor // indexes in lower case (from / cc / bcc) header *mail.Header parent models.OriginalMail // parent of current message, only set if reply acctConfig *config.AccountConfig config *config.AercConfig acct *AccountView aerc *Aerc attachments []string editor *Terminal email *os.File grid *ui.Grid heditors *ui.Grid // from, to, cc display a user can jump to review *reviewMessage worker *types.Worker completer *completer.Completer sign bool encrypt bool layout HeaderLayout focusable []ui.MouseableDrawableInteractive focused int sent bool onClose []func(ti *Composer) width int } func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig, acctConfig *config.AccountConfig, worker *types.Worker, template string, h *mail.Header, orig models.OriginalMail) (*Composer, error) { if h == nil { h = new(mail.Header) } if fl, err := h.AddressList("from"); err != nil || fl == nil { fl, err = mail.ParseAddressList(acctConfig.From) // realistically this blows up way before us during the config loading if err != nil { return nil, err } if fl != nil { h.SetAddressList("from", fl) } } templateData := templates.ParseTemplateData(h, orig) cmpl := completer.New(conf.Compose.AddressBookCmd, func(err error) { aerc.PushError( fmt.Sprintf("could not complete header: %v", err)) worker.Logger.Printf("could not complete header: %v", err) }, aerc.Logger()) email, err := ioutil.TempFile("", "aerc-compose-*.eml") if err != nil { // TODO: handle this better return nil, err } c := &Composer{ acct: acct, acctConfig: acctConfig, aerc: aerc, config: conf, header: h, parent: orig, email: email, worker: worker, // You have to backtab to get to "From", since you usually don't edit it focused: 1, completer: cmpl, } c.buildComposeHeader(aerc, cmpl) if err := c.AddTemplate(template, templateData); err != nil { return nil, err } c.AddSignature() c.updateGrid() c.ShowTerminal() return c, nil } func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) { c.layout = aerc.conf.Compose.HeaderLayout c.editors = make(map[string]*headerEditor) c.focusable = make([]ui.MouseableDrawableInteractive, 0) for i, row := range c.layout { for j, h := range row { h = strings.ToLower(h) c.layout[i][j] = h // normalize to lowercase e := newHeaderEditor(h, c.header, aerc.SelectedAccount().UiConfig()) if aer
#!/usr/bin/python3
"""Run all the tests inside the test/ directory as a test suite."""
if __name__ == '__main__':
import unittest
from test import *
tests = []
for key, val in vars().copy().items():
if key.startswith('tc_'):
tests.extend(v for k,v in vars(val).items() if type(v) == type)
suite = unittest.TestSuite(map(unittest.makeSuite, tests))
unittest.TextTestRunner(verbosity=2).run(suite)