-
-
Notifications
You must be signed in to change notification settings - Fork 151
/
Copy pathkeys.ts
159 lines (152 loc) · 4.67 KB
/
keys.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
export const nonLiteralKeys: {[key: string]: string} = {
" ": "<Space>",
"<": "<lt>",
"ArrowDown": "<Down>",
"ArrowLeft": "<Left>",
"ArrowRight": "<Right>",
"ArrowUp": "<Up>",
"Backspace": "<BS>",
"Delete": "<Del>",
"End": "<End>",
"Enter": "<CR>",
"Escape": "<Esc>",
"F1": "<F1>",
"F10": "<F10>",
"F11": "<F11>",
"F12": "<F12>",
"F13": "<F13>",
"F14": "<F14>",
"F15": "<F15>",
"F16": "<F16>",
"F17": "<F17>",
"F18": "<F18>",
"F19": "<F19>",
"F2": "<F2>",
"F20": "<F20>",
"F21": "<F21>",
"F22": "<F22>",
"F23": "<F23>",
"F24": "<F24>",
"F3": "<F3>",
"F4": "<F4>",
"F5": "<F5>",
"F6": "<F6>",
"F7": "<F7>",
"F8": "<F8>",
"F9": "<F9>",
"Home": "<Home>",
"PageDown": "<PageDown>",
"PageUp": "<PageUp>",
"Tab": "<Tab>",
"\\": "<Bslash>",
"|": "<Bar>",
};
const nonLiteralVimKeys = Object.fromEntries(Object
.entries(nonLiteralKeys)
.map(([x, y]) => [y, x]));
const nonLiteralKeyCodes: {[key: string]: number} = {
"Enter": 13,
"Space": 32,
"Tab": 9,
"Delete": 46,
"End": 35,
"Home": 36,
"Insert": 45,
"PageDown": 34,
"PageUp": 33,
"ArrowDown": 40,
"ArrowLeft": 37,
"ArrowRight": 39,
"ArrowUp": 38,
"Escape": 27,
};
// Given a "special" key representation (e.g. <Enter> or <M-l>), returns an
// array of three javascript keyevents, the first one representing the
// corresponding keydown, the second one a keypress and the third one a keyup
// event.
function modKeyToEvents(k: string) {
let mods = "";
let key = nonLiteralVimKeys[k];
let ctrlKey = false;
let altKey = false;
let shiftKey = false;
if (key === undefined) {
const arr = k.slice(1, -1).split("-");
mods = arr[0];
key = arr[1];
ctrlKey = /c/i.test(mods);
altKey = /a/i.test(mods);
const specialChar = "<" + key + ">";
if (nonLiteralVimKeys[specialChar] !== undefined) {
key = nonLiteralVimKeys[specialChar];
shiftKey = false;
} else {
shiftKey = key !== key.toLocaleLowerCase();
}
}
// Some pages rely on keyCodes to figure out what key was pressed. This is
// awful because keycodes aren't guaranteed to be the same acrross
// browsers/OS/keyboard layouts but try to do the right thing anyway.
// https://github.com/glacambre/firenvim/issues/723
let keyCode = 0;
if (/^[a-zA-Z0-9]$/.test(key)) {
keyCode = key.charCodeAt(0);
} else if (nonLiteralKeyCodes[key] !== undefined) {
keyCode = nonLiteralKeyCodes[key];
}
const init = { key, keyCode, ctrlKey, altKey, shiftKey, bubbles: true };
return [
new KeyboardEvent("keydown", init),
new KeyboardEvent("keypress", init),
new KeyboardEvent("keyup", init),
];
}
// Given a "simple" key (e.g. `a`, `1`…), returns an array of three javascript
// events representing the action of pressing the key.
function keyToEvents(key: string) {
const shiftKey = key !== key.toLocaleLowerCase();
return [
new KeyboardEvent("keydown", { key, shiftKey, bubbles: true }),
new KeyboardEvent("keypress", { key, shiftKey, bubbles: true }),
new KeyboardEvent("keyup", { key, shiftKey, bubbles: true }),
];
}
// Given an array of string representation of keys (e.g. ["a", "<Enter>", …]),
// returns an array of javascript keyboard events that simulate these keys
// being pressed.
export function keysToEvents(keys: string[]) {
// Code to split mod keys and non-mod keys:
// const keys = str.match(/([<>][^<>]+[<>])|([^<>]+)/g)
// if (keys === null) {
// return [];
// }
return keys.map((key) => {
if (key[0] === "<") {
return modKeyToEvents(key);
}
return keyToEvents(key);
}).flat();
}
// Turns a non-literal key (e.g. "Enter") into a vim-equivalent "<Enter>"
export function translateKey(key: string) {
if (nonLiteralKeys[key] !== undefined) {
return nonLiteralKeys[key];
}
return key;
}
// Add modifier `mod` (`A`, `C`, `S`…) to `text` (a vim key `b`, `<Enter>`,
// `<CS-x>`…)
export function addModifier(mod: string, text: string) {
let match;
let modifiers = "";
let key = "";
if ((match = text.match(/^<([A-Z]{1,5})-(.+)>$/))) {
modifiers = match[1];
key = match[2];
} else if ((match = text.match(/^<(.+)>$/))) {
key = match[1];
} else {
key = text;
}
return "<" + mod + modifiers + "-" + key + ">";
}