aboutsummaryrefslogtreecommitdiffstats
path: root/config/binds.go
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2022-12-11 23:57:30 +0100
committerRobin Jarry <robin@jarry.cc>2022-12-14 11:22:53 +0100
commit9d0297e9d913a92b2d7ae02692e83f0f4093a766 (patch)
treeb34425a8a295b3cc52c4cf20904f85019b6352ab /config/binds.go
parent2937830491b5adedf79c8c218afb2c80b17c019a (diff)
downloadaerc-9d0297e9d913a92b2d7ae02692e83f0f4093a766.tar.gz
config: rework contextual sections implementation
The current contextual binds and ui config API is awkward and cumbersome to use. Rework it to make it more elegant. Store the contextual sections as private fields of the UIConfig and KeyBindings structures. Add cache to avoid recomputation of the composed UIConfig and KeyBindings objects every time a contextual item is requested. Replace the cache from DirectoryList with that. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Diffstat (limited to 'config/binds.go')
-rw-r--r--config/binds.go90
1 files changed, 62 insertions, 28 deletions
diff --git a/config/binds.go b/config/binds.go
index 6ddeb1e1..abaff78c 100644
--- a/config/binds.go
+++ b/config/binds.go
@@ -27,11 +27,17 @@ type BindingConfig struct {
Terminal *KeyBindings
}
+type bindsContextType int
+
+const (
+ bindsContextFolder bindsContextType = iota
+ bindsContextAccount
+)
+
type BindingConfigContext struct {
- ContextType ContextType
+ ContextType bindsContextType
Regex *regexp.Regexp
Bindings *KeyBindings
- BindContext string
}
type KeyStroke struct {
@@ -47,11 +53,20 @@ type Binding struct {
type KeyBindings struct {
Bindings []*Binding
-
// If false, disable global keybindings in this context
Globals bool
// Which key opens the ex line (default is :)
ExKey KeyStroke
+
+ // private
+ contextualBinds []*BindingConfigContext
+ contextualCounts map[bindsContextType]int
+ contextualCache map[bindsContextKey]*KeyBindings
+}
+
+type bindsContextKey struct {
+ ctxType bindsContextType
+ value string
}
const (
@@ -115,13 +130,6 @@ func (config *AercConfig) parseBinds(root string) error {
}
}
- config.Bindings.Global.Globals = false
- for _, contextBind := range config.ContextualBinds {
- if contextBind.BindContext == "default" {
- contextBind.Bindings.Globals = false
- }
- }
-
log.Debugf("binds.conf: %#v", config.Bindings)
return nil
}
@@ -168,6 +176,12 @@ func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup
*baseGroup = MergeBindings(binds, *baseGroup)
}
+ b := *baseGroup
+
+ if baseName == "default" {
+ b.Globals = false
+ }
+
for _, sectionName := range binds.SectionStrings() {
if !strings.Contains(sectionName, baseName+":") ||
strings.Contains(sectionName, baseName+"::") {
@@ -183,10 +197,12 @@ func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup
if err != nil {
return err
}
+ if baseName == "default" {
+ binds.Globals = false
+ }
contextualBind := BindingConfigContext{
- Bindings: binds,
- BindContext: baseName,
+ Bindings: binds,
}
var index int
@@ -215,15 +231,16 @@ func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup
log.Warnf("binds.conf: unexistent account: %s", acctName)
continue
}
- contextualBind.ContextType = BIND_CONTEXT_ACCOUNT
+ contextualBind.ContextType = bindsContextAccount
case "folder":
// No validation needed. If the folder doesn't exist, the binds
// never get used
- contextualBind.ContextType = BIND_CONTEXT_FOLDER
+ contextualBind.ContextType = bindsContextFolder
default:
return fmt.Errorf("Unknown Context Bind Section: %s", sectionName)
}
- config.ContextualBinds = append(config.ContextualBinds, contextualBind)
+ b.contextualBinds = append(b.contextualBinds, &contextualBind)
+ b.contextualCounts[contextualBind.ContextType]++
}
return nil
@@ -245,8 +262,10 @@ func defaultBindsConfig() BindingConfig {
func NewKeyBindings() *KeyBindings {
return &KeyBindings{
- ExKey: KeyStroke{tcell.ModNone, tcell.KeyRune, ':'},
- Globals: true,
+ ExKey: KeyStroke{tcell.ModNone, tcell.KeyRune, ':'},
+ Globals: true,
+ contextualCache: make(map[bindsContextKey]*KeyBindings),
+ contextualCounts: make(map[bindsContextType]int),
}
}
@@ -260,26 +279,41 @@ func MergeBindings(bindings ...*KeyBindings) *KeyBindings {
return merged
}
-func (config AercConfig) MergeContextualBinds(baseBinds *KeyBindings,
- contextType ContextType, reg string, bindCtx string,
+func (base *KeyBindings) contextual(
+ contextType bindsContextType, reg string,
) *KeyBindings {
- bindings := baseBinds
- for _, contextualBind := range config.ContextualBinds {
+ if base.contextualCounts[contextType] == 0 {
+ // shortcut if no contextual binds for that type
+ return base
+ }
+
+ key := bindsContextKey{ctxType: contextType, value: reg}
+ c, found := base.contextualCache[key]
+ if found {
+ return c
+ }
+
+ c = base
+ for _, contextualBind := range base.contextualBinds {
if contextualBind.ContextType != contextType {
continue
}
-
if !contextualBind.Regex.Match([]byte(reg)) {
continue
}
+ c = MergeBindings(contextualBind.Bindings, c)
+ }
+ base.contextualCache[key] = c
- if contextualBind.BindContext != bindCtx {
- continue
- }
+ return c
+}
- bindings = MergeBindings(contextualBind.Bindings, bindings)
- }
- return bindings
+func (bindings *KeyBindings) ForAccount(account string) *KeyBindings {
+ return bindings.contextual(bindsContextAccount, account)
+}
+
+func (bindings *KeyBindings) ForFolder(folder string) *KeyBindings {
+ return bindings.contextual(bindsContextFolder, folder)
}
func (bindings *KeyBindings) Add(binding *Binding) {