コード例 #1
0
    def _create_buffer_control(self, editor_buffer):
        """
        Create a new BufferControl for a given location.
        """
        buffer_name = editor_buffer.buffer_name

        @Condition
        def preview_search(cli):
            return self.editor.incsearch

        @Condition
        def wrap_lines(cli):
            return self.editor.wrap_lines

        input_processors = [
            # Processor for visualising spaces. (should come before the
            # selection processor, otherwise, we won't see these spaces
            # selected.)
            ConditionalProcessor(
                ShowTrailingWhiteSpaceProcessor(),
                Condition(
                    lambda cli: self.editor.display_unprintable_characters)),

            # Reporting of errors, for Pyflakes.
            ReportingProcessor(editor_buffer),

            # Replace tabs by spaces.
            TabsProcessor(self.editor)
        ]

        highlighters = [
            # Highlighting of the selection.
            SelectionHighlighter(),

            # Highlighting of the search.
            ConditionalHighlighter(
                SearchHighlighter(preview_search=preview_search),
                Condition(lambda cli: self.editor.highlight_search)),

            # Highlight matching parentheses.
            MatchingBracketHighlighter(),
        ]

        return BufferControl(lexer=DocumentLexer(editor_buffer),
                             input_processors=input_processors,
                             highlighters=highlighters,
                             buffer_name=buffer_name,
                             preview_search=preview_search,
                             wrap_lines=wrap_lines,
                             focus_on_click=True)
コード例 #2
0
    def create_python_input_window():
        def menu_position(cli):
            """
            When there is no autocompletion menu to be shown, and we have a signature,
            set the pop-up position at `bracket_start`.
            """
            b = cli.buffers[DEFAULT_BUFFER]

            if b.complete_state is None and python_input.signatures:
                row, col = python_input.signatures[0].bracket_start
                index = b.document.translate_row_col_to_index(row - 1, col)
                return index

        return Window(
            BufferControl(
                buffer_name=DEFAULT_BUFFER,
                lexer=lexer,
                highlighters=[
                    # Show matching parentheses, but only while editing.
                    ConditionalHighlighter(
                        highlighter=MatchingBracketHighlighter(chars='[](){}'),
                        filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()
                        & Condition(lambda cli: python_input.
                                    highlight_matching_parenthesis)),
                    ConditionalHighlighter(
                        highlighter=SearchHighlighter(preview_search=Always()),
                        filter=HasFocus(SEARCH_BUFFER)),
                    SelectionHighlighter(),
                ],
                input_processors=[
                    ConditionalProcessor(processor=AppendAutoSuggestion(),
                                         filter=~IsDone())
                ] + extra_buffer_processors,
                menu_position=menu_position,
                wrap_lines=Condition(lambda cli: python_input.wrap_lines),

                # Make sure that we always see the result of an reverse-i-search:
                preview_search=Always(),
            ),
            left_margins=[PromptMargin(python_input)],
            # Scroll offsets. The 1 at the bottom is important to make sure the
            # cursor is never below the "Press [Meta+Enter]" message which is a float.
            scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4),
            # As long as we're editing, prefer a minimal height of 6.
            get_height=(lambda cli:
                        (None if cli.is_done or python_input.
                         show_exit_confirmation else input_buffer_height)),
        )
コード例 #3
0
ファイル: layout.py プロジェクト: ABaldwinHunter/pymux-clone
def _create_container_for_process(pymux, arrangement_pane, zoom=False):
    """
    Create a `Container` with a titlebar for a process.
    """
    assert isinstance(arrangement_pane, arrangement.Pane)
    process = arrangement_pane.process

    def has_focus(cli):
        return pymux.arrangement.get_active_pane(cli) == arrangement_pane

    def get_titlebar_token(cli):
        return Token.TitleBar.Focussed if has_focus(cli) else Token.TitleBar

    def get_titlebar_name_token(cli):
        return Token.TitleBar.Name.Focussed if has_focus(cli) else Token.TitleBar.Name

    def get_title_tokens(cli):
        token = get_titlebar_token(cli)
        name_token = get_titlebar_name_token(cli)
        result = []

        if zoom:
            result.append((Token.TitleBar.Zoom, ' Z '))

        if process.is_terminated:
            result.append((Token.Terminated, ' Terminated '))

        # Scroll buffer info.
        if arrangement_pane.display_scroll_buffer:
            result.append((token.CopyMode, ' %s ' % arrangement_pane.scroll_buffer_title))

            # Cursor position.
            document = arrangement_pane.scroll_buffer.document
            result.append((token.CopyMode.Position, ' %i,%i ' % (
                document.cursor_position_row, document.cursor_position_col)))

        if arrangement_pane.name:
            result.append((name_token, ' %s ' % arrangement_pane.name))
            result.append((token, ' '))

        return result + [
            (token.Title, format_pymux_string(pymux, cli, ' #T ', pane=arrangement_pane))  # XXX: Make configurable.
        ]

    def get_pane_index(cli):
        token = get_titlebar_token(cli)

        try:
            w = pymux.arrangement.get_active_window(cli)
            index = w.get_pane_index(arrangement_pane)
        except ValueError:
            index = '/'

        return [(token.PaneIndex, '%3s ' % index)]

    def on_click(cli):
        " Click handler for the clock. When clicked, select this pane. "
        pymux.arrangement.get_active_window(cli).active_pane = arrangement_pane
        pymux.invalidate()

    clock_is_visible = Condition(lambda cli: arrangement_pane.clock_mode)
    pane_numbers_are_visible = Condition(lambda cli: pymux.display_pane_numbers)

    return TracePaneWritePosition(
        pymux, arrangement_pane,
        content=HSplit([
            # The title bar.
            VSplit([
                Window(
                    height=D.exact(1),
                    content=TokenListControl(
                        get_title_tokens,
                        get_default_char=lambda cli: Char(' ', get_titlebar_token(cli)))
                ),
                Window(
                    height=D.exact(1),
                    width=D.exact(4),
                    content=TokenListControl(get_pane_index)
                )
            ]),
            # The pane content.
            FloatContainer(
                content=HSplit([
                    # The 'screen' of the pseudo terminal.
                    ConditionalContainer(
                        content=PaneWindow(pymux, arrangement_pane, process),
                        filter=~clock_is_visible & Condition(lambda cli: not arrangement_pane.display_scroll_buffer)),

                    # The copy/paste buffer.
                    ConditionalContainer(
                        content=Window(BufferControl(
                            buffer_name='pane-%i' % arrangement_pane.pane_id,
                            wrap_lines=False,
                            focus_on_click=True,
                            default_char=Char(token=Token),
                            preview_search=True,
                            get_search_state=lambda cli: arrangement_pane.search_state,
                            search_buffer_name='search-%i' % arrangement_pane.pane_id,
                            input_processors=[_UseCopyTokenListProcessor(arrangement_pane)],
                            highlighters=[
                                SearchHighlighter(
                                   search_buffer_name='search-%i' % arrangement_pane.pane_id,
                                   get_search_state=lambda cli: arrangement_pane.search_state,
                                   preview_search=True),
                                SelectionHighlighter(),
                            ],
                        )),
                        filter=~clock_is_visible & Condition(lambda cli: arrangement_pane.display_scroll_buffer)
                    ),
                    # Search toolbar. (Displayed when this pane has the focus, and searching.)
                    ConditionalContainer(
                        content=SearchWindow(pymux, arrangement_pane),
                        filter=~clock_is_visible & Condition(lambda cli: arrangement_pane.is_searching)
                    ),
                    # The clock.
                    ConditionalContainer(
                        # Add a dummy VSplit/HSplit around the BigClock in order to center it.
                        # (Using a FloatContainer to do the centering doesn't work well, because
                        # the boundaries are not clipt when the parent is smaller.)
                        content=VSplit([
                            Window(_FillControl(on_click)),
                            HSplit([
                                Window(_FillControl(on_click)),
                                Window(BigClock(on_click), height=D.exact(BigClock.HEIGHT)),
                                Window(_FillControl(on_click)),
                            ]),
                            Window(_FillControl(on_click)),
                        ], get_dimensions=lambda cli: [None, D.exact(BigClock.WIDTH), None]),

                        filter=clock_is_visible,
                    ),
                ]),
                # Pane numbers. (Centered.)
                floats=[
                    Float(content=ConditionalContainer(
                        content=Window(PaneNumber(pymux, arrangement_pane, on_click)),
                        filter=pane_numbers_are_visible)),
                ]
            )
        ])
    )
コード例 #4
0
ファイル: layout.py プロジェクト: ABaldwinHunter/pymux-clone
    def _create_layout(self):
        """
        Generate the main prompt_toolkit layout.
        """
        waits_for_confirmation = WaitsForConfirmation(self.pymux)
        waits_for_prompt = WaitsForPrompt(self.pymux)
        in_command_mode = InCommandMode(self.pymux)

        return FloatContainer(
            content=HSplit([
                # The main window.
                HighlightBorders(self, self.pymux, FloatContainer(
                    Background(),
                    floats=[
                        Float(get_width=lambda cli: self.pymux.get_window_size(cli).columns,
                              get_height=lambda cli: self.pymux.get_window_size(cli).rows,
                              content=TraceBodyWritePosition(self.pymux, DynamicBody(self.pymux)))
                    ])),
                # Status bar.
                ConditionalContainer(
                    content=VSplit([
                        # Left.
                        Window(
                            height=D.exact(1),
                            get_width=(lambda cli: D(max=self.pymux.status_left_length)),
                            dont_extend_width=True,
                            content=TokenListControl(
                                self._get_status_left_tokens,
                                default_char=Char(' ', Token.StatusBar))),
                        # List of windows in the middle.
                        Window(
                            height=D.exact(1),
                            content=TokenListControl(
                                self._get_status_tokens,
                                align_right=Condition(self._status_align_right),
                                align_center=Condition(self._status_align_center),
                                default_char=Char(' ', Token.StatusBar))),
                        # Right.
                        Window(
                            height=D.exact(1),
                            get_width=(lambda cli: D(max=self.pymux.status_right_length)),
                            dont_extend_width=True,
                            content=TokenListControl(
                                self._get_status_right_tokens,
                                align_right=True,
                                default_char=Char(' ', Token.StatusBar)))
                    ]),
                    filter=Condition(lambda cli: self.pymux.enable_status),
                )
            ]),
            floats=[
                Float(bottom=1, left=0, content=MessageToolbar(self.pymux)),
                Float(left=0, right=0, bottom=0, content=HSplit([
                    # Wait for confirmation toolbar.
                    ConditionalContainer(
                        content=Window(
                            height=D.exact(1),
                            content=ConfirmationToolbar(self.pymux),
                        ),
                        filter=waits_for_confirmation,
                    ),
                    # ':' prompt toolbar.
                    ConditionalContainer(
                        content=Window(
                            height=D(min=1),  # Can be more if the command is multiline.
                            dont_extend_height=True,
                            content=BufferControl(
                                buffer_name=COMMAND,
                                default_char=Char(' ', Token.CommandLine),
                                lexer=SimpleLexer(Token.CommandLine),
                                preview_search=True,
                                highlighters=[SelectionHighlighter()],
                                input_processors=[
                                    AppendAutoSuggestion(),
                                    DefaultPrompt(lambda cli:[(Token.CommandLine.Prompt, ':')]),
                                ])
                        ),
                        filter=in_command_mode,
                    ),
                    # Other command-prompt commands toolbar.
                    ConditionalContainer(
                        content=Window(
                            height=D.exact(1),
                            content=BufferControl(
                                buffer_name=PROMPT,
                                default_char=Char(' ', Token.CommandLine),
                                lexer=SimpleLexer(Token.CommandLine),
                                highlighters=[SelectionHighlighter()],
                                input_processors=[
                                    BeforeInput(self._before_prompt_command_tokens),
                                    AppendAutoSuggestion(),
                                ])
                        ),
                        filter=waits_for_prompt,
                    ),
                ])),
                Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=12)),
            ]
        )
コード例 #5
0
ファイル: shortcuts.py プロジェクト: wshanks/xonsh
    def create_prompt_layout(self,
                             message='',
                             lexer=None,
                             is_password=False,
                             reserve_space_for_menu=8,
                             get_prompt_tokens=None,
                             get_bottom_toolbar_tokens=None,
                             display_completions_in_columns=False,
                             extra_input_processors=None,
                             multiline=False,
                             wrap_lines=True):
        """Create a Container instance for a prompt.

        Parameters
        ----------
        message : Text to be used as prompt.
        lexer : ~prompt_toolkit.layout.lexers.Lexer to be used for
            the highlighting.
        is_password : bool or ~prompt_toolkit.filters.CLIFilter.
            When True, display input as '*'.
        reserve_space_for_menu : Space to be reserved for the menu. When >0,
            make sure that a minimal height is allocated in the terminal, in order
            to display the completion menu.
        get_prompt_tokens : An optional callable that returns the tokens to be
            shown in the menu. (To be used instead of a `message`.)
        get_bottom_toolbar_tokens : An optional callable that returns the
            tokens for a toolbar at the bottom.
        display_completions_in_columns : `bool` or
            :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
            multiple columns.
        multiline : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
            When True, prefer a layout that is more adapted for multiline input.
            Text after newlines is automatically indented, and search/arg input is
            shown below the input, instead of replacing the prompt.
        wrap_lines : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
            When True (the default), automatically wrap long lines instead of
            scrolling horizontally.

        Notes
        -----
        This method was forked from the mainline prompt-toolkit repo.
        Copyright (c) 2014, Jonathan Slenders, All rights reserved.

        WARNING; This method is due for removal once prompt-toolkit >v0.54 
        is released.
        """
        assert isinstance(message, str)
        assert get_bottom_toolbar_tokens is None or callable(
            get_bottom_toolbar_tokens)
        assert get_prompt_tokens is None or callable(get_prompt_tokens)
        assert not (message and get_prompt_tokens)

        display_completions_in_columns = to_cli_filter(
            display_completions_in_columns)
        multiline = to_cli_filter(multiline)

        if get_prompt_tokens is None:
            get_prompt_tokens = lambda _: [(Token.Prompt, message)]

        get_prompt_tokens_1, get_prompt_tokens_2 = _split_multiline_prompt(
            get_prompt_tokens)

        # `lexer` is supposed to be a `Lexer` instance. But if a Pygments lexer
        # class is given, turn it into a PygmentsLexer. (Important for
        # backwards-compatibility.)
        try:
            if issubclass(lexer, pygments.lexer.Lexer):
                lexer = PygmentsLexer(lexer)
        except TypeError:  # Happens when lexer is `None` or an instance of something else.
            pass

        # Create highlighters and processors list.
        if ConditionalHighlighter is None:
            highlighters = None
            highlighters_kwargs = {}
        else:
            highlighters = [
                ConditionalHighlighter(
                    # By default, only highlight search when the search
                    # input has the focus. (Note that this doesn't mean
                    # there is no search: the Vi 'n' binding for instance
                    # still allows to jump to the next match in
                    # navigation mode.)
                    SearchHighlighter(preview_search=True),
                    HasFocus(SEARCH_BUFFER)),
                SelectionHighlighter()
            ]
            highlighters_kwargs = {'highlighters': highlighters}

        input_processors = [
            ConditionalProcessor(AppendAutoSuggestion(),
                                 HasFocus(DEFAULT_BUFFER) & ~IsDone()),
            ConditionalProcessor(PasswordProcessor(), is_password)
        ]

        if extra_input_processors:
            input_processors.extend(extra_input_processors)

        # Show the prompt before the input (using the DefaultPrompt processor.
        # This also replaces it with reverse-i-search and 'arg' when required.
        # (Only for single line mode.)
        # (DefaultPrompt should always be at the end of the processors.)
        input_processors.append(
            ConditionalProcessor(DefaultPrompt(get_prompt_tokens), ~multiline))

        # Create bottom toolbar.
        if get_bottom_toolbar_tokens:
            toolbars = [
                ConditionalContainer(
                    Window(TokenListControl(get_bottom_toolbar_tokens,
                                            default_char=Char(
                                                ' ', Token.Toolbar)),
                           height=LayoutDimension.exact(1)),
                    filter=~IsDone() & RendererHeightIsKnown())
            ]
        else:
            toolbars = []

        def get_height(cli):
            # If there is an autocompletion menu to be shown, make sure that our
            # layout has at least a minimal height in order to display it.
            if reserve_space_for_menu and not cli.is_done:
                return LayoutDimension(min=reserve_space_for_menu)
            else:
                return LayoutDimension()

        # Create and return Container instance.
        return HSplit([
            ConditionalContainer(
                Window(TokenListControl(get_prompt_tokens_1),
                       dont_extend_height=True),
                filter=multiline,
            ),
            VSplit([
                # In multiline mode, the prompt is displayed in a left pane.
                ConditionalContainer(
                    Window(
                        TokenListControl(get_prompt_tokens_2),
                        dont_extend_width=True,
                    ),
                    filter=multiline,
                ),
                # The main input, with completion menus floating on top of it.
                FloatContainer(
                    Window(
                        BufferControl(
                            input_processors=input_processors,
                            lexer=lexer,
                            wrap_lines=wrap_lines,
                            # Enable preview_search, we want to have immediate feedback
                            # in reverse-i-search mode.
                            preview_search=True,
                            **highlighters_kwargs),
                        get_height=get_height,
                    ),
                    [
                        Float(xcursor=True,
                              ycursor=True,
                              content=CompletionsMenu(
                                  max_height=16,
                                  scroll_offset=1,
                                  extra_filter=HasFocus(DEFAULT_BUFFER)
                                  & ~display_completions_in_columns)),
                        Float(xcursor=True,
                              ycursor=True,
                              content=MultiColumnCompletionsMenu(
                                  extra_filter=HasFocus(DEFAULT_BUFFER)
                                  & display_completions_in_columns,
                                  show_meta=True))
                    ]),
            ]),
            ValidationToolbar(),
            SystemToolbar(),

            # In multiline mode, we use two toolbars for 'arg' and 'search'.
            ConditionalContainer(ArgToolbar(), multiline),
            ConditionalContainer(SearchToolbar(), multiline),
        ] + toolbars)