From 967aa7bf31998f667616f19f9b83e409340b66d1 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 2 Oct 2016 09:01:29 +0100 Subject: Rework key-sequence parsing. This reworks the parsing of key sequences like `x`: Advantages over the status quo: - Parses key sequences in one only place (previously two), - Removes two hideous regular expression. - Admits multi-modifier bindings (like ``). - Adds more (and better) tests. - (And it should be easier to maintain.) Replaces #2210 (this also simplifies key parsing substantially). --- background_scripts/commands.coffee | 45 ++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index e905c410..f43bd02b 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -23,13 +23,13 @@ Commands = @availableCommands[command] = extend options, description: description - mapKeyToCommand: ({ key, command, options }) -> + mapKeyToCommand: ({ key, keySequence, command, options }) -> unless @availableCommands[command] BgUtils.log "#{command} doesn't exist!" return options ?= {} - @keyToCommandRegistry[key] = extend { command, options }, @availableCommands[command] + @keyToCommandRegistry[key] = extend { keySequence, command, options }, @availableCommands[command] # Lower-case the appropriate portions of named keys. # @@ -39,10 +39,18 @@ Commands = # humans may prefer other forms or . # On the other hand, and are different named keys - for one of # them you have to press "shift" as well. + # We sort modifiers here to match the order used in keyboard_utils.coffee. normalizeKey: (key) -> - key.replace(/<[acm]-/ig, (match) -> match.toLowerCase()) - .replace(/<([acm]-)?([a-zA-Z0-9]{2,})>/g, (match, optionalPrefix, keyName) -> - "<" + (if optionalPrefix then optionalPrefix else "") + keyName.toLowerCase() + ">") + if key.length == 0 + [] + else if 0 == key.search /^<([^<>]+)>(.*)/ # Parse "bcd" as "" and "bcd". + [modifiers..., keyChar] = RegExp.$1.split "-" + keyChar = keyChar.toLowerCase() unless keyChar.length == 1 + modifiers = (modifier.toLowerCase() for modifier in modifiers) + modifiers.sort() + ["<#{[modifiers..., keyChar].join "-"}>", @normalizeKey(RegExp.$2)...] + else + [key[0], @normalizeKey(key[1..])...] parseCustomKeyMappings: (customKeyMappings) -> for line in customKeyMappings.split "\n" @@ -52,13 +60,15 @@ Commands = when "map" [ _, key, command, optionList... ] = tokens if command? and @availableCommands[command] - key = @normalizeKey key + keySequence = @normalizeKey key + key = keySequence.join "" BgUtils.log "Mapping #{key} to #{command}" - @mapKeyToCommand { key, command, options: @parseCommandOptions command, optionList } + @mapKeyToCommand { key, command, keySequence, options: @parseCommandOptions command, optionList } when "unmap" if tokens.length == 2 - key = @normalizeKey tokens[1] + keySequence = @normalizeKey tokens[1] + key = keySequence.join "" BgUtils.log "Unmapping #{key}" delete @keyToCommandRegistry[key] @@ -90,24 +100,25 @@ Commands = clearKeyMappingsAndSetDefaults: -> @keyToCommandRegistry = {} - @mapKeyToCommand { key, command } for own key, command of defaultKeyMappings + for own key, command of defaultKeyMappings + keySequence = @normalizeKey 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: -> - # Keys are either literal characters, or "named" - for example (alt+b), (left arrow) or - # 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,})>)(.*)$/ keyStateMapping = {} for own keys, registryEntry of @keyToCommandRegistry currentMapping = keyStateMapping - while 0 < keys.length - [key, keys] = if 0 == keys.search namedKeyRegex then [RegExp.$1, RegExp.$2] else [keys[0], keys[1..]] + for key, index in registryEntry.keySequence if currentMapping[key]?.command - break # Do not overwrite existing command bindings, they take priority. - else if 0 < keys.length + # Do not overwrite existing command bindings, they take priority. NOTE(smblott) This is the legacy + # behaviour. + break + else if index < registryEntry.keySequence.length - 1 currentMapping = currentMapping[key] ?= {} else + delete registryEntry.keySequence # We don't need this any more. currentMapping[key] = registryEntry chrome.storage.local.set normalModeKeyStateMapping: keyStateMapping -- cgit v1.2.3 From 3245cb8e605ba3fd59b9f99bdd28714157ed06eb Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 2 Oct 2016 09:34:06 +0100 Subject: Add comment giving example key parsing. --- background_scripts/commands.coffee | 1 + 1 file changed, 1 insertion(+) (limited to 'background_scripts') diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index f43bd02b..7d9839aa 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -40,6 +40,7 @@ Commands = # On the other hand, and are different named keys - for one of # them you have to press "shift" as well. # We sort modifiers here to match the order used in keyboard_utils.coffee. + # The return value is a sequence of keys: e.g. "b" -> ["", "", "b"]. normalizeKey: (key) -> if key.length == 0 [] -- cgit v1.2.3 From 4305730d512276fd929eaf12b8c134e69df52437 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 2 Oct 2016 09:39:18 +0100 Subject: Rename normalizeKey to parseKeySequence. The new name better describes which the function does. --- background_scripts/commands.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index 7d9839aa..09149786 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -41,7 +41,7 @@ Commands = # them you have to press "shift" as well. # We sort modifiers here to match the order used in keyboard_utils.coffee. # The return value is a sequence of keys: e.g. "b" -> ["", "", "b"]. - normalizeKey: (key) -> + parseKeySequence: (key) -> if key.length == 0 [] else if 0 == key.search /^<([^<>]+)>(.*)/ # Parse "bcd" as "" and "bcd". @@ -49,9 +49,9 @@ Commands = keyChar = keyChar.toLowerCase() unless keyChar.length == 1 modifiers = (modifier.toLowerCase() for modifier in modifiers) modifiers.sort() - ["<#{[modifiers..., keyChar].join "-"}>", @normalizeKey(RegExp.$2)...] + ["<#{[modifiers..., keyChar].join "-"}>", @parseKeySequence(RegExp.$2)...] else - [key[0], @normalizeKey(key[1..])...] + [key[0], @parseKeySequence(key[1..])...] parseCustomKeyMappings: (customKeyMappings) -> for line in customKeyMappings.split "\n" @@ -61,14 +61,14 @@ Commands = when "map" [ _, key, command, optionList... ] = tokens if command? and @availableCommands[command] - keySequence = @normalizeKey key + keySequence = @parseKeySequence key key = keySequence.join "" BgUtils.log "Mapping #{key} to #{command}" @mapKeyToCommand { key, command, keySequence, options: @parseCommandOptions command, optionList } when "unmap" if tokens.length == 2 - keySequence = @normalizeKey tokens[1] + keySequence = @parseKeySequence tokens[1] key = keySequence.join "" BgUtils.log "Unmapping #{key}" delete @keyToCommandRegistry[key] @@ -102,7 +102,7 @@ Commands = clearKeyMappingsAndSetDefaults: -> @keyToCommandRegistry = {} for own key, command of defaultKeyMappings - keySequence = @normalizeKey key + keySequence = @parseKeySequence key key = keySequence.join "" @mapKeyToCommand { key, command, keySequence } -- cgit v1.2.3 From d0092f4f078a7b590746092c78b91da35c6a403e Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 2 Oct 2016 09:40:56 +0100 Subject: Single quotes are clearer here. --- background_scripts/commands.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'background_scripts') diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index 09149786..e1f82b72 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -49,7 +49,7 @@ Commands = keyChar = keyChar.toLowerCase() unless keyChar.length == 1 modifiers = (modifier.toLowerCase() for modifier in modifiers) modifiers.sort() - ["<#{[modifiers..., keyChar].join "-"}>", @parseKeySequence(RegExp.$2)...] + ["<#{[modifiers..., keyChar].join '-'}>", @parseKeySequence(RegExp.$2)...] else [key[0], @parseKeySequence(key[1..])...] -- cgit v1.2.3 From 54139c11231bf7e7a3a9f4c98fb688d2d0fe22c9 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 2 Oct 2016 12:25:20 +0100 Subject: Better regexp (to match legacy behaviour for '>'. --- background_scripts/commands.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'background_scripts') diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index e1f82b72..7ab09f24 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -44,7 +44,8 @@ Commands = parseKeySequence: (key) -> if key.length == 0 [] - else if 0 == key.search /^<([^<>]+)>(.*)/ # Parse "bcd" as "" and "bcd". + # Parse "bcd" as "" and "bcd". + else if 0 == key.search /^<((?:[acm]-)*(?:.|[a-zA-Z0-9]{2,}))>(.*)/i [modifiers..., keyChar] = RegExp.$1.split "-" keyChar = keyChar.toLowerCase() unless keyChar.length == 1 modifiers = (modifier.toLowerCase() for modifier in modifiers) -- cgit v1.2.3