コード例 #1
0
ファイル: prompt.py プロジェクト: rokn/python-prompt-toolkit
    def _create_layout(self):
        """
        Create `Layout` for this prompt.
        """
        dyncond = self._dyncond

        # Create functions that will dynamically split the prompt. (If we have
        # a multiline prompt.)
        has_before_fragments, get_prompt_text_1, get_prompt_text_2 = \
            _split_multiline_prompt(self._get_prompt)

        default_buffer = self.default_buffer
        search_buffer = self.search_buffer

        # Create processors list.
        all_input_processors = [
            HighlightIncrementalSearchProcessor(),
            HighlightSelectionProcessor(),
            ConditionalProcessor(AppendAutoSuggestion(),
                                 has_focus(default_buffer) & ~is_done),
            ConditionalProcessor(PasswordProcessor(), dyncond('is_password')),
            DisplayMultipleCursors(),

            # Users can insert processors here.
            DynamicProcessor(
                lambda: merge_processors(self.input_processors or [])),

            # For single line mode, show the prompt before the input.
            ConditionalProcessor(
                merge_processors([
                    BeforeInput(get_prompt_text_2),
                    ShowArg(),
                ]), ~dyncond('multiline'))
        ]

        # Create bottom toolbars.
        bottom_toolbar = ConditionalContainer(
            Window(FormattedTextControl(lambda: self.bottom_toolbar,
                                        style='class:bottom-toolbar.text'),
                   style='class:bottom-toolbar',
                   dont_extend_height=True,
                   height=Dimension(min=1)),
            filter=~is_done & renderer_height_is_known
            & Condition(lambda: self.bottom_toolbar is not None))

        search_toolbar = SearchToolbar(
            search_buffer, ignore_case=dyncond('search_ignore_case'))

        search_buffer_control = SearchBufferControl(
            buffer=search_buffer,
            input_processors=[
                ReverseSearchProcessor(),
                ShowArg(),
            ],
            ignore_case=dyncond('search_ignore_case'))

        system_toolbar = SystemToolbar(
            enable_global_bindings=dyncond('enable_system_prompt'))

        def get_search_buffer_control():
            " Return the UIControl to be focused when searching start. "
            if _true(self.multiline):
                return search_toolbar.control
            else:
                return search_buffer_control

        default_buffer_control = BufferControl(
            buffer=default_buffer,
            search_buffer_control=get_search_buffer_control,
            input_processors=all_input_processors,
            include_default_input_processors=False,
            lexer=DynamicLexer(lambda: self.lexer),
            preview_search=True)

        default_buffer_window = Window(
            default_buffer_control,
            height=self._get_default_buffer_control_height,
            left_margins=[
                # In multiline mode, use the window margin to display
                # the prompt and continuation fragments.
                ConditionalMargin(
                    PromptMargin(get_prompt_text_2, self._get_continuation),
                    filter=dyncond('multiline'),
                )
            ],
            wrap_lines=dyncond('wrap_lines'))

        @Condition
        def multi_column_complete_style():
            return self.complete_style == CompleteStyle.MULTI_COLUMN

        # Build the layout.
        layout = HSplit([
            # The main input, with completion menus floating on top of it.
            FloatContainer(
                HSplit([
                    ConditionalContainer(
                        Window(FormattedTextControl(get_prompt_text_1),
                               dont_extend_height=True),
                        Condition(has_before_fragments)),
                    ConditionalContainer(
                        default_buffer_window,
                        Condition(lambda: get_app().layout.current_control !=
                                  search_buffer_control),
                    ),
                    ConditionalContainer(
                        Window(search_buffer_control),
                        Condition(lambda: get_app().layout.current_control ==
                                  search_buffer_control),
                    ),
                ]),
                [
                    # Completion menus.
                    Float(xcursor=True,
                          ycursor=True,
                          content=CompletionsMenu(
                              max_height=16,
                              scroll_offset=1,
                              extra_filter=has_focus(default_buffer)
                              & ~multi_column_complete_style)),
                    Float(xcursor=True,
                          ycursor=True,
                          content=MultiColumnCompletionsMenu(
                              show_meta=True,
                              extra_filter=has_focus(default_buffer)
                              & multi_column_complete_style)),
                    # The right prompt.
                    Float(right=0,
                          top=0,
                          hide_when_covering_content=True,
                          content=_RPrompt(lambda: self.rprompt)),
                ]),
            ConditionalContainer(ValidationToolbar(), filter=~is_done),
            ConditionalContainer(system_toolbar,
                                 dyncond('enable_system_prompt') & ~is_done),

            # In multiline mode, we use two toolbars for 'arg' and 'search'.
            ConditionalContainer(
                Window(FormattedTextControl(self._get_arg_text), height=1),
                dyncond('multiline') & has_arg),
            ConditionalContainer(search_toolbar,
                                 dyncond('multiline') & ~is_done),
            bottom_toolbar,
        ])

        return Layout(layout, default_buffer_window)
コード例 #2
0
ファイル: modalprompt.py プロジェクト: jimhester/rice
    def create_layout(self):
        # Create functions that will dynamically split the prompt. (If we have
        # a multiline prompt.)
        has_before_fragments, get_prompt_text_1, get_prompt_text_2 = \
            _split_multiline_prompt(self.formatted_message)

        default_buffer = ModalBuffer(
            name=DEFAULT_BUFFER,
            complete_while_typing=Condition(
                lambda: self.complete_while_typing),
            completer=DynamicCompleter(lambda: self.completer),
            history=self.history,
            get_tempfile_suffix=lambda: self.tempfile_suffix)

        search_buffer = Buffer(name=SEARCH_BUFFER)

        search_toolbar = SearchToolbar(search_buffer)

        input_processor = merge_processors([
            ConditionalProcessor(HighlightSearchProcessor(preview_search=True),
                                 has_focus(search_buffer)),
            HighlightSelectionProcessor(),
            HighlightMatchingBracketProcessor(),
            DisplayMultipleCursors()
        ])

        default_buffer_control = BufferControl(
            buffer=default_buffer,
            search_buffer_control=search_toolbar.control,
            input_processor=input_processor,
            lexer=DynamicLexer(lambda: self.lexer),
            preview_search=True)

        def get_default_buffer_control_height():
            # 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.
            space = self.reserve_space_for_menu

            if space and not get_app().is_done:
                buff = default_buffer
                if buff.complete_while_typing(
                ) or buff.complete_state is not None:
                    return Dimension(min=space)
            return Dimension()

        def get_continuation(width):
            prompt_continuation = self.prompt_continuation

            if callable(prompt_continuation):
                prompt_continuation = prompt_continuation(width)

            return to_formatted_text(prompt_continuation,
                                     style='class:prompt-continuation')

        default_buffer_window = Window(
            default_buffer_control,
            height=get_default_buffer_control_height,
            left_margins=[PromptMargin(get_prompt_text_2, get_continuation)],
            wrap_lines=True)

        def get_arg_text():
            arg = self.app.key_processor.arg
            if arg == '-':
                arg = '-1'

            return [('class:arg-toolbar', 'Repeat: '),
                    ('class:arg-toolbar.text', arg)]

        # Build the layout.
        layout = HSplit([
            # The main input, with completion menus floating on top of it.
            FloatContainer(
                HSplit([
                    ConditionalContainer(
                        Window(FormattedTextControl(get_prompt_text_1),
                               dont_extend_height=True),
                        Condition(has_before_fragments)),
                    default_buffer_window,
                ]),
                [
                    # Completion menus.
                    Float(xcursor=True,
                          ycursor=True,
                          content=MultiColumnCompletionsMenu(
                              show_meta=True,
                              extra_filter=has_focus(default_buffer)))
                ]),
            ConditionalContainer(
                Window(FormattedTextControl(get_arg_text), height=1), has_arg),
            search_toolbar
        ])

        return Layout(layout, default_buffer_window)
コード例 #3
0
def create_layout(python_input,
                  lexer=PythonLexer,
                  extra_body=None,
                  extra_toolbars=None,
                  extra_buffer_processors=None,
                  input_buffer_height=None):
    D = Dimension
    extra_body = [extra_body] if extra_body else []
    extra_toolbars = extra_toolbars or []
    extra_buffer_processors = extra_buffer_processors or []
    input_buffer_height = input_buffer_height or D(min=6)

    search_toolbar = SearchToolbar(python_input.search_buffer)

    def create_python_input_window():
        def menu_position():
            """
            When there is no autocompletion menu to be shown, and we have a signature,
            set the pop-up position at `bracket_start`.
            """
            b = python_input.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=python_input.default_buffer,
                search_buffer_control=search_toolbar.control,
                lexer=lexer,
                include_default_input_processors=False,
                input_processors=[
                    ConditionalProcessor(
                        processor=HighlightIncrementalSearchProcessor(),
                        filter=has_focus(SEARCH_BUFFER)
                        | has_focus(search_toolbar.control),
                    ),
                    HighlightSelectionProcessor(),
                    DisplayMultipleCursors(),
                    # Show matching parentheses, but only while editing.
                    ConditionalProcessor(
                        processor=HighlightMatchingBracketProcessor(
                            chars='[](){}'),
                        filter=has_focus(DEFAULT_BUFFER) & ~is_done
                        & Condition(lambda: python_input.
                                    highlight_matching_parenthesis)),
                    ConditionalProcessor(processor=AppendAutoSuggestion(),
                                         filter=~is_done)
                ] + extra_buffer_processors,
                menu_position=menu_position,

                # Make sure that we always see the result of an reverse-i-search:
                preview_search=True,
            ),
            left_margins=[PythonPromptMargin(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.
            height=(lambda: (None if get_app().is_done or python_input.
                             show_exit_confirmation else input_buffer_height)),
            wrap_lines=Condition(lambda: python_input.wrap_lines),
        )

    root_container = HSplit([
        VSplit([
            HSplit([
                FloatContainer(
                    content=HSplit([create_python_input_window()] +
                                   extra_body),
                    floats=[
                        Float(xcursor=True,
                              ycursor=True,
                              content=ConditionalContainer(
                                  content=CompletionsMenu(scroll_offset=(
                                      lambda: python_input.
                                      completion_menu_scroll_offset),
                                                          max_height=12),
                                  filter=show_completions_menu(python_input))),
                        Float(xcursor=True,
                              ycursor=True,
                              content=ConditionalContainer(
                                  content=MultiColumnCompletionsMenu(),
                                  filter=show_multi_column_completions_menu(
                                      python_input))),
                        Float(xcursor=True,
                              ycursor=True,
                              content=signature_toolbar(python_input)),
                        Float(left=2,
                              bottom=1,
                              content=exit_confirmation(python_input)),
                        Float(bottom=0,
                              right=0,
                              height=1,
                              content=meta_enter_message(python_input),
                              hide_when_covering_content=True),
                        Float(bottom=1,
                              left=1,
                              right=0,
                              content=python_sidebar_help(python_input)),
                    ]),
                ArgToolbar(),
                search_toolbar,
                SystemToolbar(),
                ValidationToolbar(),
                ConditionalContainer(content=CompletionsToolbar(),
                                     filter=show_completions_toolbar(
                                         python_input)),

                # Docstring region.
                ConditionalContainer(content=Window(
                    height=D.exact(1), char='\u2500', style='class:separator'),
                                     filter=HasSignature(python_input)
                                     & ShowDocstring(python_input) & ~is_done),
                ConditionalContainer(
                    content=Window(
                        BufferControl(
                            buffer=python_input.docstring_buffer,
                            lexer=SimpleLexer(style='class:docstring'),
                            #lexer=PythonLexer,
                        ),
                        height=D(max=12)),
                    filter=HasSignature(python_input)
                    & ShowDocstring(python_input) & ~is_done),
            ]),
            ConditionalContainer(content=HSplit([
                python_sidebar(python_input),
                Window(style='class:sidebar,separator', height=1),
                python_sidebar_navigation(python_input),
            ]),
                                 filter=ShowSidebar(python_input) & ~is_done)
        ]),
    ] + extra_toolbars + [
        VSplit([
            status_bar(python_input),
            show_sidebar_button_info(python_input),
        ])
    ])

    return Layout(root_container)
コード例 #4
0
    def __init__(self, pager: "Pager") -> None:
        self.pager = pager
        self.dynamic_body = _DynamicBody(pager)

        # Build an interface.
        has_colon = HasColon(pager)

        self.examine_control: BufferControl = BufferControl(
            buffer=pager.examine_buffer,
            lexer=SimpleLexer(style="class:examine,examine-text"),
            input_processors=[
                BeforeInput(lambda: [("class:examine", " Examine: ")])
            ],
        )

        self.search_toolbar = SearchToolbar(vi_mode=True,
                                            search_buffer=pager.search_buffer)

        self.container = FloatContainer(
            content=HSplit([
                ConditionalContainer(
                    content=Titlebar(pager),
                    filter=Condition(lambda: pager.display_titlebar),
                ),
                self.dynamic_body,
                self.search_toolbar,
                SystemToolbar(),
                ConditionalContainer(
                    content=VSplit([
                        Window(
                            height=1,
                            content=FormattedTextControl(
                                self._get_statusbar_left_tokens),
                            style="class:statusbar",
                        ),
                        Window(
                            height=1,
                            content=FormattedTextControl(
                                self._get_statusbar_right_tokens),
                            style="class:statusbar.cursorposition",
                            align=WindowAlign.RIGHT,
                        ),
                    ]),
                    filter=~HasSearch()
                    & ~has_focus(SYSTEM_BUFFER)
                    & ~has_colon
                    & ~has_focus("EXAMINE"),
                ),
                ConditionalContainer(
                    content=Window(FormattedTextControl(" :"),
                                   height=1,
                                   style="class:examine"),
                    filter=has_colon,
                ),
                ConditionalContainer(
                    content=Window(self.examine_control,
                                   height=1,
                                   style="class:examine"),
                    filter=has_focus(pager.examine_buffer),
                ),
            ]),
            floats=[
                Float(right=0, height=1, bottom=1, content=_Arg()),
                Float(
                    bottom=1,
                    left=0,
                    right=0,
                    height=1,
                    content=ConditionalContainer(
                        content=MessageToolbarBar(pager),
                        filter=Condition(lambda: bool(pager.message)),
                    ),
                ),
                Float(
                    right=0,
                    height=1,
                    bottom=1,
                    content=ConditionalContainer(
                        content=FormattedTextToolbar(
                            lambda: [("class:loading", " Loading... ")], ),
                        filter=Condition(lambda: pager.current_source_info.
                                         waiting_for_input_stream),
                    ),
                ),
                Float(xcursor=True,
                      ycursor=True,
                      content=MultiColumnCompletionsMenu()),
            ],
        )
コード例 #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)
コード例 #6
0
ファイル: cli.py プロジェクト: zheilbron/atomix
    def _create_layout(self,
                       message='',
                       lexer=None,
                       is_password=False,
                       reserve_space_for_menu=8,
                       get_prompt_tokens=None,
                       get_continuation_tokens=None,
                       get_rprompt_tokens=None,
                       get_bottom_toolbar_tokens=None,
                       get_url_tokens=None,
                       display_completions_in_columns=False,
                       extra_input_processors=None,
                       multiline=False,
                       wrap_lines=True):
        """
        Create a :class:`.Container` instance for a prompt.
        :param message: Text to be used as prompt.
        :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for
            the highlighting.
        :param is_password: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
            When True, display input as '*'.
        :param 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.
        :param get_prompt_tokens: An optional callable that returns the tokens to be
            shown in the menu. (To be used instead of a `message`.)
        :param get_continuation_tokens: An optional callable that takes a
            CommandLineInterface and width as input and returns a list of (Token,
            text) tuples to be used for the continuation.
        :param get_bottom_toolbar_tokens: An optional callable that returns the
            tokens for a toolbar at the bottom.
        :param display_completions_in_columns: `bool` or
            :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
            multiple columns.
        :param 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.
        :param wrap_lines: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
            When True (the default), automatically wrap long lines instead of
            scrolling horizontally.
        """
        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 get_rprompt_tokens is None or callable(get_rprompt_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)]

        has_before_tokens, 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 pygments_Lexer and issubclass(lexer, pygments_Lexer):
                lexer = PygmentsLexer(lexer, sync_from_start=True)
        except TypeError:  # Happens when lexer is `None` or an instance of something else.
            pass

        # Create processors list.
        input_processors = [
            ConditionalProcessor(
                # 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.)
                HighlightSearchProcessor(preview_search=True),
                HasFocus(SEARCH_BUFFER)),
            HighlightSelectionProcessor(),
            ConditionalProcessor(AppendAutoSuggestion(),
                                 HasFocus(DEFAULT_BUFFER) & ~IsDone()),
            ConditionalProcessor(PasswordProcessor(), is_password),
            DisplayMultipleCursors(DEFAULT_BUFFER),
        ]

        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_2),
                                 ~multiline))

        # Create bottom toolbar.
        if get_bottom_toolbar_tokens:
            toolbars = [
                ConditionalContainer(VSplit([
                    Window(TokenListControl(get_url_tokens,
                                            default_char=Char(
                                                ' ', Token.Toolbar)),
                           height=LayoutDimension.exact(1)),
                    Window(TokenListControl(get_bottom_toolbar_tokens,
                                            default_char=Char(
                                                ' ', Token.Toolbar),
                                            align_right=True),
                           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:
                buff = cli.current_buffer

                # Reserve the space, either when there are completions, or when
                # `complete_while_typing` is true and we expect completions very
                # soon.
                if buff.complete_while_typing(
                ) or buff.complete_state is not None:
                    return LayoutDimension(min=reserve_space_for_menu)

            return LayoutDimension()

        # Create and return Container instance.
        return HSplit([
            # The main input, with completion menus floating on top of it.
            FloatContainer(
                HSplit([
                    ConditionalContainer(
                        Window(TokenListControl(get_prompt_tokens_1),
                               dont_extend_height=True),
                        Condition(has_before_tokens)),
                    Window(
                        BufferControl(
                            input_processors=input_processors,
                            lexer=lexer,
                            # Enable preview_search, we want to have immediate feedback
                            # in reverse-i-search mode.
                            preview_search=True),
                        get_height=get_height,
                        left_margins=[
                            # In multiline mode, use the window margin to display
                            # the prompt and continuation tokens.
                            ConditionalMargin(PromptMargin(
                                get_prompt_tokens_2, get_continuation_tokens),
                                              filter=multiline)
                        ],
                        wrap_lines=wrap_lines,
                    ),
                ]),
                [
                    # Completion menus.
                    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)),

                    # The right prompt.
                    Float(right=0,
                          top=0,
                          hide_when_covering_content=True,
                          content=_RPrompt(get_rprompt_tokens)),
                ]),
            ValidationToolbar(),
            SystemToolbar(),

            # In multiline mode, we use two toolbars for 'arg' and 'search'.
            ConditionalContainer(ArgToolbar(), multiline),
            ConditionalContainer(SearchToolbar(), multiline),
        ] + toolbars)
コード例 #7
0
def create_default_layout(app,
                          message='',
                          lexer=None,
                          is_password=False,
                          reserve_space_for_menu=False,
                          get_prompt_tokens=None,
                          get_bottom_toolbar_tokens=None,
                          display_completions_in_columns=False,
                          extra_input_processors=None,
                          multiline=False):
    """
    Generate default layout.

    Returns a ``Layout`` instance.

    :param message: Text to be used as prompt.
    :param lexer: Lexer to be used for the highlighting.
    :param is_password: `bool` or `CLIFilter`. When True, display input as '*'.
    :param reserve_space_for_menu: When True, make sure that a minimal height
        is allocated in the terminal, in order to display the completion menu.
    :param get_prompt_tokens: An optional callable that returns the tokens to
        be shown in the menu. (To be used instead of a `message`.)
    :param get_bottom_toolbar_tokens: An optional callable that returns the
        tokens for a toolbar at the bottom.
    :param display_completions_in_columns: `bool` or `CLIFilter`. Display the
        completions in multiple columns.
    :param multiline: `bool` or `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.
    """
    assert isinstance(message, text_type)
    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, Lexer):
            lexer = PygmentsLexer(lexer)
    except TypeError:
        # Happens when lexer is `None` or an instance of something else.
        pass

    # Create processors list.
    # (DefaultPrompt should always be at the end.)
    input_processors = [
        ConditionalProcessor(
            # 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.)
            HighlightSearchProcessor(preview_search=Always()),
            HasFocus(SEARCH_BUFFER)),
        HighlightSelectionProcessor(),
        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.)
    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=8)
        else:
            return LayoutDimension()

    def separator():
        return ConditionalContainer(content=Window(
            height=LayoutDimension.exact(1),
            content=FillControl(u'\u2500', token=Token.Separator)),
                                    filter=HasDocumentation(app) & ~IsDone())

    # Create and return Layout 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,
                        # Enable preview_search, we want to have immediate
                        # feedback in reverse-i-search mode.
                        preview_search=Always(),
                        focus_on_click=True,
                    ),
                    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
                                            ))),  # noqa E501
                    Float(xcursor=True,
                          ycursor=True,
                          content=MultiColumnCompletionsMenu(
                              extra_filter=(HasFocus(DEFAULT_BUFFER)
                                            & display_completions_in_columns),
                              show_meta=Always()))
                ]),
        ]),
        separator(),
        ConditionalContainer(
            content=Window(BufferControl(
                focus_on_click=True,
                buffer_name=u'clidocs',
            ),
                           height=LayoutDimension(max=15)),
            filter=HasDocumentation(app) & ~IsDone(),
        ),
        separator(),
        ValidationToolbar(),
        SystemToolbar(),

        # In multiline mode, we use two toolbars for 'arg' and 'search'.
        ConditionalContainer(ArgToolbar(), multiline),
        ConditionalContainer(SearchToolbar(), multiline),
    ] + toolbars)
コード例 #8
0
ファイル: layout.py プロジェクト: mm4nn/pypager
    def __init__(self, pager):
        self.pager = pager
        self.dynamic_body = _DynamicBody(pager)

        # Build an interface.
        has_colon = HasColon(pager)

        self.container = FloatContainer(content=HSplit([
            Titlebar(pager),
            self.dynamic_body,
            SearchToolbar(vi_mode=True),
            SystemToolbar(),
            ConditionalContainer(content=VSplit([
                Window(height=D.exact(1),
                       content=TokenListControl(
                           self._get_statusbar_left_tokens,
                           default_char=Char(' ', Token.Statusbar))),
                Window(height=D.exact(1),
                       content=TokenListControl(
                           self._get_statusbar_right_tokens,
                           align_right=True,
                           default_char=Char(' ', Token.Statusbar))),
            ]),
                                 filter=~HasSearch() & ~HasFocus(SYSTEM_BUFFER)
                                 & ~has_colon & ~HasFocus('EXAMINE')),
            ConditionalContainer(content=TokenListToolbar(
                lambda cli: [(Token.Statusbar, ' :')],
                default_char=Char(token=Token.Statusbar)),
                                 filter=has_colon),
            ConditionalContainer(content=Window(BufferControl(
                buffer_name='EXAMINE',
                default_char=Char(token=Token.Toolbar.Examine),
                lexer=SimpleLexer(default_token=Token.Toolbar.Examine.Text),
                input_processors=[
                    BeforeInput(
                        lambda cli: [(Token.Toolbar.Examine, ' Examine: ')]),
                ]),
                                                height=D.exact(1)),
                                 filter=HasFocus('EXAMINE')),
            ConditionalContainer(content=Window(BufferControl(
                buffer_name='PATTERN_FILTER',
                default_char=Char(token=Token.Toolbar.Search),
                lexer=SimpleLexer(default_token=Token.Toolbar.Search.Text),
                input_processors=[
                    BeforeInput(lambda cli: [(Token.Toolbar.Search, '&/')]),
                ]),
                                                height=D.exact(1)),
                                 filter=HasFocus('PATTERN_FILTER')),
        ]),
                                        floats=[
                                            Float(right=0,
                                                  height=1,
                                                  bottom=1,
                                                  content=_Arg()),
                                            Float(bottom=1,
                                                  left=0,
                                                  right=0,
                                                  height=1,
                                                  content=MessageToolbarBar(
                                                      pager)),
                                            Float(
                                                right=0,
                                                height=1,
                                                bottom=1,
                                                content=ConditionalContainer(
                                                    content=TokenListToolbar(
                                                        lambda cli: [
                                                            (Token.Loading,
                                                             ' Loading... ')
                                                        ],
                                                        default_char=Char(
                                                            token=Token.
                                                            Statusbar)),
                                                    filter=Condition(
                                                        lambda cli: pager.
                                                        waiting_for_input_stream
                                                    ))),
                                            Float(
                                                xcursor=True,
                                                ycursor=True,
                                                content=
                                                MultiColumnCompletionsMenu()),
                                        ])
コード例 #9
0
def create_layout(python_input, key_bindings_manager,
                  lexer=PythonLexer,
                  extra_body=None, extra_toolbars=None,
                  extra_buffer_processors=None, input_buffer_height=None):
    D = LayoutDimension
    extra_body = [extra_body] if extra_body else []
    extra_toolbars = extra_toolbars or []
    extra_buffer_processors = extra_buffer_processors or []
    input_buffer_height = input_buffer_height or D(min=6)

    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,
                input_processors=[
                                  # Show matching parentheses, but only while editing.
                                  ConditionalProcessor(
                                      processor=HighlightMatchingBracketProcessor(chars='[](){}'),
                                      filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
                                          Condition(lambda cli: python_input.highlight_matching_parenthesis)),
                                  ConditionalProcessor(
                                      processor=HighlightSearchProcessor(preview_search=Always()),
                                      filter=HasFocus(SEARCH_BUFFER)),
                                  HighlightSelectionProcessor(),
                                  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)),
        )

    return HSplit([
        VSplit([
            HSplit([
                FloatContainer(
                    content=HSplit(
                        [create_python_input_window()] + extra_body
                    ),
                    floats=[
                        Float(xcursor=True,
                              ycursor=True,
                              content=CompletionsMenu(
                                  scroll_offset=Integer.from_callable(
                                      lambda: python_input.completion_menu_scroll_offset),
                                  max_height=12,
                                  extra_filter=show_completions_menu(python_input))),
                        Float(xcursor=True,
                              ycursor=True,
                              content=MultiColumnCompletionsMenu(
                                  extra_filter=show_multi_column_completions_menu(python_input))),
                        Float(xcursor=True,
                              ycursor=True,
                              content=signature_toolbar(python_input)),
                        Float(left=2,
                              bottom=1,
                              content=exit_confirmation(python_input)),
                        Float(bottom=0, right=0, height=1,
                              content=meta_enter_message(python_input)),
                        Float(bottom=1, left=1, right=0, content=python_sidebar_help(python_input)),
                    ]),
                ArgToolbar(),
                SearchToolbar(),
                SystemToolbar(),
                ValidationToolbar(),
                CompletionsToolbar(extra_filter=show_completions_toolbar(python_input)),

                # Docstring region.
                ConditionalContainer(
                    content=Window(height=D.exact(1),
                                   content=FillControl('\u2500', token=Token.Separator)),
                    filter=HasSignature(python_input) & ShowDocstring(python_input) & ~IsDone()),
                ConditionalContainer(
                    content=Window(
                        BufferControl(
                            buffer_name='docstring',
                            lexer=SimpleLexer(default_token=Token.Docstring),
                            #lexer=PythonLexer,
                        ),
                        height=D(max=12)),
                    filter=HasSignature(python_input) & ShowDocstring(python_input) & ~IsDone(),
                ),
            ]),
            HSplit([
                python_sidebar(python_input),
                python_sidebar_navigation(python_input),
            ])
        ]),
    ] + extra_toolbars + [
        VSplit([
            status_bar(key_bindings_manager, python_input),
            show_sidebar_button_info(python_input),
        ])
    ])
コード例 #10
0
    def _create_application(self, editing_mode, erase_when_done):
        def dyncond(attr_name):
            """
            Dynamically take this setting from this 'Prompt' class.
            `attr_name` represents an attribute name of this class. Its value
            can either be a boolean or a `Filter`.

            This returns something that can be used as either a `Filter`
            or `Filter`.
            """
            @Condition
            def dynamic():
                value = getattr(self, attr_name)
                return to_filter(value)()

            return dynamic

        # Create functions that will dynamically split the prompt. (If we have
        # a multiline prompt.)
        has_before_fragments, get_prompt_text_1, get_prompt_text_2 = \
            _split_multiline_prompt(self._get_prompt)

        # Create buffers list.
        def accept(buff):
            """ Accept the content of the default buffer. This is called when
            the validation succeeds. """
            self.app.set_result(buff.document.text)

            # Reset content before running again.
            self.app.pre_run_callables.append(buff.reset)

        default_buffer = Buffer(
            name=DEFAULT_BUFFER,
            # Make sure that complete_while_typing is disabled when
            # enable_history_search is enabled. (First convert to Filter,
            # to avoid doing bitwise operations on bool objects.)
            complete_while_typing=Condition(
                lambda: _true(self.complete_while_typing) and not _true(
                    self.enable_history_search) and not self.complete_style ==
                CompleteStyle.READLINE_LIKE),
            validate_while_typing=dyncond('validate_while_typing'),
            enable_history_search=dyncond('enable_history_search'),
            validator=DynamicValidator(lambda: self.validator),
            completer=ThreadedCompleter(
                completer=DynamicCompleter(lambda: self.completer),
                in_thread=dyncond('complete_in_thread'),
            ),
            history=DynamicHistory(lambda: self.history),
            auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest),
            accept_handler=accept,
            get_tempfile_suffix=lambda: self.tempfile_suffix)

        search_buffer = Buffer(name=SEARCH_BUFFER)

        # Create processors list.
        input_processor = merge_processors([
            ConditionalProcessor(
                # 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.)
                HighlightSearchProcessor(preview_search=True),
                has_focus(search_buffer)),
            HighlightSelectionProcessor(),
            ConditionalProcessor(AppendAutoSuggestion(),
                                 has_focus(default_buffer) & ~is_done),
            ConditionalProcessor(PasswordProcessor(), dyncond('is_password')),
            DisplayMultipleCursors(),

            # Users can insert processors here.
            DynamicProcessor(lambda: self.extra_input_processor),

            # For single line mode, show the prompt before the input.
            ConditionalProcessor(
                merge_processors([
                    BeforeInput(get_prompt_text_2),
                    ShowArg(),
                ]), ~dyncond('multiline'))
        ])

        # Create bottom toolbars.
        bottom_toolbar = ConditionalContainer(
            Window(FormattedTextControl(lambda: self.bottom_toolbar,
                                        style='class:bottom-toolbar.text'),
                   style='class:bottom-toolbar',
                   dont_extend_height=True,
                   height=Dimension(min=1)),
            filter=~is_done & renderer_height_is_known
            & Condition(lambda: self.bottom_toolbar is not None))

        search_toolbar = SearchToolbar(
            search_buffer,
            get_search_state=lambda: default_buffer_control.get_search_state())
        search_buffer_control = BufferControl(buffer=search_buffer,
                                              input_processor=merge_processors(
                                                  [
                                                      ReverseSearchProcessor(),
                                                      ShowArg(),
                                                  ]))

        system_toolbar = SystemToolbar()

        def get_search_buffer_control():
            " Return the UIControl to be focused when searching start. "
            if _true(self.multiline):
                return search_toolbar.control
            else:
                return search_buffer_control

        default_buffer_control = BufferControl(
            buffer=default_buffer,
            get_search_buffer_control=get_search_buffer_control,
            input_processor=input_processor,
            lexer=DynamicLexer(lambda: self.lexer),
            preview_search=True)

        default_buffer_window = Window(
            default_buffer_control,
            height=self._get_default_buffer_control_height,
            left_margins=[
                # In multiline mode, use the window margin to display
                # the prompt and continuation fragments.
                ConditionalMargin(
                    PromptMargin(get_prompt_text_2, self._get_continuation),
                    filter=dyncond('multiline'),
                )
            ],
            wrap_lines=dyncond('wrap_lines'))

        @Condition
        def multi_column_complete_style():
            return self.complete_style == CompleteStyle.MULTI_COLUMN

        # Build the layout.
        layout = HSplit([
            # The main input, with completion menus floating on top of it.
            FloatContainer(
                HSplit([
                    ConditionalContainer(
                        Window(FormattedTextControl(get_prompt_text_1),
                               dont_extend_height=True),
                        Condition(has_before_fragments)),
                    ConditionalContainer(
                        default_buffer_window,
                        Condition(lambda: get_app().layout.current_control !=
                                  search_buffer_control),
                    ),
                    ConditionalContainer(
                        Window(search_buffer_control),
                        Condition(lambda: get_app().layout.current_control ==
                                  search_buffer_control),
                    ),
                ]),
                [
                    # Completion menus.
                    Float(xcursor=True,
                          ycursor=True,
                          content=CompletionsMenu(
                              max_height=16,
                              scroll_offset=1,
                              extra_filter=has_focus(default_buffer)
                              & ~multi_column_complete_style)),
                    Float(xcursor=True,
                          ycursor=True,
                          content=MultiColumnCompletionsMenu(
                              show_meta=True,
                              extra_filter=has_focus(default_buffer)
                              & multi_column_complete_style)),
                    # The right prompt.
                    Float(right=0,
                          top=0,
                          hide_when_covering_content=True,
                          content=_RPrompt(lambda: self.rprompt)),
                ]),
            ConditionalContainer(ValidationToolbar(), filter=~is_done),
            ConditionalContainer(system_toolbar,
                                 dyncond('enable_system_prompt') & ~is_done),

            # In multiline mode, we use two toolbars for 'arg' and 'search'.
            ConditionalContainer(
                Window(FormattedTextControl(self._get_arg_text), height=1),
                dyncond('multiline') & has_arg),
            ConditionalContainer(search_toolbar,
                                 dyncond('multiline') & ~is_done),
            bottom_toolbar,
        ])

        # Default key bindings.
        auto_suggest_bindings = load_auto_suggest_bindings()
        open_in_editor_bindings = load_open_in_editor_bindings()
        prompt_bindings = self._create_prompt_bindings()

        # Create application
        application = Application(
            layout=Layout(layout, default_buffer_window),
            style=DynamicStyle(lambda: self.style),
            include_default_pygments_style=dyncond(
                'include_default_pygments_style'),
            clipboard=DynamicClipboard(lambda: self.clipboard),
            key_bindings=merge_key_bindings([
                merge_key_bindings([
                    auto_suggest_bindings,
                    ConditionalKeyBindings(
                        open_in_editor_bindings,
                        dyncond('enable_open_in_editor')
                        & has_focus(DEFAULT_BUFFER)), prompt_bindings
                ]),
                ConditionalKeyBindings(
                    system_toolbar.get_global_key_bindings(),
                    dyncond('enable_system_prompt')),
                DynamicKeyBindings(lambda: self.extra_key_bindings),
            ]),
            mouse_support=dyncond('mouse_support'),
            editing_mode=editing_mode,
            erase_when_done=erase_when_done,
            reverse_vi_search_direction=True,

            # I/O.
            input=self.input,
            output=self.output)

        # During render time, make sure that we focus the right search control
        # (if we are searching). - This could be useful if people make the
        # 'multiline' property dynamic.
        '''
        def on_render(app):
            multiline = _true(self.multiline)
            current_control = app.layout.current_control

            if multiline:
                if current_control == search_buffer_control:
                    app.layout.current_control = search_toolbar.control
                    app.invalidate()
            else:
                if current_control == search_toolbar.control:
                    app.layout.current_control = search_buffer_control
                    app.invalidate()

        app.on_render += on_render
        '''

        return application, default_buffer, default_buffer_control