Example #1
0
def _get_asyncio_loop_cls():
    # Inline import, to make sure the rest doesn't break on Python 2. (Where
    # asyncio is not available.)
    if is_windows():
        from polymorph.deps.prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop
    else:
        from polymorph.deps.prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop
    return AsyncioEventLoop
Example #2
0
 def height_is_known(self):
     """
     True when the height from the cursor until the bottom of the terminal
     is known. (It's often nicer to draw bottom toolbars only if the height
     is known, in order to avoid flickering when the CPR response arrives.)
     """
     return self.full_screen or self._min_available_height > 0 or \
         is_windows()  # On Windows, we don't have to wait for a CPR.
Example #3
0
def create_input(stdin=None):
    stdin = stdin or sys.stdin

    if is_windows():
        from .win32 import Win32Input
        return Win32Input(stdin)
    else:
        from .vt100 import Vt100Input
        return Vt100Input(stdin)
Example #4
0
def create_event_loop(recognize_win32_paste=True):
    """
    Create and return an
    :class:`~prompt_toolkit.eventloop.base.EventLoop` instance.
    """
    if is_windows():
        from .win32 import Win32EventLoop
        return Win32EventLoop(recognize_paste=recognize_win32_paste)
    else:
        from .posix import PosixEventLoop
        return PosixEventLoop()
Example #5
0
    def call_inputhook(self, input_is_ready_func, inputhook):
        """
        Call the inputhook. (Called by a prompt-toolkit eventloop.)

        :param input_is_ready_func: A callable which returns True when there is
            input ready for the main event loop to process. This means that we
            should quit our input hook. This callable takes a boolean `wait`.
            Wen `True` this needs to be a blocking call which only returns when
            there is input ready.
        :param inputhook: This is a callable that runs the inputhook. This
            function should take this object (the `InputHookContext`) as input.
        """
        assert callable(input_is_ready_func)
        assert callable(inputhook)

        self._input_is_ready = input_is_ready_func

        # Start thread that activates this pipe when there is input to process.
        def thread():
            input_is_ready_func(wait=True)
            os.write(self._w, b'x')

        threading.Thread(target=thread).start()

        # Call inputhook.
        inputhook(self)

        # Flush the read end of the pipe.
        try:
            # Before calling 'os.read', call select.select. This is required
            # when the gevent monkey patch has been applied. 'os.read' is never
            # monkey patched and won't be cooperative, so that would block all
            # other select() calls otherwise.
            # See: http://www.gevent.org/gevent.os.html

            # Note: On Windows, this is apparently not an issue.
            #       However, if we would ever want to add a select call, it
            #       should use `windll.kernel32.WaitForMultipleObjects`,
            #       because `select.select` can't wait for a pipe on Windows.
            if not is_windows():
                select_fds([self._r], timeout=None)

            os.read(self._r, 1024)
        except OSError:
            # This happens when the window resizes and a SIGWINCH was received.
            # We get 'Error: [Errno 4] Interrupted system call'
            # Just ignore.
            pass
        self._input_is_ready = None
Example #6
0
    def request_absolute_cursor_position(self):
        """
        Get current cursor position.
        For vt100: Do CPR request. (answer will arrive later.)
        For win32: Do API call. (Answer comes immediately.)
        """
        # Only do this request when the cursor is at the top row. (after a
        # clear or reset). We will rely on that in `report_absolute_cursor_row`.
        assert self._cursor_pos.y == 0

        # For Win32, we have an API call to get the number of rows below the
        # cursor.
        if is_windows():
            self._min_available_height = self.output.get_rows_below_cursor_position(
            )
        else:
            if self.full_screen:
                self._min_available_height = self.output.get_size().rows
            elif self.cpr_support == CPR_Support.NOT_SUPPORTED:
                return
            else:
                # Asks for a cursor position report (CPR).
                self._waiting_for_cpr_futures.append(Future())
                self.output.ask_for_cpr()

                # If we don't know whether CPR is supported, test using timer.
                if self.cpr_support == CPR_Support.UNKNOWN:

                    def timer():
                        time.sleep(self.CPR_TIMEOUT)

                        # Not set in the meantime -> not supported.
                        if self.cpr_support == CPR_Support.UNKNOWN:
                            self.cpr_support = CPR_Support.NOT_SUPPORTED

                            if self.cpr_not_supported_callback:
                                # Make sure to call this callback in the main thread.
                                get_event_loop().call_from_executor(
                                    self.cpr_not_supported_callback)

                    t = threading.Thread(target=timer)
                    t.daemon = True
                    t.start()
Example #7
0
    def default(cls, term=''):
        """
        If the user doesn't specify a color depth, use this as a default.
        """
        if term in ('linux', 'eterm-color'):
            return cls.DEPTH_4_BIT

        # For now, always use 4 bit color on Windows 10 by default, even when
        # vt100 escape sequences with ENABLE_VIRTUAL_TERMINAL_PROCESSING are
        # supported. We don't have a reliable way yet to know whether our
        # console supports true color or only 4-bit.
        if is_windows() and 'PROMPT_TOOLKIT_COLOR_DEPTH' not in os.environ:
            return cls.DEPTH_4_BIT

        # Check the `PROMPT_TOOLKIT_COLOR_DEPTH` environment variable.
        if os.environ.get('PROMPT_TOOLKIT_COLOR_DEPTH') in cls._ALL:
            return os.environ['PROMPT_TOOLKIT_COLOR_DEPTH']

        return cls.DEPTH_8_BIT
Example #8
0
    def _(event):
        """
        Handling of mouse events for Windows.
        """
        assert is_windows()  # This key binding should only exist for Windows.

        # Parse data.
        event_type, x, y = event.data.split(';')
        x = int(x)
        y = int(y)

        # Make coordinates absolute to the visible part of the terminal.
        screen_buffer_info = event.app.renderer.output.get_win32_screen_buffer_info(
        )
        rows_above_cursor = screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y
        y -= rows_above_cursor

        # Call the mouse event handler.
        handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y]
        handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type))
Example #9
0
    def reset(self, _scroll=False, leave_alternate_screen=True):
        # Reset position
        self._cursor_pos = Point(x=0, y=0)

        # Remember the last screen instance between renderers. This way,
        # we can create a `diff` between two screens and only output the
        # difference. It's also to remember the last height. (To show for
        # instance a toolbar at the bottom position.)
        self._last_screen = None
        self._last_size = None
        self._last_style = None

        # Default MouseHandlers. (Just empty.)
        self.mouse_handlers = MouseHandlers()

        #: Space from the top of the layout, until the bottom of the terminal.
        #: We don't know this until a `report_absolute_cursor_row` call.
        self._min_available_height = 0

        # In case of Windows, also make sure to scroll to the current cursor
        # position. (Only when rendering the first time.)
        if is_windows() and _scroll:
            self.output.scroll_buffer_to_prompt()

        # Quit alternate screen.
        if self._in_alternate_screen and leave_alternate_screen:
            self.output.quit_alternate_screen()
            self._in_alternate_screen = False

        # Disable mouse support.
        if self._mouse_support_enabled:
            self.output.disable_mouse_support()
            self._mouse_support_enabled = False

        # Disable bracketed paste.
        if self._bracketed_paste_enabled:
            self.output.disable_bracketed_paste()
            self._bracketed_paste_enabled = False

        # Flush output. `disable_mouse_support` needs to write to stdout.
        self.output.flush()
Example #10
0
def is_win_vt100_enabled():
    """
    Returns True when we're running Windows and VT100 escape sequences are
    supported.
    """
    if not is_windows():
        return False

    hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)

    # Get original console mode.
    original_mode = DWORD(0)
    windll.kernel32.GetConsoleMode(hconsole, byref(original_mode))

    try:
        # Try to enable VT100 sequences.
        result = windll.kernel32.SetConsoleMode(
            hconsole,
            DWORD(ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING))

        return result == 1
    finally:
        windll.kernel32.SetConsoleMode(hconsole, original_mode)
Example #11
0
def create_output(stdout=None):
    """
    Return an :class:`~prompt_toolkit.output.Output` instance for the command
    line.

    :param stdout: The stdout object
    """
    stdout = stdout or sys.__stdout__

    if is_windows():
        from .conemu import ConEmuOutput
        from .win32 import Win32Output
        from .windows10 import is_win_vt100_enabled, Windows10_Output

        if is_win_vt100_enabled():
            return Windows10_Output(stdout)
        if is_conemu_ansi():
            return ConEmuOutput(stdout)
        else:
            return Win32Output(stdout)
    else:
        from .vt100 import Vt100_Output
        return Vt100_Output.from_pty(stdout,
                                     term=get_term_environment_variable())