switch: add -n and -p flags for relative switch

Allow switching to next or previous account with switch-account -n and
switch-account -p, respectively. By default, these are bound to Alt-n
and Alt-p.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Koni Marti <koni.marti@gmail.com>
This commit is contained in:
Robin Jarry 2022-09-19 23:58:24 +02:00
parent fcd75ab529
commit bb9ac43e13
5 changed files with 79 additions and 9 deletions

View file

@ -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. - Cursor shape support in embedded terminals.
- Bracketed paste support. - Bracketed paste support.
- Display current directory in `status-line.render-format` with `%p`. - Display current directory in `status-line.render-format` with `%p`.
- Change accounts while composing a message with `:switch-account`.
### Changed ### Changed

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
"git.sr.ht/~sircmpwn/getopt"
) )
type AccountSwitcher interface { 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 { 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 := "" name := ""
if acct := aerc.SelectedAccount(); acct != nil { if acct := aerc.SelectedAccount(); acct != nil {
name = fmt.Sprintf("Current account: %s. ", acct.Name()) name = fmt.Sprintf("Current account: %s. ", acct.Name())
} }
return errors.New(name + "Usage: switch-account <account-name>") return errors.New(name + "Usage: switch-account [-np] <account-name>")
} }
switcher, ok := aerc.SelectedTabContent().(AccountSwitcher) 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") return errors.New("this tab cannot switch accounts")
} }
if acct, err := aerc.Account(args[1]); err != nil { 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 err
} else { }
return switcher.SwitchAccount(acct) return switcher.SwitchAccount(acct)
} }
}

View file

@ -94,6 +94,8 @@ $noinherit = true
$ex = <C-x> $ex = <C-x>
<C-k> = :prev-field<Enter> <C-k> = :prev-field<Enter>
<C-j> = :next-field<Enter> <C-j> = :next-field<Enter>
<A-p> = :switch-account -p<Enter>
<A-n> = :switch-account -n<Enter>
<tab> = :next-field<Enter> <tab> = :next-field<Enter>
<C-p> = :prev-tab<Enter> <C-p> = :prev-tab<Enter>
<C-n> = :next-tab<Enter> <C-n> = :next-tab<Enter>

View file

@ -476,9 +476,12 @@ message list, the message in the message viewer, etc).
configuration. For details on configuring outgoing mail delivery consult configuration. For details on configuring outgoing mail delivery consult
*aerc-config*(5). *aerc-config*(5).
*switch-account* <account-name> *switch-account* <-n|-p|account-name>
Switches the account. If run without arguments, the current account name Switches the account. Can be used to switch to a specific account from
is displayed. 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] <field> [value] *header* [-f] <field> [value]
Add a new email header. If the header already exists, -f must be Add a new email header. If the header already exists, -f must be

View file

@ -382,6 +382,42 @@ func (aerc *Aerc) Account(name string) (*AccountView, error) {
return nil, fmt.Errorf("account <%s> not found", name) 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 { func (aerc *Aerc) AccountNames() []string {
results := make([]string, 0) results := make([]string, 0)
for name := range aerc.accounts { for name := range aerc.accounts {