Beispiel #1
0
def create_radian_prompt_session(options):

    history_file = ".radian_history"
    if options.no_history:
        history = ModalInMemoryHistory()
    elif not options.global_history and os.path.exists(history_file):
        history = ModalFileHistory(os.path.abspath(history_file))
    else:
        history = ModalFileHistory(
            os.path.join(os.path.expanduser("~"), history_file))

    if is_windows():
        output = None
    else:
        output = CustomVt100Output.from_pty(
            sys.stdout, term=get_term_environment_variable())

    def get_inputhook():
        terminal_width = [None]

        def _(context):
            while True:
                if context.input_is_ready():
                    break
                try:
                    process_events()
                except Exception:
                    pass

                output_width = session.app.output.get_size().columns
                if output_width and terminal_width[0] != output_width:
                    terminal_width[0] = output_width
                    setoption("width", max(terminal_width[0], 20))
                time.sleep(1.0 / 30)

        return _

    session = ModalPromptSession(
        color_depth=ColorDepth.default(term=os.environ.get("TERM")),
        history=history,
        enable_history_search=True,
        enable_suspend=True,
        tempfile_suffix=".R",
        input=CustomVt100Input(sys.stdin) if not is_windows() else None,
        output=output,
        inputhook=get_inputhook(),
        mode_class=RadianMode)

    load_settings(session)
    register_modes(session)

    return session
    def reset(self):
        # 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_char = None
        self._last_style = None  # When the style changes, we have to do a full
                                 # redraw as well.

        # Remember the last title. Only set the title when it changes.
        self._last_title = None

        #: 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 Windown, also make sure to scroll to the current cursor
        # position.
        if is_windows():
            self.output.scroll_buffer_to_prompt()

        # Quit alternate screen.
        if self._in_alternate_screen:
            self.output.quit_alternate_screen()
            self.output.flush()
            self._in_alternate_screen = False
Beispiel #3
0
def create_client(socket_name):
    if is_windows():
        from .windows import WindowsClient
        return WindowsClient(socket_name)
    else:
        from .posix import PosixClient
        return PosixClient(socket_name)
Beispiel #4
0
    def __init__(self,
                 editing_mode=EditingMode.EMACS,
                 history=None,
                 lexer=None,
                 style=None,
                 completer=None,
                 extra_key_bindings=None,
                 tempfile_suffix=None,
                 input=None,
                 output=None,
                 on_render=None):

        self.editing_mode = editing_mode
        self.history = history
        self.lexer = lexer
        self.style = None
        self.completer = completer
        self.extra_key_bindings = extra_key_bindings
        self.tempfile_suffix = tempfile_suffix
        if not is_windows():
            self.input = input or CustomVt100Input(sys.stdin)
        else:
            self.input = input or get_default_input()
        self.output = output or get_default_output()

        self.on_render = on_render

        self.create_layout()
        self.create_application()
Beispiel #5
0
def create_output(stdout=None, true_color=False, ansi_colors_only=None):
    """
    Return an :class:`~prompt_toolkit.output.Output` instance for the command
    line.

    :param true_color: When True, use 24bit colors instead of 256 colors.
        (`bool` or :class:`~prompt_toolkit.filters.Filter`.)
    :param ansi_colors_only: When True, restrict to 16 ANSI colors only.
        (`bool` or :class:`~prompt_toolkit.filters.Filter`.)
    """
    stdout = stdout or sys.__stdout__
    true_color = to_filter(true_color)

    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
        term = os.environ.get('TERM', '')
        if PY2:
            term = term.decode('utf-8')

        return Vt100_Output.from_pty(stdout,
                                     true_color=true_color,
                                     ansi_colors_only=ansi_colors_only,
                                     term=term)
    def reset(self):
        # 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_char = None
        self._last_style = None  # When the style changes, we have to do a full
        # redraw as well.

        # Remember the last title. Only set the title when it changes.
        self._last_title = None

        #: 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 Windown, also make sure to scroll to the current cursor
        # position.
        if is_windows():
            self.output.scroll_buffer_to_prompt()

        # Quit alternate screen.
        if self._in_alternate_screen:
            self.output.quit_alternate_screen()
            self.output.flush()
            self._in_alternate_screen = False
Beispiel #7
0
def get_title_bar_right_text():
    copy_key = "CTRL + SHIFT" if is_windows() else "fn"
    return [
        ("class:title", f"[Double Ctrl + C] QUIT      "),
        ("class:title", f"[Ctrl + S] STATUS      "),
        ("class:title", f"Hold down \"{copy_key}\" for selecting and copying text"),
    ]
Beispiel #8
0
    def create_output(stdout=None, true_color=False):
        """
        Return an :class:`~prompt_toolkit.output.Output` instance for the command
        line.
        :param true_color: When True, use 24bit colors instead of 256 colors.
            (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)

        Notes
        -----
        This method was forked from the mainline prompt-toolkit repo.
        Copyright (c) 2014, Jonathan Slenders, All rights reserved.
        This is deprecated and slated for removal after a prompt-toolkit
        v0.57+ release.
        """
        stdout = stdout or sys.__stdout__
        true_color = to_simple_filter(true_color)

        if is_windows():
            if is_conemu_ansi():
                return ConEmuOutput(stdout)
            else:
                return Win32Output(stdout)
        else:
            term = os.environ.get('TERM', '')
            if PY2:
                term = term.decode('utf-8')

            return Vt100_Output.from_pty(stdout,
                                         true_color=true_color)  #, term=term)
Beispiel #9
0
def create_input(stdin: Optional[TextIO] = None,
                 always_prefer_tty: bool = False) -> Input:
    """
    Create the appropriate `Input` object for the current os/environment.

    :param always_prefer_tty: When set, if `sys.stdin` is connected to a Unix
        `pipe`, check whether `sys.stdout` or `sys.stderr` are connected to a
        pseudo terminal. If so, open the tty for reading instead of reading for
        `sys.stdin`. (We can open `stdout` or `stderr` for reading, this is how
        a `$PAGER` works.)
    """
    if is_windows():
        from .win32 import Win32Input

        return Win32Input(stdin or sys.stdin)
    else:
        from .vt100 import Vt100Input

        # If no input TextIO is given, use stdin/stdout.
        if stdin is None:
            stdin = sys.stdin

            if always_prefer_tty:
                for io in [sys.stdin, sys.stdout, sys.stderr]:
                    if io.isatty():
                        stdin = io
                        break

        return Vt100Input(stdin)
Beispiel #10
0
    def _mouse(event: E) -> None:
        """
        Handling of mouse events for Windows.
        """
        assert is_windows()  # This key binding should only exist for Windows.

        # Parse data.
        pieces = event.data.split(";")

        event_type = MouseEventType(pieces[0])
        x = int(pieces[1])
        y = int(pieces[2])

        # Make coordinates absolute to the visible part of the terminal.
        output = event.app.renderer.output

        from prompt_toolkit.output.win32 import Win32Output

        if isinstance(output, Win32Output):
            screen_buffer_info = 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))
def create_output(stdout: Optional[TextIO] = None) -> Output:
    """
    Return an :class:`~prompt_toolkit.output.Output` instance for the command
    line.

    :param stdout: The stdout object
    """
    if stdout is None:
        # By default, render to stdout. If the output is piped somewhere else,
        # render to stderr. The prompt_toolkit render output is not meant to be
        # consumed by something other then a terminal, so this is a reasonable
        # default.
        if sys.stdout.isatty():
            stdout = sys.stdout
        else:
            stdout = sys.stderr

    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 cast(Output, Windows10_Output(stdout))
        if is_conemu_ansi():
            return cast(Output, ConEmuOutput(stdout))
        else:
            return Win32Output(stdout)
    else:
        from .vt100 import Vt100_Output
        return Vt100_Output.from_pty(stdout,
                                     term=get_term_environment_variable())
Beispiel #12
0
    def create_output(stdout=None, true_color=False):
        """
        Return an :class:`~prompt_toolkit.output.Output` instance for the command
        line.
        :param true_color: When True, use 24bit colors instead of 256 colors.
            (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)

        Notes
        -----
        This method was forked from the mainline prompt-toolkit repo.
        Copyright (c) 2014, Jonathan Slenders, All rights reserved.
        This is deprecated and slated for removal after a prompt-toolkit
        v0.57+ release.
        """
        stdout = stdout or sys.__stdout__
        true_color = to_simple_filter(true_color)

        if is_windows():
            if is_conemu_ansi():
                return ConEmuOutput(stdout)
            else:
                return Win32Output(stdout)
        else:
            term = os.environ.get('TERM', '')
            if PY2:
                term = term.decode('utf-8')

            return Vt100_Output.from_pty(stdout, true_color=true_color)#, term=term)
def create_input(stdin: Optional[TextIO] = None) -> Input:
    """
    Create the appropriate `Input` object for the current os/environment.
    """
    if is_windows():
        from .win32 import Win32Input

        return Win32Input(stdin or sys.stdin)
    else:
        from .vt100 import Vt100Input

        # If no input TextIO is given, use stdin/stdout.
        if stdin is None:
            # Try stdin first, if it's a TTY.
            if sys.stdin.isatty():
                stdin = sys.stdin
            # If stdin is not a TTY, it's possible we're piping something into
            # stdin. Use stdout instead if stdout is a TTY. (We can actually
            # use stdout to read input from, this is how a $PAGER works.)
            elif sys.stdout.isatty():
                stdin = sys.stdout
            # If stdout is also not a tty, then use stdin. (This will print a
            # "Input is not a terminal" warning in `Vt100Input`.)
            else:
                stdin = sys.stdin

        return Vt100Input(stdin)
Beispiel #14
0
def generate_layout(input_field: TextArea, output_field: TextArea, log_field: TextArea):
    copy_key = "CTRL + SHIFT" if is_windows() else "fn"
    root_container = VSplit([
        FloatContainer(
            HSplit([
                output_field,
                Window(height=1, char='-', style='class:line'),
                input_field,
                TextArea(height=1,
                         text=f'Version: {version}    [Double Ctrl + C] QUIT    '
                         f'Hold down "{copy_key}" for selecting and copying text',
                         style='class:label'),
            ]),
            [
                # Completion menus.
                Float(xcursor=True,
                      ycursor=True,
                      transparent=True,
                      content=CompletionsMenu(
                          max_height=16,
                          scroll_offset=1)),
            ]
        ),
        Window(width=1, char='|', style='class:line'),
        log_field,
    ])
    return Layout(root_container, focused_element=input_field)
def create_output(
    stdout: Optional[TextIO] = None, always_prefer_tty: bool = True
) -> Output:
    """
    Return an :class:`~prompt_toolkit.output.Output` instance for the command
    line.

    :param stdout: The stdout object
    :param always_prefer_tty: When set, look for `sys.stderr` if `sys.stdout`
        is not a TTY. (The prompt_toolkit render output is not meant to be
        consumed by something other then a terminal, so this is a reasonable
        default.)
    """
    # Consider TERM and PROMPT_TOOLKIT_COLOR_DEPTH environment variables.
    # Notice that PROMPT_TOOLKIT_COLOR_DEPTH value is the default that's used
    # if the Application doesn't override it.
    term_from_env = get_term_environment_variable()
    color_depth_from_env = ColorDepth.from_env()

    if stdout is None:
        # By default, render to stdout. If the output is piped somewhere else,
        # render to stderr.
        stdout = sys.stdout

        if always_prefer_tty:
            for io in [sys.stdout, sys.stderr]:
                if io.isatty():
                    stdout = io
                    break

    # If the patch_stdout context manager has been used, then sys.stdout is
    # replaced by this proxy. For prompt_toolkit applications, we want to use
    # the real stdout.
    from prompt_toolkit.patch_stdout import StdoutProxy

    while isinstance(stdout, StdoutProxy):
        stdout = stdout.original_stdout

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

        if is_win_vt100_enabled():
            return cast(
                Output,
                Windows10_Output(stdout, default_color_depth=color_depth_from_env),
            )
        if is_conemu_ansi():
            return cast(
                Output, ConEmuOutput(stdout, default_color_depth=color_depth_from_env)
            )
        else:
            return Win32Output(stdout, default_color_depth=color_depth_from_env)
    else:
        from .vt100 import Vt100_Output

        return Vt100_Output.from_pty(
            stdout, term=term_from_env, default_color_depth=color_depth_from_env
        )
Beispiel #16
0
def load_style(config_map=global_config_map):
    """
    Return a dict mapping {ui_style_name -> style_dict}.
    """

    # Load config
    color_top_pane = config_map.get("top-pane").value
    color_bottom_pane = config_map.get("bottom-pane").value
    color_output_pane = config_map.get("output-pane").value
    color_input_pane = config_map.get("input-pane").value
    color_logs_pane = config_map.get("logs-pane").value
    color_terminal_primary = config_map.get("terminal-primary").value

    if is_windows():
        # Load default style
        style = win32_code_style

        # Translate HEX to ANSI
        color_top_pane = hex_to_ansi(color_top_pane)
        color_bottom_pane = hex_to_ansi(color_bottom_pane)
        color_output_pane = hex_to_ansi(color_output_pane)
        color_input_pane = hex_to_ansi(color_input_pane)
        color_logs_pane = hex_to_ansi(color_logs_pane)
        color_terminal_primary = hex_to_ansi(color_terminal_primary)

        # Apply custom configuration
        style[
            "output-field"] = "bg:" + color_output_pane + " " + color_terminal_primary
        style["input-field"] = "bg:" + color_input_pane + " " + style[
            "input-field"].split(' ')[-1]
        style["log-field"] = "bg:" + color_logs_pane + " " + style[
            "log-field"].split(' ')[-1]
        style["header"] = "bg:" + color_top_pane + " " + style["header"].split(
            ' ')[-1]
        style["footer"] = "bg:" + color_bottom_pane + " " + style[
            "footer"].split(' ')[-1]
        style["primary"] = color_terminal_primary
        style["search"] = color_terminal_primary
        style["search.current"] = color_terminal_primary

        return Style.from_dict(style)

    else:
        # Load default style
        style = default_ui_style

        # Apply custom configuration
        style[
            "output-field"] = "bg:" + color_output_pane + " " + color_terminal_primary
        style["input-field"] = "bg:" + color_input_pane + " " + style[
            "input-field"].split(' ')[-1]
        style["log-field"] = "bg:" + color_logs_pane + " " + style[
            "log-field"].split(' ')[-1]
        style["header"] = "bg:" + color_top_pane + " " + style["header"].split(
            ' ')[-1]
        style["footer"] = "bg:" + color_bottom_pane + " " + style[
            "footer"].split(' ')[-1]
        style["primary"] = color_terminal_primary

        return Style.from_dict(style)
Beispiel #17
0
def list_clients():
    if is_windows():
        from .windows import list_clients
        return list_clients()
    else:
        from .posix import list_clients
        return list_clients()
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 prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop
    else:
        from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop
    return AsyncioEventLoop
Beispiel #19
0
def load_style():
    """
    Return a dict mapping {ui_style_name -> style_dict}.
    """
    if is_windows():
        return Style.from_dict(win32_code_style)
    else:
        return Style.from_dict(default_ui_style)
 def height_is_known(self) -> bool:
     """
     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.
Beispiel #21
0
def create_terminal(command, before_exec_func):
    if is_windows():
        from .backends.win32 import Win32Terminal
        return Win32Terminal()
    else:
        from .backends.posix import PosixTerminal
        return PosixTerminal.from_command(command,
                                          before_exec_func=before_exec_func)
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 prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop
    else:
        from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop
    return AsyncioEventLoop
Beispiel #23
0
    def request_absolute_cursor_position(self):
        """
        Get current cursor position.

        We do this to calculate the minimum available height that we can
        consume for rendering the prompt. This is the available space below te
        cursor.

        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

        # In full-screen mode, always use the total height as min-available-height.
        if self.full_screen:
            self._min_available_height = self.output.get_size().rows

        # For Win32, we have an API call to get the number of rows below the
        # cursor.
        elif is_windows():
            self._min_available_height = self.output.get_rows_below_cursor_position(
            )

        # Use CPR.
        else:
            if self.cpr_support == CPR_Support.NOT_SUPPORTED:
                return

            def do_cpr():
                # Asks for a cursor position report (CPR).
                self._waiting_for_cpr_futures.append(Future())
                self.output.ask_for_cpr()

            if self.cpr_support == CPR_Support.SUPPORTED:
                do_cpr()

            # If we don't know whether CPR is supported, only do a request if
            # none is pending, and test it, using a timer.
            elif self.cpr_support == CPR_Support.UNKNOWN and not self.waiting_for_cpr:
                do_cpr()

                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()
def create_input(stdin: Optional[TextIO] = None) -> Input:
    stdin = stdin or sys.stdin

    if is_windows():
        from .win32 import Win32Input
        return Win32Input(stdin)
    else:
        from .vt100 import Vt100Input
        return Vt100Input(stdin)
Beispiel #25
0
    def select(
        self,
        timeout: Optional[float] = None
    ) -> List[Tuple["SelectorKey", "_EventMask"]]:
        # If there are tasks in the current event loop,
        # don't run the input hook.
        if len(getattr(get_event_loop(), "_ready", [])) > 0:
            return self.selector.select(timeout=timeout)

        ready = False
        result = None

        # Run selector in other thread.
        def run_selector() -> None:
            nonlocal ready, result
            result = self.selector.select(timeout=timeout)
            os.write(self._w, b"x")
            ready = True

        th = threading.Thread(target=run_selector)
        th.start()

        def input_is_ready() -> bool:
            return ready

        # Call inputhook.
        # The inputhook function is supposed to return when our selector
        # becomes ready. The inputhook can do that by registering the fd in its
        # own loop, or by checking the `input_is_ready` function regularly.
        self.inputhook(InputHookContext(self._r, input_is_ready))

        # 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.select([self._r], [], [], 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

        # Wait for the real selector to be done.
        th.join()
        assert result is not None
        return result
Beispiel #26
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)
    def request_absolute_cursor_position(self):
        """
        Get current cursor position.

        We do this to calculate the minimum available height that we can
        consume for rendering the prompt. This is the available space below te
        cursor.

        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

        # In full-screen mode, always use the total height as min-available-height.
        if self.full_screen:
            self._min_available_height = self.output.get_size().rows

        # For Win32, we have an API call to get the number of rows below the
        # cursor.
        elif is_windows():
            self._min_available_height = self.output.get_rows_below_cursor_position()

        # Use CPR.
        else:
            if self.cpr_support == CPR_Support.NOT_SUPPORTED:
                return

            def do_cpr():
                # Asks for a cursor position report (CPR).
                self._waiting_for_cpr_futures.append(Future())
                self.output.ask_for_cpr()

            if self.cpr_support == CPR_Support.SUPPORTED:
                do_cpr()

            # If we don't know whether CPR is supported, only do a request if
            # none is pending, and test it, using a timer.
            elif self.cpr_support == CPR_Support.UNKNOWN and not self.waiting_for_cpr:
                do_cpr()

                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()
Beispiel #28
0
def create_write_console_ex(session, stderr_format):
    output = session.app.output
    from prompt_toolkit.utils import is_windows

    write_console_ex = None

    if is_windows():
        from prompt_toolkit.output.win32 import Win32Output
        if isinstance(output, Win32Output):
            # we use print_formatted_text to support ANSI sequences in older Windows
            from prompt_toolkit.formatted_text import ANSI
            from prompt_toolkit.shortcuts import print_formatted_text

            def write_console_ex(buf, otype):
                if otype == 0:
                    if sys.stdout:
                        buf = buf.replace("\r\n", "\n")
                        sbuf = buf.split("\r")
                        for i, b in enumerate(sbuf):
                            print_formatted_text(ANSI(b),
                                                 end="",
                                                 output=output)
                            if i < len(sbuf) - 1:
                                output.write("\r")
                        output.flush()
                        TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")
                else:
                    if sys.stderr:
                        buf = buf.replace("\r\n", "\n")
                        sbuf = buf.split("\r")
                        for i, b in enumerate(sbuf):
                            print_formatted_text(ANSI(stderr_format.format(b)),
                                                 end="",
                                                 output=output)
                            if i < len(sbuf) - 1:
                                output.write("\r")
                        output.flush()
                        TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")

    if not write_console_ex:

        def write_console_ex(buf, otype):
            if otype == 0:
                # although we do not use sys.stdout and sys.stderr directly, we use them to flag
                # whether we should print to them
                if sys.stdout:
                    output.write_raw(buf)
                    output.flush()
                    TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")
            else:
                if sys.stderr:
                    output.write_raw(stderr_format.format(buf))
                    output.flush()
                    TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")

    return write_console_ex
Beispiel #29
0
def create_terminal(command, before_exec_func, fake=False):
    if fake:
        from .backends.simulated import SimTerminal
        return SimTerminal()
    elif is_windows():
        from .backends.win32 import Win32Terminal
        return Win32Terminal()
    else:
        from .backends.posix import PosixTerminal
        return PosixTerminal.from_command(command, before_exec_func=before_exec_func)
Beispiel #30
0
def create_write_console_ex(session, stderr_format):
    app = session.app
    output = app.output
    from prompt_toolkit.utils import is_windows

    write_console_ex = None

    if is_windows():
        from prompt_toolkit.output.win32 import Win32Output
        if isinstance(output, Win32Output):
            # we use print_formatted_text to support ANSI sequences in older Windows
            from prompt_toolkit.formatted_text import ANSI
            from prompt_toolkit.shortcuts import print_formatted_text

            def write_console_ex(buf, otype):
                if otype == 0:
                    if not SUPPRESS_STDOUT:
                        buf = buf.replace("\r\n", "\n")
                        sbuf = buf.split("\r")
                        for i, b in enumerate(sbuf):
                            print_formatted_text(ANSI(b),
                                                 end="",
                                                 output=output)
                            if i < len(sbuf) - 1:
                                output.write("\r")
                        output.flush()
                        TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")
                else:
                    if not SUPPRESS_STDERR:
                        buf = buf.replace("\r\n", "\n")
                        sbuf = buf.split("\r")
                        for i, b in enumerate(sbuf):
                            print_formatted_text(ANSI(stderr_format.format(b)),
                                                 end="",
                                                 output=output)
                            if i < len(sbuf) - 1:
                                output.write("\r")
                        output.flush()
                        TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")

    if not write_console_ex:

        def write_console_ex(buf, otype):
            if otype == 0:
                if not SUPPRESS_STDOUT:
                    output.write_raw(buf)
                    output.flush()
                    TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")
            else:
                if not SUPPRESS_STDERR:
                    output.write_raw(stderr_format.format(buf))
                    output.flush()
                    TERMINAL_CURSOR_AT_BEGINNING[0] = buf.endswith("\n")

    return write_console_ex
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()
Beispiel #32
0
def create_pipe_input():
    """
    Create an input pipe.
    This is mostly useful for unit testing.
    """
    if is_windows():
        from .win32_pipe import Win32PipeInput
        return Win32PipeInput()
    else:
        from .posix_pipe import PosixPipeInput
        return PosixPipeInput()
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()
Beispiel #34
0
 def build_model_df_data(
         config_map: ClientConfigAdapter,
         to_print: Optional[List[str]] = None) -> List[Tuple[str, Any]]:
     model_data = []
     for traversal_item in config_map.traverse():
         if to_print is not None and traversal_item.attr not in to_print:
             continue
         attr_printout = ("  " * (traversal_item.depth - 1) +
                          (u"\u221F " if not is_windows() else "  ") +
                          traversal_item.attr
                          ) if traversal_item.depth else traversal_item.attr
         model_data.append((attr_printout, traversal_item.printable_value))
     return model_data
Beispiel #35
0
def bind_and_listen_on_socket(socket_name, accept_callback):
    """
    Return socket name.

    :param accept_callback: Callback is called with a `PipeConnection` as
        argument.
    """
    if is_windows():
        from .win32_server import bind_and_listen_on_win32_socket
        return bind_and_listen_on_win32_socket(socket_name, accept_callback)
    else:
        from .posix import bind_and_listen_on_posix_socket
        return bind_and_listen_on_posix_socket(socket_name, accept_callback)
Beispiel #36
0
def create_pipe_input(responds_to_cpr: bool = True) -> PipeInput:
    """
    Create an input pipe.
    This is mostly useful for unit testing.
    """
    if is_windows():
        from .win32_pipe import Win32PipeInput

        return Win32PipeInput(responds_to_cpr=responds_to_cpr)
    else:
        from .posix_pipe import PosixPipeInput

        return PosixPipeInput(responds_to_cpr=responds_to_cpr)
Beispiel #37
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_char = None

        # When the style hash changes, we have to do a full redraw as well as
        # clear the `_attrs_for_token` dictionary.
        self._last_style_hash = None
        self._attrs_for_token = None

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

        # Remember the last title. Only set the title when it changes.
        self._last_title = None

        #: 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 Windown, 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()
Beispiel #38
0
def get_default_shell():
    """
    return the path to the default shell for the current user.
    """
    if is_windows():
        return 'cmd.exe'
    else:
        import pwd
        import getpass

        if 'SHELL' in os.environ:
            return os.environ['SHELL']
        else:
            username = getpass.getuser()
            shell = pwd.getpwnam(username).pw_shell
            return shell
    def _(event: E) -> None:
        """
        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))
    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.use_alternate_screen:
                self._min_available_height = self.output.get_size().rows
            else:
                # Asks for a cursor position report (CPR).
                self.output.ask_for_cpr()
    def default(cls, term: str = '') -> 'ColorDepth':
        """
        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.
        all_values = [i.value for i in ColorDepth]

        if os.environ.get('PROMPT_TOOLKIT_COLOR_DEPTH') in all_values:
            return cls(os.environ['PROMPT_TOOLKIT_COLOR_DEPTH'])

        return cls.DEPTH_8_BIT
def is_win_vt100_enabled() -> bool:
    """
    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)
Beispiel #43
0
    def call_inputhook(self, input_is_ready_func):
        """
        Call the inputhook. (Called by a prompt-toolkit eventloop.)
        """
        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.
        self.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
Beispiel #44
0
def run():
    if is_windows():
        from prompt_toolkit.eventloop.win32 import Win32EventLoop
        loop = Win32EventLoop()
    else:
        from prompt_toolkit.eventloop.posix import PosixEventLoop
        from prompt_toolkit.eventloop.select import SelectSelector
        loop = PosixEventLoop(selector=SelectSelector)
    set_event_loop(loop)

    if not sys.stdin.isatty():
        pager = Pager.from_pipe()
        pager.run()
    else:
        parser = argparse.ArgumentParser(description='Browse through a text file.')
        parser.add_argument('filename', metavar='filename', nargs='+',
                            help='The file to be displayed.')
        parser.add_argument('--vi', help='Prefer Vi key bindings.', action='store_true')
        parser.add_argument('--emacs', help='Prefer Emacs key bindings.', action='store_true')

        args = parser.parse_args()

        # Determine input mode.
        vi_mode = 'vi' in os.environ.get('EDITOR', '').lower()
        if args.vi: vi_mode = True
        if args.emacs: vi_mode = False

        pager = Pager(vi_mode=vi_mode)

        # Open files.
        for filename in args.filename:
            # When a filename is given, take a lexer from that filename.
            lexer = PygmentsLexer.from_filename(filename, sync_from_start=False)

            pager.add_source(FileSource(filename, lexer=lexer))

        # Run UI.
        pager.run()
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())
Beispiel #46
0
    # Help Window.
    'window-border':                          '#aaaaaa',
    'window-title':                           'bg:#bbbbbb #000000',

    # Meta-enter message.
    'accept-message':                          'bg:#ffff88 #444444',

    # Exit confirmation.
    'exit-confirmation':                       'bg:#884444 #ffffff',
}


# Some changes to get a bit more contrast on Windows consoles.
# (They only support 16 colors.)
if is_windows() and not is_conemu_ansi() and not is_windows_vt100_supported():
    default_ui_style.update({
        'sidebar.title':                          'bg:#00ff00 #ffffff',
        'exitconfirmation':                       'bg:#ff4444 #ffffff',
        'toolbar.validation':                     'bg:#ff4444 #ffffff',

        'menu.completions.completion':            'bg:#ffffff #000000',
        'menu.completions.completion.current':    'bg:#aaaaaa #000000',
    })


blue_ui_style = {}
blue_ui_style.update(default_ui_style)
#blue_ui_style.update({
#        # Line numbers.
#        Token.LineNumber:                             '#aa6666',
        return b''.join(self._data)

    def flush(self):
        pass

    def isatty(self):
        return True

    def fileno(self):
        # File descriptor is not used for printing formatted text.
        # (It is only needed for getting the terminal size.)
        return -1


@pytest.mark.skipif(
    is_windows(), reason="Doesn't run on Windows yet.")
def test_print_formatted_text():
    f = _Capture()
    pt_print([('', 'hello'), ('', 'world')], file=f)
    assert b'hello' in f.data
    assert b'world' in f.data


@pytest.mark.skipif(
    is_windows(), reason="Doesn't run on Windows yet.")
def test_with_style():
    f = _Capture()
    style = Style.from_dict({
        'hello': '#ff0066',
        'world': '#44ff44 italic',
    })
    def __init__(self,
                 get_globals=None, get_locals=None, history_filename=None,
                 vi_mode=False,

                 input=None,
                 output=None,
                 color_depth=None,

                 # For internal use.
                 extra_key_bindings=None,
                 _completer=None, _validator=None,
                 _lexer=None, _extra_buffer_processors=None,
                 _extra_layout_body=None, _extra_toolbars=None,
                 _input_buffer_height=None):

        self.get_globals = get_globals or (lambda: {})
        self.get_locals = get_locals or self.get_globals

        self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals)
        self._validator = _validator or PythonValidator(self.get_compiler_flags)
        self._lexer = _lexer or PygmentsLexer(PythonLexer)

        if history_filename:
            self.history = ThreadedHistory(FileHistory(history_filename))
        else:
            self.history = InMemoryHistory()

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        self.extra_key_bindings = extra_key_bindings or KeyBindings()

        # Settings.
        self.show_signature = False
        self.show_docstring = False
        self.show_meta_enter_message = True
        self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.completion_menu_scroll_offset = 1

        self.show_line_numbers = False
        self.show_status_bar = True
        self.wrap_lines = True
        self.complete_while_typing = True
        self.paste_mode = False  # When True, don't insert whitespace after newline.
        self.confirm_exit = True  # Ask for confirmation when Control-D is pressed.
        self.accept_input_on_enter = 2  # Accept when pressing Enter 'n' times.
                                        # 'None' means that meta-enter is always required.
        self.enable_open_in_editor = True
        self.enable_system_bindings = True
        self.enable_input_validation = True
        self.enable_auto_suggest = False
        self.enable_mouse_support = False
        self.enable_history_search = False  # When True, like readline, going
                                            # back in history will filter the
                                            # history on the records starting
                                            # with the current input.

        self.enable_syntax_highlighting = True
        self.swap_light_and_dark = False
        self.highlight_matching_parenthesis = False
        self.show_sidebar = False  # Currently show the sidebar.
        self.show_sidebar_help = True # When the sidebar is visible, also show the help text.
        self.show_exit_confirmation = False  # Currently show 'Do you really want to exit?'
        self.terminal_title = None  # The title to be displayed in the terminal. (None or string.)
        self.exit_message = 'Do you really want to exit?'
        self.insert_blank_line_after_output = True  # (For the REPL.)

        # The buffers.
        self.default_buffer = self._create_buffer()
        self.search_buffer = Buffer()
        self.docstring_buffer = Buffer(read_only=True)

        # Tokens to be shown at the prompt.
        self.prompt_style = 'classic'  # The currently active style.

        self.all_prompt_styles = {  # Styles selectable from the menu.
            'ipython': IPythonPrompt(self),
            'classic': ClassicPrompt(),
        }

        self.get_input_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].in_prompt()

        self.get_output_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].out_prompt()

        #: Load styles.
        self.code_styles = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name = 'default'
        self._current_ui_style_name = 'default'

        if is_windows():
            self._current_code_style_name = 'win32'

        self._current_style = self._generate_style()
        self.color_depth = color_depth or ColorDepth.default()

        self.max_brightness = 1.0
        self.min_brightness = 0.0

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index = 0

        #: Incremeting integer counting the current statement.
        self.current_statement_index = 1

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures = []

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running = False

        self.output = output or create_output()
        self.input = input or create_input(sys.stdin)

        self.style_transformation = merge_style_transformations([
            ConditionalStyleTransformation(
                SwapLightAndDarkStyleTransformation(),
                filter=Condition(lambda: self.swap_light_and_dark)),
            AdjustBrightnessStyleTransformation(
                lambda: self.min_brightness,
                lambda: self.max_brightness),
        ])
        self.ptpython_layout = PtPythonLayout(
            self,
            lexer=DynamicLexer(
                lambda: self._lexer if self.enable_syntax_highlighting else SimpleLexer()),
            input_buffer_height=self._input_buffer_height,
            extra_buffer_processors=self._extra_buffer_processors,
            extra_body=self._extra_layout_body,
            extra_toolbars=self._extra_toolbars)

        self.app = self._create_application()

        if vi_mode:
            self.app.editing_mode = EditingMode.VI
Beispiel #49
0
    def __init__(self,
                 get_globals=None, get_locals=None, history_filename=None,
                 vi_mode=False,

                 # For internal use.
                 _completer=None, _validator=None, _python_prompt_control=None,
                 _lexer=None, _extra_buffers=None, _extra_buffer_processors=None,
                 _on_start=None,
                 _extra_layout_body=None, _extra_toolbars=None,
                 _input_buffer_height=None,
                 _accept_action=AcceptAction.RETURN_DOCUMENT,
                 _on_exit=AbortAction.RAISE_EXCEPTION):

        self.get_globals = get_globals or (lambda: {})
        self.get_locals = get_locals or self.get_globals

        self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals)
        self._validator = _validator or PythonValidator(self.get_compiler_flags)
        self._history = FileHistory(history_filename) if history_filename else InMemoryHistory()
        self._lexer = _lexer or PygmentsLexer(PythonLexer)
        self._extra_buffers = _extra_buffers
        self._accept_action = _accept_action
        self._on_exit = _on_exit
        self._on_start = _on_start

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        self._python_prompt_control = _python_prompt_control or PythonPrompt(self)

        # Settings.
        self.show_signature = True
        self.show_docstring = False
        self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.completion_menu_scroll_offset = 1

        self.show_line_numbers = True
        self.show_status_bar = True
        self.complete_while_typing = True
        self.vi_mode = vi_mode
        self.paste_mode = False  # When True, don't insert whitespace after newline.
        self.confirm_exit = True  # Ask for confirmation when Control-D is pressed.
        self.accept_input_on_enter = 2  # Accept when pressing Enter 'n' times.
                                        # 'None' means that meta-enter is always required.
        self.enable_open_in_editor = True
        self.enable_system_bindings = True
        self.enable_input_validation = True
        self.enable_history_search = False  # When True, like readline, going
                                            # back in history will filter the
                                            # history on the records starting
                                            # with the current input.

        self.show_sidebar = False  # Currently show the sidebar.
        self.show_sidebar_help = True # When the sidebar is visible, also show the help text.
        self.show_exit_confirmation = False  # Currently show 'Do you really want to exit?'
        self.terminal_title = None  # The title to be displayed in the terminal. (None or string.)
        self.exit_message = 'Do you really want to exit?'

        #: Load styles.
        self.code_styles = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name = 'default'
        self._current_ui_style_name = 'default'

        if is_windows():
            self._current_code_style_name = 'win32'

        self._current_style = self._generate_style()

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index = 0

        #: Incremeting integer counting the current statement.
        self.current_statement_index = 1

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures = []

        # Use a KeyBindingManager for loading the key bindings.
        self.key_bindings_manager = KeyBindingManager(
            enable_vi_mode=Condition(lambda cli: self.vi_mode),
            enable_open_in_editor=Condition(lambda cli: self.enable_open_in_editor),
            enable_system_bindings=Condition(lambda cli: self.enable_system_bindings),

            # Disable all default key bindings when the sidebar or the exit confirmation
            # are shown.
            enable_all=Condition(lambda cli: not (self.show_sidebar or self.show_exit_confirmation)))

        load_python_bindings(self.key_bindings_manager, self)
        load_sidebar_bindings(self.key_bindings_manager, self)
        load_confirm_exit_bindings(self.key_bindings_manager, self)

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running = False
Beispiel #50
0
from __future__ import unicode_literals

# noinspection PyUnresolvedReferences
import plenum.cli.ensure_logging_not_setup

from typing import Dict

import re
from prompt_toolkit.utils import is_windows, is_conemu_ansi

from plenum.client.signer import SimpleSigner

if is_windows():
    from prompt_toolkit.terminal.win32_output import Win32Output
    from prompt_toolkit.terminal.conemu_output import ConEmuOutput
else:
    from prompt_toolkit.terminal.vt100_output import Vt100_Output

import configparser
import os
from configparser import ConfigParser

import time
import ast

from functools import reduce, partial
import logging
import sys
from collections import defaultdict

from prompt_toolkit.history import FileHistory
Beispiel #51
0
        # Help Window.
        Token.Window.Border:                          '#bbbbbb',
        Token.Window.Title:                           'bg:#bbbbbb #000000',

        # Meta-enter message.
        Token.AcceptMessage:                          'bg:#ffff88 #444444',

        # Exit confirmation.
        Token.ExitConfirmation:                       'bg:#884444 #ffffff',
}


# Some changes to get a bit more contrast on Windows consoles.
# (They only support 16 colors.)
if is_windows() and not is_conemu_ansi():
    default_ui_style.update({
        Token.Sidebar.Title:                          'bg:#00ff00 #ffffff',
        Token.ExitConfirmation:                       'bg:#ff4444 #ffffff',
        Token.Toolbar.Validation:                     'bg:#ff4444 #ffffff',

        Token.Menu.Completions.Completion:            'bg:#ffffff #000000',
        Token.Menu.Completions.Completion.Current:    'bg:#aaaaaa #000000',
    })


blue_ui_style = {}
blue_ui_style.update(default_ui_style)
blue_ui_style.update({
        # Line numbers.
        Token.LineNumber:                             '#aa6666',
Beispiel #52
0
    def __init__(self,
                 get_globals=None, get_locals=None, history_filename=None,
                 vi_mode=False,

                 # For internal use.
                 _completer=None, _validator=None,
                 _lexer=None, _extra_buffers=None, _extra_buffer_processors=None,
                 _on_start=None,
                 _extra_layout_body=None, _extra_toolbars=None,
                 _input_buffer_height=None,
                 _accept_action=AcceptAction.RETURN_DOCUMENT,
                 _on_exit=AbortAction.RAISE_EXCEPTION):

        self.get_globals = get_globals or (lambda: {})
        self.get_locals = get_locals or self.get_globals

        self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals)
        self._validator = _validator or PythonValidator(self.get_compiler_flags)
        self.history = FileHistory(history_filename) if history_filename else InMemoryHistory()
        self._lexer = _lexer or PygmentsLexer(PythonLexer)
        self._extra_buffers = _extra_buffers
        self._accept_action = _accept_action
        self._on_exit = _on_exit
        self._on_start = _on_start

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        # Settings.
        self.settings = Settings({
            'show_signature': True,
            'show_docstring': False,
            'show_meta_enter_message': True,
            'completion_visualisation': 'CompletionVisualisation.MULTI_COLUMN',
            'completion_menu_scroll_offset': 1,
            
            'show_line_numbers': False,
            'show_status_bar': True,
            'wrap_lines': True,
            'complete_while_typing': True,
            'vi_mode': vi_mode,
            'paste_mode': False,  # When True, don't insert whitespace after newline.
            'confirm_exit': True,  # Ask for confirmation when Control-D is pressed.
            'accept_input_on_enter': 2,  # Accept when pressing Enter 'n' times.
                                         # 'None' means that meta-enter is always required.
            'enable_open_in_editor': True,
            'enable_system_bindings': True,
            'enable_input_validation': True,
            'enable_auto_suggest': False,
            'enable_mouse_support': False,
            'enable_history_search': False,  # When True, like readline, going
                                             # back in history will filter the
                                             # history on the records starting
                                             # with the current input.
            
            'highlight_matching_parenthesis': True,
            'show_sidebar': False,  # Currently show the sidebar.
            'show_sidebar_help': True, # When the sidebar is visible, also show the help text.
            'terminal_title': None,  # The title to be displayed in the terminal. (None or string.)
            'exit_message': 'Do you really want to exit?',
            
            # Tokens to be shown at the prompt.
            'prompt_style': 'classic'  # The currently active style.
        })

        self.show_exit_confirmation = False

        self.all_prompt_styles = {  # Styles selectable from the menu.
            'ipython': IPythonPrompt(self),
            'classic': ClassicPrompt(),
        }

        self.get_input_prompt_tokens = lambda cli: \
            self.all_prompt_styles[self.settings.prompt_style].in_tokens(cli)

        self.get_output_prompt_tokens = lambda cli: \
            self.all_prompt_styles[self.settings.prompt_style].out_tokens(cli)

        #: Load styles.
        self.code_styles = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name = 'default'
        self._current_ui_style_name = 'default'

        if is_windows():
            self._current_code_style_name = 'win32'

        self._current_style = self._generate_style()

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index = 0

        #: Incremeting integer counting the current statement.
        self.current_statement_index = 1

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures = []

        # Use a KeyBindingManager for loading the key bindings.
        self.key_bindings_manager = KeyBindingManager(
            enable_abort_and_exit_bindings=True,
            enable_search=True,
            enable_vi_mode=Condition(lambda cli: self.settings.vi_mode),
            enable_open_in_editor=Condition(lambda cli: self.settings.enable_open_in_editor),
            enable_system_bindings=Condition(lambda cli: self.settings.enable_system_bindings),
            enable_auto_suggest_bindings=Condition(lambda cli: self.settings.enable_auto_suggest),

            # Disable all default key bindings when the sidebar or the exit confirmation
            # are shown.
            enable_all=Condition(lambda cli: not (self.settings.show_sidebar or self.show_exit_confirmation)))

        load_python_bindings(self.key_bindings_manager, self)
        load_sidebar_bindings(self.key_bindings_manager, self)
        load_confirm_exit_bindings(self.key_bindings_manager, self)

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running = False
Beispiel #53
0
    def __init__(self, looper, basedirpath, nodeReg, cliNodeReg, output=None, debug=False,
                 logFileName=None):
        self.curClientPort = None
        logging.root.addHandler(CliHandler(self.out))

        self.looper = looper
        self.basedirpath = basedirpath
        self.nodeReg = nodeReg
        self.cliNodeReg = cliNodeReg

        # Used to store created clients
        self.clients = {}  # clientName -> Client
        # To store the created requests
        self.requests = {}
        # To store the nodes created
        self.nodes = {}
        self.externalClientKeys = {}  # type: Dict[str,str]

        self.cliCmds = {'status', 'new'}
        self.nodeCmds = self.cliCmds | {'keyshare'}
        self.helpablesCommands = self.cliCmds | self.nodeCmds
        self.simpleCmds = {'status', 'exit', 'quit', 'license'}
        self.commands = {'list', 'help'} | self.simpleCmds
        self.cliActions = {'send', 'show'}
        self.commands.update(self.cliCmds)
        self.commands.update(self.nodeCmds)
        self.node_or_cli = ['node',  'client']
        self.nodeNames = list(self.nodeReg.keys()) + ["all"]
        self.debug = debug
        self.plugins = {}
        '''
        examples:
        status

        new node Alpha
        new node all
        new client Joe
        client Joe send <msg>
        client Joe show 1
        '''

        psep = re.escape(os.path.sep)

        self.utilGrams = [
            "(\s* (?P<simple>{}) \s*) |".format(self.relist(self.simpleCmds)),
            "(\s* (?P<load>load) \s+ (?P<file_name>[.a-zA-z0-9{}]+) \s*) |".format(psep),
            "(\s* (?P<command>help) (\s+ (?P<helpable>[a-zA-Z0-9]+) )? (\s+ (?P<node_or_cli>{}) )?\s*) |".format(self.relist(self.node_or_cli)),
            "(\s* (?P<command>list) \s*)"
        ]

        self.nodeGrams = [
            "(\s* (?P<node_command>{}) \s+ (?P<node_or_cli>nodes?)   \s+ (?P<node_name>[a-zA-Z0-9]+)\s*) |".format(self.relist(self.nodeCmds)),
            "(\s* (?P<load_plugins>load\s+plugins\s+from) \s+ (?P<plugin_dir>[a-zA-Z0-9-:{}]+) \s*)".format(psep),
        ]

        self.clientGrams = [
            "(\s* (?P<client_command>{}) \s+ (?P<node_or_cli>clients?)   \s+ (?P<client_name>[a-zA-Z0-9]+) \s*) |".format(self.relist(self.cliCmds)),
            "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>send) \s+ (?P<msg>\{\s*.*\})  \s*)  |",
            "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>show) \s+ (?P<req_id>[0-9]+)  \s*)  |",
            "(\s* (?P<add_key>add\s+key) \s+ (?P<verkey>[a-fA-F0-9]+) \s+ (?P<for_client>for\s+client) \s+ (?P<identifier>[a-zA-Z0-9]+) \s*)",
        ]

        self.lexers = {
            'node_command': SimpleLexer(Token.Keyword),
            'command': SimpleLexer(Token.Keyword),
            'helpable': SimpleLexer(Token.Keyword),
            'load_plugins': SimpleLexer(Token.Keyword),
            'load': SimpleLexer(Token.Keyword),
            'node_or_cli': SimpleLexer(Token.Keyword),
            'arg1': SimpleLexer(Token.Name),
            'node_name': SimpleLexer(Token.Name),
            'more_nodes': SimpleLexer(Token.Name),
            'simple': SimpleLexer(Token.Keyword),
            'client_command': SimpleLexer(Token.Keyword),
            'add_key': SimpleLexer(Token.Keyword),
            'verkey': SimpleLexer(Token.Literal),
            'for_client': SimpleLexer(Token.Keyword),
            'identifier': SimpleLexer(Token.Name),
        }

        self.clientWC = WordCompleter([])

        self.completers = {
            'node_command': WordCompleter(self.nodeCmds),
            'client_command': WordCompleter(self.cliCmds),
            'client': WordCompleter(['client']),
            'command': WordCompleter(self.commands),
            'node_or_cli': WordCompleter(self.node_or_cli),
            'node_name': WordCompleter(self.nodeNames),
            'more_nodes': WordCompleter(self.nodeNames),
            'helpable': WordCompleter(self.helpablesCommands),
            'load_plugins': WordCompleter(['load plugins from']),
            'client_name': self.clientWC,
            'cli_action': WordCompleter(self.cliActions),
            'simple': WordCompleter(self.simpleCmds),
            'add_key': WordCompleter(['add key']),
            'for_client': WordCompleter(['for client']),
        }

        self.initializeGrammar()

        self.initializeGrammarLexer()

        self.initializeGrammarCompleter()

        self.style = PygmentsStyle.from_defaults({
            Token.Operator: '#33aa33 bold',
            Token.Number: '#aa3333 bold',
            Token.Name: '#ffff00 bold',
            Token.Heading: 'bold',
            Token.TrailingInput: 'bg:#662222 #ffffff',
            Token.BoldGreen: '#33aa33 bold',
            Token.BoldOrange: '#ff4f2f bold',
            Token.BoldBlue: '#095cab bold'})

        self.functionMappings = self.createFunctionMappings()

        self.voidMsg = "<none>"

        # Create an asyncio `EventLoop` object. This is a wrapper around the
        # asyncio loop that can be passed into prompt_toolkit.
        eventloop = create_asyncio_eventloop(looper.loop)

        pers_hist = FileHistory('.{}-cli-history'.format(self.name))

        # Create interface.
        app = create_prompt_application('{}> '.format(self.name),
                                        lexer=self.grammarLexer,
                                        completer=self.grammarCompleter,
                                        style=self.style,
                                        history=pers_hist)

        if output:
            out = output
        else:
            if is_windows():
                if is_conemu_ansi():
                    out = ConEmuOutput(sys.__stdout__)
                else:
                    out = Win32Output(sys.__stdout__)
            else:
                out = CustomOutput.from_pty(sys.__stdout__, true_color=True)

        self.cli = CommandLineInterface(
            application=app,
            eventloop=eventloop,
            output=out)

        # Patch stdout in something that will always print *above* the prompt
        # when something is written to stdout.
        sys.stdout = self.cli.stdout_proxy()
        setupLogging(TRACE_LOG_LEVEL,
                     Console.Wordage.mute,
                     filename=logFileName)

        self.logger = getlogger("cli")
        self.print("\n{}-CLI (c) 2016 Evernym, Inc.".format(self.properName))
        self.print("Node registry loaded.")
        self.print("None of these are created or running yet.")

        self.showNodeRegistry()
        self.print("Type 'help' for more information.")