def test_split_lines_3():
    " Edge cases: inputs ending with newlines. "
    # -1-
    lines = list(split_lines([
        ('class:a', 'line1\nline2\n')
    ]))

    assert lines == [
        [('class:a', 'line1')],
        [('class:a', 'line2')],
        [('class:a', '')],
    ]

    # -2-
    lines = list(split_lines([
        ('class:a', '\n'),
    ]))

    assert lines == [
        [],
        [('class:a', '')],
    ]

    # -3-
    lines = list(split_lines([
        ('class:a', ''),
    ]))

    assert lines == [
        [('class:a', '')],
    ]
示例#2
0
def test_split_lines_3():
    " Edge cases: inputs ending with newlines. "
    # -1-
    lines = list(split_lines([("class:a", "line1\nline2\n")]))

    assert lines == [
        [("class:a", "line1")],
        [("class:a", "line2")],
        [("class:a", "")],
    ]

    # -2-
    lines = list(split_lines([("class:a", "\n"),]))

    assert lines == [
        [],
        [("class:a", "")],
    ]

    # -3-
    lines = list(split_lines([("class:a", ""),]))

    assert lines == [
        [("class:a", "")],
    ]
示例#3
0
def test_split_lines_3():
    " Edge cases: inputs ending with newlines. "
    # -1-
    lines = list(split_lines([('class:a', 'line1\nline2\n')]))

    assert lines == [
        [('class:a', 'line1')],
        [('class:a', 'line2')],
        [('class:a', '')],
    ]

    # -2-
    lines = list(split_lines([
        ('class:a', '\n'),
    ]))

    assert lines == [
        [],
        [('class:a', '')],
    ]

    # -3-
    lines = list(split_lines([
        ('class:a', ''),
    ]))

    assert lines == [
        [('class:a', '')],
    ]
示例#4
0
    def create_content(self, width, height):
        # Get fragments
        fragments_with_mouse_handlers = self._get_formatted_text_cached()
        fragment_lines_with_mouse_handlers = list(
            split_lines(fragments_with_mouse_handlers))

        # Strip mouse handlers from fragments.
        fragment_lines = [[tuple(item[:2]) for item in line]
                          for line in fragment_lines_with_mouse_handlers]

        # Keep track of the fragments with mouse handler, for later use in
        # `mouse_handler`.
        self._fragments = fragments_with_mouse_handlers

        cursor_position = self.get_cursor_position()

        # Create content, or take it from the cache.
        key = (tuple(fragments_with_mouse_handlers), width, cursor_position)

        def get_content():
            return UIContent(get_line=lambda i: fragment_lines[i],
                             line_count=len(fragment_lines),
                             cursor_position=cursor_position,
                             show_cursor=self.show_cursor)

        return self._content_cache.get(key, get_content)
示例#5
0
def test_split_lines():
    lines = list(split_lines([("class:a", "line1\nline2\nline3")]))

    assert lines == [
        [("class:a", "line1")],
        [("class:a", "line2")],
        [("class:a", "line3")],
    ]
示例#6
0
def test_split_lines():
    lines = list(split_lines([('class:a', 'line1\nline2\nline3')]))

    assert lines == [
        [('class:a', 'line1')],
        [('class:a', 'line2')],
        [('class:a', 'line3')],
    ]
def test_split_lines():
    lines = list(split_lines([('class:a', 'line1\nline2\nline3')]))

    assert lines == [
        [('class:a', 'line1')],
        [('class:a', 'line2')],
        [('class:a', 'line3')],
    ]
示例#8
0
    def show_result(self, result: object) -> None:
        """
        Show __repr__ for an `eval` result.
        """
        out_prompt = to_formatted_text(self.get_output_prompt())

        # If the repr is valid Python code, use the Pygments lexer.
        result_repr = repr(result)
        try:
            compile(result_repr, "", "eval")
        except SyntaxError:
            formatted_result_repr = to_formatted_text(result_repr)
        else:
            formatted_result_repr = to_formatted_text(
                PygmentsTokens(list(_lex_python_result(result_repr))))

        # If __pt_repr__ is present, take this. This can return
        # prompt_toolkit formatted text.
        if hasattr(result, "__pt_repr__"):
            try:
                formatted_result_repr = to_formatted_text(
                    getattr(result, "__pt_repr__")())
                if isinstance(formatted_result_repr, list):
                    formatted_result_repr = FormattedText(
                        formatted_result_repr)
            except:
                pass

        # Align every line to the prompt.
        line_sep = "\n" + " " * fragment_list_width(out_prompt)
        indented_repr: StyleAndTextTuples = []

        lines = list(split_lines(formatted_result_repr))

        for i, fragment in enumerate(lines):
            indented_repr.extend(fragment)

            # Add indentation separator between lines, not after the last line.
            if i != len(lines) - 1:
                indented_repr.append(("", line_sep))

        # Write output tokens.
        if self.enable_syntax_highlighting:
            formatted_output = merge_formatted_text(
                [out_prompt, indented_repr])
        else:
            formatted_output = FormattedText(out_prompt + [(
                "", fragment_list_to_text(formatted_result_repr))])

        print_formatted_text(
            formatted_output,
            style=self._current_style,
            style_transformation=self.style_transformation,
            include_default_pygments_style=False,
            output=self.app.output,
        )
        self.app.output.flush()
示例#9
0
    def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
        lines = list(split_lines(self._get_text_fragments(document.text)))

        def get_line(lineno: int) -> StyleAndTextTuples:
            try:
                return lines[lineno]
            except IndexError:
                return []

        return get_line
    def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
        lines = list(split_lines(self._get_text_fragments(document.text)))

        def get_line(lineno: int) -> StyleAndTextTuples:
            try:
                return lines[lineno]
            except IndexError:
                return []

        return get_line
示例#11
0
    def lex_document(self, document):
        lines = list(split_lines(self._get_text_fragments(document.text)))

        def get_line(lineno):
            try:
                return lines[lineno]
            except IndexError:
                return []

        return get_line
    def lex_document(self, document):
        lines = list(split_lines(self._get_text_fragments(document.text)))

        def get_line(lineno):
            try:
                return lines[lineno]
            except IndexError:
                return []

        return get_line
    def create_content(self, width: int, height: Optional[int]) -> UIContent:
        # Get fragments
        fragments_with_mouse_handlers = self._get_formatted_text_cached()
        fragment_lines_with_mouse_handlers = list(
            split_lines(fragments_with_mouse_handlers)
        )

        # Strip mouse handlers from fragments.
        fragment_lines: List[StyleAndTextTuples] = [
            [(item[0], item[1]) for item in line]
            for line in fragment_lines_with_mouse_handlers
        ]

        # Keep track of the fragments with mouse handler, for later use in
        # `mouse_handler`.
        self._fragments = fragments_with_mouse_handlers

        # If there is a `[SetCursorPosition]` in the fragment list, set the
        # cursor position here.
        def get_cursor_position(
            fragment: str = "[SetCursorPosition]",
        ) -> Optional[Point]:
            for y, line in enumerate(fragment_lines):
                x = 0
                for style_str, text, *_ in line:
                    if fragment in style_str:
                        return Point(x=x, y=y)
                    x += len(text)
            return None

        # If there is a `[SetMenuPosition]`, set the menu over here.
        def get_menu_position() -> Optional[Point]:
            return get_cursor_position("[SetMenuPosition]")

        cursor_position = (self.get_cursor_position or get_cursor_position)()

        # Create content, or take it from the cache.
        key = (tuple(fragments_with_mouse_handlers), width, cursor_position)

        def get_content() -> UIContent:
            return UIContent(
                get_line=lambda i: fragment_lines[i],
                line_count=len(fragment_lines),
                show_cursor=self.show_cursor,
                cursor_position=cursor_position,
                menu_position=get_menu_position(),
            )

        return self._content_cache.get(key, get_content)
示例#14
0
文件: repl.py 项目: Secozzi/ptpython
    def show_result(self, result: object) -> None:
        if hasattr(result, "__pt_repr__"):
            out_prompt = to_formatted_text(self.get_output_prompt())
            try:
                formatted_result_repr = to_formatted_text(
                    getattr(result, "__pt_repr__")())
                if isinstance(formatted_result_repr, list):
                    formatted_result_repr = FormattedText(
                        formatted_result_repr)
            except:
                pass
            line_sep = "\n" + " " * fragment_list_width(out_prompt)
            indented_repr: StyleAndTextTuples = []

            lines = list(split_lines(formatted_result_repr))

            for i, fragment in enumerate(lines):
                indented_repr.extend(fragment)

                # Add indentation separator between lines, not after the last line.
                if i != len(lines) - 1:
                    indented_repr.append(("", line_sep))

            # Write output tokens.
            if self.enable_syntax_highlighting:
                formatted_output = merge_formatted_text(
                    [out_prompt, indented_repr])
            else:
                formatted_output = FormattedText(out_prompt + [(
                    "", fragment_list_to_text(formatted_result_repr))])

            if self.enable_pager:
                self.print_paginated_formatted_text(
                    to_formatted_text(formatted_output))
            else:
                self.print_formatted_text(to_formatted_text(formatted_output))

            self.app.output.flush()

            if self.insert_blank_line_after_output:
                self.app.output.write("\n")
        else:
            if self._formatter:
                result = self._formatter(result)
            self.console.print(result)
        def create_line_generator(start_lineno: int, column: int = 0) -> LineGenerator:
            """
            Create a generator that yields the lexed lines.
            Each iteration it yields a (line_number, [(style_str, text), ...]) tuple.
            """
            def get_text_fragments() -> Iterable[Tuple[str, str]]:
                text = '\n'.join(document.lines[start_lineno:])[column:]

                # We call `get_text_fragments_unprocessed`, because `get_tokens` will
                # still replace \r\n and \r by \n.  (We don't want that,
                # Pygments should return exactly the same amount of text, as we
                # have given as input.)
                for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text):
                    # Turn Pygments `Token` object into prompt_toolkit style
                    # strings.
                    yield _token_cache[t], v

            yield from enumerate(split_lines(list(get_text_fragments())), start_lineno)
示例#16
0
        def create_line_generator(start_lineno, column=0):
            """
            Create a generator that yields the lexed lines.
            Each iteration it yields a (line_number, [(token, text), ...]) tuple.
            """
            def get_text_fragments():
                text = '\n'.join(document.lines[start_lineno:])[column:]

                # We call `get_text_fragments_unprocessed`, because `get_tokens` will
                # still replace \r\n and \r by \n.  (We don't want that,
                # Pygments should return exactly the same amount of text, as we
                # have given as input.)
                for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text):
                    # Turn Pygments `Token` object into prompt_toolkit `Token`
                    # objects.
                    yield _token_cache[t], v

            return enumerate(split_lines(get_text_fragments()), start_lineno)
    def create_content(self, width: int, height: Optional[int]) -> UIContent:
        # Get fragments
        fragments_with_mouse_handlers = self._get_formatted_text_cached()
        fragment_lines_with_mouse_handlers = list(split_lines(fragments_with_mouse_handlers))

        # Strip mouse handlers from fragments.
        fragment_lines: List[StyleAndTextTuples] = [
            [(item[0], item[1]) for item in line]
            for line in fragment_lines_with_mouse_handlers
        ]

        # Keep track of the fragments with mouse handler, for later use in
        # `mouse_handler`.
        self._fragments = fragments_with_mouse_handlers

        # If there is a `[SetCursorPosition]` in the fragment list, set the
        # cursor position here.
        def get_cursor_position(fragment: str = '[SetCursorPosition]') -> Optional[Point]:
            for y, line in enumerate(fragment_lines):
                x = 0
                for style_str, text, *_ in line:
                    if fragment in style_str:
                        return Point(x=x, y=y)
                    x += len(text)
            return None

        # If there is a `[SetMenuPosition]`, set the menu over here.
        def get_menu_position() -> Optional[Point]:
            return get_cursor_position('[SetMenuPosition]')

        cursor_position = (self.get_cursor_position or get_cursor_position)()

        # Create content, or take it from the cache.
        key = (tuple(fragments_with_mouse_handlers), width, cursor_position)

        def get_content() -> UIContent:
            return UIContent(get_line=lambda i: fragment_lines[i],
                             line_count=len(fragment_lines),
                             show_cursor=self.show_cursor,
                             cursor_position=cursor_position,
                             menu_position=get_menu_position())

        return self._content_cache.get(key, get_content)
示例#18
0
    def mouse_handler(self, mouse_event: MouseEvent) -> "NotImplementedOrNone":
        """
        Handle mouse events.

        (When the fragment list contained mouse handlers and the user clicked on
        on any of these, the matching handler is called. This handler can still
        return `NotImplemented` in case we want the
        :class:`~prompt_toolkit.layout.Window` to handle this particular
        event.)
        """
        if self._fragments:
            # Read the generator.
            fragments_for_line = list(split_lines(self._fragments))

            try:
                fragments = fragments_for_line[mouse_event.position.y]
            except IndexError:
                return NotImplemented
            else:
                # Find position in the fragment list.
                xpos = mouse_event.position.x

                # Find mouse handler for this character.
                count = 0
                for item in fragments:
                    count += len(item[1])
                    if count >= xpos:
                        if len(item) >= 3:
                            # Handler found. Call it.
                            # (Handler can return NotImplemented, so return
                            # that result.)
                            handler = item[2]  # type: ignore
                            return handler(mouse_event)
                        else:
                            break

        # Otherwise, don't handle here.
        return NotImplemented
    def mouse_handler(self, mouse_event: MouseEvent) -> 'NotImplementedOrNone':
        """
        Handle mouse events.

        (When the fragment list contained mouse handlers and the user clicked on
        on any of these, the matching handler is called. This handler can still
        return `NotImplemented` in case we want the
        :class:`~prompt_toolkit.layout.Window` to handle this particular
        event.)
        """
        if self._fragments:
            # Read the generator.
            fragments_for_line = list(split_lines(self._fragments))

            try:
                fragments = fragments_for_line[mouse_event.position.y]
            except IndexError:
                return NotImplemented
            else:
                # Find position in the fragment list.
                xpos = mouse_event.position.x

                # Find mouse handler for this character.
                count = 0
                for item in fragments:
                    count += len(item[1])
                    if count >= xpos:
                        if len(item) >= 3:
                            # Handler found. Call it.
                            # (Handler can return NotImplemented, so return
                            # that result.)
                            handler = item[2]  # type: ignore
                            return handler(mouse_event)
                        else:
                            break

        # Otherwise, don't handle here.
        return NotImplemented
示例#20
0
文件: repl.py 项目: roee30/ptpython
    def print_paginated_formatted_text(
        self,
        formatted_text: StyleAndTextTuples,
        end: str = "\n",
    ) -> None:
        """
        Print formatted text, using --MORE-- style pagination.
        (Avoid filling up the terminal's scrollback buffer.)
        """
        pager_prompt = self.create_pager_prompt()
        size = self.app.output.get_size()

        abort = False
        print_all = False

        # Max number of lines allowed in the buffer before painting.
        max_rows = size.rows - 1

        # Page buffer.
        rows_in_buffer = 0
        columns_in_buffer = 0
        page: StyleAndTextTuples = []

        def flush_page() -> None:
            nonlocal page, columns_in_buffer, rows_in_buffer
            self.print_formatted_text(page, end="")
            page = []
            columns_in_buffer = 0
            rows_in_buffer = 0

        def show_pager() -> None:
            nonlocal abort, max_rows, print_all

            # Run pager prompt in another thread.
            # Same as for the input. This prevents issues with nested event
            # loops.
            pager_result = None

            def in_thread() -> None:
                nonlocal pager_result
                pager_result = pager_prompt.prompt()

            th = threading.Thread(target=in_thread)
            th.start()
            th.join()

            if pager_result == PagerResult.ABORT:
                print("...")
                abort = True

            elif pager_result == PagerResult.NEXT_LINE:
                max_rows = 1

            elif pager_result == PagerResult.NEXT_PAGE:
                max_rows = size.rows - 1

            elif pager_result == PagerResult.PRINT_ALL:
                print_all = True

        # Loop over lines. Show --MORE-- prompt when page is filled.

        formatted_text = formatted_text + [("", end)]
        lines = list(split_lines(formatted_text))

        for lineno, line in enumerate(lines):
            for style, text, *_ in line:
                for c in text:
                    width = get_cwidth(c)

                    # (Soft) wrap line if it doesn't fit.
                    if columns_in_buffer + width > size.columns:
                        # Show pager first if we get too many lines after
                        # wrapping.
                        if rows_in_buffer + 1 >= max_rows and not print_all:
                            page.append(("", "\n"))
                            flush_page()
                            show_pager()
                            if abort:
                                return

                        rows_in_buffer += 1
                        columns_in_buffer = 0

                    columns_in_buffer += width
                    page.append((style, c))

            if rows_in_buffer + 1 >= max_rows and not print_all:
                page.append(("", "\n"))
                flush_page()
                show_pager()
                if abort:
                    return
            else:
                # Add line ending between lines (if `end="\n"` was given, one
                # more empty line is added in `split_lines` automatically to
                # take care of the final line ending).
                if lineno != len(lines) - 1:
                    page.append(("", "\n"))
                    rows_in_buffer += 1
                    columns_in_buffer = 0

        flush_page()
示例#21
0
文件: repl.py 项目: roee30/ptpython
    def show_result(self, result: object) -> None:
        """
        Show __repr__ for an `eval` result.

        Note: this can raise `KeyboardInterrupt` if either calling `__repr__`,
              `__pt_repr__` or formatting the output with "Black" takes to long
              and the user presses Control-C.
        """
        out_prompt = to_formatted_text(self.get_output_prompt())

        # If the repr is valid Python code, use the Pygments lexer.
        try:
            result_repr = repr(result)
        except KeyboardInterrupt:
            raise  # Don't catch here.
        except BaseException as e:
            # Calling repr failed.
            self._handle_exception(e)
            return

        try:
            compile(result_repr, "", "eval")
        except SyntaxError:
            formatted_result_repr = to_formatted_text(result_repr)
        else:
            # Syntactically correct. Format with black and syntax highlight.
            if self.enable_output_formatting:
                # Inline import. Slightly speed up start-up time if black is
                # not used.
                import black

                result_repr = black.format_str(
                    result_repr,
                    mode=black.FileMode(
                        line_length=self.app.output.get_size().columns),
                )

            formatted_result_repr = to_formatted_text(
                PygmentsTokens(list(_lex_python_result(result_repr))))

        # If __pt_repr__ is present, take this. This can return prompt_toolkit
        # formatted text.
        try:
            if hasattr(result, "__pt_repr__"):
                formatted_result_repr = to_formatted_text(
                    getattr(result, "__pt_repr__")())
                if isinstance(formatted_result_repr, list):
                    formatted_result_repr = FormattedText(
                        formatted_result_repr)
        except KeyboardInterrupt:
            raise  # Don't catch here.
        except:
            # For bad code, `__getattr__` can raise something that's not an
            # `AttributeError`. This happens already when calling `hasattr()`.
            pass

        # Align every line to the prompt.
        line_sep = "\n" + " " * fragment_list_width(out_prompt)
        indented_repr: StyleAndTextTuples = []

        lines = list(split_lines(formatted_result_repr))

        for i, fragment in enumerate(lines):
            indented_repr.extend(fragment)

            # Add indentation separator between lines, not after the last line.
            if i != len(lines) - 1:
                indented_repr.append(("", line_sep))

        # Write output tokens.
        if self.enable_syntax_highlighting:
            formatted_output = merge_formatted_text(
                [out_prompt, indented_repr])
        else:
            formatted_output = FormattedText(out_prompt + [(
                "", fragment_list_to_text(formatted_result_repr))])

        if self.enable_pager:
            self.print_paginated_formatted_text(
                to_formatted_text(formatted_output))
        else:
            self.print_formatted_text(to_formatted_text(formatted_output))

        self.app.output.flush()

        if self.insert_blank_line_after_output:
            self.app.output.write("\n")