Beispiel #1
0
 def test_on_feed_key_backspace(self, shell):
     shell.on_feed_key(KeyPress('x'))
     assert shell.current_command_key == 'm'
     shell.on_feed_key(KeyPress(Keys.Backspace))
     assert shell.current_command_key == 'i'
     shell.on_feed_key(KeyPress(Keys.Backspace))
     assert shell.current_command_key == 'i'
Beispiel #2
0
 def test_on_feed_key_backspace(self, shell):
     shell.on_feed_key(KeyPress("x"))
     assert shell.current_command_key == "m"
     shell.on_feed_key(KeyPress(Keys.Backspace))
     assert shell.current_command_key == "i"
     shell.on_feed_key(KeyPress(Keys.Backspace))
     assert shell.current_command_key == "i"
Beispiel #3
0
 def test_on_feed_key_does_not_increment_pos_past_length_of_command(
         self, make_shell):
     shell = make_shell(commands=["1+1"], speed=2)
     shell.on_feed_key(KeyPress("xx"))
     assert shell.current_command_pos == len("1+1") - 1
     shell.on_feed_key(KeyPress("x"))
     assert shell.current_command_pos == len("1+1")
     shell.on_feed_key(KeyPress("x"))
     assert shell.current_command_pos == len("1+1")
Beispiel #4
0
 def test_on_feed_key_does_not_increment_pos_past_length_of_command(
         self, make_shell):
     shell = make_shell(commands=['1+1'], speed=2)
     shell.on_feed_key(KeyPress('xx'))
     assert shell.current_command_pos == len('1+1') - 1
     shell.on_feed_key(KeyPress('x'))
     assert shell.current_command_pos == len('1+1')
     shell.on_feed_key(KeyPress('x'))
     assert shell.current_command_pos == len('1+1')
    def test_common_prefix(self):
        # Sending Control_X should not yet do anything, because there is
        # another sequence starting with that as well.
        self.processor.feed_key(KeyPress(Keys.ControlX, ''))
        self.assertEqual(self.handlers.called, [])

        # When another key is pressed, we know that we did not meant the longer
        # "ControlX ControlC" sequence and the callbacks are called.
        self.processor.feed_key(KeyPress(Keys.ControlD, ''))

        self.assertEqual(self.handlers.called, ['control_x', 'control_d'])
    def _event_to_key_presses(self, ev):
        """
        For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances.
        """
        assert type(ev) == KEY_EVENT_RECORD and ev.KeyDown

        result = None

        if ev.AsciiChar == b'\0':
            if ev.VirtualKeyCode in self.keycodes:
                result = KeyPress(self.keycodes[ev.VirtualKeyCode], '')
        else:
            enc = sys.stdin.encoding
            if ev.AsciiChar in self.mappings:
                result = KeyPress(self.mappings[ev.AsciiChar], ev.AsciiChar.decode(enc))
            else:
                result = KeyPress(ev.AsciiChar.decode(enc), ev.AsciiChar.decode(enc))

        # Correctly handle Control-Arrow keys.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result:
            if result.key == Keys.Left:
                result.key = Keys.ControlLeft

            if result.key == Keys.Right:
                result.key = Keys.ControlRight

            if result.key == Keys.Up:
                result.key = Keys.ControlUp

            if result.key == Keys.Down:
                result.key = Keys.ControlDown

        # Turn 'Tab' into 'BackTab' when shift was pressed.
        if ev.ControlKeyState & self.SHIFT_PRESSED and result:
            if result.key == Keys.Tab:
                result.key = Keys.BackTab

        # Turn 'Space' into 'ControlSpace' when control was pressed.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and result.data == ' ':
            result = KeyPress(Keys.ControlSpace, ' ')

        # Return result. If alt was pressed, prefix the result with an
        # 'Escape' key, just like unix VT100 terminals do.
        if result:
            meta_pressed = ev.ControlKeyState & self.LEFT_ALT_PRESSED or \
                ev.ControlKeyState & self.RIGHT_ALT_PRESSED

            if meta_pressed:
                return [KeyPress(Keys.Escape, ''), result]
            else:
                return [result]

        else:
            return []
Beispiel #7
0
def test_common_prefix(processor, handlers):
    # Sending Control_X should not yet do anything, because there is
    # another sequence starting with that as well.
    processor.feed(KeyPress(Keys.ControlX, ''))
    processor.process_keys()

    assert handlers.called == []

    # When another key is pressed, we know that we did not meant the longer
    # "ControlX ControlC" sequence and the callbacks are called.
    processor.feed(KeyPress(Keys.ControlD, ''))
    processor.process_keys()

    assert handlers.called == ['control_x', 'control_d']
Beispiel #8
0
 def on_feed_key(self, key_press):
     """Handles the magictyping when a key is pressed"""
     if key_press.key in {Keys.Escape, Keys.ControlC}:
         echo(carriage_return=True)
         raise Abort()
     if key_press.key == Keys.Backspace:
         if self.current_command_pos > 0:
             self.current_command_pos -= 1
         return key_press
     ret = None
     if key_press.key != Keys.CPRResponse:
         if self.current_command_pos < len(self.current_command):
             current_key = self.current_command_key
             ret = KeyPress(current_key)
             increment = min([
                 self.speed,
                 len(self.current_command) - self.current_command_pos
             ])
             self.current_command_pos += increment
         else:
             # Command is finished, wait for Enter
             if key_press.key != Keys.Enter:
                 return None
             self.current_command_index += 1
             self.current_command_pos = 0
             ret = key_press
     return ret
Beispiel #9
0
    def _handle_keyboard_interrupt(self, e, platform):
        """Handles keyboard interrupts more gracefully on Mac/Unix/Linux.

        Allows Mac/Unix/Linux to continue running on keyboard interrupt,
        as the user might interrupt a long-running AWS command with Control-C
        while continuing to work with Saws.

        On Windows, the "Terminate batch job (Y/N)" confirmation makes it
        tricky to handle this gracefully.  Thus, we re-raise KeyboardInterrupt.

        Args:
            * e: A KeyboardInterrupt.
            * platform: A string that denotes platform such as
                'Windows', 'Darwin', etc.

        Returns:
            None

        Raises:
            Exception: A KeyboardInterrupt if running on Windows.
        """
        if platform == 'Windows':
            raise e
        else:
            # Clear the renderer and send a carriage return
            self.aws_cli.renderer.clear()
            self.aws_cli.input_processor.feed_key(KeyPress(Keys.ControlM, ''))
Beispiel #10
0
    def feed(self, data):
        """
        Feed the input stream.

        :param data: Input string (unicode).
        """
        assert isinstance(data, six.text_type)

        if _DEBUG_RENDERER_INPUT:
            self.LOG.write(repr(data).encode('utf-8') + b'\n')
            self.LOG.flush()

        # Handle bracketed paste. (We bypass the parser that matches all other
        # key presses and keep reading input until we see the end mark.)
        # This is much faster then parsing character by character.
        if self._in_bracketed_paste:
            self._paste_buffer += data
            end_mark = '\x1b[201~'

            if end_mark in self._paste_buffer:
                end_index = self._paste_buffer.index(end_mark)

                # Feed content to key bindings.
                paste_content = self._paste_buffer[:end_index]
                self.feed_key_callback(
                    KeyPress(Keys.BracketedPaste, paste_content))

                # Quit bracketed paste mode and handle remaining input.
                self._in_bracketed_paste = False
                remaining = self._paste_buffer[end_index + len(end_mark):]
                self._paste_buffer = ''

                self.feed(remaining)

        # Handle normal input character by character.
        else:
            for i, c in enumerate(data):
                if self._in_bracketed_paste:
                    # Quit loop and process from this position when the parser
                    # entered bracketed paste.
                    self.feed(data[i:])
                    break
                else:
                    # Replace \r by \n. (Some clients send \r instead of \n
                    # when enter is pressed. E.g. telnet and some other
                    # terminals.)

                    # XXX: We should remove this in a future version. It *is*
                    #      now possible to recognise the difference.
                    #      (We remove ICRNL/INLCR/IGNCR below.)
                    #      However, this breaks IPython and maybe other applications,
                    #      because they bind ControlJ (\n) for handling the Enter key.

                    #      When this is removed, replace Enter=ControlJ by
                    #      Enter=ControlM in keys.py.
                    if c == '\r':
                        c = '\n'
                    self._input_parser.send(c)
Beispiel #11
0
def prefix_meta(event):
    """
    Metafy the next character typed. This is for keyboards without a meta key.

    Sometimes people also want to bind other keys to Meta, e.g. 'jj'::

        registry.add_key_binding('j', 'j', filter=ViInsertMode())(prefix_meta)
    """
    event.cli.input_processor.feed(KeyPress(Keys.Escape))
def test_previous_key_sequence(processor, handlers):
    """
    test whether we receive the correct previous_key_sequence.
    """
    events = []

    def handler(event):
        events.append(event)

    # Build registry.
    registry = Registry()
    registry.add_binding('a', 'a')(handler)
    registry.add_binding('b', 'b')(handler)
    processor = InputProcessor(registry, lambda: None)

    # Create processor and feed keys.
    processor.feed(KeyPress('a', 'a'))
    processor.feed(KeyPress('a', 'a'))
    processor.feed(KeyPress('b', 'b'))
    processor.feed(KeyPress('b', 'b'))
    processor.process_keys()

    # Test.
    assert len(events) == 2
    assert len(events[0].key_sequence) == 2
    assert events[0].key_sequence[0].key == 'a'
    assert events[0].key_sequence[0].data == 'a'
    assert events[0].key_sequence[1].key == 'a'
    assert events[0].key_sequence[1].data == 'a'
    assert events[0].previous_key_sequence == []

    assert len(events[1].key_sequence) == 2
    assert events[1].key_sequence[0].key == 'b'
    assert events[1].key_sequence[0].data == 'b'
    assert events[1].key_sequence[1].key == 'b'
    assert events[1].key_sequence[1].data == 'b'
    assert len(events[1].previous_key_sequence) == 2
    assert events[1].previous_key_sequence[0].key == 'a'
    assert events[1].previous_key_sequence[0].data == 'a'
    assert events[1].previous_key_sequence[1].key == 'a'
    assert events[1].previous_key_sequence[1].data == 'a'
Beispiel #13
0
 def _call_handler(self, key, insert_text):
     """
     Callback to handler.
     """
     if isinstance(key, tuple):
         for k in key:
             self._call_handler(k, insert_text)
     else:
         if key == Keys.BracketedPaste:
             self._in_bracketed_paste = True
             self._paste_buffer = ''
         else:
             self.feed_key_callback(KeyPress(key, insert_text))
Beispiel #14
0
    def read(self):
        """
        Return a list of `KeyPress` instances. It won't return anything when
        there was nothing to read.  (This function doesn't block.)

        http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx
        """
        max_count = 2048  # Max events to read at the same time.

        read = DWORD(0)
        arrtype = INPUT_RECORD * max_count
        input_records = arrtype()

        # Get next batch of input event.
        windll.kernel32.ReadConsoleInputW(self.handle, pointer(input_records),
                                          max_count, pointer(read))

        # First, get all the keys from the input buffer, in order to determine
        # whether we should consider this a paste event or not.
        all_keys = list(self._get_keys(read, input_records))

        if self.recognize_paste and self._is_paste(all_keys):
            gen = iter(all_keys)
            for k in gen:
                # Pasting: if the current key consists of text or \n, turn it
                # into a BracketedPaste.
                data = []
                while k and (isinstance(k.key, six.text_type)
                             or k.key == Keys.ControlJ):
                    data.append(k.data)
                    try:
                        k = next(gen)
                    except StopIteration:
                        k = None

                if data:
                    yield KeyPress(Keys.BracketedPaste, ''.join(data))
                if k is not None:
                    yield k
        else:
            for k in all_keys:
                yield k
Beispiel #15
0
    def _handle_mouse(self, ev):
        """
        Handle mouse events. Return a list of KeyPress instances.
        """
        FROM_LEFT_1ST_BUTTON_PRESSED = 0x1

        result = []

        # Check event type.
        if ev.ButtonState == FROM_LEFT_1ST_BUTTON_PRESSED:
            # On a key press, generate both the mouse down and up event.
            for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]:
                data = ';'.join([
                   event_type,
                   str(ev.MousePosition.X),
                   str(ev.MousePosition.Y)
                ])
                result.append(KeyPress(Keys.WindowsMouseEvent, data))

        return result
    def test_feed_several(self):
        # First an unknown key first.
        self.processor.feed_key(KeyPress(Keys.ControlQ, ''))
        self.assertEqual(self.handlers.called, [])

        # Followed by a know key sequence.
        self.processor.feed_key(KeyPress(Keys.ControlX, ''))
        self.processor.feed_key(KeyPress(Keys.ControlC, ''))
        self.assertEqual(self.handlers.called, ['controlx_controlc'])

        # Followed by another unknown sequence.
        self.processor.feed_key(KeyPress(Keys.ControlR, ''))
        self.processor.feed_key(KeyPress(Keys.ControlS, ''))

        # Followed again by a know key sequence.
        self.processor.feed_key(KeyPress(Keys.ControlD, ''))
        self.assertEqual(self.handlers.called,
                         ['controlx_controlc', 'control_d'])
Beispiel #17
0
def test_feed_several(processor, handlers):
    # First an unknown key first.
    processor.feed(KeyPress(Keys.ControlQ, ''))
    processor.process_keys()

    assert handlers.called == []

    # Followed by a know key sequence.
    processor.feed(KeyPress(Keys.ControlX, ''))
    processor.feed(KeyPress(Keys.ControlC, ''))
    processor.process_keys()

    assert handlers.called == ['controlx_controlc']

    # Followed by another unknown sequence.
    processor.feed(KeyPress(Keys.ControlR, ''))
    processor.feed(KeyPress(Keys.ControlS, ''))

    # Followed again by a know key sequence.
    processor.feed(KeyPress(Keys.ControlD, ''))
    processor.process_keys()

    assert handlers.called == ['controlx_controlc', 'control_d']
Beispiel #18
0
 def test_on_feed_key_ctrlc_aborts(self, shell):
     with pytest.raises(click.Abort):
         shell.on_feed_key(KeyPress(Keys.ControlC))
Beispiel #19
0
 def test_on_feed_key_escape_aborts(self, shell):
     with pytest.raises(click.Abort):
         shell.on_feed_key(KeyPress(Keys.Escape))
Beispiel #20
0
 def test_assert_on_feed_key_with_speed(self, make_shell):
     shell = make_shell(commands=["import math", "1 + 1"], speed=2)
     assert shell.current_command_key == "im"
     shell.on_feed_key(KeyPress("x"))
     assert shell.current_command_key == "po"
Beispiel #21
0
 def test_on_feed_key_goes_to_next_command_after_enter(self, shell):
     assert shell.current_command_key == "i"
     for _ in range(len("import math")):
         shell.on_feed_key(KeyPress("x"))
     shell.on_feed_key(KeyPress(Keys.Enter))
     assert shell.current_command == "1 + 1"
Beispiel #22
0
 def test_on_feed_key_backspace_with_speed(self, make_shell):
     shell = make_shell(commands=["1+1"], speed=2)
     shell.on_feed_key(KeyPress("x"))
     assert shell.current_command_key == "1"
     shell.on_feed_key(KeyPress(Keys.Backspace))
     assert shell.current_command_key == "+1"
Beispiel #23
0
 def test_F2(self):
     # orig_paginate = self.haxor.paginate_comments
     self.processor.feed(KeyPress(Keys.F2, u''))
     self.processor.process_keys()
Beispiel #24
0
def test_feed_simple(processor, handlers):
    processor.feed(KeyPress(Keys.ControlX, '\x18'))
    processor.feed(KeyPress(Keys.ControlC, '\x03'))
    processor.process_keys()

    assert handlers.called == ['controlx_controlc']
Beispiel #25
0
 def test_F10(self):
     with self.assertRaises(EOFError):
         self.processor.feed(KeyPress(Keys.F10, u''))
         self.processor.process_keys()
Beispiel #26
0
def test_control_square_closed_any(processor, handlers):
    processor.feed(KeyPress(Keys.ControlSquareClose, ''))
    processor.feed(KeyPress('C', 'C'))
    processor.process_keys()

    assert handlers.called == ['control_square_close_any']
Beispiel #27
0
    def _event_to_key_presses(self, ev):
        """
        For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances.
        """
        assert type(ev) == KEY_EVENT_RECORD and ev.KeyDown

        result = None

        u_char = ev.uChar.UnicodeChar
        ascii_char = ev.uChar.AsciiChar

        if u_char == '\x00':
            if ev.VirtualKeyCode in self.keycodes:
                result = KeyPress(self.keycodes[ev.VirtualKeyCode], '')
        else:
            if ascii_char in self.mappings:
                result = KeyPress(self.mappings[ascii_char], u_char)
            else:
                result = KeyPress(u_char, u_char)

        # Correctly handle Control-Arrow keys.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED
                or ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result:
            if result.key == Keys.Left:
                result.key = Keys.ControlLeft

            if result.key == Keys.Right:
                result.key = Keys.ControlRight

            if result.key == Keys.Up:
                result.key = Keys.ControlUp

            if result.key == Keys.Down:
                result.key = Keys.ControlDown

        # Turn 'Tab' into 'BackTab' when shift was pressed.
        if ev.ControlKeyState & self.SHIFT_PRESSED and result:
            if result.key == Keys.Tab:
                result.key = Keys.BackTab

        # Turn 'Space' into 'ControlSpace' when control was pressed.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or ev.ControlKeyState
                & self.RIGHT_CTRL_PRESSED) and result and result.data == ' ':
            result = KeyPress(Keys.ControlSpace, ' ')

        # Turn Control-Enter into META-Enter. (On a vt100 terminal, we cannot
        # detect this combination. But it's really practical on Windows.)
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and \
                result.key == Keys.ControlJ:
            return [KeyPress(Keys.Escape, ''), result]

        # Return result. If alt was pressed, prefix the result with an
        # 'Escape' key, just like unix VT100 terminals do.
        if result:
            meta_pressed = ev.ControlKeyState & self.LEFT_ALT_PRESSED or \
                ev.ControlKeyState & self.RIGHT_ALT_PRESSED

            if meta_pressed:
                return [KeyPress(Keys.Escape, ''), result]
            else:
                return [result]

        else:
            return []
    def test_feed_simple(self):
        self.processor.feed_key(KeyPress(Keys.ControlX, '\x18'))
        self.processor.feed_key(KeyPress(Keys.ControlC, '\x03'))

        self.assertEqual(self.handlers.called, ['controlx_controlc'])
Beispiel #29
0
 def _(event):
     " Map 'jj' to Escape. "
     event.cli.input_processor.feed(KeyPress(Keys.Escape))
    def test_control_square_closed_any(self):
        self.processor.feed_key(KeyPress(Keys.ControlSquareClose, ''))
        self.processor.feed_key(KeyPress('C', 'C'))

        self.assertEqual(self.handlers.called, ['control_square_close_any'])
Beispiel #31
0
 def test_on_feed_key(self, shell):
     assert shell.current_command_key == "i"
     key_press = KeyPress("x")
     shell.on_feed_key(key_press)
     assert shell.current_command_key == "m"
    def _event_to_key_presses(self, ev):
        """
        For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances.
        """
        assert type(ev) == KEY_EVENT_RECORD and ev.KeyDown

        result = None

        u_char = ev.uChar.UnicodeChar
        ascii_char = ev.uChar.AsciiChar

        if u_char == '\x00':
            if ev.VirtualKeyCode in self.keycodes:
                result = KeyPress(self.keycodes[ev.VirtualKeyCode], '')
        else:
            if ascii_char in self.mappings:
                result = KeyPress(self.mappings[ascii_char], u_char)
            else:
                result = KeyPress(u_char, u_char)

        # Correctly handle Control-Arrow keys.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result:
            if result.key == Keys.Left:
                result.key = Keys.ControlLeft

            if result.key == Keys.Right:
                result.key = Keys.ControlRight

            if result.key == Keys.Up:
                result.key = Keys.ControlUp

            if result.key == Keys.Down:
                result.key = Keys.ControlDown

        # Turn 'Tab' into 'BackTab' when shift was pressed.
        if ev.ControlKeyState & self.SHIFT_PRESSED and result:
            if result.key == Keys.Tab:
                result.key = Keys.BackTab

        # Turn 'Space' into 'ControlSpace' when control was pressed.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and result.data == ' ':
            result = KeyPress(Keys.ControlSpace, ' ')

        # Turn Control-Enter into META-Enter. (On a vt100 terminal, we cannot
        # detect this combination. But it's really practical on Windows.)
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and \
                result.key == Keys.ControlJ:
            return [KeyPress(Keys.Escape, ''), result]

        # Return result. If alt was pressed, prefix the result with an
        # 'Escape' key, just like unix VT100 terminals do.

        # NOTE: Only replace the left alt with escape. The right alt key often
        #       acts as altgr and is used in many non US keyboard layouts for
        #       typing some special characters, like a backslash. We don't want
        #       all backslashes to be prefixed with escape. (Esc-\ has a
        #       meaning in E-macs, for instance.)
        if result:
            meta_pressed = ev.ControlKeyState & self.LEFT_ALT_PRESSED

            if meta_pressed:
                return [KeyPress(Keys.Escape, ''), result]
            else:
                return [result]

        else:
            return []
    def _event_to_key_presses(self, ev):
        """
        For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances.
        """
        assert type(ev) == KEY_EVENT_RECORD and ev.KeyDown

        result = None

        u_char = ev.uChar.UnicodeChar
        ascii_char = ev.uChar.AsciiChar

        if u_char == '\x00':
            if ev.VirtualKeyCode in self.keycodes:
                result = KeyPress(self.keycodes[ev.VirtualKeyCode], '')
        else:
            if ascii_char in self.mappings:
                result = KeyPress(self.mappings[ascii_char], u_char)
            else:
                result = KeyPress(u_char, u_char)

        # Correctly handle Control-Arrow keys.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result:
            if result.key == Keys.Left:
                result.key = Keys.ControlLeft

            if result.key == Keys.Right:
                result.key = Keys.ControlRight

            if result.key == Keys.Up:
                result.key = Keys.ControlUp

            if result.key == Keys.Down:
                result.key = Keys.ControlDown

        # Turn 'Tab' into 'BackTab' when shift was pressed.
        if ev.ControlKeyState & self.SHIFT_PRESSED and result:
            if result.key == Keys.Tab:
                result.key = Keys.BackTab

        # Turn 'Space' into 'ControlSpace' when control was pressed.
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and result.data == ' ':
            result = KeyPress(Keys.ControlSpace, ' ')

        # Turn Control-Enter into META-Enter. (On a vt100 terminal, we cannot
        # detect this combination. But it's really practical on Windows.)
        if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
                ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and \
                result.key == Keys.ControlJ:
            return [KeyPress(Keys.Escape, ''), result]

        # Return result. If alt was pressed, prefix the result with an
        # 'Escape' key, just like unix VT100 terminals do.
        if result:
            meta_pressed = ev.ControlKeyState & self.LEFT_ALT_PRESSED or \
                ev.ControlKeyState & self.RIGHT_ALT_PRESSED

            if meta_pressed:
                return [KeyPress(Keys.Escape, ''), result]
            else:
                return [result]

        else:
            return []