Files
cthulhu/internal/input/tentacle_bindings.go

47 lines
1.5 KiB
Go

package input
import (
"fmt"
"strings"
)
// Tentacle bindings are runtime registrations, never persisted core overrides.
// The native input owner arbitrates them again whenever core settings change.
func ValidateTentacleBindings(bindings []BindingOverride) error {
if len(bindings) > 16*32*4 {
return fmt.Errorf("too many tentacle bindings")
}
for _, binding := range bindings {
if !strings.HasPrefix(string(binding.Command), "tentacle/") || len(binding.Command) > 400 ||
(binding.Layout != DesktopKeyboardLayout && binding.Layout != LaptopKeyboardLayout) ||
(binding.Scope != "global" && binding.Scope != "browse") || len(binding.Keys) != 1 {
return fmt.Errorf("invalid tentacle binding")
}
if _, err := ParseCommandChord(binding.Keys[0]); err != nil {
return err
}
}
return nil
}
// MergeTentacleBindings preserves core bindings and registration order. A
// conflicting suggestion stays unbound. Callers validate both inputs first.
func MergeTentacleBindings(core, suggestions []BindingOverride) []BindingOverride {
result := CloneBindingOverrides(core)
for _, layout := range []KeyboardLayout{DesktopKeyboardLayout, LaptopKeyboardLayout} {
occupied, _ := ResolveCommandBindings(layout, true, core)
for _, suggestion := range suggestions {
if suggestion.Layout != layout {
continue
}
chord, _ := ParseCommandChord(suggestion.Keys[0])
if occupied[chord] != "" {
continue
}
occupied[chord] = suggestion.Command
result = append(result, CloneBindingOverrides([]BindingOverride{suggestion})[0])
}
}
return result
}