Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aerc for openSUSE:Factory checked in 
at 2025-01-27 20:52:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aerc (Old)
 and      /work/SRC/openSUSE:Factory/.aerc.new.2316 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aerc"

Mon Jan 27 20:52:48 2025 rev:15 rq:1240313 version:0.20.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/aerc/aerc.changes        2025-01-15 
17:44:11.087128926 +0100
+++ /work/SRC/openSUSE:Factory/.aerc.new.2316/aerc.changes      2025-01-27 
20:53:15.405694383 +0100
@@ -1,0 +2,23 @@
+Sat Jan 25 23:44:42 UTC 2025 - Hannes Braun <apple.han...@gmail.com> - 0.20.0
+
+- Update to upstream version 0.20.0
+  * copy-to now supports multiple destination folders.
+  * All commands that involve composing messages (:compose, :reply, :recall,
+    :unsubscribe and :forward) now have a new -s flag to skip opening the text
+    editor and go directly to the review screen. Previously, this flag was
+    restricted to calendar invitations response commands (:accept,
+    :accept-tentative and :decline).
+  * copy-to-replied now properly works without having copy-to also set.
+  * copy-to-replied creates empty messages when copy-to is also set.
+  * The address-book completion popovers now again appear under the field being
+    completed.
+  * The new-message bell is now rung again for threaded directories as well.
+  * The "default" styleset status line background has been reset to the default
+    color (light or dark, depending on your terminal color scheme) in order to
+    make error, warning or success messages more readable.
+  * Key bindings in the compose review screen are now displayed in the order in
+    which they are defined in the [compose::review] section of binds.conf.
+  * It is now possible to explicitly hide key bindings from the compose review
+    screen by using a special " # -" annotation.
+
+-------------------------------------------------------------------

Old:
----
  aerc-0.19.0.tar.gz

New:
----
  aerc-0.20.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aerc.spec ++++++
--- /var/tmp/diff_new_pack.j2uRwL/_old  2025-01-27 20:53:17.633786216 +0100
+++ /var/tmp/diff_new_pack.j2uRwL/_new  2025-01-27 20:53:17.633786216 +0100
@@ -18,7 +18,7 @@
 
 
 Name:           aerc
-Version:        0.19.0
+Version:        0.20.0
 Release:        0
 Summary:        An email client for terminals
 License:        GPL-3.0-or-later

++++++ aerc-0.19.0.tar.gz -> aerc-0.20.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/.builds/alpine-edge.yml 
new/aerc-0.20.0/.builds/alpine-edge.yml
--- old/aerc-0.19.0/.builds/alpine-edge.yml     2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/.builds/alpine-edge.yml     2025-01-25 21:55:48.000000000 
+0100
@@ -5,6 +5,7 @@
   - go
   - gnupg
   - notmuch-dev
+  - py3-codespell
   - scdoc
   - valgrind
 sources:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/.codespellrc new/aerc-0.20.0/.codespellrc
--- old/aerc-0.19.0/.codespellrc        1970-01-01 01:00:00.000000000 +0100
+++ new/aerc-0.20.0/.codespellrc        2025-01-25 21:55:48.000000000 +0100
@@ -0,0 +1,27 @@
+# ex: ft=dosini
+
+[codespell]
+quiet-level = 35
+skip =
+       *.1,
+       *.5,
+       *.7,
+       *log*,
+       *.log*,
+       .changelog.md,
+       .env,
+       contrib/aerc.desktop,
+       filters/vectors/*,
+       tags,
+ignore-words-list =
+       DeVault,
+       Fo,
+       THRID,
+       fo,
+       fpr,
+       froms,
+       localY,
+       ment,
+       struc,
+       te,
+       thrid,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/.gitignore new/aerc-0.20.0/.gitignore
--- old/aerc-0.19.0/.gitignore  2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/.gitignore  2025-01-25 21:55:48.000000000 +0100
@@ -1,15 +1,14 @@
-.go
-/aerc2
 /aerc
 /aerc.debug
 /wrap
 /colorize
 /linters.so
-*.log*
-*.1
-*.5
-*.7
+/*log*
+/*.log*
+/*.1
+/*.5
+/*.7
 /.env
 /.changelog.md
-aerc-release-stats.png
-tags
+/aerc-release-stats.png
+/tags
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/CHANGELOG.md new/aerc-0.20.0/CHANGELOG.md
--- old/aerc-0.19.0/CHANGELOG.md        2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/CHANGELOG.md        2025-01-25 21:55:48.000000000 +0100
@@ -3,6 +3,39 @@
 All notable changes to aerc will be documented in this file.
 The format is based on [Keep a 
Changelog](https://keepachangelog.com/en/1.0.0/).
 
+## [0.20.0](https://git.sr.ht/~rjarry/aerc/refs/0.20.0) - 2025-01-25
+
+### Added
+
+- `copy-to` now supports multiple destination folders.
+- All commands that involve composing messages (`:compose`, `:reply`,
+  `:recall`, `:unsubscribe` and `:forward`) now have a new `-s` flag to skip
+  opening the text editor and go directly to the review screen. Previously,
+  this flag was restricted to calendar invitations response commands
+  (`:accept`, `:accept-tentative` and `:decline`).
+
+### Fixed
+
+- `copy-to-replied` now properly works without having `copy-to` also set.
+- `copy-to-replied` creates empty messages when `copy-to` is also set.
+- The address-book completion popovers now again appear under the field being
+  completed.
+- The new-message bell is now rung again for threaded directories as well.
+
+### Changed
+
+- The `default` styleset status line background has been reset to the default
+  color (light or dark, depending on your terminal color scheme) in order to
+  make error, warning or success messages more readable.
+- Key bindings in the compose review screen are now displayed in the order in
+  which they are defined in the `[compose::review]` section of `binds.conf`.
+- It is now possible to explicitly hide key bindings from the compose review
+  screen by using a special ` # -` annotation.
+
+### Closed Tickets
+
+- [#296: :compose: add flag to go directly to review 
screen](https://todo.sr.ht/~rjarry/aerc/296)
+
 ## [0.19.0](https://git.sr.ht/~rjarry/aerc/refs/0.19.0) - 2025-01-14
 
 ### Added
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/GNUmakefile new/aerc-0.20.0/GNUmakefile
--- old/aerc-0.19.0/GNUmakefile 2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/GNUmakefile 2025-01-25 21:55:48.000000000 +0100
@@ -1,6 +1,6 @@
 # variables that can be changed by users
 #
-VERSION ?= $(shell git describe --long --abbrev=12 --tags --dirty 2>/dev/null 
|| echo 0.19.0)
+VERSION ?= $(shell git describe --long --abbrev=12 --tags --dirty 2>/dev/null 
|| echo 0.20.0)
 DATE ?= $(shell date +%Y-%m-%d)
 PREFIX ?= /usr/local
 BINDIR ?= $(PREFIX)/bin
@@ -57,6 +57,7 @@
        @$(GO) run mvdan.cc/gofumpt@$(gofumpt_tag) -d . | grep ^ \
                && echo The above files need to be formatted, please run make 
fmt && exit 1 \
                || echo all files formatted.
+       codespell *
        $(GO) run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2 
run \
                $$(echo $(GOFLAGS) | sed s/-tags=/--build-tags=/)
        $(GO) run $(GOFLAGS) contrib/linters.go ./...
@@ -84,7 +85,7 @@
 
 .PHONY: clean
 clean:
-       $(RM) $(docs) aerc $(cfilters) linters.so
+       $(RM) $(docs) aerc $(cfilters)
 
 # Dependencies are added dynamically to the "install" rule with macros
 .PHONY: install
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/README.md new/aerc-0.20.0/README.md
--- old/aerc-0.19.0/README.md   2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/README.md   2025-01-25 21:55:48.000000000 +0100
@@ -46,6 +46,7 @@
 - 
[aerc-stylesets(7)](https://git.sr.ht/~rjarry/aerc/tree/master/item/doc/aerc-stylesets.7.scd)
 - 
[aerc-templates(7)](https://git.sr.ht/~rjarry/aerc/tree/master/item/doc/aerc-templates.7.scd)
 - 
[aerc-tutorial(7)](https://git.sr.ht/~rjarry/aerc/tree/master/item/doc/aerc-tutorial.7.scd)
+- 
[carddav-query(1)](https://git.sr.ht/~rjarry/aerc/tree/master/item/doc/carddav-query.1.scd)
 
 User contributions and integration with external tools:
 
@@ -63,6 +64,7 @@
 - [Fedora](https://packages.fedoraproject.org/pkgs/aerc/aerc/)
 - [openSUSE](https://build.opensuse.org/package/show/openSUSE:Factory/aerc)
 - [macOS through Homebrew](https://formulae.brew.sh/formula/aerc)
+- [Slackware](https://slackbuilds.org/result/?search=aerc)
 
 And likely other platforms.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/app/aerc.go new/aerc-0.20.0/app/aerc.go
--- old/aerc-0.19.0/app/aerc.go 2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/app/aerc.go 2025-01-25 21:55:48.000000000 +0100
@@ -836,7 +836,7 @@
        acctConf.Default = "INBOX"
        acctConf.Archive = "Archive"
        acctConf.Postpone = "Drafts"
-       acctConf.CopyTo = "Sent"
+       acctConf.CopyTo = []string{"Sent"}
 
        defer ui.Invalidate()
 
@@ -938,7 +938,7 @@
        return key.Matches(exKey.Key, exKey.Modifiers)
 }
 
-// CmdFallbackSearch checks cmds for the first executable availabe in PATH. An 
error is
+// CmdFallbackSearch checks cmds for the first executable available in PATH. 
An error is
 // returned if none are found
 func CmdFallbackSearch(cmds []string, silent bool) (string, error) {
        var tried []string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/app/compose.go 
new/aerc-0.20.0/app/compose.go
--- old/aerc-0.19.0/app/compose.go      2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/app/compose.go      2025-01-25 21:55:48.000000000 +0100
@@ -9,7 +9,6 @@
        "os"
        "os/exec"
        "path/filepath"
-       "sort"
        "strconv"
        "strings"
        "sync"
@@ -888,6 +887,30 @@
        } else if err != nil {
                return nil, fmt.Errorf("mail.ReadMessage: %w", err)
        }
+
+       // merge repeated to, cc, and bcc headers into a single one of each
+       for _, key := range []string{"To", "Cc", "Bcc"} {
+               fields := msg.Header.FieldsByKey(key)
+               if fields.Len() <= 1 {
+                       continue
+               }
+               var addrs []*mail.Address
+               for fields.Next() {
+                       if strings.TrimSpace(fields.Value()) == "" {
+                               continue
+                       }
+                       al, err := mail.ParseAddressList(fields.Value())
+                       if err != nil {
+                               return nil, fmt.Errorf(
+                                       "%s: cannot parse address list: %w", 
key, err)
+                       }
+                       addrs = append(addrs, al...)
+               }
+               msg.Header.SetAddressList(key, addrs)
+               PushWarning(fmt.Sprintf(
+                       "Multiple %s headers found; merged in a single one.", 
key))
+       }
+
        return &msg.Header, nil
 }
 
@@ -1651,64 +1674,58 @@
        grid     *ui.Grid
 }
 
+var defaultAnnotations = map[string]string{
+       ":send<enter>":     "Send",
+       ":edit<enter>":     "Edit (body and headers)",
+       ":attach<space>":   "Add attachment",
+       ":detach<space>":   "Remove attachment",
+       ":postpone<enter>": "Postpone",
+       ":preview<enter>":  "Preview message",
+       ":abort<enter>":    "Abort (discard message, no confirmation)",
+       ":choose -o d discard abort -o p postpone postpone<enter>": "Abort or 
postpone",
+}
+
 func newReviewMessage(composer *Composer, err error) *reviewMessage {
        bindings := config.Binds.ComposeReview.ForAccount(
                composer.acctConfig.Name,
        )
        bindings = bindings.ForFolder(composer.SelectedDirectory())
 
-       const maxInputWidth = 6
        type reviewCmd struct {
+               input      string
                output     string
                annotation string
-               input      string
        }
 
-       reviewCmds := []reviewCmd{
-               {":send<enter>", "Send", ""},
-               {":edit<enter>", "Edit (body and headers)", ""},
-               {":attach<space>", "Add attachment", ""},
-               {":detach<space>", "Remove attachment", ""},
-               {":postpone<enter>", "Postpone", ""},
-               {":preview<enter>", "Preview message", ""},
-               {":abort<enter>", "Abort (discard message, no confirmation)", 
""},
-               {":choose -o d discard abort -o p postpone postpone<enter>", 
"Abort or postpone", ""},
-       }
-       knownCommands := len(reviewCmds)
-       var actions []string
+       var reviewCmds []reviewCmd
+
        for _, binding := range bindings.Bindings {
+               if binding.Annotation == "-" {
+                       // explicitly hidden by user
+                       continue
+               }
+
                inputs := config.FormatKeyStrokes(binding.Input)
                outputs := config.FormatKeyStrokes(binding.Output)
-               found := false
-               for i, rcmd := range reviewCmds {
-                       if outputs == rcmd.output {
-                               found = true
-                               if reviewCmds[i].input == "" {
-                                       reviewCmds[i].input = inputs
-                               } else {
-                                       reviewCmds[i].input += ", " + inputs
-                               }
-                               if binding.Annotation != "" {
-                                       // overwrite default description with
-                                       // user annotations if present
-                                       reviewCmds[i].annotation = 
binding.Annotation
+               annotation := binding.Annotation
+               if annotation == "" {
+                       for i := range reviewCmds {
+                               r := &reviewCmds[i]
+                               if r.output == outputs {
+                                       // aliased action with a different 
binding
+                                       r.input += ", " + inputs
+                                       goto next
                                }
-                               break
                        }
+                       annotation = defaultAnnotations[outputs]
                }
-               if !found {
-                       rcmd := reviewCmd{
-                               output:     outputs,
-                               annotation: binding.Annotation,
-                               input:      inputs,
-                       }
-                       reviewCmds = append(reviewCmds, rcmd)
-               }
+               reviewCmds = append(reviewCmds, reviewCmd{
+                       input:      inputs,
+                       output:     outputs,
+                       annotation: annotation,
+               })
+       next:
        }
-       unknownCommands := reviewCmds[knownCommands:]
-       sort.Slice(unknownCommands, func(i, j int) bool {
-               return unknownCommands[i].input < unknownCommands[j].input
-       })
 
        longest := 0
        for _, rcmd := range reviewCmds {
@@ -1717,17 +1734,17 @@
                }
        }
 
+       const maxInputWidth = 6
        width := longest
        if longest < maxInputWidth {
                width = maxInputWidth
        }
        widthstr := strconv.Itoa(width)
 
+       var actions []string
        for _, rcmd := range reviewCmds {
-               if rcmd.input != "" {
-                       actions = append(actions, fmt.Sprintf("  
%-"+widthstr+"s  %-40s  %s",
-                               rcmd.input, rcmd.annotation, rcmd.output))
-               }
+               actions = append(actions, fmt.Sprintf("  %-"+widthstr+"s  %-40s 
 %s",
+                       rcmd.input, rcmd.annotation, rcmd.output))
        }
 
        spec := []ui.GridSpec{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/account/compose.go 
new/aerc-0.20.0/commands/account/compose.go
--- old/aerc-0.19.0/commands/account/compose.go 2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/account/compose.go 2025-01-25 21:55:48.000000000 
+0100
@@ -16,11 +16,12 @@
 )
 
 type Compose struct {
-       Headers  string `opt:"-H" action:"ParseHeader" desc:"Add the specified 
header to the message."`
-       Template string `opt:"-T" complete:"CompleteTemplate" desc:"Template 
name."`
-       Edit     bool   `opt:"-e" desc:"Force [compose].edit-headers = true."`
-       NoEdit   bool   `opt:"-E" desc:"Force [compose].edit-headers = false."`
-       Body     string `opt:"..." required:"false"`
+       Headers    string `opt:"-H" action:"ParseHeader" desc:"Add the 
specified header to the message."`
+       Template   string `opt:"-T" complete:"CompleteTemplate" desc:"Template 
name."`
+       Edit       bool   `opt:"-e" desc:"Force [compose].edit-headers = true."`
+       NoEdit     bool   `opt:"-E" desc:"Force [compose].edit-headers = 
false."`
+       SkipEditor bool   `opt:"-s" desc:"Skip the editor and go directly to 
the review screen."`
+       Body       string `opt:"..." required:"false"`
 }
 
 func init() {
@@ -87,5 +88,8 @@
                return err
        }
        composer.Tab = app.NewTab(composer, "New email")
+       if c.SkipEditor {
+               composer.Terminal().Close()
+       }
        return nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/compose/send.go 
new/aerc-0.20.0/commands/compose/send.go
--- old/aerc-0.19.0/commands/compose/send.go    2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/compose/send.go    2025-01-25 21:55:48.000000000 
+0100
@@ -25,8 +25,8 @@
 )
 
 type Send struct {
-       Archive string `opt:"-a" action:"ParseArchive" 
metavar:"flat|year|month" complete:"CompleteArchive" desc:"Archive the message 
being replied to."`
-       CopyTo  string `opt:"-t" complete:"CompleteFolders" desc:"Override the 
Copy-To folder."`
+       Archive string   `opt:"-a" action:"ParseArchive" 
metavar:"flat|year|month" complete:"CompleteArchive" desc:"Archive the message 
being replied to."`
+       CopyTo  []string `opt:"-t" complete:"CompleteFolders" 
action:"ParseCopyTo" desc:"Override the Copy-To folders."`
 
        CopyToReplied   bool `opt:"-r" desc:"Save sent message to current 
folder."`
        NoCopyToReplied bool `opt:"-R" desc:"Do not save sent message to 
current folder."`
@@ -66,6 +66,11 @@
        return errors.New("unsupported archive type")
 }
 
+func (o *Send) ParseCopyTo(arg string) error {
+       o.CopyTo = append(o.CopyTo, strings.Split(arg, ",")...)
+       return nil
+}
+
 func (s Send) Execute(args []string) error {
        tab := app.SelectedTab()
        if tab == nil {
@@ -80,7 +85,7 @@
 
        config := composer.Config()
 
-       if s.CopyTo == "" {
+       if len(s.CopyTo) == 0 {
                s.CopyTo = config.CopyTo
        }
        copyToReplied := config.CopyToReplied || (s.CopyToReplied && 
!s.NoCopyToReplied)
@@ -173,7 +178,7 @@
 }
 
 func sendHelper(composer *app.Composer, header *mail.Header, uri *url.URL, 
domain string,
-       from *mail.Address, rcpts []*mail.Address, tabName string, copyTo 
string,
+       from *mail.Address, rcpts []*mail.Address, tabName string, copyTo 
[]string,
        archive string, copyToReplied bool,
 ) {
        // we don't want to block the UI thread while we are sending
@@ -184,7 +189,7 @@
        // enter no-quit mode
        mode.NoQuit()
 
-       var shouldCopy bool = copyTo != "" && !strings.HasPrefix(uri.Scheme, 
"jmap")
+       var shouldCopy bool = (len(copyTo) > 0 || copyToReplied) && 
!strings.HasPrefix(uri.Scheme, "jmap")
        var copyBuf bytes.Buffer
 
        failCh := make(chan error)
@@ -193,9 +198,7 @@
                defer log.PanicHandler()
 
                var folders []string
-               if copyTo != "" {
-                       folders = append(folders, copyTo)
-               }
+               folders = append(folders, copyTo...)
                if copyToReplied && composer.Parent() != nil {
                        folders = append(folders, composer.Parent().Folder)
                }
@@ -234,7 +237,7 @@
                        return
                }
                if shouldCopy {
-                       app.PushStatus("Copying to "+copyTo, 10*time.Second)
+                       app.PushStatus("Copying to copy-to folders", 
10*time.Second)
                        errch := copyToSent(copyTo, copyToReplied, 
copyBuf.Len(),
                                &copyBuf, composer)
                        err = <-errch
@@ -275,7 +278,7 @@
        return rcpts, nil
 }
 
-func copyToSent(dest string, copyToReplied bool, n int, msg io.Reader, 
composer *app.Composer) <-chan error {
+func copyToSent(dests []string, copyToReplied bool, n int, msg *bytes.Buffer, 
composer *app.Composer) <-chan error {
        errCh := make(chan error, 1)
        acct := composer.Account()
        if acct == nil {
@@ -287,27 +290,29 @@
                errCh <- errors.New("No message store selected")
                return errCh
        }
-       store.Append(
-               dest,
-               models.SeenFlag,
-               time.Now(),
-               msg,
-               n,
-               func(msg types.WorkerMessage) {
-                       switch msg := msg.(type) {
-                       case *types.Done:
-                               errCh <- nil
-                       case *types.Error:
-                               errCh <- msg.Error
-                       }
-               },
-       )
+       for _, dest := range dests {
+               store.Append(
+                       dest,
+                       models.SeenFlag,
+                       time.Now(),
+                       bytes.NewReader(msg.Bytes()),
+                       n,
+                       func(msg types.WorkerMessage) {
+                               switch msg := msg.(type) {
+                               case *types.Done:
+                                       errCh <- nil
+                               case *types.Error:
+                                       errCh <- msg.Error
+                               }
+                       },
+               )
+       }
        if copyToReplied && composer.Parent() != nil {
                store.Append(
                        composer.Parent().Folder,
                        models.SeenFlag,
                        time.Now(),
-                       msg,
+                       bytes.NewReader(msg.Bytes()),
                        n,
                        func(msg types.WorkerMessage) {
                                switch msg := msg.(type) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/msg/forward.go 
new/aerc-0.20.0/commands/msg/forward.go
--- old/aerc-0.19.0/commands/msg/forward.go     2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/msg/forward.go     2025-01-25 21:55:48.000000000 
+0100
@@ -30,6 +30,7 @@
        Edit       bool     `opt:"-e" desc:"Force [compose].edit-headers = 
true."`
        NoEdit     bool     `opt:"-E" desc:"Force [compose].edit-headers = 
false."`
        Template   string   `opt:"-T" complete:"CompleteTemplate" 
desc:"Template name."`
+       SkipEditor bool     `opt:"-s" desc:"Skip the editor and go directly to 
the review screen."`
        To         []string `opt:"..." required:"false" complete:"CompleteTo" 
desc:"Recipient from address book."`
 }
 
@@ -106,9 +107,12 @@
                }
 
                composer.Tab = app.NewTab(composer, subject)
-               if !h.Has("to") {
+               switch {
+               case f.SkipEditor:
+                       composer.Terminal().Close()
+               case !h.Has("to"):
                        composer.FocusEditor("to")
-               } else {
+               default:
                        composer.FocusTerminal()
                }
                return composer, nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/msg/invite.go 
new/aerc-0.20.0/commands/msg/invite.go
--- old/aerc-0.19.0/commands/msg/invite.go      2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/msg/invite.go      2025-01-25 21:55:48.000000000 
+0100
@@ -141,7 +141,11 @@
                if err != nil {
                        return fmt.Errorf("failed to write invitation: %w", err)
                }
-               composer.FocusTerminal()
+               if i.SkipEditor {
+                       composer.Terminal().Close()
+               } else {
+                       composer.FocusTerminal()
+               }
 
                composer.Tab = app.NewTab(composer, subject)
 
@@ -158,10 +162,6 @@
                        }
                })
 
-               if i.SkipEditor {
-                       composer.Terminal().Close()
-               }
-
                return nil
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/msg/recall.go 
new/aerc-0.20.0/commands/msg/recall.go
--- old/aerc-0.19.0/commands/msg/recall.go      2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/msg/recall.go      2025-01-25 21:55:48.000000000 
+0100
@@ -20,9 +20,10 @@
 )
 
 type Recall struct {
-       Force  bool `opt:"-f" desc:"Force recall if not in postpone directory."`
-       Edit   bool `opt:"-e" desc:"Force [compose].edit-headers = true."`
-       NoEdit bool `opt:"-E" desc:"Force [compose].edit-headers = false."`
+       Force      bool `opt:"-f" desc:"Force recall if not in postpone 
directory."`
+       Edit       bool `opt:"-e" desc:"Force [compose].edit-headers = true."`
+       NoEdit     bool `opt:"-E" desc:"Force [compose].edit-headers = false."`
+       SkipEditor bool `opt:"-s" desc:"Skip the editor and go directly to the 
review screen."`
 }
 
 func init() {
@@ -129,7 +130,7 @@
                                        }
                                }
 
-                               // add attachements if present
+                               // add attachments if present
                                var mu sync.Mutex
                                parts := 
lib.FindAllNonMultipart(msg.BodyStructure(), nil, nil)
                                for _, p := range parts {
@@ -162,8 +163,12 @@
                                        
composer.SetRecalledFrom(acct.SelectedDirectory())
                                }
 
-                               // focus the terminal since the header fields 
are likely already done
-                               composer.FocusTerminal()
+                               if r.SkipEditor {
+                                       composer.Terminal().Close()
+                               } else {
+                                       // focus the terminal since the header 
fields are likely already done
+                                       composer.FocusTerminal()
+                               }
                                addTab(composer)
                        })
                })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/msg/reply.go 
new/aerc-0.20.0/commands/msg/reply.go
--- old/aerc-0.19.0/commands/msg/reply.go       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/msg/reply.go       2025-01-25 21:55:48.000000000 
+0100
@@ -23,14 +23,15 @@
 )
 
 type reply struct {
-       All      bool   `opt:"-a" desc:"Reply to all recipients."`
-       Close    bool   `opt:"-c" desc:"Close the view tab when replying."`
-       From     bool   `opt:"-f" desc:"Reply to all addresses in From and 
Reply-To headers."`
-       Quote    bool   `opt:"-q" desc:"Alias of -T quoted-reply."`
-       Template string `opt:"-T" complete:"CompleteTemplate" desc:"Template 
name."`
-       Edit     bool   `opt:"-e" desc:"Force [compose].edit-headers = true."`
-       NoEdit   bool   `opt:"-E" desc:"Force [compose].edit-headers = false."`
-       Account  string `opt:"-A" complete:"CompleteAccount" desc:"Reply with 
the specified account."`
+       All        bool   `opt:"-a" desc:"Reply to all recipients."`
+       Close      bool   `opt:"-c" desc:"Close the view tab when replying."`
+       From       bool   `opt:"-f" desc:"Reply to all addresses in From and 
Reply-To headers."`
+       Quote      bool   `opt:"-q" desc:"Alias of -T quoted-reply."`
+       Template   string `opt:"-T" complete:"CompleteTemplate" desc:"Template 
name."`
+       Edit       bool   `opt:"-e" desc:"Force [compose].edit-headers = true."`
+       NoEdit     bool   `opt:"-E" desc:"Force [compose].edit-headers = 
false."`
+       Account    string `opt:"-A" complete:"CompleteAccount" desc:"Reply with 
the specified account."`
+       SkipEditor bool   `opt:"-s" desc:"Skip the editor and go directly to 
the review screen."`
 }
 
 func init() {
@@ -181,7 +182,9 @@
                        app.RemoveTab(mv, true)
                }
 
-               if args[0] == "reply" {
+               if r.SkipEditor {
+                       composer.Terminal().Close()
+               } else if args[0] == "reply" {
                        composer.FocusTerminal()
                }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/commands/msg/unsubscribe.go 
new/aerc-0.20.0/commands/msg/unsubscribe.go
--- old/aerc-0.19.0/commands/msg/unsubscribe.go 2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/commands/msg/unsubscribe.go 2025-01-25 21:55:48.000000000 
+0100
@@ -19,8 +19,9 @@
 // Unsubscribe helps people unsubscribe from mailing lists by way of the
 // List-Unsubscribe header.
 type Unsubscribe struct {
-       Edit   bool `opt:"-e" desc:"Force [compose].edit-headers = true."`
-       NoEdit bool `opt:"-E" desc:"Force [compose].edit-headers = false."`
+       Edit       bool `opt:"-e" desc:"Force [compose].edit-headers = true."`
+       NoEdit     bool `opt:"-E" desc:"Force [compose].edit-headers = false."`
+       SkipEditor bool `opt:"-s" desc:"Skip the editor and go directly to the 
review screen."`
 }
 
 func init() {
@@ -68,7 +69,7 @@
                var err error
                switch strings.ToLower(method.Scheme) {
                case "mailto":
-                       err = unsubscribeMailto(method, editHeaders)
+                       err = unsubscribeMailto(method, editHeaders, 
u.SkipEditor)
                case "http", "https":
                        err = unsubscribeHTTP(method)
                default:
@@ -140,7 +141,7 @@
        }
 }
 
-func unsubscribeMailto(u *url.URL, editHeaders bool) error {
+func unsubscribeMailto(u *url.URL, editHeaders, skipEditor bool) error {
        widget := app.SelectedTabContent().(app.ProvidesMessage)
        acct := widget.SelectedAccount()
        if acct == nil {
@@ -154,7 +155,6 @@
        }
 
        composer, err := app.NewComposer(
-
                acct,
                acct.AccountConfig(),
                acct.Worker(),
@@ -168,7 +168,11 @@
                return err
        }
        composer.Tab = app.NewTab(composer, "unsubscribe")
-       composer.FocusTerminal()
+       if skipEditor {
+               composer.Terminal().Close()
+       } else {
+               composer.FocusTerminal()
+       }
        return nil
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/accounts.go 
new/aerc-0.20.0/config/accounts.go
--- old/aerc-0.19.0/config/accounts.go  2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/config/accounts.go  2025-01-25 21:55:48.000000000 +0100
@@ -97,7 +97,7 @@
        Params map[string]string
 
        Archive           string          `ini:"archive" default:"Archive"`
-       CopyTo            string          `ini:"copy-to"`
+       CopyTo            []string        `ini:"copy-to" delim:","`
        CopyToReplied     bool            `ini:"copy-to-replied" 
default:"false"`
        StripBcc          bool            `ini:"strip-bcc" default:"true"`
        Default           string          `ini:"default" default:"INBOX"`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/aerc.conf 
new/aerc-0.20.0/config/aerc.conf
--- old/aerc-0.19.0/config/aerc.conf    2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/config/aerc.conf    2025-01-25 21:55:48.000000000 +0100
@@ -676,7 +676,7 @@
 
 # Specifies the command to be used to select attachments. Any occurrence of
 # '%s' in the file-picker-cmd will be replaced with the argument <arg>
-# to :attach -m <arg>. Any occurence of '%f' will be replaced by the
+# to :attach -m <arg>. Any occurrence of '%f' will be replaced by the
 # location of a temporary file, from which aerc will read the selected files.
 #
 # If '%f' is not present, the command must output the selected files to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/binds.conf 
new/aerc-0.20.0/config/binds.conf
--- old/aerc-0.19.0/config/binds.conf   2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/config/binds.conf   2025-01-25 21:55:48.000000000 +0100
@@ -167,6 +167,8 @@
 # Inline comments are used as descriptions on the review screen
 y = :send<Enter> # Send
 n = :abort<Enter> # Abort (discard message, no confirmation)
+s = :sign<Enter> # Toggle signing of this message with your PGP key
+x = :encrypt<Enter> # Toggle encryption of this message to all recipients
 v = :preview<Enter> # Preview message
 p = :postpone<Enter> # Postpone
 q = :choose -o d discard abort -o p postpone postpone<Enter> # Abort or 
postpone
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/binds.go 
new/aerc-0.20.0/config/binds.go
--- old/aerc-0.19.0/config/binds.go     2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/config/binds.go     2025-01-25 21:55:48.000000000 +0100
@@ -130,7 +130,7 @@
 
        // Base Bindings
        for _, sectionName := range binds.SectionStrings() {
-               // Handle :: delimeter
+               // Handle :: delimiter
                baseSectionName := strings.ReplaceAll(sectionName, "::", "////")
                sections := strings.Split(baseSectionName, ":")
                baseOnly := len(sections) == 1
@@ -173,9 +173,9 @@
 
 func LoadBindingSection(sec *ini.Section) (*KeyBindings, error) {
        bindings := NewKeyBindings()
-       for key, value := range sec.KeysHash() {
-               var annotation string
-               value, annotation, _ = strings.Cut(value, " # ")
+       for _, k := range sec.Keys() {
+               key := k.Name()
+               value, annotation, _ := strings.Cut(k.String(), " # ")
                value = strings.TrimSpace(value)
                switch key {
                case "$ex":
@@ -471,18 +471,21 @@
        var sb strings.Builder
 
        for _, stroke := range keystrokes {
+               special := false
                s := ""
                for name, ks := range keyNames {
                        if (ks.Modifiers == stroke.Modifiers || ks.Modifiers == 
vaxis.ModifierMask(0)) && ks.Key == stroke.Key {
                                switch name {
                                case "cr":
-                                       s = "<enter>"
+                                       special = true
+                                       s = "enter"
                                case "space":
                                        s = " "
                                case "semicolon":
                                        s = ";"
                                default:
-                                       s = fmt.Sprintf("<%s>", name)
+                                       special = true
+                                       s = name
                                }
                                // remove any modifiers this named key comes
                                // with so we format properly
@@ -490,6 +493,12 @@
                                break
                        }
                }
+               if stroke.Modifiers != vaxis.ModifierMask(0) {
+                       special = true
+               }
+               if special {
+                       sb.WriteString("<")
+               }
                if stroke.Modifiers&vaxis.ModCtrl > 0 {
                        sb.WriteString("c-")
                }
@@ -503,6 +512,9 @@
                        s = string(stroke.Key)
                }
                sb.WriteString(s)
+               if special {
+                       sb.WriteString(">")
+               }
        }
 
        // replace leading & trailing spaces with explicit <space> keystrokes
@@ -609,38 +621,9 @@
        "f61":     {vaxis.ModifierMask(0), vaxis.KeyF61},
        "f62":     {vaxis.ModifierMask(0), vaxis.KeyF62},
        "f63":     {vaxis.ModifierMask(0), vaxis.KeyF63},
-       "nul":     {vaxis.ModCtrl, ' '},
-       "soh":     {vaxis.ModCtrl, 'a'},
-       "stx":     {vaxis.ModCtrl, 'b'},
-       "etx":     {vaxis.ModCtrl, 'c'},
-       "eot":     {vaxis.ModCtrl, 'd'},
-       "enq":     {vaxis.ModCtrl, 'e'},
-       "ack":     {vaxis.ModCtrl, 'f'},
-       "bel":     {vaxis.ModCtrl, 'g'},
-       "bs":      {vaxis.ModCtrl, 'h'},
        "tab":     {vaxis.ModifierMask(0), vaxis.KeyTab},
-       "lf":      {vaxis.ModCtrl, 'j'},
-       "vt":      {vaxis.ModCtrl, 'k'},
-       "ff":      {vaxis.ModCtrl, 'l'},
        "cr":      {vaxis.ModifierMask(0), vaxis.KeyEnter},
-       "so":      {vaxis.ModCtrl, 'n'},
-       "si":      {vaxis.ModCtrl, 'o'},
-       "dle":     {vaxis.ModCtrl, 'p'},
-       "dc1":     {vaxis.ModCtrl, 'q'},
-       "dc2":     {vaxis.ModCtrl, 'r'},
-       "dc3":     {vaxis.ModCtrl, 's'},
-       "dc4":     {vaxis.ModCtrl, 't'},
-       "nak":     {vaxis.ModCtrl, 'u'},
-       "syn":     {vaxis.ModCtrl, 'v'},
-       "etb":     {vaxis.ModCtrl, 'w'},
-       "can":     {vaxis.ModCtrl, 'x'},
-       "em":      {vaxis.ModCtrl, 'y'},
-       "sub":     {vaxis.ModCtrl, 'z'},
        "esc":     {vaxis.ModifierMask(0), vaxis.KeyEsc},
-       "fs":      {vaxis.ModCtrl, '\\'},
-       "gs":      {vaxis.ModCtrl, ']'},
-       "rs":      {vaxis.ModCtrl, '^'},
-       "us":      {vaxis.ModCtrl, '_'},
        "del":     {vaxis.ModifierMask(0), vaxis.KeyDelete},
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/binds_test.go 
new/aerc-0.20.0/config/binds_test.go
--- old/aerc-0.19.0/config/binds_test.go        2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/config/binds_test.go        2025-01-25 21:55:48.000000000 
+0100
@@ -92,7 +92,9 @@
                formatted string
        }{
                {KeyStroke{vaxis.ModifierMask(0), vaxis.KeyLeft}, "<left>"},
-               {KeyStroke{vaxis.ModCtrl, vaxis.KeyLeft}, "c-<left>"},
+               {KeyStroke{vaxis.ModCtrl, vaxis.KeyLeft}, "<c-left>"},
+               {KeyStroke{vaxis.ModCtrl, 'e'}, "<c-e>"},
+               {KeyStroke{vaxis.ModifierMask(0), vaxis.KeySpace}, "<space>"},
        }
 
        for _, test := range tests {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/style.go 
new/aerc-0.20.0/config/style.go
--- old/aerc-0.19.0/config/style.go     2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/config/style.go     2025-01-25 21:55:48.000000000 +0100
@@ -327,12 +327,15 @@
 *.selected.fg = 15
 *.selected.bold = true
 statusline_*.dim = true
-statusline_*.bg = 8
-statusline_*.fg = 15
-*warning.fg = 3
-*success.fg = 2
-*error.fg = 1
+*warning.dim = false
+*warning.bold = true
+*warning.fg = 11
+*success.dim = false
+*success.bold = true
+*success.fg = 10
+*error.dim = false
 *error.bold = true
+*error.fg = 9
 border.fg = 12
 border.bold = true
 title.bg = 12
@@ -505,8 +508,8 @@
 }
 
 var (
-       styleObjRe            = 
regexp.MustCompile(`^([\w\*\?]+)(?:\.([\w-]+,.+?)+?)?(\.selected)?\.(\w+)$`)
-       styleHeaderPatternsRe = regexp.MustCompile(`([\w-]+),(.+?)\.`)
+       styleObjRe            = 
regexp.MustCompile(`^([\w\*\?]+)(\.(?:[\w-]+,.+?)+?)?(\.selected)?\.(\w+)$`)
+       styleHeaderPatternsRe = 
regexp.MustCompile(`([\w-]+),(~/(?:.+?)/|(?:.+?))\.`)
 )
 
 func (ss *StyleSet) parseKey(key *ini.Key, selected bool) error {
@@ -577,9 +580,12 @@
 
        for _, p := range headerPatterns {
                var pattern string
-               if strings.HasPrefix(p.RawPattern, "~") {
+               switch {
+               case strings.HasPrefix(p.RawPattern, "~/"):
+                       pattern = p.RawPattern[2 : len(p.RawPattern)-1]
+               case strings.HasPrefix(p.RawPattern, "~"):
                        pattern = p.RawPattern[1:]
-               } else {
+               default:
                        pattern = "^" + regexp.QuoteMeta(p.RawPattern) + "$"
                }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/config/style_test.go 
new/aerc-0.20.0/config/style_test.go
--- old/aerc-0.19.0/config/style_test.go        2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/config/style_test.go        2025-01-25 21:55:48.000000000 
+0100
@@ -11,9 +11,10 @@
 msglist_*.fg = salmon
 msglist_*.From,~^"Bob Foo".fg = khaki
 msglist_*.From,~^"Bob Foo".selected.fg = palegreen
-msglist_*.From,~^"Bob Foo".Subject,~PATCH.fg = coral
+msglist_*.Subject,~PATCH.From,~^"Bob Foo".fg = coral
 msglist_*.From,~^"Bob 
Foo".Subject,~PATCH.X-Baz,exact.X-Clacks-Overhead,~Pratchett$.fg = plum
 msglist_*.From,~^"Bob Foo".Subject,~PATCH.X-Clacks-Overhead,~Pratchett$.fg = 
pink
+msglist_*.From,~^"Bob Foo".List-ID,~/lists\.sr\.ht/.fg = pink
 `
 
 func TestStyleMultiHeaderPattern(t *testing.T) {
@@ -85,5 +86,16 @@
                if s.Foreground != colorNames["pink"] {
                        t.Errorf("expected:#%x got:#%x", colorNames["pink"], 
s.Foreground)
                }
+       })
+
+       t.Run("handles uris in regular expressions", func(t *testing.T) {
+               var h mail.Header
+               h.SetAddressList("From", []*mail.Address{{"Bob Foo", 
"b...@foo.org"}})
+               h.SetText("List-ID", "List-ID: ~rjarry/aerc-discuss 
<~rjarry/aerc-discuss.lists.sr.ht>")
+
+               s := ss.Get(STYLE_MSGLIST_DEFAULT, &h)
+               if s.Foreground != colorNames["pink"] {
+                       t.Errorf("expected:#%x got:#%x", colorNames["pink"], 
s.Foreground)
+               }
        })
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/contrib/check-patches 
new/aerc-0.20.0/contrib/check-patches
--- old/aerc-0.19.0/contrib/check-patches       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/contrib/check-patches       2025-01-25 21:55:48.000000000 
+0100
@@ -78,6 +78,10 @@
                err "body has less than three words, please describe your 
changes"
        fi
 
+       if ! git log --format='%s%n%b' -1 "$rev" | codespell -; then
+               err "typos in title and/or body"
+       fi
+
        if [ "$fail" = true ]; then
                continue
        fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-accounts.5.scd 
new/aerc-0.20.0/doc/aerc-accounts.5.scd
--- old/aerc-0.19.0/doc/aerc-accounts.5.scd     2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-accounts.5.scd     2025-01-25 21:55:48.000000000 
+0100
@@ -50,8 +50,11 @@
 
        Default: _0_
 
-*copy-to* = _<folder>_
-       Specifies a folder to copy sent mails to, usually _Sent_.
+*copy-to* = _<folder1,folder2,folder3...>_
+       Specifies a comma separated list of folders to copy sent mails to,
+       usually _Sent_.
+
+       By default, the mail is copied to no folders;
 
 *copy-to-replied* = _true_|_false_
        In addition of *copy-to*, also copy replies to the folder in which the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-binds.5.scd 
new/aerc-0.20.0/doc/aerc-binds.5.scd
--- old/aerc-0.19.0/doc/aerc-binds.5.scd        2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-binds.5.scd        2025-01-25 21:55:48.000000000 
+0100
@@ -54,12 +54,19 @@
        keybindings for the composer, when reviewing the email before it's sent
 
        To customize the description shown on the review screen, add a comment
-       (" # ") at the end of the keybinding.
-
-       Example:
+       (_" # "_) at the end of the keybinding. Example:
 
                p = :postpone<Enter> # I'll work on it later
 
+       The order in which bindings are defined is preserved on the review
+       screen. If a non-default binding is not annotated it will be displayed
+       without any description.
+
+       To hide a binding from the review screen, explicitly annotate it with
+       a _" # -"_ comment. Example:
+
+               <C-e> = :encrypt<Enter> # -
+
 *[terminal]*
        keybindings for terminal tabs
 
@@ -108,7 +115,7 @@
 ```
 [compose::review]
 a = :attach<space>
-d = :deatch<space>
+d = :detach<space>
 
 [compose::review:account=no-attachments]
 a =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-config.5.scd 
new/aerc-0.20.0/doc/aerc-config.5.scd
--- old/aerc-0.19.0/doc/aerc-config.5.scd       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-config.5.scd       2025-01-25 21:55:48.000000000 
+0100
@@ -207,7 +207,7 @@
 
 *message-view-this-week-time-format* = _<timeformat>_
        If set, overrides *timestamp-format* in the message view for messages
-       that were recieved/sent within the last 7 days.
+       that were received/sent within the last 7 days.
 
 *message-view-this-year-time-format* = _<timeformat>_
        If set, overrides *timestamp-format* in the message view for messages
@@ -910,7 +910,7 @@
 *file-picker-cmd* = _<command>_
        Specifies the command to be used to select attachments. Any occurrence 
of
        _%s_ in the *file-picker-cmd* will be replaced with the argument _<arg>_
-       to *:attach -m* _<arg>_. Any occurence of _%f_ will be replaced by the
+       to *:attach -m* _<arg>_. Any occurrence of _%f_ will be replaced by the
        location of a temporary file, from which aerc will read the selected 
files.
 
        If _%f_ is not present, the command must output the selected files to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-patch.7.scd 
new/aerc-0.20.0/doc/aerc-patch.7.scd
--- old/aerc-0.19.0/doc/aerc-patch.7.scd        2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-patch.7.scd        2025-01-25 21:55:48.000000000 
+0100
@@ -43,7 +43,7 @@
        Completions for the _<tag>_ are available based on the subject lines of
        the selected or marked messages.
 
-       *-c* _<cmd>_: Apply patches with the provided _<cmd>_. Any occurence of
+       *-c* _<cmd>_: Apply patches with the provided _<cmd>_. Any occurrence of
        '%r' in the command string will be replaced with the root directory of
        the current project. Note that this approach is not recommended in
        general and should only be used for very specific purposes, i.e. when
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-stylesets.7.scd 
new/aerc-0.20.0/doc/aerc-stylesets.7.scd
--- old/aerc-0.19.0/doc/aerc-stylesets.7.scd    2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-stylesets.7.scd    2025-01-25 21:55:48.000000000 
+0100
@@ -313,7 +313,8 @@
        *msglist_<name>*._<header>_,_<header_value>_.*<attribute>* = 
_<attr_value>_
 
 If _<header_value>_ starts with a tilde character _~_, it will be interpreted 
as
-a regular expression.
+a regular expression. If you are writing regular expressions that try to match
+with _._ or _\._ you need to wrap like this _~/<expression>/_.
 
 _<header>,<header_value>_ can be specified multiple times to narrow down 
matches
 to more than one email header value. In that case, all given headers must match
@@ -328,6 +329,7 @@
 "msglist_*.Subject,~^(\\[[\w-]+\]\\s*)?\\[(RFC )?PATCH.fg" = #ffffaf
 "msglist_*.Subject,~^(\\[[\w-]+\]\\s*)?\\[(RFC )?PATCH.selected.fg" = #ffffaf
 "msglist_*.From,~^Bob.Subject,~^(\\[[\w-]+\]\\s*)?\\[(RFC )?PATCH.selected.fg" 
= #ffffaf
+"msglist_*.List-ID,~/lists\.sr\.ht/selected.fg" = blue
 ```
 
 When a dynamic style is matched to an email header, it will be used in priority
@@ -378,12 +380,15 @@
 *.selected.fg = 15
 *.selected.bold = true
 statusline_*.dim = true
-statusline_*.bg = 8
-statusline_*.fg = 15
-*warning.fg = 3
-*success.fg = 2
-*error.fg = 1
+*warning.dim = false
+*warning.bold = true
+*warning.fg = 11
+*success.dim = false
+*success.bold = true
+*success.fg = 10
+*error.dim = false
 *error.bold = true
+*error.fg = 9
 border.bg = 12
 border.fg = 15
 title.bg = 12
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc-templates.7.scd 
new/aerc-0.20.0/doc/aerc-templates.7.scd
--- old/aerc-0.19.0/doc/aerc-templates.7.scd    2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/doc/aerc-templates.7.scd    2025-01-25 21:55:48.000000000 
+0100
@@ -159,7 +159,7 @@
        {{.Header "x-foo-bar"}}
        ```
 
-       Any header values of the original forwared or replied message:
+       Any header values of the original forwarded or replied message:
 
        ```
        {{.OriginalHeader "x-foo-bar"}}
@@ -557,7 +557,7 @@
        ```
 
 *switch*
-       Do swich/case/default control flows. The switch value is compared with
+       Do switch/case/default control flows. The switch value is compared with
        regular expressions. If none of the case/default arms match, an empty
        string is returned.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/doc/aerc.1.scd 
new/aerc-0.20.0/doc/aerc.1.scd
--- old/aerc-0.19.0/doc/aerc.1.scd      2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/doc/aerc.1.scd      2025-01-25 21:55:48.000000000 +0100
@@ -175,7 +175,7 @@
        Send keystrokes to the currently visible terminal, if any. Can be used 
to
        control embedded editors to save drafts or quit in a safe manner.
 
-       Here's an example of quiting a Vim-like editor:
+       Here's an example of quitting a Vim-like editor:
 
                *:send-keys* _<Esc>:wq!<Enter>_
 
@@ -317,7 +317,7 @@
        The *-m* option sets the multi-file strategy. See *aerc-notmuch*(5) for 
more
        details.
 
-*:accept* [*-e*|*-E*|*-s*]
+*:accept* [*-e*|*-E*] [*-s*]
        Accepts an iCalendar meeting invitation. This opens a compose window
        with a specially crafted attachment. Sending the email will let the
        inviter know that you accepted and will likely update their calendar as
@@ -331,7 +331,7 @@
 
        *-s*: Skips the editor and goes directly to the review screen.
 
-*:accept-tentative* [*-e*|*-E*]
+*:accept-tentative* [*-e*|*-E*] [*-s*]
        Accepts an iCalendar meeting invitation tentatively.
 
        *-e*: Forces *[compose].edit-headers* = _true_ for this message only.
@@ -353,7 +353,7 @@
 
        *-m*: Set the multi-file strategy. See *aerc-notmuch*(5) for more 
details.
 
-*:decline* [*-e*|*-E*]
+*:decline* [*-e*|*-E*] [*-s*]
        Declines an iCalendar meeting invitation.
 
        *-e*: Forces *[compose].edit-headers* = _true_ for this message only.
@@ -377,7 +377,7 @@
                User-defined format specifier requiring two _%s_ for the key and
                value strings. Default format: _%-20.20s: %s_
 
-*:recall* [*-f*] [*-e*|*-E*]
+*:recall* [*-f*] [*-e*|*-E*] [*-s*]
        Opens the selected message for re-editing. Messages can only be
        recalled from the postpone directory.
 
@@ -389,12 +389,14 @@
 
        *-E*: Forces *[compose].edit-headers* = _false_ for this message only.
 
+       *-s*: Skips the editor and goes directly to the review screen.
+
        Original recalled messages are deleted if they are sent or postponed 
again.
        In both cases you have another copy of the message somewhere. Otherwise 
the
        recalled message is left intact. This happens if the recalled message is
        discarded after editing. It can be deleted with *:rm* if it is not 
needed.
 
-*:forward* [*-A*|*-F*] [*-T* _<template-file>_] [*-e*|*-E*] [_<address>_...]
+*:forward* [*-A*|*-F*] [*-T* _<template-file>_] [*-e*|*-E*] [*-s*] 
[_<address>_...]
        Opens the composer to forward the selected message to another recipient.
 
        *-A*: Forward the message and all attachments.
@@ -411,6 +413,8 @@
 
        *-E*: Forces *[compose].edit-headers* = _false_ for this message only.
 
+       *-s*: Skips the editor and goes directly to the review screen.
+
 *:move* [*-p*] [*-a* _<account>_] [*-m* _<strategy>_] _<folder>_++
 *:mv* [*-p*] [*-a* _<account>_] [*-m* _<strategy>_] _<folder>_
        Moves the selected message(s) to _<folder>_.
@@ -452,7 +456,7 @@
        _[PATCH X/Y]_), all marked messages will be sorted by subject to ensure
        that the patches are applied in order.
 
-*:reply* [*-acfq*] [*-T* _<template-file>_] [*-A* _<account>_] [*-e*|*-E*]
+*:reply* [*-acfqs*] [*-T* _<template-file>_] [*-A* _<account>_] [*-e*|*-E*]
        Opens the composer to reply to the selected message.
 
        *-a*: Reply all
@@ -466,6 +470,8 @@
        editor. This defaults to what is set as *quoted-reply* in the 
*[templates]*
        section of _aerc.conf_.
 
+       *-s*: Skip opening the text editor and go directly to the review screen.
+
        *-T* _<template-file>_
                Use the specified template file for creating the initial
                message body.
@@ -521,7 +527,7 @@
 
                *:modify-labels* _+inbox_ _-spam_ _unread_
 
-*:unsubscribe* [*-e*|*-E*]
+*:unsubscribe* [*-e*|*-E*] [*-s*]
        Attempt to automatically unsubscribe the user from the mailing list 
through
        use of the List-Unsubscribe header. If supported, aerc may open a 
compose
        window pre-filled with the unsubscribe information or open the 
unsubscribe
@@ -531,6 +537,8 @@
 
        *-E*: Forces *[compose].edit-headers* = _false_ for this message only.
 
+       *-s*: Skips the editor and goes directly to the review screen.
+
 ## MESSAGE LIST COMMANDS
 
 *:align* _top|center|bottom_
@@ -565,7 +573,7 @@
        check-mail-cmd to be set in order for aerc to initiate a check for new 
mail.
        Issuing a manual *:check-mail* command will reset the timer for 
automatic checking.
 
-*:compose* [*-H* _"<header>: <value>"_] [*-T* _<template-file>_] [*-e*|*-E*] 
[_<body>_]
+*:compose* [*-H* _"<header>: <value>"_] [*-T* _<template-file>_] [*-e*|*-E*] 
[*-s*] [_<body>_]
        Open the compose window to send a new email. The new email will be sent 
with
        the current account's outgoing transport configuration. For details on
        configuring outgoing mail delivery consult *aerc-accounts*(5).
@@ -583,6 +591,8 @@
 
        *-E*: Forces *[compose].edit-headers* = _false_ for this message only.
 
+       *-s*: Skips the editor and goes directly to the review screen.
+
        _<body>_: The initial message body.
 
 *:bounce* [*-A* _<account>_] _<address>_ [_<address>_...]++
@@ -803,7 +813,7 @@
          Subsequent args are passed to that program.
        - _{}_ will be expanded as the temporary filename to be opened. If it is
          not encountered in the arguments, the temporary filename will be
-         appened to the end of the command.
+         appended to the end of the command.
 
 *:open-link* _<url>_ [_<args...>_]
        Open the specified URL with an external program. The opening logic is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/filters/wrap.c 
new/aerc-0.20.0/filters/wrap.c
--- old/aerc-0.19.0/filters/wrap.c      2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/filters/wrap.c      2025-01-25 21:55:48.000000000 +0100
@@ -30,7 +30,7 @@
        puts("  -w INT   preferred wrap margin (default 80)");
        puts("  -r       reflow all paragraphs even if no trailing space");
        puts("  -l INT   minimum percentage of letters in a line to be");
-       puts("           considered a paragaph");
+       puts("           considered a paragraph");
        puts("  -f FILE  read from filename (default stdin)");
 }
 
@@ -383,7 +383,7 @@
 
 /*
  * BUFSIZ has different values depending on the libc implementation.
- * Use a self defined value to have consistent behaviour accross all platforms.
+ * Use a self defined value to have consistent behaviour across all platforms.
  */
 #define BUFFER_SIZE 8192
 
@@ -495,7 +495,7 @@
 
        if (!locale) {
                /* Neither LC_ALL nor LANG env vars are defined or are set to
-                * a non existant/installed locale. Try with a generic UTF-8
+                * a non existent/installed locale. Try with a generic UTF-8
                 * locale which is expected to be available on all POSIX
                 * systems. */
                locale = setlocale(LC_ALL, "C.UTF-8");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/ipc/message.go 
new/aerc-0.20.0/lib/ipc/message.go
--- old/aerc-0.19.0/lib/ipc/message.go  2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/ipc/message.go  2025-01-25 21:55:48.000000000 +0100
@@ -2,7 +2,7 @@
 
 import "encoding/json"
 
-// Request constains all parameters needed for the main instance to respond to
+// Request contains all parameters needed for the main instance to respond to
 // a request.
 type Request struct {
        // Arguments contains the commandline arguments. The detection of what
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/iterator/index.go 
new/aerc-0.20.0/lib/iterator/index.go
--- old/aerc-0.19.0/lib/iterator/index.go       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/iterator/index.go       2025-01-25 21:55:48.000000000 
+0100
@@ -1,6 +1,6 @@
 package iterator
 
-// IndexProvider implements a subset of the Interator interface
+// IndexProvider implements a subset of the Iterator interface
 type IndexProvider interface {
        StartIndex() int
        EndIndex() int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/iterator/iterator_test.go 
new/aerc-0.20.0/lib/iterator/iterator_test.go
--- old/aerc-0.19.0/lib/iterator/iterator_test.go       2025-01-14 
23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/iterator/iterator_test.go       2025-01-25 
21:55:48.000000000 +0100
@@ -55,18 +55,18 @@
                got = append(got, iter.Value().(models.UID))
        }
        if len(got) != len(want) {
-               t.Errorf(label + "number of elements not correct")
+               t.Errorf("%s: number of elements not correct", label)
        }
        for i, u := range want {
                if got[i] != u {
-                       t.Errorf(label + "order not correct")
+                       t.Errorf("%s: order not correct", label)
                }
        }
        if iter.StartIndex() != start {
-               t.Errorf(label + "start index not correct")
+               t.Errorf("%s: start index not correct", label)
        }
        if iter.EndIndex() != end {
-               t.Errorf(label + "end index not correct")
+               t.Errorf("%s: end index not correct", label)
        }
 }
 
@@ -80,17 +80,17 @@
                got = append(got, iter.Value().(*types.Thread))
        }
        if len(got) != len(want) {
-               t.Errorf(label + "number of elements not correct")
+               t.Errorf("%s: number of elements not correct", label)
        }
        for i, th := range want {
                if got[i].Uid != th.Uid {
-                       t.Errorf(label + "order not correct")
+                       t.Errorf("%s: order not correct", label)
                }
        }
        if iter.StartIndex() != start {
-               t.Errorf(label + "start index not correct")
+               t.Errorf("%s: start index not correct", label)
        }
        if iter.EndIndex() != end {
-               t.Errorf(label + "end index not correct")
+               t.Errorf("%s: end index not correct", label)
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/marker/marker.go 
new/aerc-0.20.0/lib/marker/marker.go
--- old/aerc-0.19.0/lib/marker/marker.go        2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/marker/marker.go        2025-01-25 21:55:48.000000000 
+0100
@@ -40,7 +40,7 @@
        }
 }
 
-// Mark markes the uid as marked
+// Mark marks the uid as marked
 func (mc *controller) Mark(uid models.UID) {
        if mc.visualMarkMode {
                // visual mode has override, bogus input from user
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/msgstore.go 
new/aerc-0.20.0/lib/msgstore.go
--- old/aerc-0.19.0/lib/msgstore.go     2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/msgstore.go     2025-01-25 21:55:48.000000000 +0100
@@ -309,6 +309,7 @@
 
                store.Messages = newMap
                update = true
+               store.directoryContentsLoaded = true
        case *types.MessageInfo:
                infoUpdated := msg.Info.Envelope != nil || msg.Info.Error != nil
                if existing, ok := store.Messages[msg.Info.Uid]; ok && existing 
!= nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/pama/init.go 
new/aerc-0.20.0/lib/pama/init.go
--- old/aerc-0.19.0/lib/pama/init.go    2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/pama/init.go    2025-01-25 21:55:48.000000000 +0100
@@ -4,7 +4,7 @@
        "git.sr.ht/~rjarry/aerc/lib/pama/models"
 )
 
-// Init creats a new revision control project
+// Init creates a new revision control project
 func (m PatchManager) Init(name, path string, overwrite bool) error {
        id, root, err := m.detect(path)
        if err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/pama/models/models.go 
new/aerc-0.20.0/lib/pama/models/models.go
--- old/aerc-0.19.0/lib/pama/models/models.go   2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/pama/models/models.go   2025-01-25 21:55:48.000000000 
+0100
@@ -76,7 +76,7 @@
        // ApplyCmd returns a string with an executable command that is used to
        // apply patches with the :pipe command.
        ApplyCmd() string
-       // CreateWorktree creats a worktree in path at commit.
+       // CreateWorktree creates a worktree in path at commit.
        CreateWorktree(path string, commit string) error
        // DeleteWorktree removes the linked worktree stored in the path
        // location. Note that this function should be called from the base
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/pama/pama_test.go 
new/aerc-0.20.0/lib/pama/pama_test.go
--- old/aerc-0.19.0/lib/pama/pama_test.go       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/pama/pama_test.go       2025-01-25 21:55:48.000000000 
+0100
@@ -133,7 +133,7 @@
 func (s *mockStore) StoreProject(p models.Project, ow bool) error {
        _, ok := s.data[p.Name]
        if ok && !ow {
-               return errors.New("alreay there")
+               return errors.New("already there")
        }
        s.data[p.Name] = p
        return nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/pama/store/store.go 
new/aerc-0.20.0/lib/pama/store/store.go
--- old/aerc-0.19.0/lib/pama/store/store.go     2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/pama/store/store.go     2025-01-25 21:55:48.000000000 
+0100
@@ -19,7 +19,7 @@
 )
 
 var (
-       // versTag should be incremented when the underyling data structure
+       // versTag should be incremented when the underlying data structure
        // changes.
        versTag    = []byte("0001")
        versTagKey = []byte("version.tag")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/rfc822/message.go 
new/aerc-0.20.0/lib/rfc822/message.go
--- old/aerc-0.19.0/lib/rfc822/message.go       2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/lib/rfc822/message.go       2025-01-25 21:55:48.000000000 
+0100
@@ -174,7 +174,7 @@
        return &body, nil
 }
 
-// CreateTextPlainBody creats a plain-vanilla text/plain body structure.
+// CreateTextPlainBody creates a plain-vanilla text/plain body structure.
 func CreateTextPlainBody() *models.BodyStructure {
        body := &models.BodyStructure{}
        body.MIMEType = "text"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/ui/context.go 
new/aerc-0.20.0/lib/ui/context.go
--- old/aerc-0.19.0/lib/ui/context.go   2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/ui/context.go   2025-01-25 21:55:48.000000000 +0100
@@ -38,7 +38,7 @@
                panic(fmt.Errorf("Attempted to create context with negative 
offset"))
        }
        win := ctx.window.New(x, y, width, height)
-       return &Context{win, x, y, ctx.onPopover}
+       return &Context{win, ctx.x + x, ctx.y + y, ctx.onPopover}
 }
 
 func (ctx *Context) SetCell(x, y int, ch rune, style vaxis.Style) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/ui/grid.go 
new/aerc-0.20.0/lib/ui/grid.go
--- old/aerc-0.19.0/lib/ui/grid.go      2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/ui/grid.go      2025-01-25 21:55:48.000000000 +0100
@@ -30,7 +30,7 @@
 
        // If Strategy = SIZE_EXACT, this function returns the number of cells
        // this row/col shall occupy. If SIZE_WEIGHT, the space left after all
-       // exact rows/cols are measured is distributed amonst the remainder
+       // exact rows/cols are measured is distributed amongst the remainder
        // weighted by the value returned by this function.
        Size func() int
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/lib/ui/ui.go new/aerc-0.20.0/lib/ui/ui.go
--- old/aerc-0.19.0/lib/ui/ui.go        2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/lib/ui/ui.go        2025-01-25 21:55:48.000000000 +0100
@@ -171,7 +171,7 @@
                Invalidate()
        default:
                // We never care about num or caps lock. Remove them so it
-               // doesn't interefere with key matching
+               // doesn't interfere with key matching
                if key, ok := event.(vaxis.Key); ok {
                        key.Modifiers &^= vaxis.ModCapsLock
                        key.Modifiers &^= vaxis.ModNumLock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/stylesets/default 
new/aerc-0.20.0/stylesets/default
--- old/aerc-0.19.0/stylesets/default   2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/stylesets/default   2025-01-25 21:55:48.000000000 +0100
@@ -17,13 +17,16 @@
 #*.selected.bold = true
 
 #statusline_*.dim = true
-#statusline_*.bg = 8
-#statusline_*.fg = 15
 
-#*warning.fg = 3
-#*success.fg = 2
-#*error.fg = 1
+#*warning.dim = false
+#*warning.bold = true
+#*warning.fg = 11
+#*success.dim = false
+#*success.bold = true
+#*success.fg = 10
+#*error.dim = false
 #*error.bold = true
+#*error.fg = 9
 
 #border.fg = 12
 #border.bold = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/worker/imap/connect.go 
new/aerc-0.20.0/worker/imap/connect.go
--- old/aerc-0.19.0/worker/imap/connect.go      2025-01-14 23:05:09.000000000 
+0100
+++ new/aerc-0.20.0/worker/imap/connect.go      2025-01-25 21:55:48.000000000 
+0100
@@ -10,6 +10,7 @@
        "git.sr.ht/~rjarry/aerc/lib/log"
        "github.com/emersion/go-imap"
        "github.com/emersion/go-imap/client"
+       "github.com/emersion/go-sasl"
 )
 
 // connect establishes a new tcp connection to the imap server, logs in and
@@ -88,6 +89,13 @@
                                username, password, w.config.name, c); err != 
nil {
                                return nil, err
                        }
+               } else if plain, err := c.SupportAuth("PLAIN"); err != nil {
+                       return nil, err
+               } else if plain {
+                       auth := sasl.NewPlainClient("", username, password)
+                       if err := c.Authenticate(auth); err != nil {
+                               return nil, err
+                       }
                } else if err := c.Login(username, password); err != nil {
                        return nil, err
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/worker/imap/extensions/xgmext/client.go 
new/aerc-0.20.0/worker/imap/extensions/xgmext/client.go
--- old/aerc-0.19.0/worker/imap/extensions/xgmext/client.go     2025-01-14 
23:05:09.000000000 +0100
+++ new/aerc-0.20.0/worker/imap/extensions/xgmext/client.go     2025-01-25 
21:55:48.000000000 +0100
@@ -24,12 +24,12 @@
        threadIds, err := h.fetchThreadIds(requested)
        if err != nil {
                return nil,
-                       fmt.Errorf("faild to fetch thread IDs: %w", err)
+                       fmt.Errorf("failed to fetch thread IDs: %w", err)
        }
        uids, err := h.searchUids(threadIds)
        if err != nil {
                return nil,
-                       fmt.Errorf("faild to search for thread IDs: %w", err)
+                       fmt.Errorf("failed to search for thread IDs: %w", err)
        }
        return uids, nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aerc-0.19.0/worker/jmap/set.go 
new/aerc-0.20.0/worker/jmap/set.go
--- old/aerc-0.19.0/worker/jmap/set.go  2025-01-14 23:05:09.000000000 +0100
+++ new/aerc-0.20.0/worker/jmap/set.go  2025-01-25 21:55:48.000000000 +0100
@@ -172,14 +172,14 @@
        for _, a := range msg.Add {
                mboxId, ok := w.dir2mbox[a]
                if !ok {
-                       return fmt.Errorf("unkown label: %q", a)
+                       return fmt.Errorf("unknown label: %q", a)
                }
                patch[w.mboxPatch(mboxId)] = true
        }
        for _, r := range msg.Remove {
                mboxId, ok := w.dir2mbox[r]
                if !ok {
-                       return fmt.Errorf("unkown label: %q", r)
+                       return fmt.Errorf("unknown label: %q", r)
                }
                patch[w.mboxPatch(mboxId)] = nil
        }

++++++ vendor.tar.zst ++++++

Reply via email to