aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts
diff options
context:
space:
mode:
authorStephen Blott2016-12-11 08:22:18 +0000
committerStephen Blott2016-12-11 08:22:18 +0000
commit1664a02c02be27a824b19633740a23ec01573c77 (patch)
treeb7ba7adf347c0b347eec0753717f4bbe746d6537 /background_scripts
parentbd06c7ccfbfcf36e6d15fba72b7af90254b05da2 (diff)
downloadvimium-1664a02c02be27a824b19633740a23ec01573c77.tar.bz2
Rework key-mapping parsing.
There are two changes here: 1. Treat built-in key mappings and custom key mappings in the same way; that is, we prepend the built-in mappings to the custom mappings and then parse them all together. This results in a number of simplifications due to previous duplication of logic and the elimination of special cases. 2. Parse key mappings in reverse order, so we can just ignore key mappings after first encountering a key sequence. So, `map`, `unmap` and `unmapAll` are all treated in more or less the same way. This is preparatory to reworking some aspects of the help page. In particular, regardless of the order of maps, unmaps, etc., this approach makes it easier to find the mapping in effect for a key sequence (and be able to recreate the order of those mappings).
Diffstat (limited to 'background_scripts')
-rw-r--r--background_scripts/commands.coffee120
1 files changed, 47 insertions, 73 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index 6aa8ca0d..2d3312ea 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -1,36 +1,54 @@
Commands =
+ availableCommands: {}
+ keyToCommandRegistry: null
+ mapKeyRegistry: null
+
init: ->
- for own command, descriptor of commandDescriptions
- @addCommand(command, descriptor[0], descriptor[1])
- @loadKeyMappings Settings.get "keyMappings"
+ for own command, [description, options] of commandDescriptions
+ @availableCommands[command] = extend (options ? {}), description: description
+
Settings.postUpdateHooks["keyMappings"] = @loadKeyMappings.bind this
+ @loadKeyMappings Settings.get "keyMappings"
loadKeyMappings: (customKeyMappings) ->
- @clearKeyMappingsAndSetDefaults()
- @parseCustomKeyMappings customKeyMappings
- @generateKeyStateMapping()
- chrome.storage.local.set mapKeyRegistry: @mapKeyRegistry
-
- availableCommands: {}
- keyToCommandRegistry: {}
-
- # Registers a command, making it available to be optionally bound to a key.
- # options:
- # - background: whether this command needs to be run against the background page.
- addCommand: (command, description, options = {}) ->
- if command of @availableCommands
- BgUtils.log "#{command} is already defined! Check commands.coffee for duplicates."
- return
+ @keyToCommandRegistry = {}
+ @mapKeyRegistry = {}
- @availableCommands[command] = extend options, description: description
+ configLines = ("map #{key} #{command}" for own key, command of defaultKeyMappings)
+ configLines.push BgUtils.parseLines(customKeyMappings)...
+ seen = {}
+ unmapAll = false
+ for line in configLines.reverse()
+ tokens = line.split /\s+/
+ switch tokens[0]
+ when "map"
+ if 3 <= tokens.length and not unmapAll
+ [_, key, command, optionsList...] = tokens
+ if not seen[key] and registryEntry = @availableCommands[command]
+ seen[key] = true
+ keySequence = @parseKeySequence key
+ options = @parseCommandOptions command, optionsList
+ @keyToCommandRegistry[key] = extend {keySequence, command, options}, @availableCommands[command]
+ when "unmap"
+ if tokens.length == 2
+ seen[tokens[1]] = true
+ when "unmapAll"
+ unmapAll = true
+ when "mapkey"
+ if tokens.length == 3
+ fromChar = @parseKeySequence tokens[1]
+ toChar = @parseKeySequence tokens[2]
+ @mapKeyRegistry[fromChar[0]] = toChar[0] if fromChar.length == toChar.length == 1
- mapKeyToCommand: ({ key, keySequence, command, options }) ->
- unless @availableCommands[command]
- BgUtils.log "#{command} doesn't exist!"
- return
+ chrome.storage.local.set mapKeyRegistry: @mapKeyRegistry
+ @installKeyStateMapping()
- options ?= {}
- @keyToCommandRegistry[key] = extend { keySequence, command, options }, @availableCommands[command]
+ # Push the key mapping for passNextKey into Settings so that it's available in the front end for insert
+ # mode. We exclude single-key mappings (that is, printable keys) because when users press printable keys
+ # in insert mode they expect the character to be input, not to be droppped into some special Vimium
+ # mode.
+ Settings.set "passNextKeyKeys",
+ (key for own key of @keyToCommandRegistry when @keyToCommandRegistry[key].command == "passNextKey" and 1 < key.length)
# Lower-case the appropriate portions of named keys.
#
@@ -60,43 +78,6 @@ Commands =
else
[key[0], @parseKeySequence(key[1..])...]
- parseCustomKeyMappings: (customKeyMappings) ->
- for line in BgUtils.parseLines customKeyMappings
- tokens = line.split /\s+/
- switch tokens[0]
- when "map"
- [ _, key, command, optionList... ] = tokens
- keySequence = @parseKeySequence key
- if command? and @availableCommands[command]
- key = keySequence.join ""
- BgUtils.log "mapping [\"#{keySequence.join '", "'}\"] to #{command}"
- @mapKeyToCommand { key, command, keySequence, options: @parseCommandOptions command, optionList }
- else
- BgUtils.log "skipping [\"#{keySequence.join '", "'}\"] for #{command} -- something is not right"
-
- when "unmap"
- if tokens.length == 2
- keySequence = @parseKeySequence tokens[1]
- key = keySequence.join ""
- BgUtils.log "Unmapping #{key}"
- delete @keyToCommandRegistry[key]
-
- when "unmapAll"
- @keyToCommandRegistry = {}
-
- when "mapkey"
- if tokens.length == 3
- fromChar = @parseKeySequence tokens[1]
- toChar = @parseKeySequence tokens[2]
- @mapKeyRegistry[fromChar[0]] = toChar[0] if fromChar.length == toChar.length == 1
-
- # Push the key mapping for passNextKey into Settings so that it's available in the front end for insert
- # mode. We exclude single-key mappings (that is, printable keys) because when users press printable keys
- # in insert mode they expect the character to be input, not to be droppped into some special Vimium
- # mode.
- Settings.set "passNextKeyKeys",
- (key for own key of @keyToCommandRegistry when @keyToCommandRegistry[key].command == "passNextKey" and 1 < key.length)
-
# Command options follow command mappings, and are of one of two forms:
# key=value - a value
# key - a flag
@@ -113,16 +94,9 @@ Commands =
options
- clearKeyMappingsAndSetDefaults: ->
- @keyToCommandRegistry = {}
- @mapKeyRegistry = {}
- for own key, command of defaultKeyMappings
- keySequence = @parseKeySequence key
- key = keySequence.join ""
- @mapKeyToCommand { key, command, keySequence }
-
- # This generates a nested key-to-command mapping structure. There is an example in mode_key_handler.coffee.
- generateKeyStateMapping: ->
+ # This generates and installs a nested key-to-command mapping structure. There is an example in
+ # mode_key_handler.coffee.
+ installKeyStateMapping: ->
keyStateMapping = {}
for own keys, registryEntry of @keyToCommandRegistry
currentMapping = keyStateMapping
@@ -136,7 +110,7 @@ Commands =
else
currentMapping[key] = extend {}, registryEntry
# We don't need these properties in the content scripts.
- delete registryEntry[prop] for prop in ["keySequence", "description"]
+ delete currentMapping[key][prop] for prop in ["keySequence", "description"]
chrome.storage.local.set normalModeKeyStateMapping: keyStateMapping
# An ordered listing of all available commands, grouped by type. This is the order they will