1package keys
2
3// Bindings maps intercepted Alt keys to actions. A Bindings value is mutable
4// while being built, then treated as frozen once published through an atomic
5// pointer; callers must clone before using mutators.
6type Bindings struct {
7 altRunes map[rune]Action
8 altArrows map[byte]Action
9}
10
11var defaultBindings = DefaultBindings()
12
13// DefaultBindings returns vev's built-in Alt-key bindings.
14func DefaultBindings() *Bindings {
15 altRunes := map[rune]Action{
16 ' ': ActionOpenPalette,
17 'a': ActionJumpAttention,
18 'f': ActionToggleFloatingPane,
19 'h': ActionFocusPaneLeft,
20 'j': ActionFocusPaneDown,
21 'k': ActionFocusPaneUp,
22 'l': ActionFocusPaneRight,
23 }
24 for idx, aliases := range topRowDigitAliases {
25 for _, alias := range aliases {
26 altRunes[alias] = ActionSwitchTab1 + Action(idx)
27 }
28 }
29 return &Bindings{
30 altRunes: altRunes,
31 altArrows: map[byte]Action{
32 'A': ActionFocusPaneUp,
33 'B': ActionFocusPaneDown,
34 'C': ActionFocusPaneRight,
35 'D': ActionFocusPaneLeft,
36 },
37 }
38}
39
40func (b *Bindings) clone() *Bindings {
41 if b == nil {
42 return DefaultBindings()
43 }
44 clone := &Bindings{
45 altRunes: make(map[rune]Action, len(b.altRunes)),
46 altArrows: make(map[byte]Action, len(b.altArrows)),
47 }
48 for key, action := range b.altRunes {
49 clone.altRunes[key] = action
50 }
51 for key, action := range b.altArrows {
52 clone.altArrows[key] = action
53 }
54 return clone
55}
56
57func (b *Bindings) removeAction(action Action) {
58 for key, bound := range b.altRunes {
59 if bound == action {
60 delete(b.altRunes, key)
61 }
62 }
63 for key, bound := range b.altArrows {
64 if bound == action {
65 delete(b.altArrows, key)
66 }
67 }
68}
69
70func (b *Bindings) bind(action Action, spec KeySpec) {
71 for _, key := range spec.altRunes {
72 b.altRunes[key] = action
73 }
74 if spec.altArrow != 0 {
75 b.altArrows[spec.altArrow] = action
76 }
77}
78
79func (b *Bindings) restoreDefaultAction(action Action) {
80 defaults := DefaultBindings()
81 for key, bound := range defaults.altRunes {
82 if bound == action {
83 if _, occupied := b.altRunes[key]; !occupied {
84 b.altRunes[key] = action
85 }
86 }
87 }
88 for key, bound := range defaults.altArrows {
89 if bound == action {
90 if _, occupied := b.altArrows[key]; !occupied {
91 b.altArrows[key] = action
92 }
93 }
94 }
95}
96
97func (b *Bindings) conflictingAction(spec KeySpec, action Action) (Action, bool) {
98 for _, key := range spec.altRunes {
99 if bound, ok := b.altRunes[key]; ok && bound != action {
100 return bound, true
101 }
102 }
103 if spec.altArrow != 0 {
104 if bound, ok := b.altArrows[spec.altArrow]; ok && bound != action {
105 return bound, true
106 }
107 }
108 return 0, false
109}
110
111func (b *Bindings) actionForAltRune(key rune) (Action, bool) {
112 if b == nil {
113 b = defaultBindings
114 }
115 action, ok := b.altRunes[key]
116 return action, ok
117}
118
119func (b *Bindings) actionForAltArrow(final byte) (Action, bool) {
120 if b == nil {
121 b = defaultBindings
122 }
123 action, ok := b.altArrows[final]
124 return action, ok
125}