Exemple #1
0
def create_buffer_window(source_info):
    """
    Window for the main content.
    """
    pager = source_info.pager

    input_processors = [
        ConditionalProcessor(
            processor=_EscapeProcessor(source_info),
            filter=Condition(lambda: not bool(source_info.source.lexer)),
        ),
        TabsProcessor(),
        ConditionalProcessor(
            processor=HighlightSearchProcessor(),
            filter=Condition(lambda: pager.highlight_search),
        ),
        ConditionalProcessor(
            processor=HighlightIncrementalSearchProcessor(),
            filter=Condition(lambda: pager.highlight_search),
        ),
        HighlightSelectionProcessor(),
        HighlightMatchingBracketProcessor(),
    ]

    return Window(
        always_hide_cursor=True,
        content=BufferControl(
            buffer=source_info.buffer,
            lexer=source_info.source.lexer,
            input_processors=input_processors,
            include_default_input_processors=False,
            preview_search=True,
            search_buffer_control=pager.layout.search_toolbar.control))
Exemple #2
0
    def create_python_input_window():
        def menu_position(cli):
            """
            When there is no autocompletion menu to be shown, and we have a signature,
            set the pop-up position at `bracket_start`.
            """
            b = cli.buffers['default']

            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))),
        )
Exemple #3
0
    def get_buffer_window(self):
        " Return the Container object according to which Buffer/Source is visible. "
        source = self.pager.source

        if source not in self._bodies:
            input_processors = [
                ConditionalProcessor(
                    processor=_EscapeProcessor(self.pager),
                    filter=Condition(
                        lambda cli: not bool(self.pager.source.lexer)),
                ),
                TabsProcessor(),
                HighlightSelectionProcessor(),
                ConditionalProcessor(
                    processor=HighlightSearchProcessor(preview_search=True),
                    filter=Condition(lambda cli: self.pager.highlight_search),
                ),
                HighlightMatchingBracketProcessor(),
            ]

            buffer_window = Window(
                always_hide_cursor=True,
                content=BufferControl(
                    buffer_name=self.pager.source_info[source].buffer_name,
                    lexer=source.lexer,
                    input_processors=input_processors))

            self._bodies[source] = buffer_window

        return self._bodies[source]
Exemple #4
0
        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),
            )
def create_default_layout(message='', lexer=None, is_password=False,
                          reserve_space_for_menu=False, get_bottom_toolbar_tokens=None):
    """
    Generate default layout.
    """
    assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens)

    # Create processors list.
    input_processors = [HighlightSearchProcessor(), HighlightSelectionProcessor()]
    if is_password:
        input_processors.extend([PasswordProcessor(), DefaultPrompt(message)])
    else:
        input_processors.append(DefaultPrompt(message))

    # Create bottom toolbar.
    if get_bottom_toolbar_tokens:
        toolbars = [Window(TokenListControl(get_bottom_toolbar_tokens,
                                            default_char=Char(' ', Token.Toolbar)),
                           height=LayoutDimension.exact(1),
                           filter=~IsDone())]
    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()

    # Create and return Layout instance.
    return HSplit([
        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()),
                get_height=get_height,
            ),
            [
                Float(xcursor=True,
                      ycursor=True,
                      content=CompletionsMenu(max_height=16,
                                              extra_filter=HasFocus(DEFAULT_BUFFER)))
            ]
        ),
        ValidationToolbar(),
        SystemToolbar(),
    ] + toolbars)
Exemple #6
0
    def create_python_input_window():
        def menu_position(cli):
            """
            When there is no autocompletion menu to be shown, and we have a signature,
            set the pop-up position at `bracket_start`.
            """
            b = cli.buffers[DEFAULT_BUFFER]

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

        return Window(
            BufferControl(
                buffer_name=DEFAULT_BUFFER,
                lexer=lexer,
                input_processors=[
                    ConditionalProcessor(
                        processor=HighlightSearchProcessor(
                            preview_search=True),
                        filter=HasFocus(SEARCH_BUFFER),
                    ),
                    HighlightSelectionProcessor(),
                    # 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),
        )
Exemple #7
0
    def _create_buffer_control(self, editor_buffer):
        """
        Create a new BufferControl for a given location.
        """
        @Condition
        def preview_search():
            return self.editor.incsearch

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

            # Replace tabs by spaces.
            TabsProcessor(
                tabstop=(lambda: self.editor.tabstop),
                char1=(lambda: '|'
                       if self.editor.display_unprintable_characters else ' '),
                char2=(lambda: _try_char('\u2508', '.',
                                         get_app().output.encoding())
                       if self.editor.display_unprintable_characters else ' '),
            ),

            # Reporting of errors, for Pyflakes.
            ReportingProcessor(editor_buffer),
            HighlightSelectionProcessor(),
            ConditionalProcessor(
                HighlightSearchProcessor(),
                Condition(lambda: self.editor.highlight_search)),
            ConditionalProcessor(
                HighlightIncrementalSearchProcessor(),
                Condition(lambda: self.editor.highlight_search)
                & preview_search),
            HighlightMatchingBracketProcessor(),
            DisplayMultipleCursors(),
        ]

        return BufferControl(lexer=DocumentLexer(editor_buffer),
                             include_default_input_processors=False,
                             input_processors=input_processors,
                             buffer=editor_buffer.buffer,
                             preview_search=preview_search,
                             search_buffer_control=self.search_control,
                             focus_on_click=True)
Exemple #8
0
 def __init__(
     self,
     text="",
     focusable=False,
     wrap_lines=True,
     width=None,
     height=None,
     scrollbar=False,
     dont_extend_height=True,
     dont_extend_width=False,
     read_only=True,
 ):
     self.read_only = read_only
     formatted_text = to_formatted_text(text)
     plain_text = fragment_list_to_text(formatted_text)
     self.buffer = Buffer(
         document=Document(plain_text, 0),
         read_only=Condition(lambda: self.read_only),
     )
     self.control = FormattedBufferControl(
         buffer=self.buffer,
         formatted_text=formatted_text,
         input_processors=[
             FormatTextProcessor(),
             HighlightSelectionProcessor()
         ],
         include_default_input_processors=False,
         focusable=focusable,
         focus_on_click=focusable,
     )
     self.scrollbar = scrollbar
     right_margins = [
         ConditionalMargin(
             ScrollbarMargin(display_arrows=True),
             filter=Condition(lambda: self.scrollbar),
         ),
     ]
     self.window = Window(
         content=self.control,
         width=width,
         height=height,
         wrap_lines=wrap_lines,
         right_margins=right_margins,
         dont_extend_height=dont_extend_height,
         dont_extend_width=dont_extend_width,
     )
Exemple #9
0
    def _create_buffer_control(self, editor_buffer):
        """
        Create a new BufferControl for a given filename.
        """
        filename = editor_buffer.filename
        buffer_name = editor_buffer.buffer_name

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

        input_processors = [
            # Highlighting of the search.
            ConditionalProcessor(
                HighlightSearchProcessor(preview_search=preview_search),
                Condition(lambda cli: self.editor.highlight_search)),

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

            # Highlight selection.
            HighlightSelectionProcessor(),

            # Highlight matching parentheses.
            HighlightMatchingBracketProcessor(),

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

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

        return BufferControl(show_line_numbers=Condition(
            lambda cli: self.editor.show_line_numbers),
                             lexer=DocumentLexer(editor_buffer),
                             input_processors=input_processors,
                             buffer_name=buffer_name,
                             preview_search=preview_search)
Exemple #10
0
    def _create_buffer_control(self, editor_buffer):
        """
        Create a new BufferControl for a given location.
        """
        buffer_name = editor_buffer.buffer_name

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

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

            # Replace tabs by spaces.
            TabsProcessor(
                tabstop=Integer.from_callable(lambda: self.editor.tabstop),
                get_char1=(
                    lambda cli: '|'
                    if self.editor.display_unprintable_characters else ' '),
                get_char2=(
                    lambda cli: '\u2508'
                    if self.editor.display_unprintable_characters else ' '),
            ),

            # Reporting of errors, for Pyflakes.
            ReportingProcessor(editor_buffer),
            HighlightSelectionProcessor(),
            ConditionalProcessor(
                HighlightSearchProcessor(preview_search=preview_search),
                Condition(lambda cli: self.editor.highlight_search)),
            HighlightMatchingBracketProcessor(),
        ]

        return BufferControl(lexer=DocumentLexer(editor_buffer),
                             input_processors=input_processors,
                             buffer_name=buffer_name,
                             preview_search=preview_search,
                             focus_on_click=True)
Exemple #11
0
    def __init__(self, shell_ctx):
        self.shell_ctx = shell_ctx

        @Condition
        def show_default(_):
            return self.shell_ctx.is_showing_default

        @Condition
        def show_symbol(_):
            return self.shell_ctx.is_symbols

        @Condition
        def show_progress(_):
            progress = get_progress_message()
            done = get_done()
            return progress != '' and not done

        @Condition
        def has_default_scope(_):
            return self.shell_ctx.default_command == ''

        self.has_default_scope = has_default_scope
        self.show_default = show_default
        self.show_symbol = show_symbol
        self.show_progress = show_progress

        # TODO fix this somehow
        self.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) & self.has_default_scope)
        ]
Exemple #12
0
def preview_element(my_app: "sqlApp"):
    help_text = """
    Press Enter in the input box to page through the table.
    Alternatively, enter a filtering SQL statement and then press Enter
    to page through the results.
    """
    formatter = TabularOutputFormatter()
    input_buffer = Buffer(name="previewbuffer",
                          tempfile_suffix=".sql",
                          multiline=False)

    input_control = BufferControl(buffer=input_buffer,
                                  include_default_input_processors=False,
                                  preview_search=False)
    input_window = Window(input_control, )

    search_buffer = Buffer(name="previewsearchbuffer")
    search_field = SearchToolbar(search_buffer)
    output_field = TextArea(
        style="class:preview-output-field",
        text=help_text,
        height=D(preferred=50),
        search_field=search_field,
        wrap_lines=False,
        focusable=True,
        read_only=True,
        preview_search=True,
        input_processors=[
            ConditionalProcessor(
                processor=HighlightIncrementalSearchProcessor(),
                filter=has_focus("previewsearchbuffer")
                | has_focus(search_field.control),
            ),
            HighlightSelectionProcessor(),
        ])

    def refresh_results(window_height) -> bool:
        sql_conn = my_app.selected_object.conn

        if sql_conn.execution_status == executionStatus.FAIL:
            # Let's display the error message to the user
            output = sql_conn.execution_err
        else:
            crsr = sql_conn.cursor
            if crsr.description:
                cols = [col.name for col in crsr.description]
            else:
                cols = []
            if len(cols):
                sql_conn.status = connStatus.FETCHING
                res = sql_conn.async_fetchmany(size=window_height - 4)
                output = formatter.format_output(res, cols, format_name="psql")
                output = "\n".join(output)
            else:
                sql_conn.status = connStatus.IDLE
                output = "No rows returned\n"

        # Add text to output buffer.
        output_field.buffer.set_document(
            Document(text=output, cursor_position=0), True)

        return True

    def accept(buff: Buffer) -> bool:
        obj = my_app.selected_object
        sql_conn = obj.conn
        catalog = None
        schema = None
        # TODO: Verify connected
        if obj.parent is not None:
            if type(obj.parent).__name__ == "myDBSchema":
                schema = obj.parent.name
            elif type(obj.parent).__name__ == "myDBCatalog":
                catalog = obj.parent.name
            if obj.parent.parent is not None:
                if type(obj.parent.parent).__name__ == "myDBCatalog":
                    catalog = obj.parent.parent.name

        if catalog:
            catalog = (sql_conn.quotechar + "%s" +
                       sql_conn.quotechar) % catalog
        if schema:
            schema = (sql_conn.quotechar + "%s" + sql_conn.quotechar) % schema
        name = (sql_conn.quotechar + "%s" + sql_conn.quotechar) % obj.name
        identifier = ".".join(list(filter(None, [catalog, schema, obj.name])))
        query = sql_conn.preview_query(table=identifier,
                                       filter_query=buff.text,
                                       limit=my_app.preview_limit_rows)

        func = partial(
            refresh_results,
            window_height=output_field.window.render_info.window_height)
        # If status is IDLE, this is the first time we are executing.
        if sql_conn.query != query or sql_conn.status == connStatus.IDLE:
            # Exit the app to execute the query
            my_app.application.exit(result=["preview", query])
            my_app.application.pre_run_callables.append(func)
        else:
            # No need to exit let's just go and fetch
            func()
        return True  # Keep filter text

    input_buffer.accept_handler = accept

    def cancel_handler() -> None:
        sql_conn = my_app.selected_object.conn
        sql_conn.close_cursor()
        sql_conn.status = connStatus.IDLE
        input_buffer.text = ""
        output_field.buffer.set_document(
            Document(text=help_text, cursor_position=0), True)
        my_app.show_preview = False
        my_app.show_sidebar = True
        my_app.application.layout.focus(input_buffer)
        my_app.application.layout.focus("sidebarbuffer")
        return None

    cancel_button = Button(text="Done", handler=cancel_handler)

    container = HSplit([
        Box(body=VSplit([input_window, cancel_button], padding=1),
            padding=1,
            style="class:preview-input-field"),
        Window(height=1, char="-", style="class:preview-divider-line"),
        output_field,
        search_field,
    ])

    frame = Shadow(body=Frame(title="Table Preview",
                              body=container,
                              style="class:dialog.body",
                              width=D(preferred=180, min=30),
                              modal=True))

    return ConditionalContainer(content=frame,
                                filter=ShowPreview(my_app) & ~is_done)
Exemple #13
0
    def _create_layout(self):
        """
        Generate the main prompt_toolkit layout.
        """
        waits_for_confirmation = WaitsForConfirmation(self.pymux)
        waits_for_prompt = WaitsForPrompt(self.pymux)
        in_command_mode = InCommandMode(self.pymux)

        return FloatContainer(
            content=HSplit([
                # The main window.
                HighlightBorders(
                    self, self.pymux,
                    FloatContainer(Background(),
                                   floats=[
                                       Float(get_width=lambda cli: self.pymux.
                                             get_window_size(cli).columns,
                                             get_height=lambda cli: self.pymux.
                                             get_window_size(cli).rows,
                                             content=TraceBodyWritePosition(
                                                 self.pymux,
                                                 DynamicBody(self.pymux)))
                                   ])),
                # Status bar.
                ConditionalContainer(
                    content=VSplit([
                        # Left.
                        Window(height=D.exact(1),
                               get_width=(lambda cli: D(max=self.pymux.
                                                        status_left_length)),
                               dont_extend_width=True,
                               content=TokenListControl(
                                   self._get_status_left_tokens,
                                   default_char=Char(' ', Token.StatusBar))),
                        # List of windows in the middle.
                        Window(height=D.exact(1),
                               content=TokenListControl(
                                   self._get_status_tokens,
                                   align_right=Condition(
                                       self._status_align_right),
                                   align_center=Condition(
                                       self._status_align_center),
                                   default_char=Char(' ', Token.StatusBar))),
                        # Right.
                        Window(height=D.exact(1),
                               get_width=(lambda cli: D(max=self.pymux.
                                                        status_right_length)),
                               dont_extend_width=True,
                               content=TokenListControl(
                                   self._get_status_right_tokens,
                                   align_right=True,
                                   default_char=Char(' ', Token.StatusBar)))
                    ]),
                    filter=Condition(lambda cli: self.pymux.enable_status),
                )
            ]),
            floats=[
                Float(bottom=1, left=0, content=MessageToolbar(self.pymux)),
                Float(
                    left=0,
                    right=0,
                    bottom=0,
                    content=HSplit([
                        # Wait for confirmation toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=D.exact(1),
                                content=ConfirmationToolbar(self.pymux),
                            ),
                            filter=waits_for_confirmation,
                        ),
                        # ':' prompt toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=D(
                                    min=1
                                ),  # Can be more if the command is multiline.
                                dont_extend_height=True,
                                content=BufferControl(
                                    buffer_name=COMMAND,
                                    default_char=Char(' ', Token.CommandLine),
                                    lexer=SimpleLexer(Token.CommandLine),
                                    preview_search=True,
                                    input_processors=[
                                        AppendAutoSuggestion(),
                                        DefaultPrompt(lambda cli: [(
                                            Token.CommandLine.Prompt, ':')]),
                                        HighlightSelectionProcessor(),
                                    ])),
                            filter=in_command_mode,
                        ),
                        # Other command-prompt commands toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=D.exact(1),
                                content=BufferControl(
                                    buffer_name=PROMPT,
                                    default_char=Char(' ', Token.CommandLine),
                                    lexer=SimpleLexer(Token.CommandLine),
                                    input_processors=[
                                        BeforeInput(
                                            self._before_prompt_command_tokens
                                        ),
                                        AppendAutoSuggestion(),
                                        HighlightSelectionProcessor(),
                                    ])),
                            filter=waits_for_prompt,
                        ),
                    ])),
                Float(xcursor=True,
                      ycursor=True,
                      content=CompletionsMenu(max_height=12)),
            ])
Exemple #14
0
    def __init__(self,
                 command=['/bin/bash'],
                 before_exec_func=None,
                 bell_func=None,
                 style='',
                 width=None,
                 height=None,
                 done_callback=None):

        self.terminal_control = _TerminalControl(
            command=command,
            before_exec_func=before_exec_func,
            bell_func=bell_func,
            done_callback=done_callback)

        self.terminal_window = _Window(terminal_control=self.terminal_control,
                                       content=self.terminal_control,
                                       wrap_lines=False)

        # Key bindigns for copy buffer.
        kb = KeyBindings()

        @kb.add('c-c')
        def _(event):
            self.exit_copy_mode()

        @kb.add('space')
        def _(event):
            " Reset selection. "
            event.current_buffer.start_selection()

        @kb.add('enter', filter=has_selection)
        def _(event):
            " Reset selection. "
            data = event.current_buffer.copy_selection()
            event.app.clipboard.set_data(data)

        self.search_toolbar = SearchToolbar(
            forward_search_prompt='Search down: ',
            backward_search_prompt='Search up: ')

        self.copy_buffer = Buffer(read_only=True)
        self.copy_buffer_control = BufferControl(
            buffer=self.copy_buffer,
            search_buffer_control=self.search_toolbar.control,
            include_default_input_processors=False,
            input_processors=[
                _UseStyledTextProcessor(self),
                HighlightSelectionProcessor(),
                HighlightSearchProcessor(),
                HighlightIncrementalSearchProcessor(),
            ],
            preview_search=
            True,  # XXX: not sure why we need twice preview_search.
            key_bindings=kb)

        self.copy_window = Window(content=self.copy_buffer_control,
                                  wrap_lines=False)

        self.is_copying = False
        self.styled_copy_lines = [
        ]  # List of lists of (style, text) tuples, for each line.

        @Condition
        def is_copying():
            return self.is_copying

        self.container = FloatContainer(
            content=HSplit(
                [
                    # Either show terminal window or copy buffer.
                    VSplit([  # XXX: this nested VSplit should not have been necessary,
                        # but the ConditionalContainer which width can become
                        # zero will collapse the other elements.
                        ConditionalContainer(self.terminal_window,
                                             filter=~is_copying),
                        ConditionalContainer(self.copy_window,
                                             filter=is_copying),
                    ]),
                    ConditionalContainer(self.search_toolbar,
                                         filter=is_copying),
                ],
                style=style,
                width=width,
                height=height),
            floats=[
                Float(top=0,
                      right=0,
                      height=1,
                      content=ConditionalContainer(Window(
                          content=FormattedTextControl(
                              text=self._copy_position_formatted_text),
                          style='class:copy-mode-cursor-position'),
                                                   filter=is_copying))
            ])
Exemple #15
0
    def __init__(self,
                 text='',
                 multiline=True,
                 password=False,
                 lexer=None,
                 completer=None,
                 accept_handler=None,
                 focusable=True,
                 wrap_lines=True,
                 read_only=False,
                 width=None,
                 height=None,
                 dont_extend_height=False,
                 dont_extend_width=False,
                 line_numbers=False,
                 scrollbar=False,
                 style='',
                 input_processor=None,
                 search_field=None,
                 preview_search=True,
                 prompt=''):
        assert isinstance(text, six.text_type)
        assert search_field is None or isinstance(search_field, SearchToolbar)

        if search_field is None:
            search_control = None
        elif isinstance(search_field, SearchToolbar):
            search_control = search_field.control

        self.buffer = Buffer(
            document=Document(text, 0),
            multiline=multiline,
            read_only=read_only,
            completer=completer,
            complete_while_typing=True,
            accept_handler=lambda buff: accept_handler and accept_handler())

        self.control = BufferControl(
            buffer=self.buffer,
            lexer=lexer,
            input_processor=merge_processors([
                ConditionalProcessor(processor=PasswordProcessor(),
                                     filter=to_filter(password)),
                HighlightSearchProcessor(preview_search=preview_search),
                HighlightSelectionProcessor(),
                DisplayMultipleCursors(),
                BeforeInput(prompt, style='class:text-area.prompt'),
            ]),
            search_buffer_control=search_control,
            preview_search=preview_search,
            focusable=focusable)

        if multiline:
            if scrollbar:
                right_margins = [ScrollbarMargin(display_arrows=True)]
            else:
                right_margins = []
            if line_numbers:
                left_margins = [NumberedMargin()]
            else:
                left_margins = []
        else:
            wrap_lines = False  # Never wrap for single line input.
            height = D.exact(1)
            left_margins = []
            right_margins = []

        style = 'class:text-area ' + style

        self.window = Window(height=height,
                             width=width,
                             dont_extend_height=dont_extend_height,
                             dont_extend_width=dont_extend_width,
                             content=self.control,
                             style=style,
                             wrap_lines=wrap_lines,
                             left_margins=left_margins,
                             right_margins=right_margins)
Exemple #16
0
    def _create_layout(self):
        """
        Generate the main prompt_toolkit layout.
        """
        waits_for_confirmation = WaitsForConfirmation(self.pymux)

        return FloatContainer(
            content=HSplit([
                # The main window.
                FloatContainer(
                    Background(),
                    floats=[
                        Float(
                            width=lambda: self.pymux.get_window_size().columns,
                            height=lambda: self.pymux.get_window_size().rows,
                            content=DynamicBody(self.pymux))
                    ]),
                # Status bar.
                ConditionalContainer(
                    content=VSplit(
                        [
                            # Left.
                            Window(height=1,
                                   width=(lambda: D(max=self.pymux.
                                                    status_left_length)),
                                   dont_extend_width=True,
                                   content=FormattedTextControl(
                                       self._get_status_left_tokens)),
                            # List of windows in the middle.
                            Window(height=1,
                                   char=' ',
                                   align=self._get_align,
                                   content=FormattedTextControl(
                                       self._get_status_tokens)),
                            # Right.
                            Window(height=1,
                                   width=(lambda: D(max=self.pymux.
                                                    status_right_length)),
                                   dont_extend_width=True,
                                   align=WindowAlign.RIGHT,
                                   content=FormattedTextControl(
                                       self._get_status_right_tokens))
                        ],
                        z_index=Z_INDEX.STATUS_BAR,
                        style='class:statusbar'),
                    filter=Condition(lambda: self.pymux.enable_status),
                )
            ]),
            floats=[
                Float(bottom=1,
                      left=0,
                      z_index=Z_INDEX.MESSAGE_TOOLBAR,
                      content=MessageToolbar(self.client_state)),
                Float(
                    left=0,
                    right=0,
                    bottom=0,
                    content=HSplit([
                        # Wait for confirmation toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=1,
                                content=ConfirmationToolbar(
                                    self.pymux, self.client_state),
                                z_index=Z_INDEX.COMMAND_LINE,
                            ),
                            filter=waits_for_confirmation,
                        ),
                        # ':' prompt toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=D(
                                    min=1
                                ),  # Can be more if the command is multiline.
                                style='class:commandline',
                                dont_extend_height=True,
                                content=BufferControl(
                                    buffer=self.client_state.command_buffer,
                                    preview_search=True,
                                    input_processors=[
                                        AppendAutoSuggestion(),
                                        BeforeInput(
                                            ':',
                                            style='class:commandline-prompt'),
                                        ShowArg(),
                                        HighlightSelectionProcessor(),
                                    ]),
                                z_index=Z_INDEX.COMMAND_LINE,
                            ),
                            filter=has_focus(self.client_state.command_buffer),
                        ),
                        # Other command-prompt commands toolbar.
                        ConditionalContainer(
                            content=Window(
                                height=1,
                                style='class:commandline',
                                content=BufferControl(
                                    buffer=self.client_state.prompt_buffer,
                                    input_processors=[
                                        BeforeInput(
                                            self._before_prompt_command_tokens
                                        ),
                                        AppendAutoSuggestion(),
                                        HighlightSelectionProcessor(),
                                    ]),
                                z_index=Z_INDEX.COMMAND_LINE,
                            ),
                            filter=has_focus(self.client_state.prompt_buffer),
                        ),
                    ])),
                # Keys pop-up.
                Float(
                    content=ConditionalContainer(
                        content=self.popup_dialog,
                        filter=Condition(
                            lambda: self.client_state.display_popup),
                    ),
                    left=3,
                    right=3,
                    top=5,
                    bottom=5,
                    z_index=Z_INDEX.POPUP,
                ),
                Float(xcursor=True,
                      ycursor=True,
                      content=CompletionsMenu(max_height=12)),
            ])
    def __init__(
        self,
        entries,
        preview_callback=None,
        input_callback=None,
        input_completions=None,
    ):
        if not entries or len(entries) == 0:
            raise RuntimeError("Entries cannot be empty.")
        self.entries = entries
        self.input_callback = input_callback
        self.preview_callback = preview_callback

        self.ansi_escape_8bit = re.compile(
            r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])"
        )
        self.current_lineno = 1
        self.max_entry_width = min(
            max(
                map(
                    lambda x: len(x) + 1, self.ansi_escape_8bit.sub("", entries).split("\n")
                )
            ),
            48,
        )

        entries_text = ANSI(self.entries)
        entries_formatted_text = to_formatted_text(entries_text)
        entries_plain_text = fragment_list_to_text(entries_formatted_text)
        self.entries_control = FormattedBufferControl(
            buffer=Buffer(
                document=Document(entries_plain_text, 0),
                name="entries",
                on_cursor_position_changed=self.update_entries,
                read_only=True,
            ),
            focusable=True,
            formatted_text=entries_formatted_text,
            include_default_input_processors=False,
            input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()],
        )

        if self.preview_callback:
            self.preview_text = ANSI(self.preview_callback(self.current_lineno))
            formatted_text = to_formatted_text(self.preview_text)
            plain_text = fragment_list_to_text(formatted_text)
            self.preview_control = FormattedBufferControl(
                buffer=Buffer(
                    document=Document(plain_text, 0),
                    name="preview",
                    on_cursor_position_changed=self.update_preview,
                    read_only=True,
                ),
                focusable=True,
                formatted_text=formatted_text,
                include_default_input_processors=False,
                input_processors=[FormatTextProcessor(), HighlightSelectionProcessor()],
            )
            # Alternative (not scrollable):
            # self.preview_control = FormattedTextControl(
            #     focusable=True,
            #     show_cursor=True,
            #     text=ANSI(self.preview_callback(self.current_lineno)),
            # )
            entries_container = VSplit(
                [
                    Window(
                        content=self.entries_control,
                        width=self.max_entry_width,
                        wrap_lines=True,
                    ),
                    Window(width=3, char=" | "),
                    Window(content=self.preview_control, wrap_lines=True),
                ]
            )
        else:
            entries_container = Window(
                content=self.entries_control,
                width=self.max_entry_width,
                wrap_lines=True,
            )
        if self.input_callback:
            self.search_field = SearchToolbar()
            self.input_field = TextArea(
                accept_handler=self.input_accept,
                completer=FuzzyWordCompleter(list(input_completions)),
                complete_while_typing=True,
                height=1,
                multiline=False,
                prompt="> ",
                search_field=self.search_field,
                wrap_lines=False,
            )
            self.root_container = FloatContainer(
                content=HSplit(
                    [entries_container, Window(height=1, char="-"), self.input_field,]
                ),
                floats=[
                    Float(
                        content=CompletionsMenu(max_height=16, scroll_offset=1),
                        xcursor=True,
                        ycursor=True,
                    )
                ],
            )

        else:
            self.root_container = entries_container
        self.layout = Layout(self.root_container)

        self.app = Application(full_screen=True, key_bindings=kb, layout=self.layout)
Exemple #18
0
    def main(self, data):
        fr = FileReader(data)
        bc = BufferCache()

        all_input_processors = [
            ConditionalProcessor(HighlightSearchProcessor(), ~is_searching),
            HighlightIncrementalSearchProcessor(),
            HighlightSelectionProcessor(),
            DisplayMultipleCursors(),
        ]

        search_toolbar = SearchToolbar(vi_mode=True)

        lst_window = Window(
            BufferControl(
                Buffer(
                    name="file_list",
                    document=Document(fr.get_list_text(), cursor_position=0),
                    read_only=True,
                ),
                search_buffer_control=search_toolbar.control,
                preview_search=True,
                include_default_input_processors=False,
                input_processors=all_input_processors,
            ),
            cursorline=True,
        )

        txt_window = Window(
            BufferControl(
                bc.current_buffer,
                search_buffer_control=search_toolbar.control,
                preview_search=True,
                include_default_input_processors=False,
                input_processors=all_input_processors,
            ),
            wrap_lines=False,
        )

        toolbar = FormattedTextToolbar(text="hello world!",
                                       style="class:buf_name")

        body = HSplit([lst_window])
        # Key bind
        kb = KeyBindings()
        kb.add(Keys.ControlD)(scroll_half_page_down)
        kb.add(Keys.ControlU)(scroll_half_page_up)

        @kb.add(Keys.ControlQ)
        def _(event):
            event.app.exit()

        @kb.add(Keys.Enter, filter=has_focus("file_list"))
        def _(event):
            idx = event.current_buffer.document.cursor_position_row
            path = str(fr.get_path(idx))
            origin_data = str(fr.get_relative_path(idx))
            origin_data2 = origin_data.split("|")[0]
            number = origin_data2.split(":")[-1]
            command = "vim " + "+" + number + " " + path
            res = subprocess.call(command.split())

        @kb.add("k")
        def _(event):
            event.current_buffer.cursor_up()
            idx = event.current_buffer.document.cursor_position_row
            path = str(fr.get_relative_path(idx))
            try:
                set_buffer_txt_window(bc.get_or_append_buffer(path, "AAAAA"))
                set_text_toolbar(bc.current_buffer_name)
            except:
                pass

        @kb.add("j")
        def _(event):
            event.current_buffer.cursor_down()
            idx = event.current_buffer.document.cursor_position_row
            path = str(fr.get_relative_path(idx))
            set_buffer_txt_window(bc.get_or_append_buffer(path, "AAAAA"))
            set_text_toolbar(bc.current_buffer_name)

        def set_buffer_txt_window(buf):
            txt_window.content.buffer = buf

        def set_text_toolbar(text):
            toolbar.content.text = text

        @Condition
        def search_buffer_is_empty():
            return get_app().current_buffer.text == ""

        style = Style([
            ("buf_name", "fg:#dddddd bg:#8a2be2"),
            ("incsearch", "fg:ansibrightyellow reverse"),
        ])

        app = Application(layout=Layout(body),
                          key_bindings=kb,
                          full_screen=True,
                          style=style)

        app.run()
def create_default_layout(message='',
                          lexer=None,
                          is_password=False,
                          reserve_space_for_menu=False,
                          get_prompt_tokens=None,
                          get_bottom_toolbar_tokens=None,
                          extra_input_processors=None):
    """
    Generate default layout.
    Returns a ``Layout`` instance.

    :param message: Text to be used as prompt.
    :param lexer: Pygments lexer to be used for the highlighting.
    :param is_password: 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.
    """
    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)

    # Create processors list.
    # (DefaultPrompt should always be at the end.)
    input_processors = [
        HighlightSearchProcessor(preview_search=Always()),
        HighlightSelectionProcessor()
    ]

    if is_password:
        input_processors.append(PasswordProcessor())

    if extra_input_processors:
        input_processors.extend(extra_input_processors)

    if message:
        input_processors.append(DefaultPrompt.from_message(message))
    else:
        input_processors.append(DefaultPrompt(get_prompt_tokens))

    # Create bottom toolbar.
    if get_bottom_toolbar_tokens:
        toolbars = [
            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()

    # Create and return Layout instance.
    return HSplit([
        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()),
                get_height=get_height,
            ),
            [
                Float(xcursor=True,
                      ycursor=True,
                      content=CompletionsMenu(max_height=16,
                                              extra_filter=HasFocus(
                                                  DEFAULT_BUFFER)))
            ]),
        ValidationToolbar(),
        SystemToolbar(),
    ] + toolbars)
Exemple #20
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
Exemple #21
0
    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)
Exemple #22
0
    """ if there is a scope on the input """
    def __call__(self, *a, **kw):
        return DEFAULT_COMMAND == ""


# TODO fix this somehow
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) & HasDefaultScope()),
]


# pylint: disable=too-few-public-methods
class ShowDefault(Filter):
    """ toggle on and off seeing the default """
    def __init__(self, shell_ctx):
        self.shell_ctx = shell_ctx

    def __call__(self, *a, **kw):
        return self.shell_ctx.is_showing_default

Exemple #23
0
def _create_container_for_process(pymux, arrangement_pane, zoom=False):
    """
    Create a `Container` with a titlebar for a process.
    """
    assert isinstance(arrangement_pane, arrangement.Pane)
    process = arrangement_pane.process

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def set_focus(cli):
        pymux.arrangement.get_active_window(cli).active_pane = arrangement_pane
        pymux.invalidate()

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

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

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

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(BufferControl(
            buffer_name='source_code',
            lexer=PygmentsLexer(PythonLexer),
            input_processors=[
                HighlightSearchProcessor(preview_search=True),
                HighlightSelectionProcessor(),
            ],
        ),
                                          left_margins=[
                                              SourceCodeMargin(self),
                                              NumberredMargin(),
                                          ],
                                          right_margins=[ScrollbarMargin()],
                                          scroll_offsets=ScrollOffsets(
                                              top=2, bottom=2),
                                          height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
            lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action=self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(processor=CompletionHint(),
                                     filter=~IsDone())
            ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0,
                                          bottom=0,
                                          content=BreakPointInfoToolbar(
                                              weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl(
                                       '\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502',
                                                       token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2,
                                                                bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(PdbShortcutsToolbar(weakref.ref(self)),
                                     show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(
            self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self,
                                     self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())
Exemple #25
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)
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)),
    ])
Exemple #27
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)
Exemple #28
0
    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)
Exemple #29
0
    def __init__(self, my_app: "sqlApp"):
        self.my_app = my_app
        help_text = """
        Press Enter in the input box to page through the table.
        Alternatively, enter a filtering SQL statement and then press Enter
        to page through the results.
        """
        self.formatter = TabularOutputFormatter()
        self.completer = PreviewCompleter(
            my_app=self.my_app,
            completer=MssqlCompleter(
                smart_completion=True,
                get_conn=lambda: self.my_app.selected_object.conn))

        history_file = config_location() + 'preview_history'
        ensure_dir_exists(history_file)
        hist = PreviewHistory(my_app=self.my_app,
                              filename=expanduser(history_file))

        self.input_buffer = PreviewBuffer(
            name="previewbuffer",
            tempfile_suffix=".sql",
            history=ThreadedHistory(hist),
            auto_suggest=ThreadedAutoSuggest(
                PreviewSuggestFromHistory(my_app)),
            completer=ThreadedCompleter(self.completer),
            #                history = hist,
            #                auto_suggest = PreviewSuggestFromHistory(my_app),
            #                completer = self.completer,
            complete_while_typing=Condition(
                lambda: self.my_app.selected_object is not None and self.my_app
                .selected_object.conn.connected()),
            multiline=False)

        input_control = BufferControl(
            buffer=self.input_buffer,
            include_default_input_processors=False,
            input_processors=[AppendAutoSuggestion()],
            preview_search=False)

        self.input_window = Window(input_control)

        search_buffer = Buffer(name="previewsearchbuffer")
        self.search_field = SearchToolbar(search_buffer)
        self.output_field = TextArea(
            style="class:preview-output-field",
            text=help_text,
            height=D(preferred=50),
            search_field=self.search_field,
            wrap_lines=False,
            focusable=True,
            read_only=True,
            preview_search=True,
            input_processors=[
                ConditionalProcessor(
                    processor=HighlightIncrementalSearchProcessor(),
                    filter=has_focus("previewsearchbuffer")
                    | has_focus(self.search_field.control),
                ),
                HighlightSelectionProcessor(),
            ])

        def refresh_results(window_height) -> bool:
            """ This method gets called when the app restarts after
                exiting for execution of preview query.  It populates
                the output buffer with results from the fetch/query.
            """
            sql_conn = self.my_app.selected_object.conn
            if sql_conn.execution_status == executionStatus.FAIL:
                # Let's display the error message to the user
                output = sql_conn.execution_err
            else:
                crsr = sql_conn.cursor
                if crsr.description:
                    cols = [col.name for col in crsr.description]
                else:
                    cols = []
                if len(cols):
                    res = sql_conn.fetch_from_cache(size=window_height - 4,
                                                    wait=True)
                    output = self.formatter.format_output(res,
                                                          cols,
                                                          format_name="psql")
                    output = "\n".join(output)
                else:
                    output = "No rows returned\n"

            # Add text to output buffer.
            self.output_field.buffer.set_document(
                Document(text=output, cursor_position=0), True)

            return True

        def accept(buff: Buffer) -> bool:
            """ This method gets called when the user presses enter/return
                in the filter box.  It is interpreted as either 'execute query'
                or 'fetch next page of results' if filter query hasn't changed.
            """
            obj = self.my_app.selected_object
            sql_conn = obj.conn
            identifier = object_to_identifier(obj)
            query = sql_conn.preview_query(
                name=identifier,
                obj_type=obj.otype,
                filter_query=buff.text,
                limit=self.my_app.preview_limit_rows)
            if query is None:
                return True

            func = partial(refresh_results,
                           window_height=self.output_field.window.render_info.
                           window_height)
            if sql_conn.query != query:
                # Exit the app to execute the query
                self.my_app.application.exit(result=["preview", query])
                self.my_app.application.pre_run_callables.append(func)
            else:
                # No need to exit let's just go and fetch
                func()
            return True  # Keep filter text

        def cancel_handler() -> None:
            sql_conn = self.my_app.selected_object.conn
            sql_conn.close_cursor()
            self.input_buffer.text = ""
            self.output_field.buffer.set_document(
                Document(text=help_text, cursor_position=0), True)
            self.my_app.show_preview = False
            self.my_app.show_sidebar = True
            self.my_app.application.layout.focus(self.input_buffer)
            self.my_app.application.layout.focus("sidebarbuffer")
            return None

        self.input_buffer.accept_handler = accept
        self.cancel_button = Button(text="Done", handler=cancel_handler)