/
key-event.coffee
153 lines (121 loc) · 4.92 KB
/
key-event.coffee
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
class window.KeyEvent
[disableVrome, passNextKey, currentKeys, keyTimes, bindings] = [false, false, '', 0, {}]
@init: =>
for disabledSite in Option.get('disablesites').split(',') when disabledSite isnt ''
@disable() if new RegExp(disabledSite.trim(), 'i').test(location.href)
document.addEventListener 'keydown', KeyEvent.exec, true
@add: (keys, func, insertMode) ->
bindings[keys] ?= [null, null]
bindings[keys][Number insertMode] = func
@stopPropagation: (e) ->
e.stopPropagation()
e.preventDefault()
@enable: =>
[disableVrome, passNextKey] = [false, false]
Post action: 'Vrome.enable'
@reset()
@disable: ->
if Option.get 'show_disabled_text'
CmdBox.set title: ' -- PASS THROUGH -- ', mouseOverTitle: CmdBox.remove
disableVrome = true
Post action: 'Vrome.disable'
desc @disable, 'Disable Vrome'
@disable.options =
disablesites:
description: "Disable Vrome in those sites. Multiple URLs can be separated with ','"
example: 'set disablesites=mail.google.com,reader.google.com'
enable_vrome_key:
description: 'Key to enable Vrome again'
example: 'set enable_vrome_key=<Esc>'
show_disabled_text:
description: 'Show Vrome Disabled text or not. You could also know this from the Action Icon'
example: 'set show_disable_text=0'
@passNextKey: ->
CmdBox.set title: ' -- PASS THROUGH (next) -- ', timeout: 2000 if Option.get 'show_disabled_text'
passNextKey = true
Post action: 'Vrome.disable'
desc @passNextKey, 'Pass next key'
@reset: ->
currentKeys = ''
keyTimes = 0
@times: (onlyRead) ->
result = keyTimes
keyTimes = 0 unless onlyRead
result
storeLast = ->
Settings.add { currentKeys, times: keyTimes }
@runLast: ->
runCurrentKeys Settings.get('@currentKeys'), Settings.get('@times'), false
desc @runLast, 'Repeat the last command'
filterKey = (key, insertMode) ->
configure = Settings.get '@configure'
mode = if insertMode then 'imap' else 'map'
return key if /^\d$/.test key
configure?[mode]?[key] or key
ignoreKey = (key, insertMode) ->
configure = Settings.get '@configure'
mode = if insertMode then 'iunmap' else 'unmap'
configure?[mode]?[key]?
showStatusLine = ->
if Option.get 'showstatus'
CmdBox.set title: "#{keyTimes or ''}#{currentKeys}", timeout: 500
runCurrentKeys = (keys, times, insertMode, e) =>
return unless keys
key = if e then getKey e else null
stopPropagation = =>
# stopPropagation if Vrome is enabled and any functions executed
@stopPropagation e if e and not (isAcceptKey(key) and
(insertMode or Hint.isHintable(document.activeElement)))
# 0 is a special command: could be used to scroll left, also could be used as run count.
if (keys is '0' and keyTimes is 0) or not /^\d$/.test keys
/^(\d*)(.+)$/.test keys
count = Number RegExp.$1
match = RegExp.$2
bindingFunction = bindings[match]?[Number insertMode]
if bindingFunction?
# Run matched function
# map j 3j
originalKeyTimes = keyTimes
if count > 1 or times > 1
keyTimes = (keyTimes or 1) * times * (count or 1)
try
bindingFunction.call e
catch error
Debug error
keyTimes = originalKeyTimes
if e
# If any function invoked, then store it to last run command.
# (don't do this when running 'repeat last command' or in InsertMode)
do storeLast if key isnt '.' and not insertMode
do stopPropagation
# If some function invoked and a key pressed, reset the count
# but don't reset it if no key pressed, this means the function is invoked by runLast.
keyTimes = 0
currentKeys = ''
else
# Check if there are any bindings that partially match
numberInsertMode = Number insertMode
startsWithKey = (command, key) ->
command is key or
(command.startsWith(key) and not command.startsWith '<')
for command, modes of bindings when modes[numberInsertMode]? and startsWithKey command, keys
someBindingMatched = true
do stopPropagation
do showStatusLine
break
currentKeys = '' if not someBindingMatched
else if not insertMode and /^\d$/.test key
# Set the count time
keyTimes = keyTimes * 10 + Number(key)
currentKeys = ''
do showStatusLine
@exec: (e) =>
key = getKey e
return @stopPropagation e if isModifierKey key
insertMode = isEditableElement e.target
# If Vrome in pass-next or disabled mode and using <C-Esc> to enable it.
return @enable() if not insertMode and (passNextKey or (disableVrome and isCtrlEscapeKey(key)))
return if disableVrome
currentKeys = filterKey currentKeys.concat(key), insertMode
return if ignoreKey currentKeys, insertMode
runCurrentKeys currentKeys, 1, insertMode, e