viewer: add key passthrough mode
When trying to search in less, keys bound to viewer functions can't be used as part of the search query, which makes the search useless. Add a view::passthrough binding mode and a :toggle-key-passthrough command go toggle in and out of that mode. By default, typing '/' in the viewer is bound to enabling key passthrough and automatically inserting '/', to easily enter "less" search mode. When in the passthrough mode, all bindings are ignored by default. The default binds.conf only defines a single keybinding in that mode: <Esc> to get back out. $ex is bound to <C-x> to allow typing colons. Signed-off-by: Kt Programs <ktprograms@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
4bc43d2741
commit
74366d895d
6 changed files with 91 additions and 24 deletions
35
commands/msgview/toggle-key-passthrough.go
Normal file
35
commands/msgview/toggle-key-passthrough.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package msgview
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/widgets"
|
||||
)
|
||||
|
||||
type ToggleKeyPassthrough struct{}
|
||||
|
||||
func init() {
|
||||
register(ToggleKeyPassthrough{})
|
||||
}
|
||||
|
||||
func (ToggleKeyPassthrough) Aliases() []string {
|
||||
return []string{"toggle-key-passthrough"}
|
||||
}
|
||||
|
||||
func (ToggleKeyPassthrough) Complete(aerc *widgets.Aerc, args []string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ToggleKeyPassthrough) Execute(aerc *widgets.Aerc, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("Usage: toggle-key-passthrough")
|
||||
}
|
||||
mv, _ := aerc.SelectedTab().(*widgets.MessageViewer)
|
||||
keyPassthroughEnabled := mv.ToggleKeyPassthrough()
|
||||
if keyPassthroughEnabled {
|
||||
aerc.SetExtraStatus("[passthrough]")
|
||||
} else {
|
||||
aerc.ClearExtraStatus()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -56,6 +56,7 @@ N = :prev-result<Enter>
|
|||
<Esc> = :clear<Enter>
|
||||
|
||||
[view]
|
||||
/ = :toggle-key-passthrough<Enter>/
|
||||
q = :close<Enter>
|
||||
| = :pipe<space>
|
||||
D = :delete<Enter>
|
||||
|
@ -74,6 +75,11 @@ H = :toggle-headers<Enter>
|
|||
J = :next<Enter>
|
||||
K = :prev<Enter>
|
||||
|
||||
[view::passthrough]
|
||||
$noinherit = true
|
||||
$ex = <C-x>
|
||||
<Esc> = :toggle-key-passthrough<Enter>
|
||||
|
||||
[compose]
|
||||
# Keybindings used when the embedded terminal is not selected in the compose
|
||||
# view
|
||||
|
|
|
@ -105,14 +105,15 @@ type AccountConfig struct {
|
|||
}
|
||||
|
||||
type BindingConfig struct {
|
||||
Global *KeyBindings
|
||||
AccountWizard *KeyBindings
|
||||
Compose *KeyBindings
|
||||
ComposeEditor *KeyBindings
|
||||
ComposeReview *KeyBindings
|
||||
MessageList *KeyBindings
|
||||
MessageView *KeyBindings
|
||||
Terminal *KeyBindings
|
||||
Global *KeyBindings
|
||||
AccountWizard *KeyBindings
|
||||
Compose *KeyBindings
|
||||
ComposeEditor *KeyBindings
|
||||
ComposeReview *KeyBindings
|
||||
MessageList *KeyBindings
|
||||
MessageView *KeyBindings
|
||||
MessageViewPassthrough *KeyBindings
|
||||
Terminal *KeyBindings
|
||||
}
|
||||
|
||||
type BindingConfigContext struct {
|
||||
|
@ -143,6 +144,7 @@ type ViewerConfig struct {
|
|||
ShowHeaders bool `ini:"show-headers"`
|
||||
AlwaysShowMime bool `ini:"always-show-mime"`
|
||||
HeaderLayout [][]string `ini:"-"`
|
||||
KeyPassthrough bool `ini:"-"`
|
||||
}
|
||||
|
||||
type TriggersConfig struct {
|
||||
|
@ -591,14 +593,15 @@ func LoadConfigFromFile(root *string, logger *log.Logger) (*AercConfig, error) {
|
|||
file.NameMapper = mapName
|
||||
config := &AercConfig{
|
||||
Bindings: BindingConfig{
|
||||
Global: NewKeyBindings(),
|
||||
AccountWizard: NewKeyBindings(),
|
||||
Compose: NewKeyBindings(),
|
||||
ComposeEditor: NewKeyBindings(),
|
||||
ComposeReview: NewKeyBindings(),
|
||||
MessageList: NewKeyBindings(),
|
||||
MessageView: NewKeyBindings(),
|
||||
Terminal: NewKeyBindings(),
|
||||
Global: NewKeyBindings(),
|
||||
AccountWizard: NewKeyBindings(),
|
||||
Compose: NewKeyBindings(),
|
||||
ComposeEditor: NewKeyBindings(),
|
||||
ComposeReview: NewKeyBindings(),
|
||||
MessageList: NewKeyBindings(),
|
||||
MessageView: NewKeyBindings(),
|
||||
MessageViewPassthrough: NewKeyBindings(),
|
||||
Terminal: NewKeyBindings(),
|
||||
},
|
||||
|
||||
ContextualBinds: []BindingConfigContext{},
|
||||
|
@ -703,13 +706,14 @@ func LoadConfigFromFile(root *string, logger *log.Logger) (*AercConfig, error) {
|
|||
}
|
||||
|
||||
baseGroups := map[string]**KeyBindings{
|
||||
"default": &config.Bindings.Global,
|
||||
"compose": &config.Bindings.Compose,
|
||||
"messages": &config.Bindings.MessageList,
|
||||
"terminal": &config.Bindings.Terminal,
|
||||
"view": &config.Bindings.MessageView,
|
||||
"compose::editor": &config.Bindings.ComposeEditor,
|
||||
"compose::review": &config.Bindings.ComposeReview,
|
||||
"default": &config.Bindings.Global,
|
||||
"compose": &config.Bindings.Compose,
|
||||
"messages": &config.Bindings.MessageList,
|
||||
"terminal": &config.Bindings.Terminal,
|
||||
"view": &config.Bindings.MessageView,
|
||||
"view::passthrough": &config.Bindings.MessageViewPassthrough,
|
||||
"compose::editor": &config.Bindings.ComposeEditor,
|
||||
"compose::review": &config.Bindings.ComposeReview,
|
||||
}
|
||||
|
||||
// Base Bindings
|
||||
|
|
|
@ -564,6 +564,10 @@ are:
|
|||
*[view]*
|
||||
keybindings for the message viewer
|
||||
|
||||
*[view::passthrough]*
|
||||
keybindings for the viewer, when in key passthrough mode
|
||||
(toggled with :toggle-key-passthrough)
|
||||
|
||||
*[compose]*
|
||||
keybindings for the message composer
|
||||
|
||||
|
|
|
@ -201,7 +201,12 @@ func (aerc *Aerc) getBindings() *config.KeyBindings {
|
|||
return aerc.conf.MergeContextualBinds(aerc.conf.Bindings.Compose, config.BIND_CONTEXT_ACCOUNT, selectedAccountName, "compose")
|
||||
}
|
||||
case *MessageViewer:
|
||||
return aerc.conf.MergeContextualBinds(aerc.conf.Bindings.MessageView, config.BIND_CONTEXT_ACCOUNT, selectedAccountName, "view")
|
||||
switch view.Bindings() {
|
||||
case "view::passthrough":
|
||||
return aerc.conf.MergeContextualBinds(aerc.conf.Bindings.MessageViewPassthrough, config.BIND_CONTEXT_ACCOUNT, selectedAccountName, "view::passthrough")
|
||||
default:
|
||||
return aerc.conf.MergeContextualBinds(aerc.conf.Bindings.MessageView, config.BIND_CONTEXT_ACCOUNT, selectedAccountName, "view")
|
||||
}
|
||||
case *Terminal:
|
||||
return aerc.conf.Bindings.Terminal
|
||||
default:
|
||||
|
|
|
@ -286,6 +286,11 @@ func (mv *MessageViewer) ToggleHeaders() {
|
|||
switcher.Invalidate()
|
||||
}
|
||||
|
||||
func (mv *MessageViewer) ToggleKeyPassthrough() bool {
|
||||
mv.conf.Viewer.KeyPassthrough = !mv.conf.Viewer.KeyPassthrough
|
||||
return mv.conf.Viewer.KeyPassthrough
|
||||
}
|
||||
|
||||
func (mv *MessageViewer) SelectedMessagePart() *PartInfo {
|
||||
switcher := mv.switcher
|
||||
part := switcher.parts[switcher.selected]
|
||||
|
@ -325,6 +330,14 @@ func (mv *MessageViewer) NextPart() {
|
|||
mv.Invalidate()
|
||||
}
|
||||
|
||||
func (mv *MessageViewer) Bindings() string {
|
||||
if mv.conf.Viewer.KeyPassthrough {
|
||||
return "view::passthrough"
|
||||
} else {
|
||||
return "view"
|
||||
}
|
||||
}
|
||||
|
||||
func (mv *MessageViewer) Close() error {
|
||||
mv.switcher.Cleanup()
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue