aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2023-11-16 14:06:11 +0100
committerRobin Jarry <robin@jarry.cc>2023-12-05 01:06:57 +0100
commit2db657b6bdd6394109c8adc32098d3f39c43f03d (patch)
treecdbdaf685aaffe52eee598ca9e4760ba18687bc2
parentc67723bcfbd5d181f2270bc25b691d6f6312a0c1 (diff)
downloadaerc-2db657b6bdd6394109c8adc32098d3f39c43f03d.tar.gz
cf: allow changing folder of another account
Add a new -a flag to :cf. When specified, an account name is required before the folder name and the focus will be changed to the corresponding account tab before changing folders. If the target folder does not exist, an explicit error will be reported. Changelog-added: Change to a folder of another account with `:cf -a <account> <folder>`. Signed-off-by: Robin Jarry <robin@jarry.cc> Co-authored-by: Johannes Thyssen Tishman <johannes@thyssentishman.com> Tested-by: Johannes Thyssen Tishman <johannes@thyssentishman.com>
-rw-r--r--app/account.go8
-rw-r--r--commands/account/cf.go89
-rw-r--r--doc/aerc.1.scd8
3 files changed, 80 insertions, 25 deletions
diff --git a/app/account.go b/app/account.go
index 734ba37a..5b540523 100644
--- a/app/account.go
+++ b/app/account.go
@@ -128,6 +128,14 @@ func (acct *AccountView) UpdateStatus() {
}
}
+func (acct *AccountView) Select() {
+ for i, widget := range aerc.tabs.TabContent.Children() {
+ if widget == acct {
+ aerc.SelectTabIndex(i)
+ }
+ }
+}
+
func (acct *AccountView) PushStatus(status string, expiry time.Duration) {
PushStatus(fmt.Sprintf("%s: %s", acct.acct.Name, status), expiry)
}
diff --git a/commands/account/cf.go b/commands/account/cf.go
index ff44c6a3..579ddd72 100644
--- a/commands/account/cf.go
+++ b/commands/account/cf.go
@@ -3,6 +3,7 @@ package account
import (
"errors"
"reflect"
+ "time"
"git.sr.ht/~rjarry/aerc/app"
"git.sr.ht/~rjarry/aerc/commands"
@@ -16,7 +17,8 @@ import (
var history map[string]string
type ChangeFolder struct {
- Folder string `opt:"..." complete:"CompleteFolder"`
+ Account bool `opt:"-a"`
+ Folder string `opt:"..." complete:"CompleteFolder"`
}
func init() {
@@ -28,8 +30,20 @@ func (ChangeFolder) Aliases() []string {
return []string{"cf"}
}
-func (*ChangeFolder) CompleteFolder(arg string) []string {
- acct := app.SelectedAccount()
+func (c *ChangeFolder) CompleteFolder(arg string) []string {
+ var acct *app.AccountView
+
+ args := opt.LexArgs(c.Folder)
+ if c.Account {
+ accountName, _ := args.ArgSafe(0)
+ if args.Count() <= 1 && arg == accountName {
+ return commands.FilterList(
+ app.AccountNames(), arg, commands.QuoteSpace)
+ }
+ acct, _ = app.Account(accountName)
+ } else {
+ acct = app.SelectedAccount()
+ }
if acct == nil {
return nil
}
@@ -45,46 +59,75 @@ func (*ChangeFolder) CompleteFolder(arg string) []string {
)
}
-func (c ChangeFolder) Execute(args []string) error {
- acct := app.SelectedAccount()
- if acct == nil {
- return errors.New("No account selected")
+func (c ChangeFolder) Execute([]string) error {
+ var target string
+ var acct *app.AccountView
+
+ args := opt.LexArgs(c.Folder)
+
+ if c.Account {
+ names, err := args.ShiftSafe(1)
+ if err != nil {
+ return errors.New("<account> is required. Usage: cf -a <account> <folder>")
+ }
+ acct, err = app.Account(names[0])
+ if err != nil {
+ return err
+ }
+ } else {
+ acct = app.SelectedAccount()
+ if acct == nil {
+ return errors.New("No account selected")
+ }
}
- var target string
+ if args.Count() == 0 {
+ return errors.New("<folder> is required. Usage: cf [-a <account>] <folder>")
+ }
notmuch, _ := handlers.GetHandlerForScheme("notmuch", new(types.Worker))
if reflect.TypeOf(notmuch) == reflect.TypeOf(acct.Worker().Backend) {
// With notmuch, :cf can change to a "dynamic folder" that
// contains the result of a query. Preserve the entered
// arguments verbatim.
- target = c.Folder
+ target = args.String()
} else {
- parts := opt.SplitArgs(c.Folder)
- if len(parts) != 1 {
- return errors.New("Unexpected argument(s). Usage: cf <folder>")
+ if args.Count() != 1 {
+ return errors.New("Unexpected argument(s). Usage: cf [-a <account>] <folder>")
}
- target = parts[0]
+ target = args.Arg(0)
}
- previous := acct.Directories().Selected()
+ finalize := func(msg types.WorkerMessage) {
+ // As we're waiting for the worker to report status we must run
+ // the rest of the actions in this callback.
+ switch msg := msg.(type) {
+ case *types.Error:
+ app.PushError(msg.Error.Error())
+ case *types.Done:
+ curAccount := app.SelectedAccount()
+ previous := curAccount.Directories().Selected()
+ history[curAccount.Name()] = previous
+ // reset store filtering if we switched folders
+ store := acct.Store()
+ if store != nil {
+ store.ApplyClear()
+ acct.SetStatus(state.SearchFilterClear())
+ }
+ // focus account tab
+ acct.Select()
+ }
+ }
if target == "-" {
if dir, ok := history[acct.Name()]; ok {
- acct.Directories().Select(dir)
+ acct.Directories().Open(dir, 0*time.Second, finalize)
} else {
return errors.New("No previous folder to return to")
}
} else {
- acct.Directories().Select(target)
+ acct.Directories().Open(target, 0*time.Second, finalize)
}
- history[acct.Name()] = previous
- // reset store filtering if we switched folders
- store := acct.Store()
- if store != nil {
- store.ApplyClear()
- acct.SetStatus(state.SearchFilterClear())
- }
return nil
}
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index 28f223bb..1a7afc46 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -386,8 +386,12 @@ message list, the message in the message viewer, etc).
*-s*: Selects the message at the top of the message list after clearing.
-*:cf* _<folder>_
- Change the folder shown in the message list.
+*:cf* [*-a* _<account>_] _<folder>_
+ Change the folder shown in the message list to _<folder>_.
+
+ *-a* _<account>_
+ Change to _<folder>_ of _<account>_ and focus its corresponding
+ tab.
*:check-mail*
Check for new mail on the selected account. Non-imap backends require