aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2016-02-27 14:20:12 +0000
committerStephen Blott2016-03-05 05:37:40 +0000
commit34b1fb0f4e2ce1696c17e703d0bc43463355d6ba (patch)
tree0bf5797129ae1f212154b56aff86be0830073a29
parent7c5fb2c312b9140c2dd091f792535ae8f592ecdb (diff)
downloadvimium-34b1fb0f4e2ce1696c17e703d0bc43463355d6ba.tar.bz2
Key bindings; initial partially-functioning version.
-rw-r--r--background_scripts/commands.coffee20
-rw-r--r--background_scripts/main.coffee1
-rw-r--r--content_scripts/mode_key_handler.coffee43
-rw-r--r--content_scripts/vimium_frontend.coffee28
4 files changed, 46 insertions, 46 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index ab9992b3..a1002929 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -94,6 +94,25 @@ Commands =
@keyToCommandRegistry = {}
@mapKeyToCommand { key, command } for own key, command of defaultKeyMappings
+ # Keys are either literal characters, or "named" - for example <a-b> (alt+b), <left> (left arrow) or <f12>
+ # This regular expression captures two groups: the first is a named key, the second is the remainder of the
+ # string.
+ namedKeyRegex: /^(<(?:[amc]-.|(?:[amc]-)?[a-z0-9]{2,5})>)(.*)$/
+
+ generateKeyStateStructure: ->
+ keyMapping = {}
+ for own keys, registryEntry of @keyToCommandRegistry
+ currentMapping = keyMapping
+ while 0 < keys.length
+ [key, rest] = if 0 == keys.search @namedKeyRegex then [RegExp.$1, RegExp.$2] else [keys[0], keys.slice(1)]
+ if 0 < rest.length
+ currentMapping[key] ?= {}
+ currentMapping = currentMapping[key]
+ else
+ currentMapping[key] = registryEntry
+ keys = rest
+ chrome.storage.local.set normalModeKeyStateMapping: keyMapping
+
# An ordered listing of all available commands, grouped by type. This is the order they will
# be shown in the help page.
commandGroups:
@@ -375,6 +394,7 @@ Commands.init()
Settings.postUpdateHooks["keyMappings"] = (value) ->
Commands.clearKeyMappingsAndSetDefaults()
Commands.parseCustomKeyMappings value
+ Commands.generateKeyStateStructure()
refreshCompletionKeysAfterMappingSave()
root = exports ? window
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 7c970866..1838eb95 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -629,6 +629,7 @@ Commands.clearKeyMappingsAndSetDefaults()
if Settings.has("keyMappings")
Commands.parseCustomKeyMappings(Settings.get("keyMappings"))
+Commands.generateKeyStateStructure()
populateValidFirstKeys()
populateSingleKeyCommands()
diff --git a/content_scripts/mode_key_handler.coffee b/content_scripts/mode_key_handler.coffee
index c79f1991..6e04addb 100644
--- a/content_scripts/mode_key_handler.coffee
+++ b/content_scripts/mode_key_handler.coffee
@@ -1,11 +1,4 @@
-# The important data structure here is the "keyState". The key state is a non-empty list of objects, the keys
-# of which are key names, and the values are other key-mapping objects or commands (strings). Key-mapping
-# objects can be arbitrarily nested; so we support any length of multi-key mapping.
-#
-# Whenever we consume a key, we append a new copy of the global key mapping to the key state (hence, the
-# global mappings are always available, and the key state is always non-empty).
-
class KeyHandlerMode extends Mode
useCount: true
countPrefix: 0
@@ -15,8 +8,6 @@ class KeyHandlerMode extends Mode
constructor: (options) ->
# A function accepting a command name and a count; required.
@commandHandler = options.commandHandler ? (->)
- # A Key mapping structure; required.
- @keyMapping = options.keyMapping ? {}
@useCount = false if options.noCount
@reset()
@@ -31,6 +22,8 @@ class KeyHandlerMode extends Mode
blur: (event) => @alwaysContinueBubbling =>
@keydownEvents = {} if event.target == window
+ setKeyMapping: (@keyMapping) -> @reset()
+
onKeydown: (event) ->
keyChar = KeyboardUtils.getKeyCharString event
@@ -65,7 +58,7 @@ class KeyHandlerMode extends Mode
keyChar = KeyboardUtils.getKeyCharString event
if keyChar and @keyCharIsKeyStatePrefix keyChar
@advanceKeyState keyChar
- commands = @keyState.filter (entry) -> "string" == typeof entry
+ commands = @keyState.filter (entry) -> entry.command
@invokeCommand commands[0] if 0 < commands.length
false # Suppress event.
else if keyChar and @isCountKey keyChar
@@ -124,35 +117,5 @@ class KeyHandlerMode extends Mode
getEventCode: (event) -> event.keyCode
-# Demo/test code.
-# A (very) poor-man's normal mode.
-
-demoKeyMapping =
- j: "scrollDown"
- k: "scrollUp"
- i: "enterInsertMode"
- g:
- g: "scrollToTop"
- a: "scrollToTop"
- z: "scrollToBottom"
- i: "focusInput"
- # A three-key binding.
- a:
- b:
- c: "enterInsertMode"
- # And this should override "j" on its own.
- j: "enterInsertMode"
-
-demoCommandHandler = (command, count) ->
- switch command
- when "scrollDown" then scrollDown()
- when "scrollUp" then scrollUp()
- when "scrollToTop" then scrollToTop count
- when "scrollToBottom" then scrollToBottom()
- when "enterInsertMode" then enterInsertMode()
- when "focusInput" then focusInput count
-
root = exports ? window
root.KeyHandlerMode = KeyHandlerMode
-root.demoKeyMapping = demoKeyMapping
-root.demoCommandHandler = demoCommandHandler
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index bce5f632..b46175fb 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -101,19 +101,35 @@ handlerStack.push
# Only exported for tests.
window.initializeModes = ->
- class NormalMode extends Mode
+ class NormalMode extends KeyHandlerMode
constructor: ->
super
name: "normal"
indicator: false # There is no mode indicator in normal mode.
- keydown: (event) => onKeydown.call @, event
- keypress: (event) => onKeypress.call @, event
- keyup: (event) => onKeyup.call @, event
+ commandHandler: @commandHandler.bind this
+ keyMapping: {}
+
+ chrome.storage.local.get "normalModeKeyStateMapping", (items) =>
+ @setKeyMapping items.normalModeKeyStateMapping
+
+ chrome.storage.onChanged.addListener (changes, area) =>
+ if area == "local" and changes.normalModeKeyStateMapping?.newValue
+ @setKeyMapping changes.normalModeKeyStateMapping.newValue
+
+ commandHandler: (registryEntry, count) ->
+ # TODO: Special handling of Vomnibar.
+ if registryEntry.isBackgroundCommand
+ true # Not yet implemnted.
+ else
+ count = 1 if registryEntry.noRepeat
+ if registryEntry.passCountToFunction
+ Utils.invokeCommandString registryEntry.command, [count]
+ else
+ Utils.invokeCommandString registryEntry.command for i in [0...count]
# Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and
# activates/deactivates itself accordingly.
- # new NormalMode
- new KeyHandlerMode commandHandler: demoCommandHandler, keyMapping: demoKeyMapping, indicator: "Demo mode."
+ new NormalMode
new PassKeysMode
new InsertMode permanent: true
Scroller.init()