diff options
| author | Stephen Blott | 2016-02-29 15:43:26 +0000 |
|---|---|---|
| committer | Stephen Blott | 2016-03-05 05:40:11 +0000 |
| commit | ff6d4b92df924b93de4366b1f0e3cc7411ac8065 (patch) | |
| tree | a72f5029216f67aee0ec76d8b1b0159fcdf5a7a5 | |
| parent | 7bf8cb11db08c61417a4d72b95c2905a4869cf67 (diff) | |
| download | vimium-ff6d4b92df924b93de4366b1f0e3cc7411ac8065.tar.bz2 | |
Key bindings; more small tweaks.
| -rw-r--r-- | content_scripts/mode_key_handler.coffee | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/content_scripts/mode_key_handler.coffee b/content_scripts/mode_key_handler.coffee index 78ce3680..df177c4a 100644 --- a/content_scripts/mode_key_handler.coffee +++ b/content_scripts/mode_key_handler.coffee @@ -1,9 +1,26 @@ +# Example key mapping (@keyMapping): +# i: +# command: "enterInsertMode", ... # This is a registryEntry object (as too are the other commands). +# g: +# g: +# command: "scrollToTop", ... +# t: +# command: "nextTab", ... +# +# This key-mapping structure is generated by Commands.generateKeyStateMapping() and may be arbitrarily deep. +# Observe that @keyMapping["g"] is itself also a valid key mapping. At any point, the key state (@keyState) +# consists of a (non-empty) list of such mappings. class KeyHandlerMode extends Mode keydownEvents: {} setKeyMapping: (@keyMapping) -> @reset() setPassKeys: (@passKeys) -> @reset() + # Reset the key state, optionally retaining the count provided. + reset: (@countPrefix = 0) -> + bgLog "Clearing key state, set count=#{@countPrefix}." + @keyState = [@keyMapping] + constructor: (options) -> @commandHandler = options.commandHandler ? (->) @setKeyMapping options.keyMapping ? {} @@ -17,22 +34,22 @@ class KeyHandlerMode extends Mode onKeydown: (event) -> keyChar = KeyboardUtils.getKeyCharString event - if KeyboardUtils.isEscape event - if @countPrefix == 0 and @keyState.length == 1 - @continueBubbling - else - @keydownEvents[event.keyCode] = true - @reset() - false # Suppress event. - else if keyChar and @keyCharIsMapped keyChar + isEscape = KeyboardUtils.isEscape event + if isEscape and @countPrefix == 0 and @keyState.length == 1 + @continueBubbling + else if isEscape + @keydownEvents[event.keyCode] = true + @reset() + false # Suppress event. + else if @keyCharIsMapped keyChar @unlessKeyCharIsPassKey keyChar, => @keydownEvents[event.keyCode] = true @handleKeyChar event, keyChar else if keyChar @continueBubbling else if (keyChar = KeyboardUtils.getKeyChar event) and (@keyCharIsMapped(keyChar) or @isCountKey keyChar) - # It looks like we will be handling a subsequent keypress event, so suppress propagation of this event - # to prevent triggering page event listeners (e.g. Google instant Search). + # It looks like we will possibly be handling a subsequent keypress event, so suppress propagation of + # this event to prevent triggering page event listeners (e.g. Google instant Search). @unlessKeyCharIsPassKey keyChar, => @keydownEvents[event.keyCode] = true DomUtils.suppressPropagation event @@ -43,7 +60,7 @@ class KeyHandlerMode extends Mode onKeypress: (event) -> keyChar = KeyboardUtils.getKeyCharString event @unlessKeyCharIsPassKey keyChar, => - if keyChar and @keyCharIsMapped keyChar + if @keyCharIsMapped keyChar @handleKeyChar event, keyChar else if @isCountKey keyChar digit = parseInt keyChar @@ -61,35 +78,28 @@ class KeyHandlerMode extends Mode else @continueBubbling + # This tests whether there is a mapping of keyChar in the current key state. + keyCharIsMapped: (keyChar) -> + (mapping for mapping in @keyState when keyChar of mapping)[0]? + handleKeyChar: (event, keyChar) -> bgLog "Handling key #{keyChar}, mode=#{@name}." - @advanceKeyState keyChar - command = (@keyState.filter (entry) -> entry.command)[0] + # Advance the key state. The new key state is the current mappings of keyChar, plus @keyMapping. + @keyState = (mapping[keyChar] for mapping in @keyState when keyChar of mapping) + @keyState.push @keyMapping + command = (mapping for mapping in @keyState when mapping.command)[0] if command? count = if 0 < @countPrefix then @countPrefix else 1 - @reset() bgLog "Calling mode=#{@name}, command=#{command.command}, count=#{count}." + @reset() @commandHandler {command, count} false # Suppress event. - keyCharIsMapped: (keyChar) -> - (mapping for mapping in @keyState when keyChar of mapping)[0]? - - # The next key state is the current mappings matching keyChar plus @keyMapping. - advanceKeyState: (keyChar) -> - newMappings = (mapping[keyChar] for mapping in @keyState when keyChar of mapping) - @keyState = [newMappings..., @keyMapping] - - # Reset the state (as if no keys had been handled), but optionally retaining the count provided. - reset: (@countPrefix = 0) -> - bgLog "Clearing key queue, set count=#{@countPrefix}." - @keyState = [@keyMapping] - isCountKey: (keyChar) -> keyChar?.length == 1 and (if 0 < @countPrefix then '0' else '1') <= keyChar <= '9' # Keystrokes are *never* considered passKeys if the user has begun entering a command. So, for example, if - # 't' is a passKey, then 'gt' and '99t' are neverthless handled as regular keys. + # 't' is a passKey, then the "t"-s of 'gt' and '99t' are neverthless handled as regular keys. unlessKeyCharIsPassKey: (keyChar, nonPassKeyCallback) -> if @countPrefix == 0 and @keyState.length == 1 and keyChar in (@passKeys ? "") @stopBubblingAndTrue |
