about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2021-10-25 15:00:43 +0200
committerRobin Jarry <robin@jarry.cc>2021-10-28 16:21:37 +0200
commit7a6c808c042bf6f662e6d6b6dba09829a1f9ed15 (patch)
treef765cba8bfecd83f787e355c688c3ebc78fb7d10
parent0b19b5e70e408bbaac5555b0b61a9451189406f8 (diff)
downloadaerc-7a6c808c042bf6f662e6d6b6dba09829a1f9ed15.tar.gz
bindings: prepare for more modifers
Prepare to support more modifiers in key bindings.

tcell has some premade ctrl-modified keys but not all keys are
supported. Other keys must be explicitly checked with a modifier mask.

Update the KeyStroke type to carry a modifier mask. Update code
accordingly.

No functional change.

Link: https://github.com/gdamore/tcell/blob/master/key.go#L265-L275
Link: https://github.com/gdamore/tcell/blob/master/key.go#L384-L419
Signed-off-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--config/bindings.go315
-rw-r--r--config/bindings_test.go26
-rw-r--r--widgets/aerc.go1
3 files changed, 174 insertions, 168 deletions
diff --git a/config/bindings.go b/config/bindings.go
index 9956b41..f517c73 100644
--- a/config/bindings.go
+++ b/config/bindings.go
@@ -11,6 +11,7 @@ import (
 )
 
 type KeyStroke struct {
+	Modifiers tcell.ModMask
 	Key  tcell.Key
 	Rune rune
 }
@@ -39,7 +40,7 @@ type BindingSearchResult int
 
 func NewKeyBindings() *KeyBindings {
 	return &KeyBindings{
-		ExKey:   KeyStroke{tcell.KeyRune, ':'},
+		ExKey:   KeyStroke{tcell.ModNone, tcell.KeyRune, ':'},
 		Globals: true,
 	}
 }
@@ -70,6 +71,9 @@ func (bindings *KeyBindings) GetBinding(
 			continue
 		}
 		for i, stroke := range input {
+			if stroke.Modifiers != binding.Input[i].Modifiers {
+				goto next
+			}
 			if stroke.Key != binding.Input[i].Key {
 				goto next
 			}
@@ -128,6 +132,7 @@ func ParseKeyStrokes(keystrokes string) ([]KeyStroke, error) {
 			return nil, errors.New("Found '>' without '<'")
 		default:
 			strokes = append(strokes, KeyStroke{
+				Modifiers: tcell.ModNone,
 				Key:  tcell.KeyRune,
 				Rune: tok,
 			})
@@ -153,158 +158,158 @@ func ParseBinding(input, output string) (*Binding, error) {
 
 func init() {
 	keyNames = make(map[string]KeyStroke)
-	keyNames["space"] = KeyStroke{tcell.KeyRune, ' '}
-	keyNames["semicolon"] = KeyStroke{tcell.KeyRune, ';'}
-	keyNames["enter"] = KeyStroke{tcell.KeyEnter, 0}
-	keyNames["up"] = KeyStroke{tcell.KeyUp, 0}
-	keyNames["down"] = KeyStroke{tcell.KeyDown, 0}
-	keyNames["right"] = KeyStroke{tcell.KeyRight, 0}
-	keyNames["left"] = KeyStroke{tcell.KeyLeft, 0}
-	keyNames["upleft"] = KeyStroke{tcell.KeyUpLeft, 0}
-	keyNames["upright"] = KeyStroke{tcell.KeyUpRight, 0}
-	keyNames["downleft"] = KeyStroke{tcell.KeyDownLeft, 0}
-	keyNames["downright"] = KeyStroke{tcell.KeyDownRight, 0}
-	keyNames["center"] = KeyStroke{tcell.KeyCenter, 0}
-	keyNames["pgup"] = KeyStroke{tcell.KeyPgUp, 0}
-	keyNames["pgdn"] = KeyStroke{tcell.KeyPgDn, 0}
-	keyNames["home"] = KeyStroke{tcell.KeyHome, 0}
-	keyNames["end"] = KeyStroke{tcell.KeyEnd, 0}
-	keyNames["insert"] = KeyStroke{tcell.KeyInsert, 0}
-	keyNames["delete"] = KeyStroke{tcell.KeyDelete, 0}
-	keyNames["help"] = KeyStroke{tcell.KeyHelp, 0}
-	keyNames["exit"] = KeyStroke{tcell.KeyExit, 0}
-	keyNames["clear"] = KeyStroke{tcell.KeyClear, 0}
-	keyNames["cancel"] = KeyStroke{tcell.KeyCancel, 0}
-	keyNames["print"] = KeyStroke{tcell.KeyPrint, 0}
-	keyNames["pause"] = KeyStroke{tcell.KeyPause, 0}
-	keyNames["backtab"] = KeyStroke{tcell.KeyBacktab, 0}
-	keyNames["f1"] = KeyStroke{tcell.KeyF1, 0}
-	keyNames["f2"] = KeyStroke{tcell.KeyF2, 0}
-	keyNames["f3"] = KeyStroke{tcell.KeyF3, 0}
-	keyNames["f4"] = KeyStroke{tcell.KeyF4, 0}
-	keyNames["f5"] = KeyStroke{tcell.KeyF5, 0}
-	keyNames["f6"] = KeyStroke{tcell.KeyF6, 0}
-	keyNames["f7"] = KeyStroke{tcell.KeyF7, 0}
-	keyNames["f8"] = KeyStroke{tcell.KeyF8, 0}
-	keyNames["f9"] = KeyStroke{tcell.KeyF9, 0}
-	keyNames["f10"] = KeyStroke{tcell.KeyF10, 0}
-	keyNames["f11"] = KeyStroke{tcell.KeyF11, 0}
-	keyNames["f12"] = KeyStroke{tcell.KeyF12, 0}
-	keyNames["f13"] = KeyStroke{tcell.KeyF13, 0}
-	keyNames["f14"] = KeyStroke{tcell.KeyF14, 0}
-	keyNames["f15"] = KeyStroke{tcell.KeyF15, 0}
-	keyNames["f16"] = KeyStroke{tcell.KeyF16, 0}
-	keyNames["f17"] = KeyStroke{tcell.KeyF17, 0}
-	keyNames["f18"] = KeyStroke{tcell.KeyF18, 0}
-	keyNames["f19"] = KeyStroke{tcell.KeyF19, 0}
-	keyNames["f20"] = KeyStroke{tcell.KeyF20, 0}
-	keyNames["f21"] = KeyStroke{tcell.KeyF21, 0}
-	keyNames["f22"] = KeyStroke{tcell.KeyF22, 0}
-	keyNames["f23"] = KeyStroke{tcell.KeyF23, 0}
-	keyNames["f24"] = KeyStroke{tcell.KeyF24, 0}
-	keyNames["f25"] = KeyStroke{tcell.KeyF25, 0}
-	keyNames["f26"] = KeyStroke{tcell.KeyF26, 0}
-	keyNames["f27"] = KeyStroke{tcell.KeyF27, 0}
-	keyNames["f28"] = KeyStroke{tcell.KeyF28, 0}
-	keyNames["f29"] = KeyStroke{tcell.KeyF29, 0}
-	keyNames["f30"] = KeyStroke{tcell.KeyF30, 0}
-	keyNames["f31"] = KeyStroke{tcell.KeyF31, 0}
-	keyNames["f32"] = KeyStroke{tcell.KeyF32, 0}
-	keyNames["f33"] = KeyStroke{tcell.KeyF33, 0}
-	keyNames["f34"] = KeyStroke{tcell.KeyF34, 0}
-	keyNames["f35"] = KeyStroke{tcell.KeyF35, 0}
-	keyNames["f36"] = KeyStroke{tcell.KeyF36, 0}
-	keyNames["f37"] = KeyStroke{tcell.KeyF37, 0}
-	keyNames["f38"] = KeyStroke{tcell.KeyF38, 0}
-	keyNames["f39"] = KeyStroke{tcell.KeyF39, 0}
-	keyNames["f40"] = KeyStroke{tcell.KeyF40, 0}
-	keyNames["f41"] = KeyStroke{tcell.KeyF41, 0}
-	keyNames["f42"] = KeyStroke{tcell.KeyF42, 0}
-	keyNames["f43"] = KeyStroke{tcell.KeyF43, 0}
-	keyNames["f44"] = KeyStroke{tcell.KeyF44, 0}
-	keyNames["f45"] = KeyStroke{tcell.KeyF45, 0}
-	keyNames["f46"] = KeyStroke{tcell.KeyF46, 0}
-	keyNames["f47"] = KeyStroke{tcell.KeyF47, 0}
-	keyNames["f48"] = KeyStroke{tcell.KeyF48, 0}
-	keyNames["f49"] = KeyStroke{tcell.KeyF49, 0}
-	keyNames["f50"] = KeyStroke{tcell.KeyF50, 0}
-	keyNames["f51"] = KeyStroke{tcell.KeyF51, 0}
-	keyNames["f52"] = KeyStroke{tcell.KeyF52, 0}
-	keyNames["f53"] = KeyStroke{tcell.KeyF53, 0}
-	keyNames["f54"] = KeyStroke{tcell.KeyF54, 0}
-	keyNames["f55"] = KeyStroke{tcell.KeyF55, 0}
-	keyNames["f56"] = KeyStroke{tcell.KeyF56, 0}
-	keyNames["f57"] = KeyStroke{tcell.KeyF57, 0}
-	keyNames["f58"] = KeyStroke{tcell.KeyF58, 0}
-	keyNames["f59"] = KeyStroke{tcell.KeyF59, 0}
-	keyNames["f60"] = KeyStroke{tcell.KeyF60, 0}
-	keyNames["f61"] = KeyStroke{tcell.KeyF61, 0}
-	keyNames["f62"] = KeyStroke{tcell.KeyF62, 0}
-	keyNames["f63"] = KeyStroke{tcell.KeyF63, 0}
-	keyNames["f64"] = KeyStroke{tcell.KeyF64, 0}
-	keyNames["c-space"] = KeyStroke{tcell.KeyCtrlSpace, 0}
-	keyNames["c-a"] = KeyStroke{tcell.KeyCtrlA, 0}
-	keyNames["c-b"] = KeyStroke{tcell.KeyCtrlB, 0}
-	keyNames["c-c"] = KeyStroke{tcell.KeyCtrlC, 0}
-	keyNames["c-d"] = KeyStroke{tcell.KeyCtrlD, 0}
-	keyNames["c-e"] = KeyStroke{tcell.KeyCtrlE, 0}
-	keyNames["c-f"] = KeyStroke{tcell.KeyCtrlF, 0}
-	keyNames["c-g"] = KeyStroke{tcell.KeyCtrlG, 0}
-	keyNames["c-h"] = KeyStroke{tcell.KeyCtrlH, 0}
-	keyNames["c-i"] = KeyStroke{tcell.KeyCtrlI, 0}
-	keyNames["c-j"] = KeyStroke{tcell.KeyCtrlJ, 0}
-	keyNames["c-k"] = KeyStroke{tcell.KeyCtrlK, 0}
-	keyNames["c-l"] = KeyStroke{tcell.KeyCtrlL, 0}
-	keyNames["c-m"] = KeyStroke{tcell.KeyCtrlM, 0}
-	keyNames["c-n"] = KeyStroke{tcell.KeyCtrlN, 0}
-	keyNames["c-o"] = KeyStroke{tcell.KeyCtrlO, 0}
-	keyNames["c-p"] = KeyStroke{tcell.KeyCtrlP, 0}
-	keyNames["c-q"] = KeyStroke{tcell.KeyCtrlQ, 0}
-	keyNames["c-r"] = KeyStroke{tcell.KeyCtrlR, 0}
-	keyNames["c-s"] = KeyStroke{tcell.KeyCtrlS, 0}
-	keyNames["c-t"] = KeyStroke{tcell.KeyCtrlT, 0}
-	keyNames["c-u"] = KeyStroke{tcell.KeyCtrlU, 0}
-	keyNames["c-v"] = KeyStroke{tcell.KeyCtrlV, 0}
-	keyNames["c-w"] = KeyStroke{tcell.KeyCtrlW, 0}
-	keyNames["c-x"] = KeyStroke{tcell.KeyCtrlX, rune(tcell.KeyCAN)}
-	keyNames["c-y"] = KeyStroke{tcell.KeyCtrlY, 0} // TODO: runes for the rest
-	keyNames["c-z"] = KeyStroke{tcell.KeyCtrlZ, 0}
-	keyNames["c-]"] = KeyStroke{tcell.KeyCtrlLeftSq, 0}
-	keyNames["c-\\"] = KeyStroke{tcell.KeyCtrlBackslash, 0}
-	keyNames["c-["] = KeyStroke{tcell.KeyCtrlRightSq, 0}
-	keyNames["c-^"] = KeyStroke{tcell.KeyCtrlCarat, 0}
-	keyNames["c-_"] = KeyStroke{tcell.KeyCtrlUnderscore, 0}
-	keyNames["nul"] = KeyStroke{tcell.KeyNUL, 0}
-	keyNames["soh"] = KeyStroke{tcell.KeySOH, 0}
-	keyNames["stx"] = KeyStroke{tcell.KeySTX, 0}
-	keyNames["etx"] = KeyStroke{tcell.KeyETX, 0}
-	keyNames["eot"] = KeyStroke{tcell.KeyEOT, 0}
-	keyNames["enq"] = KeyStroke{tcell.KeyENQ, 0}
-	keyNames["ack"] = KeyStroke{tcell.KeyACK, 0}
-	keyNames["bel"] = KeyStroke{tcell.KeyBEL, 0}
-	keyNames["bs"] = KeyStroke{tcell.KeyBS, 0}
-	keyNames["tab"] = KeyStroke{tcell.KeyTAB, 0}
-	keyNames["lf"] = KeyStroke{tcell.KeyLF, 0}
-	keyNames["vt"] = KeyStroke{tcell.KeyVT, 0}
-	keyNames["ff"] = KeyStroke{tcell.KeyFF, 0}
-	keyNames["cr"] = KeyStroke{tcell.KeyCR, 0}
-	keyNames["so"] = KeyStroke{tcell.KeySO, 0}
-	keyNames["si"] = KeyStroke{tcell.KeySI, 0}
-	keyNames["dle"] = KeyStroke{tcell.KeyDLE, 0}
-	keyNames["dc1"] = KeyStroke{tcell.KeyDC1, 0}
-	keyNames["dc2"] = KeyStroke{tcell.KeyDC2, 0}
-	keyNames["dc3"] = KeyStroke{tcell.KeyDC3, 0}
-	keyNames["dc4"] = KeyStroke{tcell.KeyDC4, 0}
-	keyNames["nak"] = KeyStroke{tcell.KeyNAK, 0}
-	keyNames["syn"] = KeyStroke{tcell.KeySYN, 0}
-	keyNames["etb"] = KeyStroke{tcell.KeyETB, 0}
-	keyNames["can"] = KeyStroke{tcell.KeyCAN, 0}
-	keyNames["em"] = KeyStroke{tcell.KeyEM, 0}
-	keyNames["sub"] = KeyStroke{tcell.KeySUB, 0}
-	keyNames["esc"] = KeyStroke{tcell.KeyESC, 0}
-	keyNames["fs"] = KeyStroke{tcell.KeyFS, 0}
-	keyNames["gs"] = KeyStroke{tcell.KeyGS, 0}
-	keyNames["rs"] = KeyStroke{tcell.KeyRS, 0}
-	keyNames["us"] = KeyStroke{tcell.KeyUS, 0}
-	keyNames["del"] = KeyStroke{tcell.KeyDEL, 0}
+	keyNames["space"] = KeyStroke{tcell.ModNone, tcell.KeyRune, ' '}
+	keyNames["semicolon"] = KeyStroke{tcell.ModNone, tcell.KeyRune, ';'}
+	keyNames["enter"] = KeyStroke{tcell.ModNone, tcell.KeyEnter, 0}
+	keyNames["up"] = KeyStroke{tcell.ModNone, tcell.KeyUp, 0}
+	keyNames["down"] = KeyStroke{tcell.ModNone, tcell.KeyDown, 0}
+	keyNames["right"] = KeyStroke{tcell.ModNone, tcell.KeyRight, 0}
+	keyNames["left"] = KeyStroke{tcell.ModNone, tcell.KeyLeft, 0}
+	keyNames["upleft"] = KeyStroke{tcell.ModNone, tcell.KeyUpLeft, 0}
+	keyNames["upright"] = KeyStroke{tcell.ModNone, tcell.KeyUpRight, 0}
+	keyNames["downleft"] = KeyStroke{tcell.ModNone, tcell.KeyDownLeft, 0}
+	keyNames["downright"] = KeyStroke{tcell.ModNone, tcell.KeyDownRight, 0}
+	keyNames["center"] = KeyStroke{tcell.ModNone, tcell.KeyCenter, 0}
+	keyNames["pgup"] = KeyStroke{tcell.ModNone, tcell.KeyPgUp, 0}
+	keyNames["pgdn"] = KeyStroke{tcell.ModNone, tcell.KeyPgDn, 0}
+	keyNames["home"] = KeyStroke{tcell.ModNone, tcell.KeyHome, 0}
+	keyNames["end"] = KeyStroke{tcell.ModNone, tcell.KeyEnd, 0}
+	keyNames["insert"] = KeyStroke{tcell.ModNone, tcell.KeyInsert, 0}
+	keyNames["delete"] = KeyStroke{tcell.ModNone, tcell.KeyDelete, 0}
+	keyNames["help"] = KeyStroke{tcell.ModNone, tcell.KeyHelp, 0}
+	keyNames["exit"] = KeyStroke{tcell.ModNone, tcell.KeyExit, 0}
+	keyNames["clear"] = KeyStroke{tcell.ModNone, tcell.KeyClear, 0}
+	keyNames["cancel"] = KeyStroke{tcell.ModNone, tcell.KeyCancel, 0}
+	keyNames["print"] = KeyStroke{tcell.ModNone, tcell.KeyPrint, 0}
+	keyNames["pause"] = KeyStroke{tcell.ModNone, tcell.KeyPause, 0}
+	keyNames["backtab"] = KeyStroke{tcell.ModNone, tcell.KeyBacktab, 0}
+	keyNames["f1"] = KeyStroke{tcell.ModNone, tcell.KeyF1, 0}
+	keyNames["f2"] = KeyStroke{tcell.ModNone, tcell.KeyF2, 0}
+	keyNames["f3"] = KeyStroke{tcell.ModNone, tcell.KeyF3, 0}
+	keyNames["f4"] = KeyStroke{tcell.ModNone, tcell.KeyF4, 0}
+	keyNames["f5"] = KeyStroke{tcell.ModNone, tcell.KeyF5, 0}
+	keyNames["f6"] = KeyStroke{tcell.ModNone, tcell.KeyF6, 0}
+	keyNames["f7"] = KeyStroke{tcell.ModNone, tcell.KeyF7, 0}
+	keyNames["f8"] = KeyStroke{tcell.ModNone, tcell.KeyF8, 0}
+	keyNames["f9"] = KeyStroke{tcell.ModNone, tcell.KeyF9, 0}
+	keyNames["f10"] = KeyStroke{tcell.ModNone, tcell.KeyF10, 0}
+	keyNames["f11"] = KeyStroke{tcell.ModNone, tcell.KeyF11, 0}
+	keyNames["f12"] = KeyStroke{tcell.ModNone, tcell.KeyF12, 0}
+	keyNames["f13"] = KeyStroke{tcell.ModNone, tcell.KeyF13, 0}
+	keyNames["f14"] = KeyStroke{tcell.ModNone, tcell.KeyF14, 0}
+	keyNames["f15"] = KeyStroke{tcell.ModNone, tcell.KeyF15, 0}
+	keyNames["f16"] = KeyStroke{tcell.ModNone, tcell.KeyF16, 0}
+	keyNames["f17"] = KeyStroke{tcell.ModNone, tcell.KeyF17, 0}
+	keyNames["f18"] = KeyStroke{tcell.ModNone, tcell.KeyF18, 0}
+	keyNames["f19"] = KeyStroke{tcell.ModNone, tcell.KeyF19, 0}
+	keyNames["f20"] = KeyStroke{tcell.ModNone, tcell.KeyF20, 0}
+	keyNames["f21"] = KeyStroke{tcell.ModNone, tcell.KeyF21, 0}
+	keyNames["f22"] = KeyStroke{tcell.ModNone, tcell.KeyF22, 0}
+	keyNames["f23"] = KeyStroke{tcell.ModNone, tcell.KeyF23, 0}
+	keyNames["f24"] = KeyStroke{tcell.ModNone, tcell.KeyF24, 0}
+	keyNames["f25"] = KeyStroke{tcell.ModNone, tcell.KeyF25, 0}
+	keyNames["f26"] = KeyStroke{tcell.ModNone, tcell.KeyF26, 0}
+	keyNames["f27"] = KeyStroke{tcell.ModNone, tcell.KeyF27, 0}
+	keyNames["f28"] = KeyStroke{tcell.ModNone, tcell.KeyF28, 0}
+	keyNames["f29"] = KeyStroke{tcell.ModNone, tcell.KeyF29, 0}
+	keyNames["f30"] = KeyStroke{tcell.ModNone, tcell.KeyF30, 0}
+	keyNames["f31"] = KeyStroke{tcell.ModNone, tcell.KeyF31, 0}
+	keyNames["f32"] = KeyStroke{tcell.ModNone, tcell.KeyF32, 0}
+	keyNames["f33"] = KeyStroke{tcell.ModNone, tcell.KeyF33, 0}
+	keyNames["f34"] = KeyStroke{tcell.ModNone, tcell.KeyF34, 0}
+	keyNames["f35"] = KeyStroke{tcell.ModNone, tcell.KeyF35, 0}
+	keyNames["f36"] = KeyStroke{tcell.ModNone, tcell.KeyF36, 0}
+	keyNames["f37"] = KeyStroke{tcell.ModNone, tcell.KeyF37, 0}
+	keyNames["f38"] = KeyStroke{tcell.ModNone, tcell.KeyF38, 0}
+	keyNames["f39"] = KeyStroke{tcell.ModNone, tcell.KeyF39, 0}
+	keyNames["f40"] = KeyStroke{tcell.ModNone, tcell.KeyF40, 0}
+	keyNames["f41"] = KeyStroke{tcell.ModNone, tcell.KeyF41, 0}
+	keyNames["f42"] = KeyStroke{tcell.ModNone, tcell.KeyF42, 0}
+	keyNames["f43"] = KeyStroke{tcell.ModNone, tcell.KeyF43, 0}
+	keyNames["f44"] = KeyStroke{tcell.ModNone, tcell.KeyF44, 0}
+	keyNames["f45"] = KeyStroke{tcell.ModNone, tcell.KeyF45, 0}
+	keyNames["f46"] = KeyStroke{tcell.ModNone, tcell.KeyF46, 0}
+	keyNames["f47"] = KeyStroke{tcell.ModNone, tcell.KeyF47, 0}
+	keyNames["f48"] = KeyStroke{tcell.ModNone, tcell.KeyF48, 0}
+	keyNames["f49"] = KeyStroke{tcell.ModNone, tcell.KeyF49, 0}
+	keyNames["f50"] = KeyStroke{tcell.ModNone, tcell.KeyF50, 0}
+	keyNames["f51"] = KeyStroke{tcell.ModNone, tcell.KeyF51, 0}
+	keyNames["f52"] = KeyStroke{tcell.ModNone, tcell.KeyF52, 0}
+	keyNames["f53"] = KeyStroke{tcell.ModNone, tcell.KeyF53, 0}
+	keyNames["f54"] = KeyStroke{tcell.ModNone, tcell.KeyF54, 0}
+	keyNames["f55"] = KeyStroke{tcell.ModNone, tcell.KeyF55, 0}
+	keyNames["f56"] = KeyStroke{tcell.ModNone, tcell.KeyF56, 0}
+	keyNames["f57"] = KeyStroke{tcell.ModNone, tcell.KeyF57, 0}
+	keyNames["f58"] = KeyStroke{tcell.ModNone, tcell.KeyF58, 0}
+	keyNames["f59"] = KeyStroke{tcell.ModNone, tcell.KeyF59, 0}
+	keyNames["f60"] = KeyStroke{tcell.ModNone, tcell.KeyF60, 0}
+	keyNames["f61"] = KeyStroke{tcell.ModNone, tcell.KeyF61, 0}
+	keyNames["f62"] = KeyStroke{tcell.ModNone, tcell.KeyF62, 0}
+	keyNames["f63"] = KeyStroke{tcell.ModNone, tcell.KeyF63, 0}
+	keyNames["f64"] = KeyStroke{tcell.ModNone, tcell.KeyF64, 0}
+	keyNames["c-space"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlSpace, 0}
+	keyNames["c-a"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlA, 0}
+	keyNames["c-b"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlB, 0}
+	keyNames["c-c"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlC, 0}
+	keyNames["c-d"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlD, 0}
+	keyNames["c-e"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlE, 0}
+	keyNames["c-f"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlF, 0}
+	keyNames["c-g"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlG, 0}
+	keyNames["c-h"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlH, 0}
+	keyNames["c-i"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlI, 0}
+	keyNames["c-j"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlJ, 0}
+	keyNames["c-k"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlK, 0}
+	keyNames["c-l"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlL, 0}
+	keyNames["c-m"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlM, 0}
+	keyNames["c-n"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlN, 0}
+	keyNames["c-o"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlO, 0}
+	keyNames["c-p"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlP, 0}
+	keyNames["c-q"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlQ, 0}
+	keyNames["c-r"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlR, 0}
+	keyNames["c-s"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlS, 0}
+	keyNames["c-t"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlT, 0}
+	keyNames["c-u"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlU, 0}
+	keyNames["c-v"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlV, 0}
+	keyNames["c-w"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlW, 0}
+	keyNames["c-x"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlX, rune(tcell.KeyCAN)}
+	keyNames["c-y"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlY, 0} // TODO: runes for the rest
+	keyNames["c-z"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlZ, 0}
+	keyNames["c-]"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlLeftSq, 0}
+	keyNames["c-\\"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlBackslash, 0}
+	keyNames["c-["] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlRightSq, 0}
+	keyNames["c-^"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlCarat, 0}
+	keyNames["c-_"] = KeyStroke{tcell.ModCtrl, tcell.KeyCtrlUnderscore, 0}
+	keyNames["nul"] = KeyStroke{tcell.ModNone, tcell.KeyNUL, 0}
+	keyNames["soh"] = KeyStroke{tcell.ModNone, tcell.KeySOH, 0}
+	keyNames["stx"] = KeyStroke{tcell.ModNone, tcell.KeySTX, 0}
+	keyNames["etx"] = KeyStroke{tcell.ModNone, tcell.KeyETX, 0}
+	keyNames["eot"] = KeyStroke{tcell.ModNone, tcell.KeyEOT, 0}
+	keyNames["enq"] = KeyStroke{tcell.ModNone, tcell.KeyENQ, 0}
+	keyNames["ack"] = KeyStroke{tcell.ModNone, tcell.KeyACK, 0}
+	keyNames["bel"] = KeyStroke{tcell.ModNone, tcell.KeyBEL, 0}
+	keyNames["bs"] = KeyStroke{tcell.ModNone, tcell.KeyBS, 0}
+	keyNames["tab"] = KeyStroke{tcell.ModNone, tcell.KeyTAB, 0}
+	keyNames["lf"] = KeyStroke{tcell.ModNone, tcell.KeyLF, 0}
+	keyNames["vt"] = KeyStroke{tcell.ModNone, tcell.KeyVT, 0}
+	keyNames["ff"] = KeyStroke{tcell.ModNone, tcell.KeyFF, 0}
+	keyNames["cr"] = KeyStroke{tcell.ModNone, tcell.KeyCR, 0}
+	keyNames["so"] = KeyStroke{tcell.ModNone, tcell.KeySO, 0}
+	keyNames["si"] = KeyStroke{tcell.ModNone, tcell.KeySI, 0}
+	keyNames["dle"] = KeyStroke{tcell.ModNone, tcell.KeyDLE, 0}
+	keyNames["dc1"] = KeyStroke{tcell.ModNone, tcell.KeyDC1, 0}
+	keyNames["dc2"] = KeyStroke{tcell.ModNone, tcell.KeyDC2, 0}
+	keyNames["dc3"] = KeyStroke{tcell.ModNone, tcell.KeyDC3, 0}
+	keyNames["dc4"] = KeyStroke{tcell.ModNone, tcell.KeyDC4, 0}
+	keyNames["nak"] = KeyStroke{tcell.ModNone, tcell.KeyNAK, 0}
+	keyNames["syn"] = KeyStroke{tcell.ModNone, tcell.KeySYN, 0}
+	keyNames["etb"] = KeyStroke{tcell.ModNone, tcell.KeyETB, 0}
+	keyNames["can"] = KeyStroke{tcell.ModNone, tcell.KeyCAN, 0}
+	keyNames["em"] = KeyStroke{tcell.ModNone, tcell.KeyEM, 0}
+	keyNames["sub"] = KeyStroke{tcell.ModNone, tcell.KeySUB, 0}
+	keyNames["esc"] = KeyStroke{tcell.ModNone, tcell.KeyESC, 0}
+	keyNames["fs"] = KeyStroke{tcell.ModNone, tcell.KeyFS, 0}
+	keyNames["gs"] = KeyStroke{tcell.ModNone, tcell.KeyGS, 0}
+	keyNames["rs"] = KeyStroke{tcell.ModNone, tcell.KeyRS, 0}
+	keyNames["us"] = KeyStroke{tcell.ModNone, tcell.KeyUS, 0}
+	keyNames["del"] = KeyStroke{tcell.ModNone, tcell.KeyDEL, 0}
 }
diff --git a/config/bindings_test.go b/config/bindings_test.go
index 4459736..d07d65a 100644
--- a/config/bindings_test.go
+++ b/config/bindings_test.go
@@ -32,30 +32,30 @@ func TestGetBinding(t *testing.T) {
 	}
 
 	test([]KeyStroke{
-		{tcell.KeyRune, 'a'},
+		{tcell.ModNone, tcell.KeyRune, 'a'},
 	}, BINDING_INCOMPLETE, "")
 	test([]KeyStroke{
-		{tcell.KeyRune, 'a'},
-		{tcell.KeyRune, 'b'},
-		{tcell.KeyRune, 'c'},
+		{tcell.ModNone, tcell.KeyRune, 'a'},
+		{tcell.ModNone, tcell.KeyRune, 'b'},
+		{tcell.ModNone, tcell.KeyRune, 'c'},
 	}, BINDING_FOUND, ":abc")
 	test([]KeyStroke{
-		{tcell.KeyRune, 'c'},
-		{tcell.KeyRune, 'b'},
-		{tcell.KeyRune, 'a'},
+		{tcell.ModNone, tcell.KeyRune, 'c'},
+		{tcell.ModNone, tcell.KeyRune, 'b'},
+		{tcell.ModNone, tcell.KeyRune, 'a'},
 	}, BINDING_FOUND, ":cba")
 	test([]KeyStroke{
-		{tcell.KeyRune, 'f'},
-		{tcell.KeyRune, 'o'},
+		{tcell.ModNone, tcell.KeyRune, 'f'},
+		{tcell.ModNone, tcell.KeyRune, 'o'},
 	}, BINDING_INCOMPLETE, "")
 	test([]KeyStroke{
-		{tcell.KeyRune, '4'},
-		{tcell.KeyRune, '0'},
-		{tcell.KeyRune, '4'},
+		{tcell.ModNone, tcell.KeyRune, '4'},
+		{tcell.ModNone, tcell.KeyRune, '0'},
+		{tcell.ModNone, tcell.KeyRune, '4'},
 	}, BINDING_NOT_FOUND, "")
 
 	add("<C-a>", "c-a")
 	test([]KeyStroke{
-		{tcell.KeyCtrlA, 0},
+		{tcell.ModCtrl, tcell.KeyCtrlA, 0},
 	}, BINDING_FOUND, "c-a")
 }
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 6df0c95..350e94e 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -229,6 +229,7 @@ func (aerc *Aerc) Event(event tcell.Event) bool {
 	case *tcell.EventKey:
 		aerc.statusline.Expire()
 		aerc.pendingKeys = append(aerc.pendingKeys, config.KeyStroke{
+			Modifiers: event.Modifiers(),
 			Key:  event.Key(),
 			Rune: event.Rune(),
 		})