Пример #1
0
    def __init__(self, first_game, engine):

        self.completer = CustomCompleter(['start'])
        self.elements = {
            'board':
            Window(FormattedTextControl(
                ANSI(show_board(chess.STARTING_BOARD_FEN))),
                   width=35,
                   height=13),
            'input':
            TextArea(height=1,
                     prompt='>>> ',
                     style='class:input-field',
                     width=80,
                     completer=self.completer),
            'p1':
            Window(FormattedTextControl(ANSI('Games')),
                   width=31,
                   height=13,
                   wrap_lines=True),
            'p2':
            Window(FormattedTextControl(ANSI('Legal Moves')),
                   width=31,
                   height=13,
                   wrap_lines=True),
        }

        self.frames = {}
        self.frames['board'] = Float(Frame(self.elements['board'],
                                           style='bg:#2e2e2e #ffffff'),
                                     top=10)
        self.frames['input'] = Float(Frame(self.elements['input'],
                                           style='bg:#2e2e2e #ffffff'),
                                     top=30)
        self.frames['p1'] = Float(Frame(self.elements['p1'],
                                        style='bg:#1e1e1e #ffffff'),
                                  top=10,
                                  left=10)
        self.frames['p2'] = Float(Frame(self.elements['p2'],
                                        style='bg:#1e1e1e #ffffff'),
                                  top=10,
                                  right=10)

        self.body = FloatContainer(content=Window(FormattedTextControl('')),
                                   floats=[v for k, v in self.frames.items()])
        self.kb = KeyBindings()

        self.app = Application(layout=Layout(
            self.body, focused_element=self.elements['input']),
                               key_bindings=self.kb,
                               full_screen=True)
        self.set_kb()

        self.game = first_game
        self.board = first_game.board()
        self.moves = list(first_game.main_line())
        self.engine = engine

        self.state = 'init'
        self.now = 0
        self.N = len(self.moves)
        self.chain = []
        self.selected = None
        self.quit = False
Пример #2
0
def get_descript(lexer):
    """ command description window """
    return Window(
        content=BufferControl(buffer_name="description", lexer=lexer))
Пример #3
0
def get_empty():
    """ returns an empty window because of syntaxical issues """
    return Window(content=FillControl(' '))
Пример #4
0
def get_vline():
    """ gets a vertical line """
    return Window(
        width=LayoutDimension.exact(1),
        height=LayoutDimension.exact(1),
        content=FillControl('*', token=Token.Line))
Пример #5
0
 def __init__(self) -> None:
     self.window = Window(char=Border.VERTICAL,
                          style='class:line,vertical-line',
                          width=1)
Пример #6
0
    def __init__(self,
                 options: Sequence[Option],
                 default_index: int = 0,
                 header_filter: Callable[[Option], str] = str,
                 match_filter: Callable[[Option], str] = str,
                 custom_filter: Optional[Callable[[str], bool]] = None,
                 search_buffer: Buffer = Buffer(multiline=False),
                 cpu_count: int = os.cpu_count()):

        self.search_buffer = search_buffer
        self.last_query_text = ''  # type: str
        self.search_buffer.on_text_changed += self.update

        self.header_filter = header_filter
        self.match_filter = match_filter
        self.current_index = default_index  # type: Optional[int]
        self.entries_left_offset = 0
        self.cpu_count = cpu_count

        self.options_headers_linecount = []  # type: List[int]
        self._indices_to_lines = []  # type: List[int]

        self.options_headers = []  # type: FormattedText
        self.options_matchers = []  # type: List[str]
        self.indices = []  # type: List[int]
        self._options = []  # type: Sequence[Option]
        self.marks = []  # type: List[int]
        self.max_entry_height = 1  # type: int

        # options are processed here also through the setter
        # ##################################################
        self.set_options(options)
        self.cursor = Point(0, 0)  # type: Point
        # ##################################################

        self.content = FormattedTextControl(
            text=self.get_tokens,
            focusable=False,
            key_bindings=None,
            get_cursor_position=lambda: self.cursor,
        )
        self.content_window = Window(
            content=self.content,
            wrap_lines=False,
            allow_scroll_beyond_bottom=True,
            scroll_offsets=ScrollOffsets(bottom=self.max_entry_height),
            cursorline=False,
            cursorcolumn=False,
            # right_margins=[NumberedMargin()],
            # left_margins=[NumberedMargin()],
            align=WindowAlign.LEFT,
            height=None,
            get_line_prefix=self.get_line_prefix
            # get_line_prefix=lambda line, b: [('bg:red', '  ')]
        )

        self.update()

        super(OptionsList,
              self).__init__(content=self.content_window,
                             filter=(custom_filter if custom_filter is not None
                                     else has_focus(self.search_buffer)))
Пример #7
0
    def __init__(self, config, out_queue, state=TaskState()):
        self.config = config
        tui_config = config['tui']
        self.tui_config = tui_config
        self.out_queue = out_queue

        def commandHandler(buffer):
            #check incoming command
            cmdString = buffer.text
            #executeCommand(cmdString)
            pass

        def commandPrompt(line_number, wrap_count):
            return "command> "

        ########################################################################

        kb = KeyBindings()

        @kb.add('c-d')
        def exit_(event):
            """
            Pressing Esc will exit the user interface.

            Setting a return value means: quit the event loop that drives the user
            interface and return this value from the `CommandLineInterface.run()` call.
            """
            event.app.exit()

        @kb.add('tab')
        def tab_(event):
            focus_next(event)

        @kb.add('s-tab')
        def stab_(event):
            focus_previous(event)

        @kb.add('s-right')
        def next_tab(event):
            state.next_tab()
            event.app.invalidate()

        @kb.add('s-left')
        def next_tab(event):
            state.prev_tab()
            event.app.invalidate()

        orders_kb = KeyBindings()

        @orders_kb.add('f5')
        def _(event):
            #command = ('refresh', something...)
            #self.out_queue.put_nowait(command)
            pass

        ########################################################################

        outputArea = TextArea(
            text="",
            multiline=True,
            wrap_lines=False,
            #lexer=lexer.OutputAreaLexer(),
            #scrollbar=enableScrollbar,
            style='class:output-field',
            read_only=True)

        content_container = Frame(outputArea, title="Output")

        log_container = Frame(
            Window(
                BufferControl(
                    buffer=Buffer(name='logger_buffer', read_only=True),
                    input_processors=[FormatTextHTML()],
                ),
                right_margins=[ScrollbarMargin(display_arrows=True)
                               ],  # low-level scrollbar
            ),
            title='Log',
            height=8,
        )

        command_container = TextArea(text="",
                                     multiline=False,
                                     accept_handler=commandHandler,
                                     get_line_prefix=commandPrompt)

        commandWindowFrame = Frame(
            command_container,
            title=
            "TuiTerminal (Ctrl-D to exit, Tab to switch focus and refresh UI, 'help' for help)",
            height=4)

        root_container = HSplit(
            [content_container, log_container, commandWindowFrame])

        layout = Layout(root_container, focused_element=command_container)

        style = Style.from_dict({
            'output-field': 'bg:#101010',
            'frame.border': 'SteelBlue',
            'frame.label': 'PowderBlue',
        })

        application = Application(
            layout=layout,
            key_bindings=kb,
            style=style,
            full_screen=tui_config.getboolean('full_screen'),
            mouse_support=tui_config.getboolean('mouse_support'),
            #after_render=after_render,
        )

        self.application = application
Пример #8
0
from prompt_toolkit.layout import Layout, HSplit
from prompt_toolkit.key_binding import KeyBindings


# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")

# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)

# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)

# správce rozvržení
hsplit = HSplit([
    window1,
    window2,
    window3])
layout = Layout(hsplit)

# napojení na klávesové zkratky
key_bindings = KeyBindings()


@key_bindings.add('escape')
Пример #9
0
    def game_runner(self, old, proc_args: list, proc_cwd: str, options: dict):

        if options["cmd_args"].not_rich:
            old(proc_args, proc_cwd, options)
            return

        title_text = self.pmc.get_message(
            "start.run.richer.title", options.get("version",
                                                  "unknown_version"),
            options.get("username", "anonymous"), options.get("uuid", "uuid"))

        buffer_window = RollingLinesWindow(400,
                                           lexer=ColoredLogLexer(),
                                           last_line_return=True)
        buffer_window.append(
            self.pmc.get_message("start.run.richer.command_line",
                                 " ".join(proc_args)), "\n")

        container = HSplit([
            VSplit([
                Window(width=2),
                Window(FormattedTextControl(text=title_text)),
            ],
                   height=1,
                   style="class:header"),
            VSplit([Window(width=1), buffer_window,
                    Window(width=1)])
        ])

        keys = KeyBindings()
        double_exit = not options["cmd_args"].single_exit

        @keys.add("c-c")
        def _exit(event: KeyPressEvent):
            nonlocal process
            if not double_exit or process is None:
                event.app.exit()
            else:
                process.kill()

        application = self.build_application(container, keys)
        process = Popen(proc_args,
                        cwd=proc_cwd,
                        stdout=PIPE,
                        stderr=PIPE,
                        bufsize=1,
                        universal_newlines=True)

        async def _run_process():
            nonlocal process
            stdout_reader = ThreadedProcessReader(cast(TextIO, process.stdout))
            stderr_reader = ThreadedProcessReader(cast(TextIO, process.stderr))
            while True:
                code = process.poll()
                if code is None:
                    done, pending = await asyncio.wait(
                        (stdout_reader.poll(), stderr_reader.poll()),
                        return_when=asyncio.FIRST_COMPLETED)
                    for done_task in done:
                        line = done_task.result()
                        if line is not None:
                            buffer_window.append(line)
                    for pending_task in pending:
                        pending_task.cancel()
                else:
                    stdout_reader.wait_until_closed()
                    stderr_reader.wait_until_closed()
                    buffer_window.append(*stdout_reader.poll_all(),
                                         *stderr_reader.poll_all())
                    break
            process = None
            if double_exit:
                buffer_window.append(
                    "",
                    "Minecraft process has terminated, Ctrl+C again to close terminal."
                )

        async def _run():
            _done, _pending = await asyncio.wait(
                (_run_process(), application.run_async()),
                return_when=asyncio.ALL_COMPLETED
                if double_exit else asyncio.FIRST_COMPLETED)
            if process is not None:
                process.kill()
                process.wait(timeout=5)
            if application.is_running:
                application.exit()

        asyncio.get_event_loop().run_until_complete(_run())
Пример #10
0
    'mouse',
    'rabbit',
    'rat',
    'snake',
    'spider',
    'turkey',
    'turtle',
],
                                 ignore_case=True)

# The layout
buff = Buffer(completer=animal_completer, complete_while_typing=True)

body = FloatContainer(content=HSplit([
    Window(FormattedTextControl('Press "q" to quit.'),
           height=1,
           style='reverse'),
    Window(BufferControl(buffer=buff)),
]),
                      floats=[
                          Float(xcursor=True,
                                ycursor=True,
                                content=CompletionsMenu(max_height=16,
                                                        scroll_offset=1))
                      ])

# Key bindings
kb = KeyBindings()


@kb.add('q')
Пример #11
0
def question(message,
             choices: List[Choice],
             default=None,
             qmark='?',
             key_bindings=None,
             **kwargs):
    """
    Builds a `prompt-toolkit` Application that display a list of choices (ChoiceControl) along with
    search features and key bindings

    Paramaters
    ==========
    kwargs: Dict[Any, Any]
        Any additional arguments that a prompt_toolkit.application.Application can take. Passed
        as-is
    """
    if key_bindings is None:
        key_bindings = KeyBindings()

    choices_control = ChoicesControl(choices, default=default)

    def get_prompt_tokens():
        tokens = []

        tokens.append(('class:question-mark', qmark))
        tokens.append(('class:question', ' %s ' % message))
        if choices_control.is_answered:
            tokens.append(('class:answer',
                           ' ' + choices_control.get_selection().display_text))
        else:
            tokens.append(('class:instruction', ' (Use arrow keys)'))
        return tokens

    @Condition
    def has_search_string():
        return choices_control.get_search_string_tokens is not None

    @key_bindings.add(Keys.ControlQ, eager=True)
    def exit_menu(event):
        event.app.exit(exception=KeyboardInterrupt())

    if not key_bindings.get_bindings_for_keys((Keys.ControlC, )):
        key_bindings.add(Keys.ControlC, eager=True)(exit_menu)

    @key_bindings.add(Keys.Down, eager=True)
    def move_cursor_down(_event):  # pylint:disable=unused-variable
        choices_control.select_next_choice()

    @key_bindings.add(Keys.Up, eager=True)
    def move_cursor_up(_event):  # pylint:disable=unused-variable
        choices_control.select_previous_choice()

    @key_bindings.add(Keys.Enter, eager=True)
    def set_answer(event):  # pylint:disable=unused-variable
        choices_control.is_answered = True
        choices_control.reset_search_string()
        event.app.exit(result=choices_control.get_selection().value)

    def search_filter(event):
        choices_control.append_to_search_string(event.key_sequence[0].key)

    for character in string.printable:
        key_bindings.add(character, eager=True)(search_filter)

    @key_bindings.add(Keys.Backspace, eager=True)
    def delete_from_search_filter(_event):  # pylint:disable=unused-variable
        choices_control.remove_last_char_from_search_string()

    layout = Layout(
        HSplit([
            # Question
            Window(
                height=D.exact(1),
                content=FormattedTextControl(get_prompt_tokens),
                always_hide_cursor=True,
            ),
            # Choices
            ConditionalContainer(
                Window(choices_control),
                filter=~IsDone()  # pylint:disable=invalid-unary-operand-type
            ),
            # Searched string
            ConditionalContainer(
                Window(height=D.exact(2),
                       content=FormattedTextControl(
                           choices_control.get_search_string_tokens)),
                filter=has_search_string & ~IsDone()  # pylint:disable=invalid-unary-operand-type
            ),
        ]))

    return Application(layout=layout,
                       key_bindings=key_bindings,
                       mouse_support=False,
                       style=default_style,
                       **kwargs)
Пример #12
0
def question(message, **kwargs):
    # TODO extract common parts for list, checkbox, rawlist, expand
    # TODO up, down navigation
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')

    choices = kwargs.pop('choices', None)
    default = kwargs.pop('default', None)
    qmark = kwargs.pop('qmark', '?')
    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    ic = InquirerControl(choices, default)

    def get_prompt_tokens():
        tokens = []

        tokens.append(('class:questionmark', qmark))
        tokens.append(('class:question', ' %s ' % message))
        if not ic.answered:
            tokens.append(('class:instruction', ' (%s)' % ''.join(
                [k[0] for k in ic.choices if not isinstance(k, Separator)])))
        else:
            tokens.append(('class:answer', ' %s' % ic.get_selected_value()))
        return tokens

    #@Condition
    #def is_help_active():
    #    return ic._help_active

    # assemble layout
    layout = HSplit([
        Window(height=D.exact(1),
               content=FormattedTextControl(get_prompt_tokens)
        ),
        ConditionalContainer(
            Window(ic),
            #filter=is_help_active & ~IsDone()  # ~ bitwise inverse
            filter=~IsDone()  # ~ bitwise inverse
        )
    ])

    # key bindings
    kb = KeyBindings()

    @kb.add('c-q', eager=True)
    @kb.add('c-c', eager=True)
    def _(event):
        raise KeyboardInterrupt()

    # add key bindings for choices
    for i, c in enumerate(ic.choices):
        if not isinstance(c, Separator):
            def _reg_binding(i, keys):
                # trick out late evaluation with a "function factory":
                # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop
                @kb.add(keys, eager=True)
                def select_choice(event):
                    ic.pointer_index = i
            if c[0] not in ['h', 'H']:
                _reg_binding(i, c[0])
                if c[0].isupper():
                    _reg_binding(i, c[0].lower())

    @kb.add('H', eager=True)
    @kb.add('h', eager=True)
    def help_choice(event):
        ic._help_active = not ic._help_active

    @kb.add('enter', eager=True)
    def set_answer(event):
        selected_value = ic.get_selected_value()
        if selected_value == '__HELP__':
            ic._help_active = True
        else:
            ic.answered = True
            event.app.exit(result=selected_value)

    return Application(
        layout=Layout(layout),
        key_bindings=kb,
        mouse_support=True,
        style=style
    )
Пример #13
0
# containers use absolute coordinates, while user controls paint on their own
# `Screen` with a relative coordinates.

# The Window class itself is a container that can contain a user control, so
# that's the adaptor between the two. The Window class also takes care of
# scrolling the content if the user control is painting on a screen that is
# larger than what was available to the window.

# So, for this example, we create a layout that shows the content of the
# default buffer on the left, shows a line in the middle and another buffer
# (called 'RESULT') on the right.

layout = VSplit([
    # One window that holds the BufferControl with the default buffer on the
    # left.
    Window(content=BufferControl(buffer_name=DEFAULT_BUFFER)),

    # A vertical line in the middle. We explicitely specify the width, to make
    # sure that the layout engine will not try to divide the whole width by
    # three for all these windows. The `FillControl` will simply fill the whole
    # window by repeating this character.
    Window(width=D.exact(1), content=FillControl('|', token=Token.Line)),

    # Display the Result buffer on the right.
    Window(content=BufferControl(buffer_name='RESULT')),
])

# As a demonstration. Let's add a title bar to the top, displaying "Hello world".

# somewhere, because usually the default key bindings include searching. (Press
# Ctrl-R.) It would be really annoying if the search key bindings are handled,
Пример #14
0
    def __init__(
            self,
            options,
            default_index=0,
            header_filter=lambda x: x,
            match_filter=lambda x: x
            ):

        self.info_window = InfoWindow()
        self.help_window = HelpWindow()
        self.message_toolbar = MessageToolbar(style="class:message_toolbar")
        self.error_toolbar = MessageToolbar(style="class:error_toolbar")
        self.status_line = MessageToolbar(style="class:status_line")
        self.status_line_format = config.get(
            'status_line_format', section="tui"
        )

        self.options_list = OptionsList(
            options,
            default_index,
            header_filter,
            match_filter,
            custom_filter=~has_focus(self.help_window)
        )
        self.options_list.search_buffer.on_text_changed += self.update

        commands, commands_kb = get_commands(self)
        self.command_line_prompt = CommandLinePrompt(commands=commands)
        kb = merge_key_bindings([create_keybindings(self), commands_kb])

        _root_container = HSplit([
            HSplit([
                Window(
                    content=BufferControl(
                        input_processors=[BeforeInput('> ')],
                        buffer=self.options_list.search_buffer
                    )
                ),
                self.options_list,
                self.info_window,
            ]),
            self.help_window,
            self.error_toolbar,
            self.message_toolbar,
            self.status_line,
            self.command_line_prompt.window,
        ])

        help_text = ""
        keys_info = get_keys_info()
        for k in keys_info:
            help_text += (
                "<ansired>{k[key]}</ansired>: {k[help]}\n".format(
                    k=keys_info[k]
                )
            )
        self.help_window.text = HTML(help_text)

        self.layout = Layout(_root_container)

        super(Picker, self).__init__(
            input=None,
            output=None,
            editing_mode=EditingMode.EMACS
            if config.get('editmode', section='tui') == 'emacs'
            else EditingMode.VI,
            layout=self.layout,
            style=Style.from_dict({
                'options_list.selected_margin': config.get(
                    'options_list.selected_margin_style', section='tui'
                ),
                'options_list.unselected_margin': config.get(
                    'options_list.unselected_margin_style', section='tui'
                ),
                'error_toolbar': config.get(
                    'error_toolbar_style', section='tui'
                ),
                'message_toolbar': config.get(
                    'message_toolbar_style', section='tui'
                ),
                'status_line': config.get(
                    'status_line_style', section='tui'
                ),
            }),
            key_bindings=kb,
            include_default_pygments_style=False,
            full_screen=True,
            enable_page_navigation_bindings=True
        )
        self.update()
Пример #15
0
def generate_layout(
    input_field: TextArea,
    output_field: TextArea,
    log_field: TextArea,
    right_pane_toggle: Button,
    log_field_button: Button,
    search_field: SearchToolbar,
    timer: TextArea,
    process_monitor: TextArea,
    trade_monitor: TextArea,
    command_tabs: Dict[str, CommandTab],
):
    components = {}

    components["item_top_version"] = Window(FormattedTextControl(get_version),
                                            style="class:header")
    components["item_top_active"] = Window(
        FormattedTextControl(get_active_strategy), style="class:header")
    components["item_top_file"] = Window(
        FormattedTextControl(get_strategy_file), style="class:header")
    components["item_top_toggle"] = right_pane_toggle
    components["pane_top"] = VSplit([
        components["item_top_version"], components["item_top_active"],
        components["item_top_file"], components["item_top_toggle"]
    ],
                                    height=1)
    components["pane_bottom"] = VSplit([trade_monitor, process_monitor, timer],
                                       height=1)
    output_pane = Box(body=output_field,
                      padding=0,
                      padding_left=2,
                      style="class:output-field")
    input_pane = Box(body=input_field,
                     padding=0,
                     padding_left=2,
                     padding_top=1,
                     style="class:input-field")
    components["pane_left"] = HSplit([output_pane, input_pane],
                                     width=Dimension(weight=1))
    if all(not t.is_selected for t in command_tabs.values()):
        log_field_button.window.style = "class:tab_button.focused"
    else:
        log_field_button.window.style = "class:tab_button"
    tab_buttons = [log_field_button]
    for tab in sorted(command_tabs.values(), key=lambda x: x.tab_index):
        if tab.button is not None:
            if tab.is_selected:
                tab.button.window.style = "class:tab_button.focused"
            else:
                tab.button.window.style = "class:tab_button"
            tab.close_button.window.style = tab.button.window.style
            tab_buttons.append(VSplit([tab.button, tab.close_button]))
    pane_right_field = log_field
    focused_right_field = [
        tab.output_field for tab in command_tabs.values() if tab.is_selected
    ]
    if focused_right_field:
        pane_right_field = focused_right_field[0]
    components["pane_right_top"] = VSplit(tab_buttons,
                                          height=1,
                                          style="class:log-field",
                                          padding_char=" ",
                                          padding=2)
    components["pane_right"] = ConditionalContainer(Box(
        body=HSplit(
            [components["pane_right_top"], pane_right_field, search_field],
            width=Dimension(weight=1)),
        padding=0,
        padding_left=2,
        style="class:log-field"),
                                                    filter=True)
    components["hint_menus"] = [
        Float(xcursor=True,
              ycursor=True,
              transparent=True,
              content=CompletionsMenu(max_height=16, scroll_offset=1))
    ]

    root_container = HSplit([
        components["pane_top"],
        VSplit([
            FloatContainer(components["pane_left"], components["hint_menus"]),
            components["pane_right"]
        ]),
        components["pane_bottom"],
    ])
    return Layout(root_container, focused_element=input_field), components
Пример #16
0
def question(message, **kwargs):
    # TODO extract common parts for list, checkbox, rawlist, expand
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')
    # this does not implement default, use checked...
    # TODO
    #if 'default' in kwargs:
    #    raise ValueError('rawlist does not implement \'default\' '
    #                     'use \'checked\':True\' in choice!')

    choices = kwargs.pop('choices', None)
    if len(choices) > 9:
        raise ValueError('rawlist supports only a maximum of 9 choices!')

    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    ic = InquirerControl(choices)

    def get_prompt_tokens(cli):
        tokens = []
        T = Token

        tokens.append((T.QuestionMark, '?'))
        tokens.append((T.Question, ' %s ' % message))
        if ic.answered:
            tokens.append((T.Answer, ' %s' % ic.get_selected_value()))
        return tokens

    # assemble layout
    layout = HSplit([
        Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)),
        ConditionalContainer(Window(ic), filter=~IsDone())
    ])

    # key bindings
    manager = KeyBindingManager.for_prompt()

    @manager.registry.add_binding(Keys.ControlQ, eager=True)
    @manager.registry.add_binding(Keys.ControlC, eager=True)
    def _(event):
        raise KeyboardInterrupt()

    # add key bindings for choices
    for i, c in enumerate(ic.choices):
        if not isinstance(c, Separator):

            def _reg_binding(i, keys):
                # trick out late evaluation with a "function factory":
                # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop
                @manager.registry.add_binding(keys, eager=True)
                def select_choice(event):
                    ic.pointer_index = i

            _reg_binding(i, '%d' % c[0])

    @manager.registry.add_binding(Keys.Enter, eager=True)
    def set_answer(event):
        ic.answered = True
        event.cli.set_return_value(ic.get_selected_value())

    return Application(layout=layout,
                       key_bindings_registry=manager.registry,
                       mouse_support=True,
                       style=style)
Пример #17
0
risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus
consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo
sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed
convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex
quis sodales maximus. """ * 100).split())

# 1. The layout
left_text = "Floating\nleft"
right_text = "Floating\nright"
top_text = "Floating\ntop"
bottom_text = "Floating\nbottom"
center_text = "Floating\ncenter"
quit_text = "Press 'q' to quit."

body = FloatContainer(
    content=Window(FormattedTextControl(LIPSUM), wrap_lines=True),
    floats=[

        # Important note: Wrapping the floating objects in a 'Frame' is
        #                 only required for drawing the border around the
        #                 floating text. We do it here to make the layout more
        #                 obvious.

        # Left float.
        Float(Frame(Window(FormattedTextControl(left_text), width=10,
                           height=2),
                    style='bg:#44ffff #ffffff'),
              left=0),

        # Right float.
        Float(Frame(Window(FormattedTextControl(right_text),
Пример #18
0
def main():
    # The layout.
    search_field = SearchToolbar()  # For reverse search.

    output_field = TextArea(style='class:output-field', text=help_text)
    input_field = TextArea(
        height=1, prompt='>>> ', style='class:input-field', multiline=False,
        wrap_lines=False, search_field=search_field)

    container = HSplit([
        output_field,
        Window(height=1, char='-', style='class:line'),
        input_field,
        search_field,
    ])

    # Attach accept handler to the input field. We do this by assigning the
    # handler to the `TextArea` that we created earlier. it is also possible to
    # pass it to the constructor of `TextArea`.
    # NOTE: It's better to assign an `accept_handler`, rather then adding a
    #       custom ENTER key binding. This will automatically reset the input
    #       field and add the strings to the history.
    def accept(buff):
        # Evaluate "calculator" expression.
        try:
            output = '\n\nIn:  {}\nOut: {}'.format(
                input_field.text,
                eval(input_field.text))  # Don't do 'eval' in real code!
        except BaseException as e:
            output = '\n\n{}'.format(e)
        new_text = output_field.text + output

        # Add text to output buffer.
        output_field.buffer.document = Document(
            text=new_text, cursor_position=len(new_text))

    input_field.accept_handler = accept

    # The key bindings.
    kb = KeyBindings()

    @kb.add('c-c')
    @kb.add('c-q')
    def _(event):
        " Pressing Ctrl-Q or Ctrl-C will exit the user interface. "
        event.app.exit()

    # Style.
    style = Style([
        ('output-field', 'bg:#000044 #ffffff'),
        ('input-field', 'bg:#000000 #ffffff'),
        ('line',        '#004400'),
    ])

    # Run application.
    application = Application(
        layout=Layout(container, focused_element=input_field),
        key_bindings=kb,
        style=style,
        mouse_support=True,
        full_screen=True)

    application.run()
Пример #19
0
def create_layout(python_input, history_mapping):
    """
    Create and return a `Container` instance for the history
    application.
    """
    default_processors = [
        HighlightSearchProcessor(preview_search=Always()),
        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=default_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,
                        wrap_lines=False,
                        lexer=PygmentsLexer(PythonLexer),
                        input_processors=default_processors),
                    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,
                        wrap_lines=False,
                        input_processors=[GrayExistingText(history_mapping)] + default_processors,
                        lexer=PygmentsLexer(PythonLexer)),
                    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)),
    ])
Пример #20
0
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout.containers import HSplit, VSplit, Window, WindowAlign
from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
from prompt_toolkit.layout.layout import Layout

# 3. Create the buffers
#    ------------------

left_buffer = Buffer()
right_buffer = Buffer()

# 1. First we create the layout
#    --------------------------

left_window = Window(BufferControl(buffer=left_buffer))
right_window = Window(BufferControl(buffer=right_buffer))

body = VSplit([
    left_window,
    # A vertical line in the middle. We explicitly specify the width, to make
    # sure that the layout engine will not try to divide the whole width by
    # three for all these windows.
    Window(width=1, char="|", style="class:line"),
    # Display the Result buffer on the right.
    right_window,
])

# As a demonstration. Let's add a title bar to the top, displaying "Hello world".

# somewhere, because usually the default key bindings include searching. (Press
Пример #21
0
    def create_layout(self, exam_lex, toolbar_lex):
        """ creates the layout """
        lexer, exam_lex, toolbar_lex = get_lexers(self.shell_ctx.lexer, exam_lex, toolbar_lex)

        if not any(isinstance(processor, DefaultPrompt) for processor in self.input_processors):
            self.input_processors.append(DefaultPrompt(self.get_prompt_tokens))

        layout_lower = ConditionalContainer(
            HSplit([
                get_anyhline(self.shell_ctx.config),
                get_descriptions(self.shell_ctx.config, exam_lex, lexer),
                get_examplehline(self.shell_ctx.config),
                get_example(self.shell_ctx.config, exam_lex),

                ConditionalContainer(
                    get_hline(),
                    filter=self.show_default | self.show_symbol
                ),
                ConditionalContainer(
                    Window(
                        content=BufferControl(
                            buffer_name='default_values',
                            lexer=lexer
                        )
                    ),
                    filter=self.show_default
                ),
                ConditionalContainer(
                    get_hline(),
                    filter=self.show_default & self.show_symbol
                ),
                ConditionalContainer(
                    Window(
                        content=BufferControl(
                            buffer_name='symbols',
                            lexer=exam_lex
                        )
                    ),
                    filter=self.show_symbol
                ),
                ConditionalContainer(
                    Window(
                        content=BufferControl(
                            buffer_name='progress',
                            lexer=lexer
                        )
                    ),
                    filter=self.show_progress
                ),
                Window(
                    content=BufferControl(
                        buffer_name='bottom_toolbar',
                        lexer=toolbar_lex
                    ),
                ),
            ]),
            filter=~IsDone() & RendererHeightIsKnown()
        )

        layout_full = HSplit([
            FloatContainer(
                Window(
                    BufferControl(
                        input_processors=self.input_processors,
                        lexer=lexer,
                        preview_search=Always()),
                    get_height=get_height,
                ),
                [
                    Float(xcursor=True,
                          ycursor=True,
                          content=CompletionsMenu(
                              max_height=MAX_COMPLETION,
                              scroll_offset=1,
                              extra_filter=(HasFocus(DEFAULT_BUFFER))))]),
            layout_lower
        ])

        return layout_full
Пример #22
0
    def __init__(self, values: Sequence[Tuple[_T, AnyFormattedText]]) -> None:
        assert len(values) > 0

        self.values = values
        # current_values will be used in multiple_selection,
        # current_value will be used otherwise.
        self.current_values: List[_T] = []
        self.current_value: _T = values[0][0]
        self._selected_index = 0

        # Key bindings.
        kb = KeyBindings()

        @kb.add("up")
        def _up(event: E) -> None:
            self._selected_index = max(0, self._selected_index - 1)

        @kb.add("down")
        def _down(event: E) -> None:
            self._selected_index = min(
                len(self.values) - 1, self._selected_index + 1)

        @kb.add("pageup")
        def _pageup(event: E) -> None:
            w = event.app.layout.current_window
            if w.render_info:
                self._selected_index = max(
                    0,
                    self._selected_index - len(w.render_info.displayed_lines))

        @kb.add("pagedown")
        def _pagedown(event: E) -> None:
            w = event.app.layout.current_window
            if w.render_info:
                self._selected_index = min(
                    len(self.values) - 1,
                    self._selected_index + len(w.render_info.displayed_lines),
                )

        @kb.add("enter")
        @kb.add(" ")
        def _click(event: E) -> None:
            self._handle_enter()

        @kb.add(Keys.Any)
        def _find(event: E) -> None:
            # We first check values after the selected value, then all values.
            values = list(self.values)
            for value in values[self._selected_index + 1:] + values:
                text = fragment_list_to_text(to_formatted_text(
                    value[1])).lower()

                if text.startswith(event.data.lower()):
                    self._selected_index = self.values.index(value)
                    return

        # Control and window.
        self.control = FormattedTextControl(self._get_text_fragments,
                                            key_bindings=kb,
                                            focusable=True)

        self.window = Window(
            content=self.control,
            style=self.container_style,
            right_margins=[
                ConditionalMargin(
                    margin=ScrollbarMargin(display_arrows=True),
                    filter=Condition(lambda: self.show_scrollbar),
                ),
            ],
            dont_extend_height=True,
        )
Пример #23
0
    def __init__(self,
                 text: str = '',
                 multiline: FilterOrBool = True,
                 password: FilterOrBool = False,
                 lexer: Optional[Lexer] = None,
                 auto_suggest: Optional[AutoSuggest] = None,
                 completer: Optional[Completer] = None,
                 complete_while_typing: FilterOrBool = True,
                 accept_handler: Optional[BufferAcceptHandler] = None,
                 history: Optional[History] = None,
                 focusable: FilterOrBool = True,
                 focus_on_click: FilterOrBool = False,
                 wrap_lines: FilterOrBool = True,
                 read_only: FilterOrBool = False,
                 width: AnyDimension = None,
                 height: AnyDimension = None,
                 dont_extend_height: FilterOrBool = False,
                 dont_extend_width: FilterOrBool = False,
                 line_numbers: bool = False,
                 get_line_prefix: Optional[GetLinePrefixCallable] = None,
                 scrollbar: bool = False,
                 style: str = '',
                 search_field: Optional[SearchToolbar] = None,
                 preview_search: FilterOrBool = True,
                 prompt: AnyFormattedText = '',
                 input_processors: Optional[List[Processor]] = None) -> None:

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

        if input_processors is None:
            input_processors = []

        # Writeable attributes.
        self.completer = completer
        self.complete_while_typing = complete_while_typing
        self.lexer = lexer
        self.auto_suggest = auto_suggest
        self.read_only = read_only
        self.wrap_lines = wrap_lines

        self.buffer = Buffer(
            document=Document(text, 0),
            multiline=multiline,
            read_only=Condition(lambda: is_true(self.read_only)),
            completer=DynamicCompleter(lambda: self.completer),
            complete_while_typing=Condition(
                lambda: is_true(self.complete_while_typing)),
            auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest),
            accept_handler=accept_handler,
            history=history)

        self.control = BufferControl(
            buffer=self.buffer,
            lexer=DynamicLexer(lambda: self.lexer),
            input_processors=[
                ConditionalProcessor(AppendAutoSuggestion(),
                                     has_focus(self.buffer) & ~is_done),
                ConditionalProcessor(processor=PasswordProcessor(),
                                     filter=to_filter(password)),
                BeforeInput(prompt, style='class:text-area.prompt'),
            ] + input_processors,
            search_buffer_control=search_control,
            preview_search=preview_search,
            focusable=focusable,
            focus_on_click=focus_on_click)

        if multiline:
            if scrollbar:
                right_margins = [ScrollbarMargin(display_arrows=True)]
            else:
                right_margins = []
            if line_numbers:
                left_margins = [NumberedMargin()]
            else:
                left_margins = []
        else:
            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=Condition(lambda: is_true(self.wrap_lines)),
            left_margins=left_margins,
            right_margins=right_margins,
            get_line_prefix=get_line_prefix)
Пример #24
0
def sql_sidebar(my_app: "sqlApp") -> Window:
    """
    Create the `Layout` for the sidebar with the configurable objects.
    """

    @if_mousedown
    def expand_item(obj: "myDBObject") -> None:
        obj.expand()

    def tokenize_obj(obj: "myDBObject") -> StyleAndTextTuples:
        " Recursively build the token list "
        tokens: StyleAndTextTuples = []
        selected = obj is my_app.selected_object
        expanded = obj.children is not None
        connected = obj.otype == "Connection" and obj.conn.connected()
        active = my_app.active_conn is not None and my_app.active_conn is obj.conn and obj.level == 0

        act = ",active" if active else ""
        sel = ",selected" if selected else ""
        if len(obj.name) > 24 -  2 * obj.level:
            name_trim = obj.name[:24 - 2 * obj.level - 3] + "..."
        else:
            name_trim = ("%-" + str(24 - 2 * obj.level) + "s") % obj.name

        tokens.append(("class:sidebar.label" + sel + act, " >" if connected else "  "))
        tokens.append(
            ("class:sidebar.label" + sel, " " * 2 * obj.level, expand_item)
        )
        tokens.append(
            ("class:sidebar.label" + sel + act,
            name_trim,
            expand_item)
        )
        tokens.append(("class:sidebar.status" + sel + act, " ", expand_item))
        tokens.append(("class:sidebar.status" + sel + act, "%+12s" % obj.otype, expand_item))

        if selected:
            tokens.append(("[SetCursorPosition]", ""))

        if expanded:
            tokens.append(("class:sidebar.status" + sel + act, "\/"))
        else:
            tokens.append(("class:sidebar.status" + sel + act, " <" if selected else "  "))

        # Expand past the edge of the visible buffer to get an even panel
        tokens.append(("class:sidebar.status" + sel + act, " " * 10))
        return tokens

    search_buffer = Buffer(name = "sidebarsearchbuffer")
    search_field = SearchToolbar(
        search_buffer = search_buffer,
        ignore_case = True
    )
    def _buffer_pos_changed(buff):
        """ This callback gets executed after cursor position changes.  Most
            of the time we register a key-press (up / down), we change the
            selected object and as a result of that the cursor changes.  By that
            time we don't need to updat the selected object (cursor changed as
            a result of the selected object being updated).  The one exception
            is when searching the sidebar buffer.  When this happens the cursor
            moves ahead of the selected object.  When that happens, here we
            update the selected object to follow suit.
        """
        if buff.document.cursor_position_row != my_app.selected_object_idx[0]:
            my_app.select(buff.document.cursor_position_row)

    sidebar_buffer = Buffer(
        name = "sidebarbuffer",
        read_only = True,
        on_cursor_position_changed = _buffer_pos_changed
    )

    class myLexer(Lexer):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self._obj_list = []

        def add_objects(self, objects: List):
            self._obj_list = objects

        def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
            def get_line(lineno: int) -> StyleAndTextTuples:
                # TODO: raise out-of-range exception
                return tokenize_obj(self._obj_list[lineno])
            return get_line


    sidebar_lexer = myLexer()

    class myControl(BufferControl):

        def move_cursor_down(self):
            my_app.select_next()
        # Need to figure out what do do here
        # AFAICT these are only called for the mouse handler
        # when events are otherwise not handled
        def move_cursor_up(self):
            my_app.select_previous()

        def mouse_handler(self, mouse_event: MouseEvent) -> "NotImplementedOrNone":
            """
                There is an intricate relationship between the cursor position
                in the sidebar document and which object is market as 'selected'
                in the linked list.  Let's not muck that up by allowing the user
                to change the cursor position in the sidebar document with the mouse.
            """
            return NotImplemented

        def create_content(self, width: int, height: Optional[int]) -> UIContent:
            # Only traverse the obj_list if it has been expanded / collapsed
            if not my_app.obj_list_changed:
                self.buffer.cursor_position = my_app.selected_object_idx[1]
                return super().create_content(width, height)

            res = []
            obj = my_app.obj_list[0]
            res.append(obj)
            while obj.next_object is not my_app.obj_list[0]:
                res.append(obj.next_object)
                obj = obj.next_object

            self.lexer.add_objects(res)
            self.buffer.set_document(Document(
                text = "\n".join([a.name for a in res]), cursor_position = my_app.selected_object_idx[1]), True)
            # Reset obj_list_changed flag, now that we have had a chance to
            # regenerate the sidebar document content
            my_app.obj_list_changed = False
            return super().create_content(width, height)



    sidebar_control = myControl(
            buffer = sidebar_buffer,
            lexer = sidebar_lexer,
            search_buffer_control = search_field.control,
            focusable = True,
            )

    return HSplit([
        search_field,
        Window(
            sidebar_control,
            right_margins = [ScrollbarMargin(display_arrows = True)],
            style = "class:sidebar",
            width = Dimension.exact( 45 ),
            height = Dimension(min = 7, preferred = 33),
            scroll_offsets = ScrollOffsets(top = 1, bottom = 1)),
        Window(
            height = Dimension.exact(1),
            char = "\u2500",
            style = "class:sidebar,separator",
            ),
        expanding_object_notification(my_app),
        sql_sidebar_navigation()])
Пример #25
0
 def __init__(self) -> None:
     self.window = Window(char=Border.HORIZONTAL,
                          style='class:line,horizontal-line',
                          height=1)
Пример #26
0
        all_remaining.text = "\n".join(remaining)
        all_excess.text = "\n".join(excess)
        all_overused.text = "\n".join(overused)


used = Buffer(on_text_changed=assess)
kb = KeyBindings()


@kb.add('c-q')
def exit_(event):
    event.app.exit()


root_container = HSplit([
    Window(height=1, content=FormattedTextControl(text=message)),
    Window(height=1, char='-'),
    VSplit([
        Window(content=BufferControl(buffer=used)),
        Window(width=1, char='|'),
        Window(content=all_remaining),
        Window(width=1, char='|'),
        Window(content=all_overused),
        Window(width=1, char='|'),
        Window(content=all_excess),
    ]),
    Window(height=1, char='-'),
    Window(height=1, content=FormattedTextControl(text="Ctrl + Q to Quit"))
])

layout = Layout(root_container)
Пример #27
0
def get_param(lexer):
    """ parameter description window """
    return Window(content=BufferControl(buffer_name="parameter", lexer=lexer))
Пример #28
0
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings

# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")

# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)

# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)

# správce rozvržení
vsplit = HSplit([
    VSplit([window1, Window(width=1, char='|'), window2]),
    Window(height=1, char='-'), window3
])
layout = Layout(vsplit)

# napojení na klávesové zkratky
key_bindings = KeyBindings()


@key_bindings.add('escape')
Пример #29
0
def get_hline():
    """ gets a horiztonal line """
    return Window(width=D.exact(1),
                  height=D.exact(1),
                  content=FillControl('-', token=Token.Line))
Пример #30
0
    def run(self, query, data):
        self.load_config()

        if data or query is not None:
            self.format = self.format_stdin
            self.echo.verbose = False

        if self.echo.verbose:
            show_version()

        if not self.connect():
            return

        if self.client:
            self.client.settings = self.settings
            self.client.cli_settings = {
                'multiline': self.multiline,
                'vi_mode': self.vi_mode,
                'format': self.format,
                'format_stdin': self.format_stdin,
                'show_formatted_query': self.show_formatted_query,
                'highlight': self.highlight,
                'highlight_output': self.highlight_output,
                'refresh_metadata_on_start': self.refresh_metadata_on_start,
                'refresh_metadata_on_query': self.refresh_metadata_on_query,
            }

        if data and query is None:
            # cat stuff.sql | clickhouse-cli
            # clickhouse-cli stuff.sql
            for subdata in data:
                self.handle_input(subdata.read(),
                                  verbose=False,
                                  refresh_metadata=False)

            return

        if not data and query is not None:
            # clickhouse-cli -q 'SELECT 1'
            return self.handle_query(query, stream=False)

        if data and query is not None:
            # cat stuff.csv | clickhouse-cli -q 'INSERT INTO stuff'
            # clickhouse-cli -q 'INSERT INTO stuff' stuff.csv
            for subdata in data:
                compress = 'gzip' if os.path.splitext(
                    subdata.name)[1] == '.gz' else False

                self.handle_query(query,
                                  data=subdata,
                                  stream=True,
                                  compress=compress)

            return

        buffer = CLIBuffer(
            client=self.client,
            multiline=self.multiline,
            metadata=self.metadata,
        )

        root_container = Window(content=BufferControl(buffer=buffer))

        layout = Layout(root_container)
        # layout.focus(root_container)

        # layout = prompt(
        #     lexer=PygmentsLexer(CHLexer) if self.highlight else None,
        #     # get_prompt_tokens=get_prompt_tokens,
        #     # get_continuation_tokens=get_continuation_tokens,
        #     multiline=self.multiline,
        # )

        hist = FileHistory(
            filename=os.path.expanduser('~/.clickhouse-cli_history'))
        self.completer = CHCompleter(self.client, self.metadata)

        self.session = PromptSession(
            style=CHStyle if self.highlight else None,
            lexer=PygmentsLexer(CHLexer) if self.highlight else None,
            message=get_prompt_tokens()[0][1],
            prompt_continuation=get_continuation_tokens()[0][1],
            multiline=is_multiline(self.multiline),
            vi_mode=self.vi_mode,
            history=hist,
            key_bindings=kb,
            complete_while_typing=self.complete_while_typing,
            completer=ThreadedCompleter(
                DynamicCompleter(lambda: self.completer)),
        )

        self.app = Application(layout=layout,
                               # buffer=buffer,
                               )

        #self.cli = CommandLineInterface(application=application, eventloop=eventloop)
        if self.refresh_metadata_on_start:
            self.app.current_buffer.completer.refresh_metadata()

        try:
            while True:
                try:
                    cli_input = self.session.prompt()
                    self.handle_input(cli_input)
                except KeyboardInterrupt:
                    # Attempt to terminate queries
                    for query_id in self.query_ids:
                        self.client.kill_query(query_id)

                    self.echo.error("\nQuery was terminated.")
                finally:
                    self.query_ids = []
        except EOFError:
            self.echo.success("Bye.")