Example #1
0
def main():
    layout = Layout(left_margin=LeftMarginWithLineNumbers(),
                    before_input=DefaultPrompt(text='Before input >> '),
                    after_input=Prompt(' << after input'),
                    top_toolbars=[
                        TextToolbar('This is a top toolbar',
                                    token=Token.TopToolbar1),
                        TextToolbar('This is another top toolbar',
                                    token=Token.TopToolbar2),
                    ],
                    bottom_toolbars=[
                        ArgToolbar(),
                        SearchToolbar(),
                        CompletionsToolbar(),
                        TextToolbar('This is a bottom toolbar',
                                    token=Token.BottomToolbar1),
                        TextToolbar('This is another bottom toolbar',
                                    token=Token.BottomToolbar2),
                    ],
                    show_tildes=True,
                    menus=[CompletionsMenu()])

    cli = CommandLineInterface(layout=layout,
                               style=TestStyle,
                               line=Line(is_multiline=True,
                                         completer=TestCompleter()))

    code_obj = cli.read_input(initial_value=lipsum)
    print('You said: ' + code_obj.text)
Example #2
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=[
                    ConditionalProcessor(
                        processor=HighlightSearchProcessor(
                            preview_search=True),
                        filter=HasFocus(SEARCH_BUFFER),
                    ),
                    HighlightSelectionProcessor(),
                    DisplayMultipleCursors(DEFAULT_BUFFER),
                    # 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=AppendAutoSuggestion(),
                                         filter=~IsDone())
                ] + 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.
            get_height=(lambda cli:
                        (None if cli.is_done or python_input.
                         show_exit_confirmation else input_buffer_height)),
            wrap_lines=Condition(lambda cli: python_input.wrap_lines),
        )

    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),
                              hide_when_covering_content=True),
                        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),
        ])
    ])
def create_layout(python_input, history_mapping):
    """
    Create and return a `Container` instance for the history
    application.
    """
    processors = [
        HighlightSearchProcessor(preview_search=True),
        HighlightSelectionProcessor()
    ]

    help_window = create_popup_window(
        title='History Help',
        body=Window(content=BufferControl(buffer_name=HELP_BUFFER,
                                          default_char=Char(token=Token),
                                          lexer=PygmentsLexer(RstLexer),
                                          input_processors=processors),
                    right_margins=[ScrollbarMargin()],
                    scroll_offsets=ScrollOffsets(top=2, bottom=2)))

    return HSplit([
        #  Top title bar.
        TokenListToolbar(get_tokens=_get_top_toolbar_tokens,
                         align_center=True,
                         default_char=Char(' ', Token.Toolbar.Status)),
        FloatContainer(
            content=VSplit([
                # Left side: history.
                Window(content=BufferControl(buffer_name=HISTORY_BUFFER,
                                             lexer=PygmentsLexer(PythonLexer),
                                             input_processors=processors),
                       wrap_lines=False,
                       left_margins=[HistoryMargin(history_mapping)],
                       scroll_offsets=ScrollOffsets(top=2, bottom=2)),
                # Separator.
                Window(width=D.exact(1),
                       content=FillControl(BORDER.LIGHT_VERTICAL,
                                           token=Token.Separator)),
                # Right side: result.
                Window(
                    content=BufferControl(buffer_name=DEFAULT_BUFFER,
                                          input_processors=processors +
                                          [GrayExistingText(history_mapping)],
                                          lexer=PygmentsLexer(PythonLexer)),
                    wrap_lines=False,
                    left_margins=[ResultMargin(history_mapping)],
                    scroll_offsets=ScrollOffsets(top=2, bottom=2)),
            ]),
            floats=[
                # Help text as a float.
                Float(
                    width=60,
                    top=3,
                    bottom=2,
                    content=ConditionalContainer(
                        # (We use InFocusStack, because it's possible to search
                        # through the help text as well, and at that point the search
                        # buffer has the focus.)
                        content=help_window,
                        filter=InFocusStack(HELP_BUFFER))),
            ]),
        # Bottom toolbars.
        ArgToolbar(),
        SearchToolbar(),
        TokenListToolbar(get_tokens=partial(_get_bottom_toolbar_tokens,
                                            python_input=python_input),
                         default_char=Char(' ', Token.Toolbar.Status)),
    ])
Example #4
0
def create_layout(buffers,
                  settings,
                  key_bindings_manager,
                  python_prompt_control=None,
                  lexer=PythonLexer,
                  extra_sidebars=None,
                  extra_buffer_processors=None):
    D = LayoutDimension
    show_all_buffers = Condition(lambda cli: settings.show_all_buffers)
    extra_sidebars = extra_sidebars or []
    extra_buffer_processors = extra_buffer_processors or []

    def create_buffer_window(buffer_name):
        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[buffer_name]

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

        return Window(
            BufferControl(
                buffer_name=buffer_name,
                lexer=lexer,
                show_line_numbers=ShowLineNumbersFilter(settings, buffer_name),
                input_processors=[BracketsMismatchProcessor()] +
                extra_buffer_processors,
                menu_position=menu_position,
            ),
            # As long as we're editing, prefer a minimal height of 8.
            get_height=(lambda cli: (None if cli.is_done else D(min=6))),

            # When done, show only if this was focussed.
            filter=(~IsDone() & show_all_buffers)
            | PythonBufferFocussed(buffer_name, settings))

    def create_buffer_window_separator(buffer_name):
        return Window(width=D.exact(1),
                      content=FillControl('\u2502', token=Token.Separator),
                      filter=~IsDone() & show_all_buffers)

    buffer_windows = []
    for b in sorted(buffers):
        if b.startswith('python-'):
            buffer_windows.append(create_buffer_window_separator(b))
            buffer_windows.append(create_buffer_window(b))

    return HSplit([
        VSplit([
            HSplit([
                TabsToolbar(settings),
                FloatContainer(content=HSplit([
                    VSplit([
                        Window(
                            python_prompt_control,
                            dont_extend_width=True,
                        ),
                        VSplit(buffer_windows),
                    ]),
                ]),
                               floats=[
                                   Float(xcursor=True,
                                         ycursor=True,
                                         content=CompletionsMenu(
                                             max_height=12,
                                             extra_filter=ShowCompletionsMenu(
                                                 settings))),
                                   Float(xcursor=True,
                                         ycursor=True,
                                         content=SignatureToolbar(settings))
                               ]),
                ArgToolbar(),
                SearchToolbar(),
                SystemToolbar(),
                ValidationToolbar(),
                CompletionsToolbar(
                    extra_filter=ShowCompletionsToolbar(settings)),

                # Docstring region.
                Window(height=D.exact(1),
                       content=FillControl('\u2500', token=Token.Separator),
                       filter=HasSignature(settings) & ShowDocstring(settings)
                       & ~IsDone()),
                Window(
                    BufferControl(
                        buffer_name='docstring',
                        default_token=Token.Docstring,
                        #lexer=PythonLexer,
                    ),
                    filter=HasSignature(settings) & ShowDocstring(settings)
                    & ~IsDone(),
                    height=D(max=12),
                ),
            ]),
        ] + extra_sidebars + [
            PythonSidebar(settings, key_bindings_manager),
        ]),
        VSplit([
            PythonToolbar(key_bindings_manager, settings),
            ShowSidebarButtonInfo(),
        ])
    ])
Example #5
0
def main():
    manager = KeyBindingManager(enable_system_bindings=Always())

    D = LayoutDimension
    layout = HSplit([
        VSplit([
            Window(width=D(min=15, max=30, preferred=30),
                   content=FillControl('a', token=Token.A)),
            Window(width=D.exact(1),
                   content=FillControl('|', token=Token.Line)),
            Window(content=TokenListControl.static([(Token.HelloWorld,
                                                     lipsum)])),
            Window(width=D.exact(1),
                   content=FillControl('|', token=Token.Line)),
            Window(content=BufferControl(
                lexer=PygmentsLexer(PythonLexer),
                margin=NumberredMargin(),
                input_processors=[
                    DefaultPrompt.from_message('python> '),
                    AfterInput.static(' <python', token=Token.AfterInput),
                ]), ),
            Window(width=D.exact(1),
                   content=FillControl('|', token=Token.Line)),
            HSplit([
                Window(width=D(max=40),
                       height=D.exact(4),
                       content=FillControl('b', token=Token.B)),
                Window(width=D(max=40),
                       content=FillControl('f', token=Token.F)),
                Window(width=D.exact(30),
                       height=D.exact(2),
                       content=FillControl('c', token=Token.C)),
            ]),
            #CompletionsMenu(),
        ]),
        Window(height=D.exact(1), content=FillControl('-', token=Token.Line)),
        Window(height=D.exact(3), content=FillControl('d', token=Token.D)),
        SystemToolbar(),
        ArgToolbar(),
        CompletionsToolbar(),
        SearchToolbar(),
    ])

    layout = FloatContainer(content=layout,
                            floats=[
                                Float(xcursor=True,
                                      ycursor=True,
                                      content=VSplit([
                                          Window(width=D.exact(5),
                                                 content=FillControl(
                                                     'f', token=Token.F)),
                                          CompletionsMenu(),
                                      ])),
                            ])

    eventloop = create_eventloop()
    application = Application(layout=layout,
                              style=TestStyle,
                              key_bindings_registry=manager.registry,
                              buffer=Buffer(is_multiline=Always(),
                                            completer=TestCompleter()))

    cli = CommandLineInterface(application=application, eventloop=eventloop)

    cli.run()
    eventloop.close()
Example #6
0
    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)
Example #7
0
def create_layout(settings, key_bindings_manager,
                  python_prompt_control=None, lexer=PythonLexer, extra_sidebars=None,
                  extra_buffer_processors=None):
    D = LayoutDimension
    extra_sidebars = extra_sidebars or []
    extra_buffer_processors = extra_buffer_processors or []

    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']

            if b.complete_state is None and settings.signatures:
                row, col = settings.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,
                show_line_numbers=ShowLineNumbersFilter(settings, 'default'),
                input_processors=[
                                  # Show matching parentheses, but only while editing.
                                  ConditionalProcessor(
                                      processor=HighlightMatchingBracketProcessor(chars='[](){}'),
                                      filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()),
                                  HighlightSearchProcessor(preview_search=Always()),
                                  HighlightSelectionProcessor()] + extra_buffer_processors,
                menu_position=menu_position,

                # Make sure that we always see the result of an reverse-i-search:
                preview_search=Always(),
            ),
            # As long as we're editing, prefer a minimal height of 6.
            get_height=(lambda cli: (None if cli.is_done else D(min=6))),
        )

    return HSplit([
        VSplit([
            HSplit([
                FloatContainer(
                    content=HSplit([
                        VSplit([
                            Window(
                                python_prompt_control,
                                dont_extend_width=True,
                            ),
                            create_python_input_window(),
                        ]),
                    ]),
                    floats=[
                        Float(xcursor=True,
                              ycursor=True,
                              content=CompletionsMenu(
                                  max_height=12,
                                  extra_filter=ShowCompletionsMenu(settings))),
                        Float(xcursor=True,
                              ycursor=True,
                              content=SignatureToolbar(settings))
                    ]),
                ArgToolbar(),
                SearchToolbar(),
                SystemToolbar(),
                ValidationToolbar(),
                CompletionsToolbar(extra_filter=ShowCompletionsToolbar(settings)),

                # Docstring region.
                Window(height=D.exact(1),
                       content=FillControl('\u2500', token=Token.Separator),
                       filter=HasSignature(settings) & ShowDocstring(settings) & ~IsDone()),
                Window(
                    BufferControl(
                        buffer_name='docstring',
                        default_token=Token.Docstring,
                        #lexer=PythonLexer,
                    ),
                    filter=HasSignature(settings) & ShowDocstring(settings) & ~IsDone(),
                    height=D(max=12),
                ),
            ]),
            ] + extra_sidebars + [
            PythonSidebar(settings, key_bindings_manager),
        ]),
        VSplit([
            PythonToolbar(key_bindings_manager, settings),
            ShowSidebarButtonInfo(),
        ])
    ])
Example #8
0
    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)
Example #9
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)
Example #10
0
    def __init__(
            self,
            get_globals=None,
            get_locals=None,
            stdin=None,
            stdout=None,
            vi_mode=False,
            history_filename=None,
            style=PythonStyle,
            autocompletion_style=AutoCompletionStyle.POPUP_MENU,
            always_multiline=False,

            # For internal use.
            _completer=None,
            _validator=None):

        self.get_globals = get_globals or (lambda: {})
        self.get_locals = get_locals or self.get_globals
        self.always_multiline = always_multiline
        self.autocompletion_style = autocompletion_style

        self.completer = _completer or PythonCompleter(self.get_globals,
                                                       self.get_locals)
        validator = _validator or PythonValidator()

        layout = Layout(
            input_processors=[BracketsMismatchProcessor()],
            min_height=7,
            lexer=PythonLexer,
            left_margin=PythonLeftMargin(),
            menus=[CompletionsMenu()]
            if autocompletion_style == AutoCompletionStyle.POPUP_MENU else [],
            bottom_toolbars=[
                ArgToolbar(),
                SignatureToolbar(),
                SearchToolbar(),
                SystemToolbar(),
                ValidationToolbar(),
            ] + ([CompletionsToolbar()] if autocompletion_style
                 == AutoCompletionStyle.HORIZONTAL_MENU else []) + [
                     PythonToolbar(vi_mode=vi_mode),
                 ],
            show_tildes=True)

        if history_filename:
            history = FileHistory(history_filename)
        else:
            history = History()

        if vi_mode:
            key_binding_factories = [vi_bindings, python_bindings]
        else:
            key_binding_factories = [emacs_bindings, python_bindings]

        line = PythonLine(always_multiline=always_multiline,
                          tempfile_suffix='.py',
                          history=history,
                          completer=self.completer,
                          validator=validator)

        #: Incremeting integer counting the current statement.
        self.current_statement_index = 1

        self.get_signatures_thread_running = False

        super(PythonCommandLineInterface,
              self).__init__(layout=layout,
                             style=style,
                             key_binding_factories=key_binding_factories,
                             line=line,
                             create_async_autocompleters=True)

        def on_input_timeout():
            """
            When there is no input activity,
            in another thread, get the signature of the current code.
            """
            # Never run multiple get-signature threads.
            if self.get_signatures_thread_running:
                return
            self.get_signatures_thread_running = True

            document = self.line.document

            def run():
                script = get_jedi_script_from_document(document,
                                                       self.get_locals(),
                                                       self.get_globals())

                # Show signatures in help text.
                if script:
                    try:
                        signatures = script.call_signatures()
                    except ValueError:
                        # e.g. in case of an invalid \\x escape.
                        signatures = []
                    except Exception:
                        # Sometimes we still get an exception (TypeError), because
                        # of probably bugs in jedi. We can silence them.
                        # See: https://github.com/davidhalter/jedi/issues/492
                        signatures = []
                else:
                    signatures = []

                self.get_signatures_thread_running = False

                # Set signatures and redraw if the text didn't change in the
                # meantime. Otherwise request new signatures.
                if self.line.text == document.text:
                    self.line.signatures = signatures
                    self.request_redraw()
                else:
                    on_input_timeout()

            self.run_in_executor(run)

        self.onInputTimeout += on_input_timeout