diff options
author | Robin Jarry <robin@jarry.cc> | 2023-11-16 14:06:11 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-12-05 01:06:57 +0100 |
commit | 2db657b6bdd6394109c8adc32098d3f39c43f03d (patch) | |
tree | cdbdaf685aaffe52eee598ca9e4760ba18687bc2 | |
parent | c67723bcfbd5d181f2270bc25b691d6f6312a0c1 (diff) | |
download | aerc-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.go | 8 | ||||
-rw-r--r-- | commands/account/cf.go | 89 | ||||
-rw-r--r-- | doc/aerc.1.scd | 8 |
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 |