Ejemplo n.º 1
0
    def apply_transformation(self, transformation_input):
        buffer_control, document, lineno, source_to_display, fragments, _, _ = transformation_input.unpack()

        # When the application is in the 'done' state, don't highlight.
        if get_app().is_done:
            return Transformation(fragments)

        # Get the highlight positions.
        key = (get_app().render_counter, document.text, document.cursor_position)
        positions = self._positions_cache.get(
            key, lambda: self._get_positions_to_highlight(document))

        # Apply if positions were found at this line.
        if positions:
            for row, col in positions:
                if row == lineno:
                    col = source_to_display(col)
                    fragments = explode_text_fragments(fragments)
                    style, text = fragments[col]

                    if col == document.cursor_position_col:
                        style += ' class:matching-bracket.cursor '
                    else:
                        style += ' class:matching-bracket.other '

                    fragments[col] = (style, text)

        return Transformation(fragments)
Ejemplo n.º 2
0
    def _get_menu_fragments(self):
        focused = get_app().layout.has_focus(self.window)

        # This is called during the rendering. When we discover that this
        # widget doesn't have the focus anymore. Reset menu state.
        if not focused:
            self.selected_menu = [0]

        # Generate text fragments for the main menu.
        def one_item(i, item):
            def mouse_handler(mouse_event):
                if mouse_event.event_type == MouseEventType.MOUSE_UP:
                    # Toggle focus.
                    app = get_app()
                    if app.layout.has_focus(self.window):
                        if self.selected_menu == [i]:
                            app.layout.focus_last()
                    else:
                        app.layout.focus(self.window)
                    self.selected_menu = [i]

            yield ('class:menu-bar', ' ', mouse_handler)
            if i == self.selected_menu[0] and focused:
                yield ('[SetMenuPosition]', '', mouse_handler)
                style = 'class:menu-bar.selected-item'
            else:
                style = 'class:menu-bar'
            yield style, item.text, mouse_handler

        result = []
        for i, item in enumerate(self.menu_items):
            result.extend(one_item(i, item))

        return result
Ejemplo n.º 3
0
 def _get_main_buffer(self, buffer_control):
     from polymorph.deps.prompt_toolkit.layout.controls import BufferControl
     prev_control = get_app().layout.search_target_buffer_control
     if isinstance(prev_control, BufferControl) and \
             prev_control.search_buffer_control == buffer_control:
         return prev_control
     return None
Ejemplo n.º 4
0
def control_is_searchable():
    " When the current UIControl is searchable. "
    from polymorph.deps.prompt_toolkit.layout.controls import BufferControl
    control = get_app().layout.current_control

    return (isinstance(control, BufferControl)
            and control.search_buffer_control is not None)
Ejemplo n.º 5
0
def emacs_insert_mode():
    app = get_app()
    if (app.editing_mode != EditingMode.EMACS
            or app.current_buffer.selection_state
            or app.current_buffer.read_only()):
        return False
    return True
Ejemplo n.º 6
0
def vi_recording_macro():
    " When recording a Vi macro. "
    app = get_app()
    if app.editing_mode != EditingMode.VI:
        return False

    return app.vi_state.recording_register is not None
Ejemplo n.º 7
0
    def _start_timeout(self):
        """
        Start auto flush timeout. Similar to Vim's `timeoutlen` option.

        Start a background thread with a timer. When this timeout expires and
        no key was pressed in the meantime, we flush all data in the queue and
        call the appropriate key binding handlers.
        """
        timeout = get_app().timeoutlen

        if timeout is None:
            return

        counter = self._keys_pressed

        def wait():
            " Wait for timeout. "
            time.sleep(timeout)

            if len(self.key_buffer) > 0 and counter == self._keys_pressed:
                # (No keys pressed in the meantime.)
                call_from_executor(flush_keys)

        def flush_keys():
            " Flush keys. "
            self.feed(_Flush)
            self.process_keys()

        # Automatically flush keys.
        # (_daemon needs to be set, otherwise, this will hang the
        # application for .5 seconds before exiting.)
        run_in_executor(wait, _daemon=True)
Ejemplo n.º 8
0
    def create_content(self, width, height):
        """
        Create a UIContent object for this control.
        """
        complete_state = get_app().current_buffer.complete_state
        if complete_state:
            completions = complete_state.completions
            index = complete_state.complete_index  # Can be None!

            # Calculate width of completions menu.
            menu_width = self._get_menu_width(width, complete_state)
            menu_meta_width = self._get_menu_meta_width(
                width - menu_width, complete_state)
            show_meta = self._show_meta(complete_state)

            def get_line(i):
                c = completions[i]
                is_current_completion = (i == index)
                result = self._get_menu_item_fragments(c,
                                                       is_current_completion,
                                                       menu_width)

                if show_meta:
                    result += self._get_menu_item_meta_fragments(
                        c, is_current_completion, menu_meta_width)
                return result

            return UIContent(get_line=get_line,
                             cursor_position=Point(x=0, y=index or 0),
                             line_count=len(completions))

        return UIContent()
Ejemplo n.º 9
0
def completion_is_selected():
    """
    True when the user selected a completion.
    """
    complete_state = get_app().current_buffer.complete_state
    return (complete_state is not None
            and complete_state.current_completion is not None)
Ejemplo n.º 10
0
    def _get_text_fragments(self):
        style = 'class:completion-menu.multi-column-meta'
        state = get_app().current_buffer.complete_state

        if state and state.current_completion and state.current_completion.display_meta:
            return [(style, ' %s ' % state.current_completion.display_meta)]

        return []
Ejemplo n.º 11
0
    def preferred_width(self, max_available_width):
        complete_state = get_app().current_buffer.complete_state
        if complete_state:
            menu_width = self._get_menu_width(500, complete_state)
            menu_meta_width = self._get_menu_meta_width(500, complete_state)

            return menu_width + menu_meta_width
        else:
            return 0
Ejemplo n.º 12
0
            def test():
                # Consider focused when any window inside this container is
                # focused.
                current_window = get_app().layout.current_window

                for c in walk(value):
                    if isinstance(c, Window) and c == current_window:
                        return True
                return False
Ejemplo n.º 13
0
    def create_content(self, width, height):
        complete_state = get_app().current_buffer.complete_state
        if complete_state:
            completions = complete_state.completions
            index = complete_state.complete_index  # Can be None!

            # Width of the completions without the left/right arrows in the margins.
            content_width = width - 6

            # Booleans indicating whether we stripped from the left/right
            cut_left = False
            cut_right = False

            # Create Menu content.
            fragments = []

            for i, c in enumerate(completions):
                # When there is no more place for the next completion
                if fragment_list_len(fragments) + len(
                        c.display) >= content_width:
                    # If the current one was not yet displayed, page to the next sequence.
                    if i <= (index or 0):
                        fragments = []
                        cut_left = True
                    # If the current one is visible, stop here.
                    else:
                        cut_right = True
                        break

                fragments.append(
                    ('class:completion-toolbar.completion.current'
                     if i == index else 'class:completion-toolbar.completion',
                     c.display))
                fragments.append(('', ' '))

            # Extend/strip until the content width.
            fragments.append(
                ('', ' ' * (content_width - fragment_list_len(fragments))))
            fragments = fragments[:content_width]

            # Return fragments
            all_fragments = [
                ('', ' '),
                ('class:completion-toolbar.arrow', '<' if cut_left else ' '),
                ('', ' '),
            ] + fragments + [
                ('', ' '),
                ('class:completion-toolbar.arrow', '>' if cut_right else ' '),
                ('', ' '),
            ]
        else:
            all_fragments = []

        def get_line(i):
            return all_fragments

        return UIContent(get_line=get_line, line_count=1)
Ejemplo n.º 14
0
        def get_formatted_text():
            arg = get_app().key_processor.arg or ''
            if arg == '-':
                arg = '-1'

            return [
                ('class:arg-toolbar', 'Repeat: '),
                ('class:arg-toolbar.text', arg),
            ]
Ejemplo n.º 15
0
    def preferred_height(self, width, max_available_height, wrap_lines):
        """
        Preferred height: as much as needed in order to display all the completions.
        """
        complete_state = get_app().current_buffer.complete_state
        column_width = self._get_column_width(complete_state)
        column_count = max(1, (width - self._required_margin) // column_width)

        return int(
            math.ceil(len(complete_state.completions) / float(column_count)))
Ejemplo n.º 16
0
 def mouse_handler(mouse_event):
     if mouse_event.event_type == MouseEventType.MOUSE_UP:
         # Toggle focus.
         app = get_app()
         if app.layout.has_focus(self.window):
             if self.selected_menu == [i]:
                 app.layout.focus_last()
         else:
             app.layout.focus(self.window)
         self.selected_menu = [i]
Ejemplo n.º 17
0
def vi_replace_mode():
    from polymorph.deps.prompt_toolkit.key_binding.vi_state import InputMode
    app = get_app()

    if (app.editing_mode != EditingMode.VI or app.vi_state.operator_func
            or app.vi_state.waiting_for_digraph
            or app.current_buffer.selection_state
            or app.current_buffer.read_only()):
        return False

    return app.vi_state.input_mode == InputMode.REPLACE
Ejemplo n.º 18
0
def renderer_height_is_known():
    """
    Only True when the renderer knows it's real height.

    (On VT100 terminals, we have to wait for a CPR response, before we can be
    sure of the available height between the cursor position and the bottom of
    the terminal. And usually it's nicer to wait with drawing bottom toolbars
    until we receive the height, in order to avoid flickering -- first drawing
    somewhere in the middle, and then again at the bottom.)
    """
    return get_app().renderer.height_is_known
Ejemplo n.º 19
0
    def _get_text_fragments(self):
        app = get_app()
        if app.key_processor.arg is None:
            return []
        else:
            arg = app.key_processor.arg

            return [
                ('class:prompt.arg', '(arg: '),
                ('class:prompt.arg.text', str(arg)),
                ('class:prompt.arg', ') '),
            ]
Ejemplo n.º 20
0
 def mouse_handler(mouse_event):
     if mouse_event.event_type == MouseEventType.MOUSE_UP:
         app = get_app()
         if item.handler:
             app.layout.focus_last()
             item.handler()
         else:
             self.selected_menu = self.selected_menu[:level
                                                     +
                                                     1] + [
                                                         i
                                                     ]
Ejemplo n.º 21
0
def vi_navigation_mode():
    " Active when the set for Vi navigation key bindings are active. "
    from polymorph.deps.prompt_toolkit.key_binding.vi_state import InputMode
    app = get_app()

    if (app.editing_mode != EditingMode.VI or app.vi_state.operator_func
            or app.vi_state.waiting_for_digraph
            or app.current_buffer.selection_state):
        return False

    return (app.vi_state.input_mode == InputMode.NAVIGATION
            or app.current_buffer.read_only())
Ejemplo n.º 22
0
        def filter():
            " Only handle key bindings if this menu is visible. "
            app = get_app()
            complete_state = app.current_buffer.complete_state

            # There need to be completions, and one needs to be selected.
            if complete_state is None or complete_state.complete_index is None:
                return False

            # This menu needs to be visible.
            return any(window.content == self
                       for window in app.layout.visible_windows)
Ejemplo n.º 23
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
Ejemplo n.º 24
0
        def move(right=False):
            buff = get_app().current_buffer
            complete_state = buff.complete_state

            if complete_state is not None and \
                    buff.complete_state.complete_index is not None:
                # Calculate new complete index.
                new_index = buff.complete_state.complete_index
                if right:
                    new_index += self._rendered_rows
                else:
                    new_index -= self._rendered_rows

                if 0 <= new_index < len(complete_state.completions):
                    buff.go_to_completion(new_index)
Ejemplo n.º 25
0
    def __init__(self,
                 key_processor_ref,
                 arg=None,
                 key_sequence=None,
                 previous_key_sequence=None,
                 is_repeat=False):
        self._key_processor_ref = key_processor_ref
        self.key_sequence = key_sequence
        self.previous_key_sequence = previous_key_sequence

        #: True when the previous key sequence was handled by the same handler.
        self.is_repeat = is_repeat

        self._arg = arg
        self._app = get_app()
Ejemplo n.º 26
0
        def get_formatted_text():
            buff = get_app().current_buffer

            if buff.validation_error:
                row, column = buff.document.translate_index_to_position(
                    buff.validation_error.cursor_position)

                if show_position:
                    text = '%s (line=%s column=%s)' % (
                        buff.validation_error.message, row + 1, column + 1)
                else:
                    text = buff.validation_error.message

                return [('class:validation-toolbar', text)]
            else:
                return []
Ejemplo n.º 27
0
    def _fix_vi_cursor_position(self, event):
        """
        After every command, make sure that if we are in Vi navigation mode, we
        never put the cursor after the last character of a line. (Unless it's
        an empty line.)
        """
        app = get_app()
        buff = app.current_buffer
        preferred_column = buff.preferred_column

        if (vi_navigation_mode() and buff.document.is_cursor_at_the_end_of_line
                and len(buff.document.current_line) > 0):
            buff.cursor_position -= 1

            # Set the preferred_column for arrow up/down again.
            # (This was cleared after changing the cursor position.)
            buff.preferred_column = preferred_column
Ejemplo n.º 28
0
    def preferred_width(self, max_available_width):
        """
        Preferred width: prefer to use at least min_rows, but otherwise as much
        as possible horizontally.
        """
        complete_state = get_app().current_buffer.complete_state
        column_width = self._get_column_width(complete_state)
        result = int(
            column_width *
            math.ceil(len(complete_state.completions) / float(self.min_rows)))

        # When the desired width is still more than the maximum available,
        # reduce by removing columns until we are less than the available
        # width.
        while result > column_width and result > max_available_width - self._required_margin:
            result -= column_width
        return result + self._required_margin
Ejemplo n.º 29
0
    def mouse_handler(self, mouse_event):
        """
        Handle mouse events: clicking and scrolling.
        """
        b = get_app().current_buffer

        if mouse_event.event_type == MouseEventType.MOUSE_UP:
            # Select completion.
            b.go_to_completion(mouse_event.position.y)
            b.complete_state = None

        elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
            # Scroll up.
            b.complete_next(count=3, disable_wrap_around=True)

        elif mouse_event.event_type == MouseEventType.SCROLL_UP:
            # Scroll down.
            b.complete_previous(count=3, disable_wrap_around=True)
Ejemplo n.º 30
0
def get_default_output():
    """
    Get the output class to be used by default.

    Called when creating a new Application(), when no `Output` has been passed.
    """
    try:
        value = _default_output.get()
    except TaskLocalNotSetError:
        # If an application is already running, take the output from there.
        # (This is important for the "ENTER for continue" prompts after
        # executing system commands and displaying readline-style completions.)
        app = get_app(return_none=True)
        if app:
            return app.output

        return create_output()
    else:
        return value