 
   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

  onKeypress: (event) ->
    keyChar = KeyboardUtils.getKeyCharString event
    @unlessKeyCharIsPassKey keyChar, =>
      if keyChar and @keyCharIsMapped keyChar
        @handleKeyChar event, keyChar
      else if @isCountKey keyChar
        digit = parseInt keyChar

    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}."
    # 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
      bgLog "Calling mode=#{@name}, command=#{command.command}, count=#{count}."
      @reset()
      @commandHandler {command, count}
    false # Suppress event.

  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 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
