aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoritz Poldrack <git@moritz.sh>2023-05-09 17:19:42 +0200
committerRobin Jarry <robin@jarry.cc>2023-05-16 13:56:58 +0200
commit2040fc1885ca4b4bea07d91e9fc6a0aaebfe7133 (patch)
tree0df09ba088414a5d74081e6a61c68afc2141c5a8
parent0eaf05d3fa6295e7df06793a967d3389d2a0f7d8 (diff)
downloadaerc-2040fc1885ca4b4bea07d91e9fc6a0aaebfe7133.tar.gz
aerc-2040fc1885ca4b4bea07d91e9fc6a0aaebfe7133.zip
imap: use delimiter from server
To accommodate servers that use a delimiter other than "/" ("." being a common alternative), the delimiter is fetched from the server when connecting. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--CHANGELOG.md1
-rw-r--r--widgets/dirlist.go3
-rw-r--r--widgets/dirtree.go20
-rw-r--r--worker/imap/connect.go11
-rw-r--r--worker/imap/worker.go18
-rw-r--r--worker/maildir/worker.go7
-rw-r--r--worker/mbox/worker.go4
-rw-r--r--worker/notmuch/worker.go7
-rw-r--r--worker/types/worker.go5
9 files changed, 58 insertions, 18 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53208c19..95043c45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Colorize can style diff chunk function names with `diff_chunk_func`.
- Warn before sending emails with an empty subject with `empty-subject-warning`
in `aerc.conf`.
+- IMAP now uses the delimiter advertised by the server
## [0.15.2](https://git.sr.ht/~rjarry/aerc/refs/0.15.2) - 2023-05-11
diff --git a/widgets/dirlist.go b/widgets/dirlist.go
index da2fa69a..6a10c99a 100644
--- a/widgets/dirlist.go
+++ b/widgets/dirlist.go
@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"math"
- "os"
"regexp"
"sort"
"time"
@@ -79,7 +78,7 @@ func NewDirectoryList(acctConf *config.AccountConfig,
dirlist.spinner.Start()
if uiConf.DirListTree {
- return NewDirectoryTree(dirlist, string(os.PathSeparator))
+ return NewDirectoryTree(dirlist)
}
return dirlist
diff --git a/widgets/dirtree.go b/widgets/dirtree.go
index 41477c5f..c11a1fd0 100644
--- a/widgets/dirtree.go
+++ b/widgets/dirtree.go
@@ -22,16 +22,14 @@ type DirectoryTree struct {
listIdx int
list []*types.Thread
- pathSeparator string
- treeDirs []string
+ treeDirs []string
}
-func NewDirectoryTree(dirlist *DirectoryList, pathSeparator string) DirectoryLister {
+func NewDirectoryTree(dirlist *DirectoryList) DirectoryLister {
dt := &DirectoryTree{
DirectoryList: dirlist,
listIdx: -1,
list: make([]*types.Thread, 0),
- pathSeparator: pathSeparator,
}
return dt
}
@@ -274,7 +272,7 @@ func (dt *DirectoryTree) countVisible(list []*types.Thread) (n int) {
}
func (dt *DirectoryTree) displayText(node *types.Thread) string {
- elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.pathSeparator)
+ elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.DirectoryList.worker.PathSeparator())
return fmt.Sprintf("%s%s%s", threadPrefix(node, false, false), getFlag(node), elems[countLevels(node)])
}
@@ -301,12 +299,12 @@ func (dt *DirectoryTree) hiddenDirectories() map[string]bool {
hidden := make(map[string]bool, 0)
for _, node := range dt.list {
if node.Hidden && node.FirstChild != nil {
- elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.pathSeparator)
+ elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.DirectoryList.worker.PathSeparator())
if levels := countLevels(node); levels < len(elems) {
if node.FirstChild != nil && (levels+1) < len(elems) {
levels += 1
}
- if dirStr := strings.Join(elems[:levels], dt.pathSeparator); dirStr != "" {
+ if dirStr := strings.Join(elems[:levels], dt.DirectoryList.worker.PathSeparator()); dirStr != "" {
hidden[dirStr] = true
}
}
@@ -317,12 +315,12 @@ func (dt *DirectoryTree) hiddenDirectories() map[string]bool {
func (dt *DirectoryTree) setHiddenDirectories(hiddenDirs map[string]bool) {
for _, node := range dt.list {
- elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.pathSeparator)
+ elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.DirectoryList.worker.PathSeparator())
if levels := countLevels(node); levels < len(elems) {
if node.FirstChild != nil && (levels+1) < len(elems) {
levels += 1
}
- strDir := strings.Join(elems[:levels], dt.pathSeparator)
+ strDir := strings.Join(elems[:levels], dt.DirectoryList.worker.PathSeparator())
if hidden, ok := hiddenDirs[strDir]; hidden && ok {
node.Hidden = true
}
@@ -340,7 +338,7 @@ func (dt *DirectoryTree) buildTree() {
sTree := make([][]string, 0)
for i, dir := range dt.dirs {
- elems := strings.Split(dir, dt.pathSeparator)
+ elems := strings.Split(dir, dt.DirectoryList.worker.PathSeparator())
if len(elems) == 0 {
continue
}
@@ -364,7 +362,7 @@ func (dt *DirectoryTree) buildTree() {
// folders-sort
if dt.DirectoryList.acctConf.EnableFoldersSort {
toStr := func(t *types.Thread) string {
- if elems := strings.Split(dt.treeDirs[getAnyUid(t)], dt.pathSeparator); len(elems) > 0 {
+ if elems := strings.Split(dt.treeDirs[getAnyUid(t)], dt.DirectoryList.worker.PathSeparator()); len(elems) > 0 {
return elems[0]
}
return ""
diff --git a/worker/imap/connect.go b/worker/imap/connect.go
index 6f341753..f0ed8043 100644
--- a/worker/imap/connect.go
+++ b/worker/imap/connect.go
@@ -94,6 +94,17 @@ func (w *IMAPWorker) connect() (*client.Client, error) {
return nil, err
}
+ info := make(chan *imap.MailboxInfo, 1)
+ if err := c.List("", "", info); err != nil {
+ return nil, fmt.Errorf("failed to retrieve delimiter: %w", err)
+ }
+ mailboxinfo := <-info
+ w.delimiter = mailboxinfo.Delimiter
+ if w.delimiter == "" {
+ // just in case some implementation does not follow standards
+ w.delimiter = "/"
+ }
+
return c, nil
}
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index 1f61f458..f9a722e6 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -61,11 +61,12 @@ type imapConfig struct {
type IMAPWorker struct {
config imapConfig
- client *imapClient
- selected *imap.MailboxStatus
- updates chan client.Update
- worker *types.Worker
- seqMap SeqMap
+ client *imapClient
+ selected *imap.MailboxStatus
+ updates chan client.Update
+ worker *types.Worker
+ seqMap SeqMap
+ delimiter string
idler *idler
observer *observer
@@ -311,3 +312,10 @@ func (w *IMAPWorker) Run() {
func (w *IMAPWorker) Capabilities() *models.Capabilities {
return w.caps
}
+
+func (w *IMAPWorker) PathSeparator() string {
+ if w.delimiter == "" {
+ return "/"
+ }
+ return w.delimiter
+}
diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go
index ba72432c..b222aab8 100644
--- a/worker/maildir/worker.go
+++ b/worker/maildir/worker.go
@@ -108,6 +108,13 @@ func (w *Worker) Capabilities() *models.Capabilities {
return w.capabilities
}
+func (w *Worker) PathSeparator() string {
+ if w.maildirpp {
+ return "."
+ }
+ return string(os.PathSeparator)
+}
+
func (w *Worker) handleAction(action types.WorkerMessage) {
msg := w.worker.ProcessAction(action)
switch msg := msg.(type) {
diff --git a/worker/mbox/worker.go b/worker/mbox/worker.go
index fbdbec36..47713048 100644
--- a/worker/mbox/worker.go
+++ b/worker/mbox/worker.go
@@ -383,6 +383,10 @@ func (w *mboxWorker) Capabilities() *models.Capabilities {
return w.capabilities
}
+func (w *mboxWorker) PathSeparator() string {
+ return "/"
+}
+
func filterUids(folder *container, uids []uint32, args []string) ([]uint32, error) {
criteria, err := lib.GetSearchCriteria(args)
if err != nil {
diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go
index 6b1b64d9..d5c012ad 100644
--- a/worker/notmuch/worker.go
+++ b/worker/notmuch/worker.go
@@ -109,6 +109,13 @@ func (w *worker) Capabilities() *models.Capabilities {
return w.capabilities
}
+func (w *worker) PathSeparator() string {
+ // make it configurable?
+ // <rockorager> You can use those in query maps to force a tree
+ // <rockorager> Might be nice to be configurable? I see some notmuch people namespace with "::"
+ return "/"
+}
+
func (w *worker) done(msg types.WorkerMessage) {
w.w.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil)
}
diff --git a/worker/types/worker.go b/worker/types/worker.go
index 55e00faf..7033bf77 100644
--- a/worker/types/worker.go
+++ b/worker/types/worker.go
@@ -15,6 +15,7 @@ var lastId int64 = 1 // access via atomic
type Backend interface {
Run()
Capabilities() *models.Capabilities
+ PathSeparator() string
}
type Worker struct {
@@ -179,3 +180,7 @@ func (worker *Worker) PostMessageInfoError(msg WorkerMessage, uid uint32, err er
Message: RespondTo(msg),
}, nil)
}
+
+func (worker *Worker) PathSeparator() string {
+ return worker.Backend.PathSeparator()
+}