コード例 #1
0
 def preferred_width(self, max_available_width: int) -> int:
     """
     Return the preferred width for this control.
     That is the width of the longest line.
     """
     text = fragment_list_to_text(self._get_formatted_text_cached())
     line_lengths = [get_cwidth(l) for l in text.split('\n')]
     return max(line_lengths)
コード例 #2
0
    def apply_transformation(
            self, transformation_input: TransformationInput) -> Transformation:

        (
            buffer_control,
            document,
            lineno,
            source_to_display,
            fragments,
            _,
            _,
        ) = transformation_input.unpack()

        search_text = self._get_search_text(buffer_control)
        searchmatch_fragment = " class:%s " % (self._classname, )
        searchmatch_current_fragment = " class:%s " % (
            self._classname_current, )

        if search_text and not get_app().is_done:
            # For each search match, replace the style string.
            line_text = fragment_list_to_text(fragments)
            fragments = explode_text_fragments(fragments)

            if buffer_control.search_state.ignore_case():
                flags = re.IGNORECASE
            else:
                flags = re.RegexFlag(0)

            # Get cursor column.
            cursor_column: Optional[int]
            if document.cursor_position_row == lineno:
                cursor_column = source_to_display(document.cursor_position_col)
            else:
                cursor_column = None

            for match in re.finditer(re.escape(search_text),
                                     line_text,
                                     flags=flags):
                if cursor_column is not None:
                    on_cursor = match.start() <= cursor_column < match.end()
                else:
                    on_cursor = False

                for i in range(match.start(), match.end()):
                    old_fragment, text, *_ = fragments[i]
                    if on_cursor:
                        fragments[i] = (
                            old_fragment + searchmatch_current_fragment,
                            fragments[i][1],
                        )
                    else:
                        fragments[i] = (
                            old_fragment + searchmatch_fragment,
                            fragments[i][1],
                        )

        return Transformation(fragments)
コード例 #3
0
        def _find(event: E) -> None:
            # We first check values after the selected value, then all values.
            values = list(self.values)
            for value in values[self._selected_index + 1 :] + values:
                text = fragment_list_to_text(to_formatted_text(value[1])).lower()

                if text.startswith(event.data.lower()):
                    self._selected_index = self.values.index(value)
                    return
コード例 #4
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()
コード例 #5
0
    def apply_transformation(self, transformation_input):
        lineno = transformation_input.lineno
        fragments = transformation_input.fragments

        if (lineno < self._lines_before or
                lineno >= self._lines_before + len(self.history_mapping.selected_lines)):
            text = fragment_list_to_text(fragments)
            return Transformation(fragments=[('class:history.existing-input', text)])
        else:
            return Transformation(fragments=fragments)
コード例 #6
0
ファイル: history_browser.py プロジェクト: qwIvan/ptpython
    def apply_transformation(self, transformation_input):
        lineno = transformation_input.lineno
        fragments = transformation_input.fragments

        if (lineno < self._lines_before or
                lineno >= self._lines_before + len(self.history_mapping.selected_lines)):
            text = fragment_list_to_text(fragments)
            return Transformation(fragments=[('class:history.existing-input', text)])
        else:
            return Transformation(fragments=fragments)
コード例 #7
0
 def get_width() -> AnyDimension:
     if width is None:
         text_fragments = to_formatted_text(self.text)
         text = fragment_list_to_text(text_fragments)
         if text:
             longest_line = max(get_cwidth(line) for line in text.splitlines())
         else:
             return D(preferred=0)
         return D(preferred=longest_line)
     else:
         return width
コード例 #8
0
 def get_width():
     if width is None:
         text_fragments = to_formatted_text(self.text)
         text = fragment_list_to_text(text_fragments)
         if text:
             longest_line = max(get_cwidth(line) for line in text.splitlines())
         else:
             return D(preferred=0)
         return D(preferred=longest_line)
     else:
         return width
コード例 #9
0
 def apply_transformation(self, ti):
     try:
         fragments = to_formatted_text(
             HTML(fragment_list_to_text(ti.fragments)))
     except Exception as ex:
         # xml.parsers.expat.ExpatError
         # not well-formed (invalid token): line 1, column 138
         logger.error('FormatText: {} {}'.format(type(ex), str(ex)))
         #return Transformation([('', ' ')])
         return Transformation([])
     return Transformation(fragments)
コード例 #10
0
    def apply_transformation(self, ti: TransformationInput) -> Transformation:
        from .controls import SearchBufferControl

        assert isinstance(
            ti.buffer_control, SearchBufferControl
        ), "`ReverseSearchProcessor` should be applied to a `SearchBufferControl` only."

        source_to_display: Optional[SourceToDisplay]
        display_to_source: Optional[DisplayToSource]

        main_control = self._get_main_buffer(ti.buffer_control)

        if ti.lineno == 0 and main_control:
            content = self._content(main_control, ti)

            # Get the line from the original document for this search.
            line_fragments = content.get_line(content.cursor_position.y)

            if main_control.search_state.direction == SearchDirection.FORWARD:
                direction_text = "i-search"
            else:
                direction_text = "reverse-i-search"

            fragments_before: StyleAndTextTuples = [
                ("class:prompt.search", "("),
                ("class:prompt.search", direction_text),
                ("class:prompt.search", ")`"),
            ]

            fragments = (
                fragments_before
                + [
                    ("class:prompt.search.text", fragment_list_to_text(ti.fragments)),
                    ("", "': "),
                ]
                + line_fragments
            )

            shift_position = fragment_list_len(fragments_before)
            source_to_display = lambda i: i + shift_position
            display_to_source = lambda i: i - shift_position
        else:
            source_to_display = None
            display_to_source = None
            fragments = ti.fragments

        return Transformation(
            fragments,
            source_to_display=source_to_display,
            display_to_source=display_to_source,
        )
コード例 #11
0
    def get_height_for_line(self, lineno, width):
        """
        Return the height that a given line would need if it is rendered in a
        space with the given width.
        """
        try:
            return self._line_heights[lineno, width]
        except KeyError:
            text = fragment_list_to_text(self.get_line(lineno))
            result = self.get_height_for_text(text, width)

            # Cache and return
            self._line_heights[lineno, width] = result
            return result
コード例 #12
0
    def apply_transformation(self, ti):
        fragments = ti.fragments

        # Walk through all te fragments.
        if fragments and fragment_list_to_text(fragments).startswith(' '):
            t = (self.style, self.get_char())
            fragments = explode_text_fragments(fragments)

            for i in range(len(fragments)):
                if fragments[i][1] == ' ':
                    fragments[i] = t
                else:
                    break

        return Transformation(fragments)
コード例 #13
0
    def apply_transformation(self, ti: TransformationInput) -> Transformation:
        fragments = ti.fragments

        # Walk through all te fragments.
        if fragments and fragment_list_to_text(fragments).startswith(' '):
            t = (self.style, self.get_char())
            fragments = explode_text_fragments(fragments)

            for i in range(len(fragments)):
                if fragments[i][1] == ' ':
                    fragments[i] = t
                else:
                    break

        return Transformation(fragments)
コード例 #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)
コード例 #15
0
    def apply_transformation(self, ti: TransformationInput) -> Transformation:
        from .controls import SearchBufferControl
        assert isinstance(ti.buffer_control, SearchBufferControl), \
            '`ReverseSearchProcessor` should be applied to a `SearchBufferControl` only.'

        source_to_display: Optional[SourceToDisplay]
        display_to_source: Optional[DisplayToSource]

        main_control = self._get_main_buffer(ti.buffer_control)

        if ti.lineno == 0 and main_control:
            content = self._content(main_control, ti)

            # Get the line from the original document for this search.
            line_fragments = content.get_line(content.cursor_position.y)

            if main_control.search_state.direction == SearchDirection.FORWARD:
                direction_text = 'i-search'
            else:
                direction_text = 'reverse-i-search'

            fragments_before: StyleAndTextTuples = [
                ('class:prompt.search', '('),
                ('class:prompt.search', direction_text),
                ('class:prompt.search', ')`'),
            ]

            fragments = fragments_before + [
                ('class:prompt.search.text', fragment_list_to_text(ti.fragments)),
                ('', "': "),
            ] + line_fragments

            shift_position = fragment_list_len(fragments_before)
            source_to_display = lambda i: i + shift_position
            display_to_source = lambda i: i - shift_position
        else:
            source_to_display = None
            display_to_source = None
            fragments = ti.fragments

        return Transformation(fragments, source_to_display=source_to_display,
                              display_to_source=display_to_source)
コード例 #16
0
    def apply_transformation(
            self, transformation_input: TransformationInput) -> Transformation:

        buffer_control, document, lineno, source_to_display, fragments, _, _ = transformation_input.unpack()

        search_text = self._get_search_text(buffer_control)
        searchmatch_fragment = ' class:%s ' % (self._classname, )
        searchmatch_current_fragment = ' class:%s ' % (self._classname_current, )

        if search_text and not get_app().is_done:
            # For each search match, replace the style string.
            line_text = fragment_list_to_text(fragments)
            fragments = explode_text_fragments(fragments)

            if buffer_control.search_state.ignore_case():
                flags = re.IGNORECASE
            else:
                flags = re.RegexFlag(0)

            # Get cursor column.
            cursor_column: Optional[int]
            if document.cursor_position_row == lineno:
                cursor_column = source_to_display(document.cursor_position_col)
            else:
                cursor_column = None

            for match in re.finditer(re.escape(search_text), line_text, flags=flags):
                if cursor_column is not None:
                    on_cursor = match.start() <= cursor_column < match.end()
                else:
                    on_cursor = False

                for i in range(match.start(), match.end()):
                    old_fragment, text, *_ = fragments[i]
                    if on_cursor:
                        fragments[i] = (old_fragment + searchmatch_current_fragment, fragments[i][1])
                    else:
                        fragments[i] = (old_fragment + searchmatch_fragment, fragments[i][1])

        return Transformation(fragments)
コード例 #17
0
    def apply_transformation(self, ti):
        main_control = self._get_main_buffer(ti.buffer_control)

        if ti.lineno == 0 and main_control:
            content = self._content(main_control, ti)

            # Get the line from the original document for this search.
            line_fragments = content.get_line(content.cursor_position.y)

            if main_control.search_state.direction == SearchDirection.FORWARD:
                direction_text = 'i-search'
            else:
                direction_text = 'reverse-i-search'

            fragments_before = [
                ('class:prompt.search', '('),
                ('class:prompt.search', direction_text),
                ('class:prompt.search', ')`'),
            ]

            fragments = fragments_before + [
                ('class:prompt.search.text', fragment_list_to_text(
                    ti.fragments)),
                ('', "': "),
            ] + line_fragments

            shift_position = fragment_list_len(fragments_before)
            source_to_display = lambda i: i + shift_position
            display_to_source = lambda i: i - shift_position
        else:
            source_to_display = None
            display_to_source = None
            fragments = ti.fragments

        return Transformation(fragments,
                              source_to_display=source_to_display,
                              display_to_source=display_to_source)
コード例 #18
0
 def get_width(self, ui_content):
     " Width to report to the `Window`. "
     # Take the width from the first line.
     text = fragment_list_to_text(self.get_prompt_fragments())
     return get_cwidth(text)
コード例 #19
0
    def get_height_for_line(
            self, lineno: int, width: int,
            get_line_prefix: Optional[GetLinePrefixCallable],
            slice_stop: Optional[int] = None) -> int:
        """
        Return the height that a given line would need if it is rendered in a
        space with the given width (using line wrapping).

        :param get_line_prefix: None or a `Window.get_line_prefix` callable
            that returns the prefix to be inserted before this line.
        :param slice_stop: Wrap only "line[:slice_stop]" and return that
            partial result. This is needed for scrolling the window correctly
            when line wrapping.
        :returns: The computed height.
        """
        # Instead of using `get_line_prefix` as key, we use render_counter
        # instead. This is more reliable, because this function could still be
        # the same, while the content would change over time.
        key = get_app().render_counter, lineno, width, slice_stop

        try:
            return self._line_heights_cache[key]
        except KeyError:
            if width == 0:
                height = 10 ** 8
            else:
                # Calculate line width first.
                line = fragment_list_to_text(self.get_line(lineno))[:slice_stop]
                text_width = get_cwidth(line)

                if get_line_prefix:
                    # Add prefix width.
                    text_width += fragment_list_width(
                        to_formatted_text(get_line_prefix(lineno, 0)))

                    # Slower path: compute path when there's a line prefix.
                    height = 1

                    # Keep wrapping as long as the line doesn't fit.
                    # Keep adding new prefixes for every wrapped line.
                    while text_width > width:
                        height += 1
                        text_width -= width

                        fragments2 = to_formatted_text(
                            get_line_prefix(lineno, height - 1))
                        prefix_width = get_cwidth(fragment_list_to_text(fragments2))

                        if prefix_width >= width:  # Prefix doesn't fit.
                            height = 10 ** 8
                            break

                        text_width += prefix_width
                else:
                    # Fast path: compute height when there's no line prefix.
                    try:
                        quotient, remainder = divmod(text_width, width)
                    except ZeroDivisionError:
                        height = 10 ** 8
                    else:
                        if remainder:
                            quotient += 1  # Like math.ceil.
                        height = max(1, quotient)

            # Cache and return
            self._line_heights_cache[key] = height
            return height
コード例 #20
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")
コード例 #21
0
ファイル: controls.py プロジェクト: a-domingu/tbcnn
    def get_height_for_line(
        self,
        lineno: int,
        width: int,
        get_line_prefix: Optional[GetLinePrefixCallable],
        slice_stop: Optional[int] = None,
    ) -> int:
        """
        Return the height that a given line would need if it is rendered in a
        space with the given width (using line wrapping).

        :param get_line_prefix: None or a `Window.get_line_prefix` callable
            that returns the prefix to be inserted before this line.
        :param slice_stop: Wrap only "line[:slice_stop]" and return that
            partial result. This is needed for scrolling the window correctly
            when line wrapping.
        :returns: The computed height.
        """
        # Instead of using `get_line_prefix` as key, we use render_counter
        # instead. This is more reliable, because this function could still be
        # the same, while the content would change over time.
        key = get_app().render_counter, lineno, width, slice_stop

        try:
            return self._line_heights_cache[key]
        except KeyError:
            if width == 0:
                height = 10**8
            else:
                # Calculate line width first.
                line = fragment_list_to_text(
                    self.get_line(lineno))[:slice_stop]
                text_width = get_cwidth(line)

                if get_line_prefix:
                    # Add prefix width.
                    text_width += fragment_list_width(
                        to_formatted_text(get_line_prefix(lineno, 0)))

                    # Slower path: compute path when there's a line prefix.
                    height = 1

                    # Keep wrapping as long as the line doesn't fit.
                    # Keep adding new prefixes for every wrapped line.
                    while text_width > width:
                        height += 1
                        text_width -= width

                        fragments2 = to_formatted_text(
                            get_line_prefix(lineno, height - 1))
                        prefix_width = get_cwidth(
                            fragment_list_to_text(fragments2))

                        if prefix_width >= width:  # Prefix doesn't fit.
                            height = 10**8
                            break

                        text_width += prefix_width
                else:
                    # Fast path: compute height when there's no line prefix.
                    try:
                        quotient, remainder = divmod(text_width, width)
                    except ZeroDivisionError:
                        height = 10**8
                    else:
                        if remainder:
                            quotient += 1  # Like math.ceil.
                        height = max(1, quotient)

            # Cache and return
            self._line_heights_cache[key] = height
            return height
コード例 #22
0
ファイル: utils.py プロジェクト: swipswaps/ptpython
 def __repr__(self) -> str:
     return fragment_list_to_text(to_formatted_text(cls.__pt_repr__(self)))