forked from philc/vimium
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmode_insert.js
More file actions
153 lines (134 loc) · 4.88 KB
/
mode_insert.js
File metadata and controls
153 lines (134 loc) · 4.88 KB
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
/* eslint-disable
class-methods-use-this,
constructor-super,
max-classes-per-file,
max-len,
no-cond-assign,
no-constant-condition,
no-eval,
no-nested-ternary,
no-new,
no-param-reassign,
no-plusplus,
no-return-assign,
no-this-before-super,
no-undef,
no-underscore-dangle,
no-use-before-define,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS001: Remove Babel/TypeScript constructor workaround
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS103: Rewrite code to no longer use __guard__
* DS104: Avoid inline assignments
* DS204: Change includes calls to have a more natural evaluation order
* DS206: Consider reworking classes to avoid initClass
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
class InsertMode extends Mode {
static initClass() {
// Static stuff. This allows PostFindMode to suppress the permanently-installed InsertMode instance.
this.suppressedEvent = null;
}
constructor(options) {
// There is one permanently-installed instance of InsertMode. It tracks focus changes and
// activates/deactivates itself (by setting @insertModeLock) accordingly.
{
// Hack: trick Babel/TypeScript into allowing this before super.
if (false) { super(); }
const thisFn = (() => this).toString();
const thisName = thisFn.match(/return (?:_assertThisInitialized\()*(\w+)\)*;/)[1];
eval(`${thisName} = this;`);
}
if (options == null) { options = {}; }
this.permanent = options.permanent;
// If truthy, then we were activated by the user (with "i").
this.global = options.global;
const handleKeyEvent = (event) => {
let needle;
if (!this.isActive(event)) { return this.continueBubbling; }
// See comment here: https://github.com/philc/vimium/commit/48c169bd5a61685bb4e67b1e76c939dbf360a658.
const activeElement = this.getActiveElement();
if ((activeElement === document.body) && activeElement.isContentEditable) { return this.passEventToPage; }
// Check for a pass-next-key key.
if ((needle = KeyboardUtils.getKeyCharString(event), Array.from(Settings.get('passNextKeyKeys')).includes(needle))) {
new PassNextKeyMode();
} else if ((event.type === 'keydown') && KeyboardUtils.isEscape(event)) {
if (DomUtils.isFocusable(activeElement)) { activeElement.blur(); }
if (!this.permanent) { this.exit(); }
} else {
return this.passEventToPage;
}
return this.suppressEvent;
};
const defaults = {
name: 'insert',
indicator: !this.permanent && !Settings.get('hideHud') ? 'Insert mode' : undefined,
keypress: handleKeyEvent,
keydown: handleKeyEvent,
};
super(extend(defaults, options));
// Only for tests. This gives us a hook to test the status of the permanently-installed instance.
if (this.permanent) { InsertMode.permanentInstance = this; }
}
isActive(event) {
if (event === InsertMode.suppressedEvent) { return false; }
if (this.global) { return true; }
return DomUtils.isFocusable(this.getActiveElement());
}
getActiveElement() {
let {
activeElement,
} = document;
while (__guard__(activeElement != null ? activeElement.shadowRoot : undefined, (x) => x.activeElement)) {
({
activeElement,
} = activeElement.shadowRoot);
}
return activeElement;
}
static suppressEvent(event) { return this.suppressedEvent = event; }
}
InsertMode.initClass();
// This implements the pasNexKey command.
class PassNextKeyMode extends Mode {
constructor(count) {
if (count == null) { count = 1; }
let seenKeyDown = false;
let keyDownCount = 0;
super({
name: 'pass-next-key',
indicator: 'Pass next key.',
// We exit on blur because, once we lose the focus, we can no longer track key events.
exitOnBlur: window,
keypress: () => this.passEventToPage,
keydown: () => {
seenKeyDown = true;
keyDownCount += 1;
return this.passEventToPage;
},
keyup: () => {
if (seenKeyDown) {
if (!(--keyDownCount > 0)) {
if (!(--count > 0)) {
this.exit();
}
}
}
return this.passEventToPage;
},
});
}
}
const root = typeof exports !== 'undefined' && exports !== null ? exports : (window.root != null ? window.root : (window.root = {}));
root.InsertMode = InsertMode;
root.PassNextKeyMode = PassNextKeyMode;
if (typeof exports === 'undefined' || exports === null) { extend(window, root); }
function __guard__(value, transform) {
return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
}