diff --git a/CHANGELOG.md b/CHANGELOG.md index f044039..83e3eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Cursor shape support in embedded terminals. - Bracketed paste support. - Display current directory in `status-line.render-format` with `%p`. +- Change accounts while composing a message with `:switch-account`. ### Changed diff --git a/commands/compose/switch.go b/commands/compose/switch.go index 5109ee0..58702b5 100644 --- a/commands/compose/switch.go +++ b/commands/compose/switch.go @@ -5,6 +5,7 @@ import ( "fmt" "git.sr.ht/~rjarry/aerc/widgets" + "git.sr.ht/~sircmpwn/getopt" ) type AccountSwitcher interface { @@ -26,12 +27,29 @@ func (SwitchAccount) Complete(aerc *widgets.Aerc, args []string) []string { } func (SwitchAccount) Execute(aerc *widgets.Aerc, args []string) error { - if len(args) != 2 { + opts, optind, err := getopt.Getopts(args, "np") + if err != nil { + return err + } + var next, prev bool + for _, opt := range opts { + switch opt.Option { + case 'n': + next = true + prev = false + case 'p': + next = false + prev = true + } + } + posargs := args[optind:] + // NOT ((prev || next) XOR (len(posargs) == 1)) + if (prev || next) == (len(posargs) == 1) { name := "" if acct := aerc.SelectedAccount(); acct != nil { name = fmt.Sprintf("Current account: %s. ", acct.Name()) } - return errors.New(name + "Usage: switch-account ") + return errors.New(name + "Usage: switch-account [-np] ") } switcher, ok := aerc.SelectedTabContent().(AccountSwitcher) @@ -39,9 +57,19 @@ func (SwitchAccount) Execute(aerc *widgets.Aerc, args []string) error { return errors.New("this tab cannot switch accounts") } - if acct, err := aerc.Account(args[1]); err != nil { - return err - } else { - return switcher.SwitchAccount(acct) + var acct *widgets.AccountView + + switch { + case prev: + acct, err = aerc.PrevAccount() + case next: + acct, err = aerc.NextAccount() + default: + acct, err = aerc.Account(posargs[0]) } + if err != nil { + return err + } + + return switcher.SwitchAccount(acct) } diff --git a/config/binds.conf b/config/binds.conf index f46111b..9e23ab9 100644 --- a/config/binds.conf +++ b/config/binds.conf @@ -94,6 +94,8 @@ $noinherit = true $ex = = :prev-field = :next-field + = :switch-account -p + = :switch-account -n = :next-field = :prev-tab = :next-tab diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index f0ca97e..38862a5 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -476,9 +476,12 @@ message list, the message in the message viewer, etc). configuration. For details on configuring outgoing mail delivery consult *aerc-config*(5). -*switch-account* - Switches the account. If run without arguments, the current account name - is displayed. +*switch-account* <-n|-p|account-name> + Switches the account. Can be used to switch to a specific account from + its name or to cycle through accounts using the -p and -n flags. + + *-p*: switch to previous account + *-n*: switch to next account *header* [-f] [value] Add a new email header. If the header already exists, -f must be diff --git a/widgets/aerc.go b/widgets/aerc.go index 656b25d..2b7a6d8 100644 --- a/widgets/aerc.go +++ b/widgets/aerc.go @@ -382,6 +382,42 @@ func (aerc *Aerc) Account(name string) (*AccountView, error) { return nil, fmt.Errorf("account <%s> not found", name) } +func (aerc *Aerc) PrevAccount() (*AccountView, error) { + cur := aerc.SelectedAccount() + if cur == nil { + return nil, fmt.Errorf("no account selected, cannot get prev") + } + for i, conf := range aerc.conf.Accounts { + if conf.Name == cur.Name() { + i -= 1 + if i == -1 { + i = len(aerc.conf.Accounts) - 1 + } + conf = aerc.conf.Accounts[i] + return aerc.Account(conf.Name) + } + } + return nil, fmt.Errorf("no prev account") +} + +func (aerc *Aerc) NextAccount() (*AccountView, error) { + cur := aerc.SelectedAccount() + if cur == nil { + return nil, fmt.Errorf("no account selected, cannot get next") + } + for i, conf := range aerc.conf.Accounts { + if conf.Name == cur.Name() { + i += 1 + if i == len(aerc.conf.Accounts) { + i = 0 + } + conf = aerc.conf.Accounts[i] + return aerc.Account(conf.Name) + } + } + return nil, fmt.Errorf("no next account") +} + func (aerc *Aerc) AccountNames() []string { results := make([]string, 0) for name := range aerc.accounts {