docs: def parse_keys(string,
                  with_spaces = False,
                  with_tabs = False,
                  with_newlines = False,
                  modifiers = None):
      "Return the parsed keys"
  
      keys = []
      if not modifiers:
          modifiers = []
      index = 0
      while index < len(string):
  
          c = string[index]
          index += 1
          # check if one of CTRL, SHIFT, ALT has been pressed
          if c in MODIFIERS.keys():
              modifier = MODIFIERS[c]
              # remember that we are currently modified
              modifiers.append(modifier)
              # hold down the modifier key
              keys.append(VirtualKeyAction(modifier, up = False))
              if DEBUG:
                  print("MODS+", modifiers)
              continue
  
          # Apply modifiers over a bunch of characters (not just one!)
          elif c == "(":
              # find the end of the bracketed text
              end_pos = string.find(")", index)
              if end_pos == -1:
                  raise KeySequenceError('`)` not found')
              keys.extend(
                  parse_keys(string[index:end_pos], modifiers = modifiers))
              index = end_pos + 1
  
          # Escape or named key
          elif c == "{":
              # We start searching from index + 1 to account for the case {}}
              end_pos = string.find("}", index + 1)
              if end_pos == -1:
                  raise KeySequenceError('`}` not found')
  
              code = string[index:end_pos]
              index = end_pos + 1
              keys.extend(handle_code(code))
  
          # unmatched ")"
          elif c == ')':
              raise KeySequenceError('`)` should be preceeded by `(`')
  
          # unmatched "}"
          elif c == '}':
              raise KeySequenceError('`}` should be preceeded by `{`')
  
          # so it is a normal character
          else:
              # don't output white space unless flags to output have been set
              if (c == ' ' and not with_spaces or
                  c == '\t' and not with_tabs or
                  c == '\n' and not with_newlines):
                  continue
  
              # output nuewline
              if c in ('~', '\n'):
                  keys.append(VirtualKeyAction(CODES["ENTER"]))
  
              # safest are the virtual keys - so if our key is a virtual key
              # use a VirtualKeyAction
              #if ord(c) in CODE_NAMES:
              #    keys.append(VirtualKeyAction(ord(c)))
  
              elif modifiers:
                  keys.append(EscapedKeyAction(c))
  
              else:
                  keys.append(KeyAction(c))
  
          # as we have handled the text - release the modifiers
          while modifiers:
              if DEBUG:
                  print("MODS-", modifiers)
              keys.append(VirtualKeyAction(modifiers.pop(), down = False))
  
      # just in case there were any modifiers left pressed - release them
      while modifiers:
          keys.append(VirtualKeyAction(modifiers.pop(), down = False))
  
      return keys