Exemplo n.º 1
0
def _trim_text(text, max_width):
    """
    Trim the text to `max_width`, append dots when the text is too long.
    Returns (text, width) tuple.
    """
    width = get_cwidth(text)

    # When the text is too wide, trim it.
    if width > max_width:
        # When there are no double width characters, just use slice operation.
        if len(text) == width:
            trimmed_text = (text[:max(1, max_width - 3)] + '...')[:max_width]
            return trimmed_text, len(trimmed_text)

        # Otherwise, loop until we have the desired width. (Rather
        # inefficient, but ok for now.)
        else:
            trimmed_text = ''
            for c in text:
                if get_cwidth(trimmed_text + c) <= max_width - 3:
                    trimmed_text += c
            trimmed_text += '...'

            return (trimmed_text, get_cwidth(trimmed_text))
    else:
        return text, width
Exemplo n.º 2
0
 def _get_menu_width(self, max_width, complete_state):
     """
     Return the width of the main column.
     """
     return min(
         max_width,
         max(
             self.MIN_WIDTH,
             max(get_cwidth(c.display)
                 for c in complete_state.completions) + 2))
Exemplo n.º 3
0
 def _get_menu_meta_width(self, max_width, complete_state):
     """
     Return the width of the meta column.
     """
     if self._show_meta(complete_state):
         return min(
             max_width,
             max(
                 get_cwidth(c.display_meta)
                 for c in complete_state.completions) + 2)
     else:
         return 0
Exemplo n.º 4
0
    def __init__(self, char=' ', style=''):
        # If this character has to be displayed otherwise, take that one.
        if char in self.display_mappings:
            char = self.display_mappings[char]
            style += 'class:control-character'

        self.char = char
        self.style = style

        # Calculate width. (We always need this, so better to store it directly
        # as a member for performance.)
        self.width = get_cwidth(char)
Exemplo n.º 5
0
def fragment_list_width(fragments):
    """
    Return the character width of this text fragment list.
    (Take double width characters into account.)

    :param fragments: List of ``(style_str, text)`` or
        ``(style_str, text, mouse_handler)`` tuples.
    """
    ZeroWidthEscape = '[ZeroWidthEscape]'
    return sum(
        get_cwidth(c) for item in fragments for c in item[1]
        if ZeroWidthEscape not in item[0])
Exemplo n.º 6
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
Exemplo n.º 7
0
    def preferred_width(self, max_available_width):
        """
        Report the width of the longest meta text as the preferred width of this control.

        It could be that we use less width, but this way, we're sure that the
        layout doesn't change when we select another completion (E.g. that
        completions are suddenly shown in more or fewer columns.)
        """
        app = get_app()
        if app.current_buffer.complete_state:
            state = app.current_buffer.complete_state
            return 2 + max(
                get_cwidth(c.display_meta) for c in state.completions)
        else:
            return 0
Exemplo n.º 8
0
 def _get_column_width(self, complete_state):
     """
     Return the width of each column.
     """
     return max(get_cwidth(c.display)
                for c in complete_state.completions) + 1
Exemplo n.º 9
0
    def write(self, data):
        if self._hidden:
            data = ' ' * get_cwidth(data)

        self._buffer.append(data)
Exemplo n.º 10
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())
     return get_cwidth(text)
Exemplo n.º 11
0
 def width(self):
     if self.children:
         return max(get_cwidth(c.text) for c in self.children)
     else:
         return 0
Exemplo n.º 12
0
def _display_completions_like_readline(app, completions):
    """
    Display the list of completions in columns above the prompt.
    This will ask for a confirmation if there are too many completions to fit
    on a single page and provide a paginator to walk through them.
    """
    from polymorph.deps.prompt_toolkit.shortcuts.prompt import create_confirm_session
    assert isinstance(completions, list)

    # Get terminal dimensions.
    term_size = app.output.get_size()
    term_width = term_size.columns
    term_height = term_size.rows

    # Calculate amount of required columns/rows for displaying the
    # completions. (Keep in mind that completions are displayed
    # alphabetically column-wise.)
    max_compl_width = min(term_width,
                          max(get_cwidth(c.text) for c in completions) + 1)
    column_count = max(1, term_width // max_compl_width)
    completions_per_page = column_count * (term_height - 1)
    page_count = int(math.ceil(len(completions) / float(completions_per_page)))

    # Note: math.ceil can return float on Python2.

    def display(page):
        # Display completions.
        page_completions = completions[page * completions_per_page:(page + 1) *
                                       completions_per_page]

        page_row_count = int(
            math.ceil(len(page_completions) / float(column_count)))
        page_columns = [
            page_completions[i * page_row_count:(i + 1) * page_row_count]
            for i in range(column_count)
        ]

        result = []
        for r in range(page_row_count):
            for c in range(column_count):
                try:
                    result.append(
                        page_columns[c][r].text.ljust(max_compl_width))
                except IndexError:
                    pass
            result.append('\n')

        app.output.write(''.join(result))
        app.output.flush()

    # User interaction through an application generator function.
    def run_compl():
        " Coroutine. "
        if len(completions) > completions_per_page:
            # Ask confirmation if it doesn't fit on the screen.
            confirm = yield create_confirm_session(
                'Display all {} possibilities? (y on n) '.format(
                    len(completions)), ).prompt(async_=True)

            if confirm:
                # Display pages.
                for page in range(page_count):
                    display(page)

                    if page != page_count - 1:
                        # Display --MORE-- and go to the next page.
                        show_more = yield _create_more_session(
                            '--MORE--').prompt(async_=True)

                        if not show_more:
                            return
            else:
                app.output.flush()
        else:
            # Display all completions.
            display(0)

    run_coroutine_in_terminal(run_compl, render_cli_done=True)