예제 #1
0
    def __init__(self, pymux):
        self.pymux = pymux

        def get_search_state(cli):
            " Return the currently active SearchState. (The one for the focussed pane.) "
            return pymux.arrangement.get_active_pane(cli).search_state

        # Start from this KeyBindingManager from prompt_toolkit, to have basic
        # editing functionality for the command line. These key binding are
        # however only active when the following `enable_all` condition is met.
        self.registry = MergedRegistry([
            ConditionalRegistry(
                registry=load_key_bindings(
                    enable_auto_suggest_bindings=True,
                    enable_search=False,  # We have our own search bindings, that support multiple panes.
                    enable_extra_page_navigation=True,
                    get_search_state=get_search_state),
                filter=(HasFocus(COMMAND) | HasFocus(PROMPT) |
                        InScrollBuffer(pymux)) & ~HasPrefix(pymux),
            ),
            load_mouse_bindings(),
            self._load_builtins(),
            _load_search_bindings(pymux),
        ])

        self._prefix = (Keys.ControlB, )
        self._prefix_binding = None

        # Load initial bindings.
        self._load_prefix_binding()

        # Custom user configured key bindings.
        # { (needs_prefix, key) -> (command, handler) }
        self.custom_bindings = {}
예제 #2
0
def choose_version(assets):
    '''choose a version from assets list'''
    versions = list(map(lambda item: item['version'], assets))
    # print(versions)
    values = list(map(lambda item: (item, item), versions))
    rdo = NewRadioList(values)

    def do_exit(event):
        # get_app().exit()
        event.app.exit(result=rdo.current_value)

    def do_up_down(event):
        print(event)
        pass

    bindings = KeyBindings()
    bindings.add('enter')(do_exit)
    app_bindings = merge_key_bindings([load_key_bindings(), bindings])

    selected = Application(layout=Layout(rdo), key_bindings=app_bindings).run()
    if selected in versions:
        print('your choice is:', end=' ')
        # refer: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/examples/print-text/ansi.py
        print_formatted_text(ANSI('\x1b[91m{0}'.format(selected)))
        return selected
    else:
        print('canceled')
예제 #3
0
    def __init__(self, pymux):
        self.pymux = pymux

        def get_search_state(cli):
            " Return the currently active SearchState. (The one for the focussed pane.) "
            return pymux.arrangement.get_active_pane(cli).search_state

        # Start from this KeyBindingManager from prompt_toolkit, to have basic
        # editing functionality for the command line. These key binding are
        # however only active when the following `enable_all` condition is met.
        self.registry = MergedRegistry([
            ConditionalRegistry(
                registry=load_key_bindings(
                    enable_auto_suggest_bindings=True,
                    enable_search=
                    False,  # We have our own search bindings, that support multiple panes.
                    enable_extra_page_navigation=True,
                    get_search_state=get_search_state),
                filter=(HasFocus(COMMAND) | HasFocus(PROMPT)
                        | InScrollBuffer(pymux)) & ~HasPrefix(pymux),
            ),
            load_mouse_bindings(),
            self._load_builtins(),
            _load_search_bindings(pymux),
        ])

        self._prefix = (Keys.ControlB, )
        self._prefix_binding = None

        # Load initial bindings.
        self._load_prefix_binding()

        # Custom user configured key bindings.
        # { (needs_prefix, key) -> (command, handler) }
        self.custom_bindings = {}
예제 #4
0
def repl(parser, interpreter, style_name='default'):
    registry = load_key_bindings()

    @registry.add_binding(Keys.Escape, Keys.Enter)  # meta-enter/alt-enter
    def _(event):
        '''Evaluate the buffer
        '''
        code = buffers[DEFAULT_BUFFER].text
        try:
            ast = parser.parse(code)
        except (UnexpectedToken, UnexpectedInput) as e:
            toolbar_value = str(e)
            return

        try:
            start_eval_time = time.time()
            retval = interpreter.eval(ast)
        except Exception as e:
            toolbar_value = "Error: %s" % e.args
            return
        else:
            buffers['RESULT'].text = str(retval)
            toolbar_value = "Time: {:0.4f}, Value: {}".format(
                time.time() - start_eval_time, str(retval))

    @registry.add_binding(Keys.ControlC, eager=True)
    @registry.add_binding(Keys.ControlQ, eager=True)
    def _(event):
        '''Exit the REPL
        '''
        event.cli.set_return_value(None)

    buffers = {
        DEFAULT_BUFFER: Buffer(is_multiline=True),
        'RESULT': Buffer(is_multiline=True),
    }
    style = style_from_pygments(get_style_by_name(style_name))

    application = Application(layout=layout,
                              buffers=buffers,
                              mouse_support=True,
                              style=style,
                              use_alternate_screen=True,
                              key_bindings_registry=registry)

    eventloop = create_eventloop()

    try:
        cli = CommandLineInterface(application=application,
                                   eventloop=eventloop)
        cli.run()

    finally:
        eventloop.close()
예제 #5
0
def _create_app(dialog: AnyContainer, style: Optional[BaseStyle]) -> Application[Any]:
    # Key bindings.
    bindings = KeyBindings()
    bindings.add("tab")(focus_next)
    bindings.add("s-tab")(focus_previous)

    return Application(
        layout=Layout(dialog),
        key_bindings=merge_key_bindings([load_key_bindings(), bindings]),
        mouse_support=True,
        style=style,
        full_screen=True,
    )
예제 #6
0
def main():
    style = Style([
        ('terminal focused', 'bg:#aaaaaa'),
        ('title', 'bg:#000044 #ffffff underline'),
    ])

    term1 = Terminal()

    text_area = TextArea(text='Press Control-W to switch focus.\n'
                         'Then you can edit this text area.\n'
                         'Press Control-X to exit')

    kb = KeyBindings()

    @kb.add('c-w')
    def _(event):
        switch_focus()

    @kb.add('c-x', eager=True)
    def _(event):
        event.app.exit()

    def switch_focus():
        " Change focus when Control-W is pressed."
        if application.layout.has_focus(term1):
            application.layout.focus(text_area)
        else:
            application.layout.focus(term1)

    application = Application(
        layout=Layout(container=HSplit([
            Window(height=1,
                   style='class:title',
                   content=FormattedTextControl(
                       ' Press Control-W to switch focus.')),
            VSplit([
                term1,
                Window(style='bg:#aaaaff', width=1),
                text_area,
            ]),
        ]),
                      focused_element=term1),
        style=style,
        key_bindings=merge_key_bindings([
            load_key_bindings(),
            kb,
        ]),
        full_screen=True,
        mouse_support=True,
    )
    application.run()
예제 #7
0
def _create_app(dialog, style):
    # Key bindings.
    bindings = KeyBindings()
    bindings.add('tab')(focus_next)
    bindings.add('s-tab')(focus_previous)

    return Application(layout=Layout(dialog),
                       key_bindings=merge_key_bindings([
                           load_key_bindings(),
                           bindings,
                       ]),
                       mouse_support=True,
                       style=style,
                       full_screen=True)
예제 #8
0
    def get_app(self):
        bindings = KeyBindings()

        @bindings.add(Keys.ControlC)
        def _ctrl_c(event):
            get_app().exit(exception=KeyboardInterrupt)

        @bindings.add(Keys.Enter)
        def _enter(event):
            get_app().exit(result=self.get_answer())

        return Application(layout=Layout(self.get_layout()),
                           key_bindings=merge_key_bindings(
                               [load_key_bindings(), bindings]),
                           style=get_theme_manager().get_current_style())
def _create_app(dialog: AnyContainer, style: Optional[BaseStyle]) -> Application[Any]:
    # Key bindings.
    bindings = KeyBindings()
    bindings.add('tab')(focus_next)
    bindings.add('s-tab')(focus_previous)

    return Application(
        layout=Layout(dialog),
        key_bindings=merge_key_bindings([
            load_key_bindings(),
            bindings,
        ]),
        mouse_support=True,
        style=style,
        full_screen=True)
def _create_app(dialog, style):
    # Key bindings.
    bindings = KeyBindings()
    bindings.add('tab')(focus_next)
    bindings.add('s-tab')(focus_previous)

    return Application(
        layout=Layout(dialog),
        key_bindings=merge_key_bindings([
            load_key_bindings(),
            bindings,
        ]),
        mouse_support=True,
        style=style,
        full_screen=True)
예제 #11
0
def show_error_dialog(messages):
    texts = []
    for message in messages:
        texts.append(
            Label(message, style='class:error', dont_extend_height=True))
    dialog = Dialog(title='Some inputs are invalid',
                    body=HSplit(texts, padding=1),
                    buttons=[
                        Button(text='Ok', handler=lambda: get_app().exit()),
                    ],
                    with_background=True)

    app = Application(layout=Layout(dialog),
                      key_bindings=load_key_bindings(),
                      mouse_support=True,
                      style=for_dialog(),
                      full_screen=True)

    app.run()
예제 #12
0
    def __init__(self, title="", label_text="", completer=None):
        self.future = Future()

        def accept_text(buf) -> bool:
            """
            Change focus to OK button after user pressed enter on text field.
            """
            get_app().layout.focus(ok_button)
            buf.complete_state = None
            return True

        def accept():
            """
            Set future result to text from text field if user pressed OK
            button.
            """
            self.future.set_result(self.text_area.text)

        def cancel():
            """
            Set future result to None if user pressed cancel button.
            """
            self.future.set_result(None)

        self.text_area = TextEditor(
            completer=completer,
            multiline=False,
            width=D(preferred=40),
            accept_handler=accept_text,
            key_bindings=load_key_bindings(),
        )

        ok_button = Button(text="OK", handler=accept)
        cancel_button = Button(text="Cancel", handler=cancel)

        self.dialog = Dialog(
            title=title,
            body=HSplit([Label(text=label_text), self.text_area]),
            buttons=[ok_button, cancel_button],
            width=D(preferred=80),
            modal=True,
        )
예제 #13
0
def radiolist_dialog(title='', values=None, style=None, async_=False):
    # Add exit key binding.
    bindings = KeyBindings()

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

    radio_list = RadioListFast(values)
    application = Application(
        layout=Layout(HSplit([Label(title), radio_list])),
        key_bindings=merge_key_bindings([load_key_bindings(), bindings]),
        mouse_support=True,
        style=style,
        full_screen=False)

    if async_:
        return application.run_async()
    else:
        return application.run()
예제 #14
0
def create_key_bindings(python_input, history_mapping):
    """
    Key bindings.
    """
    registry = load_key_bindings(enable_search=True,
                                 enable_extra_page_navigation=True)
    handle = registry.add_binding

    @handle(' ', filter=HasFocus(HISTORY_BUFFER))
    def _(event):
        """
        Space: select/deselect line from history pane.
        """
        b = event.current_buffer
        line_no = b.document.cursor_position_row

        if line_no in history_mapping.selected_lines:
            # Remove line.
            history_mapping.selected_lines.remove(line_no)
            history_mapping.update_default_buffer(event.cli)
        else:
            # Add line.
            history_mapping.selected_lines.add(line_no)
            history_mapping.update_default_buffer(event.cli)

            # Update cursor position
            default_buffer = event.cli.buffers[DEFAULT_BUFFER]
            default_lineno = sorted(history_mapping.selected_lines).index(line_no) + \
                history_mapping.result_line_offset
            default_buffer.cursor_position = \
                default_buffer.document.translate_row_col_to_index(default_lineno, 0)

        # Also move the cursor to the next line. (This way they can hold
        # space to select a region.)
        b.cursor_position = b.document.translate_row_col_to_index(
            line_no + 1, 0)

    @handle(' ', filter=HasFocus(DEFAULT_BUFFER))
    @handle(Keys.Delete, filter=HasFocus(DEFAULT_BUFFER))
    @handle(Keys.ControlH, filter=HasFocus(DEFAULT_BUFFER))
    def _(event):
        """
        Space: remove line from default pane.
        """
        b = event.current_buffer
        line_no = b.document.cursor_position_row - history_mapping.result_line_offset

        if line_no >= 0:
            try:
                history_lineno = sorted(
                    history_mapping.selected_lines)[line_no]
            except IndexError:
                pass  # When `selected_lines` is an empty set.
            else:
                history_mapping.selected_lines.remove(history_lineno)

            history_mapping.update_default_buffer(event.cli)

    help_focussed = HasFocus(HELP_BUFFER)
    main_buffer_focussed = HasFocus(HISTORY_BUFFER) | HasFocus(DEFAULT_BUFFER)

    @handle(Keys.Tab, filter=main_buffer_focussed)
    @handle(Keys.ControlX, filter=main_buffer_focussed, eager=True)
    # Eager: ignore the Emacs [Ctrl-X Ctrl-X] binding.
    @handle(Keys.ControlW, filter=main_buffer_focussed)
    def _(event):
        " Select other window. "
        _select_other_window(event.cli)

    @handle(Keys.F4)
    def _(event):
        " Switch between Emacs/Vi mode. "
        python_input.vi_mode = not python_input.vi_mode

    @handle(Keys.F1)
    def _(event):
        " Display/hide help. "
        _toggle_help(event.cli)

    @handle(Keys.ControlJ, filter=help_focussed)
    @handle(Keys.ControlC, filter=help_focussed)
    @handle(Keys.ControlG, filter=help_focussed)
    @handle(Keys.Escape, filter=help_focussed)
    def _(event):
        " Leave help. "
        event.cli.pop_focus()

    @handle('q', filter=main_buffer_focussed)
    @handle(Keys.F3, filter=main_buffer_focussed)
    @handle(Keys.ControlC, filter=main_buffer_focussed)
    @handle(Keys.ControlG, filter=main_buffer_focussed)
    def _(event):
        " Cancel and go back. "
        event.cli.set_return_value(None)

    enable_system_bindings = Condition(
        lambda cli: python_input.enable_system_bindings)

    @handle(Keys.ControlZ, filter=enable_system_bindings)
    def _(event):
        " Suspend to background. "
        event.cli.suspend_to_background()

    return registry
예제 #15
0
파일: application.py 프로젝트: Arrendi/rice
    def __init__(
            self,
            layout=None,
            style=None,
            key_bindings=None,
            clipboard=None,
            full_screen=False,
            mouse_support=False,
            enable_page_navigation_bindings=False,
            paste_mode=False,
            editing_mode=EditingMode.EMACS,
            erase_when_done=False,
            reverse_vi_search_direction=False,
            min_redraw_interval=None,
            max_render_postpone_time=0,
            on_reset=None,
            on_render=None,
            on_invalidate=None,

            # I/O.
            input=None,
            output=None):

        paste_mode = to_filter(paste_mode)
        mouse_support = to_filter(mouse_support)
        reverse_vi_search_direction = to_filter(reverse_vi_search_direction)
        enable_page_navigation_bindings = to_filter(
            enable_page_navigation_bindings)

        assert layout is None or isinstance(layout, Layout)
        assert key_bindings is None or isinstance(key_bindings,
                                                  KeyBindingsBase)
        assert clipboard is None or isinstance(clipboard, Clipboard)
        assert isinstance(full_screen, bool)
        assert isinstance(editing_mode, six.string_types)
        assert style is None or isinstance(style, BaseStyle)
        assert isinstance(erase_when_done, bool)
        assert min_redraw_interval is None or isinstance(
            min_redraw_interval, (float, int))
        assert max_render_postpone_time is None or isinstance(
            max_render_postpone_time, (float, int))

        assert on_reset is None or callable(on_reset)
        assert on_render is None or callable(on_render)
        assert on_invalidate is None or callable(on_invalidate)

        assert output is None or isinstance(output, Output)
        assert input is None or isinstance(input, Input)

        self.style = style

        if layout is None:
            layout = create_dummy_layout()

        # Key bindings.
        self.key_bindings = key_bindings
        self._default_bindings = load_key_bindings()
        self._page_navigation_bindings = load_page_navigation_bindings()

        self.layout = layout
        self.clipboard = clipboard or InMemoryClipboard()
        self.full_screen = full_screen
        self.mouse_support = mouse_support

        self.paste_mode = paste_mode
        self.editing_mode = editing_mode
        self.erase_when_done = erase_when_done
        self.reverse_vi_search_direction = reverse_vi_search_direction
        self.enable_page_navigation_bindings = enable_page_navigation_bindings
        self.min_redraw_interval = min_redraw_interval
        self.max_render_postpone_time = max_render_postpone_time

        # Events.
        self.on_invalidate = Event(self, on_invalidate)
        self.on_render = Event(self, on_render)
        self.on_reset = Event(self, on_reset)

        # I/O.
        self.output = output or get_default_output()
        self.input = input or get_default_input()

        # List of 'extra' functions to execute before a Application.run.
        self.pre_run_callables = []

        self._is_running = False
        self.future = None

        #: Quoted insert. This flag is set if we go into quoted insert mode.
        self.quoted_insert = False

        #: Vi state. (For Vi key bindings.)
        self.vi_state = ViState()

        #: When to flush the input (For flushing escape keys.) This is important
        #: on terminals that use vt100 input. We can't distinguish the escape
        #: key from for instance the left-arrow key, if we don't know what follows
        #: after "\x1b". This little timer will consider "\x1b" to be escape if
        #: nothing did follow in this time span.
        #: This seems to work like the `ttimeoutlen` option in Vim.
        self.input_timeout = .5

        #: The `Renderer` instance.
        # Make sure that the same stdout is used, when a custom renderer has been passed.
        self._merged_style = merge_styles([
            default_style(),
            DynamicStyle(lambda: self.style),
        ])

        self.renderer = Renderer(
            self._merged_style,
            self.output,
            full_screen=full_screen,
            mouse_support=mouse_support,
            cpr_not_supported_callback=self.cpr_not_supported_callback)

        #: Render counter. This one is increased every time the UI is rendered.
        #: It can be used as a key for caching certain information during one
        #: rendering.
        self.render_counter = 0

        # Invalidate flag. When 'True', a repaint has been scheduled.
        self._invalidated = False
        self._invalidate_events = [
        ]  # Collection of 'invalidate' Event objects.
        self._last_redraw_time = 0  # Unix timestamp of last redraw. Used when
        # `min_redraw_interval` is given.

        #: The `InputProcessor` instance.
        self.key_processor = KeyProcessor(_CombinedRegistry(self))

        # If `run_in_terminal` was called. This will point to a `Future` what will be
        # set at the point whene the previous run finishes.
        self._running_in_terminal = False
        self._running_in_terminal_f = None

        # Trigger initialize callback.
        self.reset()
    def __init__(self,
                 layout: Optional[Layout] = None,
                 style: Optional[BaseStyle] = None,
                 include_default_pygments_style: FilterOrBool = True,
                 style_transformation: Optional[StyleTransformation] = None,
                 key_bindings: Optional[KeyBindingsBase] = None,
                 clipboard: Optional[Clipboard] = None,
                 full_screen: bool = False,
                 color_depth: Union[ColorDepth, Callable[[], Union[ColorDepth, None]], None] = None,
                 mouse_support: FilterOrBool = False,

                 enable_page_navigation_bindings: Optional[FilterOrBool] = None,  # Can be None, True or False.

                 paste_mode: FilterOrBool = False,
                 editing_mode: EditingMode = EditingMode.EMACS,
                 erase_when_done: bool = False,
                 reverse_vi_search_direction: FilterOrBool = False,
                 min_redraw_interval: Union[float, int, None] = None,
                 max_render_postpone_time: Union[float, int, None] = .01,

                 on_reset: Optional[ApplicationEventHandler] = None,
                 on_invalidate: Optional[ApplicationEventHandler] = None,
                 before_render: Optional[ApplicationEventHandler] = None,
                 after_render: Optional[ApplicationEventHandler] = None,

                 # I/O.
                 input: Optional[Input] = None,
                 output: Optional[Output] = None):

        # If `enable_page_navigation_bindings` is not specified, enable it in
        # case of full screen applications only. This can be overridden by the user.
        if enable_page_navigation_bindings is None:
            enable_page_navigation_bindings = Condition(lambda: self.full_screen)

        paste_mode = to_filter(paste_mode)
        mouse_support = to_filter(mouse_support)
        reverse_vi_search_direction = to_filter(reverse_vi_search_direction)
        enable_page_navigation_bindings = to_filter(enable_page_navigation_bindings)
        include_default_pygments_style = to_filter(include_default_pygments_style)

        if layout is None:
            layout = create_dummy_layout()

        if style_transformation is None:
            style_transformation = DummyStyleTransformation()

        self.style = style
        self.style_transformation = style_transformation

        # Key bindings.
        self.key_bindings = key_bindings
        self._default_bindings = load_key_bindings()
        self._page_navigation_bindings = load_page_navigation_bindings()

        self.layout = layout
        self.clipboard = clipboard or InMemoryClipboard()
        self.full_screen: bool = full_screen
        self._color_depth = color_depth
        self.mouse_support = mouse_support

        self.paste_mode = paste_mode
        self.editing_mode = editing_mode
        self.erase_when_done = erase_when_done
        self.reverse_vi_search_direction = reverse_vi_search_direction
        self.enable_page_navigation_bindings = enable_page_navigation_bindings
        self.min_redraw_interval = min_redraw_interval
        self.max_render_postpone_time = max_render_postpone_time

        # Events.
        self.on_invalidate = Event(self, on_invalidate)
        self.on_reset = Event(self, on_reset)
        self.before_render = Event(self, before_render)
        self.after_render = Event(self, after_render)

        # I/O.
        session = get_app_session()
        self.output = output or session.output
        self.input = input or session.input

        # List of 'extra' functions to execute before a Application.run.
        self.pre_run_callables: List[Callable[[], None]] = []

        self._is_running = False
        self.future: Optional[Future[_AppResult]] = None
        self.loop: Optional[AbstractEventLoop] = None
        self.context: Optional[contextvars.Context] = None

        #: Quoted insert. This flag is set if we go into quoted insert mode.
        self.quoted_insert = False

        #: Vi state. (For Vi key bindings.)
        self.vi_state = ViState()
        self.emacs_state = EmacsState()

        #: When to flush the input (For flushing escape keys.) This is important
        #: on terminals that use vt100 input. We can't distinguish the escape
        #: key from for instance the left-arrow key, if we don't know what follows
        #: after "\x1b". This little timer will consider "\x1b" to be escape if
        #: nothing did follow in this time span.
        #: This seems to work like the `ttimeoutlen` option in Vim.
        self.ttimeoutlen = .5  # Seconds.

        #: Like Vim's `timeoutlen` option. This can be `None` or a float.  For
        #: instance, suppose that we have a key binding AB and a second key
        #: binding A. If the uses presses A and then waits, we don't handle
        #: this binding yet (unless it was marked 'eager'), because we don't
        #: know what will follow. This timeout is the maximum amount of time
        #: that we wait until we call the handlers anyway. Pass `None` to
        #: disable this timeout.
        self.timeoutlen = 1.0

        #: The `Renderer` instance.
        # Make sure that the same stdout is used, when a custom renderer has been passed.
        self._merged_style = self._create_merged_style(include_default_pygments_style)

        self.renderer = Renderer(
            self._merged_style,
            self.output,
            self.input,
            full_screen=full_screen,
            mouse_support=mouse_support,
            cpr_not_supported_callback=self.cpr_not_supported_callback)

        #: Render counter. This one is increased every time the UI is rendered.
        #: It can be used as a key for caching certain information during one
        #: rendering.
        self.render_counter = 0

        # Invalidate flag. When 'True', a repaint has been scheduled.
        self._invalidated = False
        self._invalidate_events: List[Event[object]] = []  # Collection of 'invalidate' Event objects.
        self._last_redraw_time = 0.0  # Unix timestamp of last redraw. Used when
                                      # `min_redraw_interval` is given.

        #: The `InputProcessor` instance.
        self.key_processor = KeyProcessor(_CombinedRegistry(self))

        # If `run_in_terminal` was called. This will point to a `Future` what will be
        # set at the point when the previous run finishes.
        self._running_in_terminal = False
        self._running_in_terminal_f: Optional[Future[None]] = None

        # Trigger initialize callback.
        self.reset()
예제 #17
0
    def _get_key_bindings(self):
        kb = KeyBindings()

        @kb.add('c-up')
        def _(event):
            self.console.enter_copy_mode()

        @kb.add('c-x', 'a', eager=True)
        def _(event):
            self._hide_tui()
            self.app.invalidate()

        @kb.add('c-x', '1', eager=True)
        def _(event):
            self._hide_tui()
            self.source.show = True
            self.app.invalidate()

        @kb.add('c-x', '2', eager=True)
        def _(event):
            self._hide_tui()
            self.source.show = True
            self.disassembly.show = True

        @kb.add('c-x', 's', eager=True)
        def _(event):
            self.source.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 'd', eager=True)
        def _(event):
            self.disassembly.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 'c', eager=True)
        def _(event):
            self.callstack.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 'v', eager=True)
        def _(event):
            self.argsnlocals.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 'b', eager=True)
        def _(event):
            self.breakpoints.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 'r', eager=True)
        def _(event):
            self.registers.toggle_show()
            self.app.invalidate()

        @kb.add('c-x', 't', eager=True)
        def _(event):
            self.threads.toggle_show()

        @kb.add('c-s', eager=True)
        def _(event):
            self._next_style()

        @kb.add('c-l')
        def _(event):
            pass

        @kb.add('c-x')
        def _(event):
            pass

        @kb.add('s-right')
        def _(event):
            self.layout.focus_next()

        @kb.add('s-left')
        def _(event):
            self.layout.focus_previous()

        kb = merge_key_bindings([load_key_bindings(), kb])
        return kb
예제 #18
0
from prompt_toolkit.key_binding.defaults import load_key_bindings
from prompt_toolkit.keys import Keys


animal_completer = WordCompleter([
    'alligator', 'ant', 'ape', 'bat', 'bear', 'beaver', 'bee', 'bison',
    'butterfly', 'cat', 'chicken', 'crocodile', 'dinosaur', 'dog', 'dolphine',
    'dove', 'duck', 'eagle', 'elephant', 'fish', 'goat', 'gorilla', 'kangoroo',
    'leopard', 'lion', 'mouse', 'rabbit', 'rat', 'snake', 'spider', 'turkey',
    'turtle',
], ignore_case=True)


# Create key bindings registry with a custom binding for the Tab key that
# displays completions like GNU readline.
registry = load_key_bindings()
registry.add_binding(Keys.ControlI)(display_completions_like_readline)


def main():
    text = prompt('Give some animals: ', completer=animal_completer,
                  key_bindings_registry=registry,

                  # Important: for this to work: `complete_while_typing` needs
                  #            to be False.
                  complete_while_typing=False)
    print('You said: %s' % text)


if __name__ == '__main__':
    main()
def create_key_bindings(python_input, history_mapping):
    """
    Key bindings.
    """
    registry = load_key_bindings(
        enable_search=True,
        enable_extra_page_navigation=True)
    handle = registry.add_binding

    @handle(' ', filter=HasFocus(HISTORY_BUFFER))
    def _(event):
        """
        Space: select/deselect line from history pane.
        """
        b = event.current_buffer
        line_no = b.document.cursor_position_row

        if line_no in history_mapping.selected_lines:
            # Remove line.
            history_mapping.selected_lines.remove(line_no)
            history_mapping.update_default_buffer(event.cli)
        else:
            # Add line.
            history_mapping.selected_lines.add(line_no)
            history_mapping.update_default_buffer(event.cli)

            # Update cursor position
            default_buffer = event.cli.buffers[DEFAULT_BUFFER]
            default_lineno = sorted(history_mapping.selected_lines).index(line_no) + \
                history_mapping.result_line_offset
            default_buffer.cursor_position = \
                default_buffer.document.translate_row_col_to_index(default_lineno, 0)

        # Also move the cursor to the next line. (This way they can hold
        # space to select a region.)
        b.cursor_position = b.document.translate_row_col_to_index(line_no + 1, 0)

    @handle(' ', filter=HasFocus(DEFAULT_BUFFER))
    @handle(Keys.Delete, filter=HasFocus(DEFAULT_BUFFER))
    @handle(Keys.ControlH, filter=HasFocus(DEFAULT_BUFFER))
    def _(event):
        """
        Space: remove line from default pane.
        """
        b = event.current_buffer
        line_no = b.document.cursor_position_row - history_mapping.result_line_offset

        if line_no >= 0:
            try:
                history_lineno = sorted(history_mapping.selected_lines)[line_no]
            except IndexError:
                pass  # When `selected_lines` is an empty set.
            else:
                history_mapping.selected_lines.remove(history_lineno)

            history_mapping.update_default_buffer(event.cli)

    help_focussed = HasFocus(HELP_BUFFER)
    main_buffer_focussed = HasFocus(HISTORY_BUFFER) | HasFocus(DEFAULT_BUFFER)

    @handle(Keys.Tab, filter=main_buffer_focussed)
    @handle(Keys.ControlX, filter=main_buffer_focussed, eager=True)
        # Eager: ignore the Emacs [Ctrl-X Ctrl-X] binding.
    @handle(Keys.ControlW, filter=main_buffer_focussed)
    def _(event):
        " Select other window. "
        _select_other_window(event.cli)

    @handle(Keys.F4)
    def _(event):
        " Switch between Emacs/Vi mode. "
        python_input.vi_mode = not python_input.vi_mode

    @handle(Keys.F1)
    def _(event):
        " Display/hide help. "
        _toggle_help(event.cli)

    @handle(Keys.ControlJ, filter=help_focussed)
    @handle(Keys.ControlC, filter=help_focussed)
    @handle(Keys.ControlG, filter=help_focussed)
    @handle(Keys.Escape, filter=help_focussed)
    def _(event):
        " Leave help. "
        event.cli.pop_focus()

    @handle('q', filter=main_buffer_focussed)
    @handle(Keys.F3, filter=main_buffer_focussed)
    @handle(Keys.ControlC, filter=main_buffer_focussed)
    @handle(Keys.ControlG, filter=main_buffer_focussed)
    def _(event):
        " Cancel and go back. "
        event.cli.set_return_value(None)

    enable_system_bindings = Condition(lambda cli: python_input.enable_system_bindings)

    @handle(Keys.ControlZ, filter=enable_system_bindings)
    def _(event):
        " Suspend to background. "
        event.cli.suspend_to_background()

    return registry
예제 #20
0
    def load_bindings(self):
        bindings = load_key_bindings(enable_abort_and_exit_bindings=True,
                                     enable_system_bindings=True)

        @bindings.add_binding('j', filter=~self.editing)
        def down(event):
            if self.lock:
                self.scroll(1, None)
            else:
                self.move_cursor(1)

        @bindings.add_binding('k', filter=~self.editing)
        def up(event):
            if self.lock:
                self.scroll(-1, None)
            else:
                self.move_cursor(-1)

        @bindings.add_binding('g', filter=~self.editing)
        def c_d(event):
            self.scroll(-self.model.line_count(), None)

        @bindings.add_binding('G', filter=~self.editing)
        def c_d(event):
            self.scroll(self.model.line_count(), None)

        @bindings.add_binding('d', filter=~self.editing)
        def c_d(event):
            self.scroll(1, True)

        @bindings.add_binding('f', filter=~self.editing)
        def c_d(event):
            self.scroll(1, False)

        @bindings.add_binding('u', filter=~self.editing)
        def c_u(event):
            self.scroll(-1, True)

        @bindings.add_binding('b', filter=~self.editing)
        def c_u(event):
            self.scroll(-1, False)

        @bindings.add_binding('w', filter=~self.editing)
        def toggle_wrap(event):
            self.model.wrap = not self.model.wrap

        @bindings.add_binding('n', filter=~self.editing)
        def toggle_numbers(event):
            self.model.numbers = not self.model.numbers

        @bindings.add_binding('q', filter=~self.editing)
        def end_loop(event):
            event.cli.set_return_value(None)

        @bindings.add_binding('/', filter=~self.editing)
        def start_edit(event):
            self.edit = True

        @bindings.add_binding(Keys.ControlC)
        def end_edit(event):
            self.edit = False

        @bindings.add_binding('l', filter=~self.editing)
        def _(event):
            self.lock = not self.lock

        return bindings
예제 #21
0
    Window(height=D.exact(1), content=FillControl('-', token=Token.Line)),

    # The 'body', like defined above.
    layout,
])

# 2. Adding key bindings
#   --------------------

# As a demonstration, we will add just a ControlQ key binding to exit the
# application.  Key bindings are registered in a
# `prompt_toolkit.key_bindings.registry.Registry` instance. We use the
# `load_default_key_bindings` utility function to create a registry that
# already contains the default key bindings.

registry = load_key_bindings()

# Now add the Ctrl-Q binding. We have to pass `eager=True` here. The reason is
# that there is another key *sequence* that starts with Ctrl-Q as well. Yes, a
# key binding is linked to a sequence of keys, not necessarily one key. So,
# what happens if there is a key binding for the letter 'a' and a key binding
# for 'ab'. When 'a' has been pressed, nothing will happen yet. Because the
# next key could be a 'b', but it could as well be anything else. If it's a 'c'
# for instance, we'll handle the key binding for 'a' and then look for a key
# binding for 'c'. So, when there's a common prefix in a key binding sequence,
# prompt-toolkit will wait calling a handler, until we have enough information.

# Now, There is an Emacs key binding for the [Ctrl-Q Any] sequence by default.
# Pressing Ctrl-Q followed by any other key will do a quoted insert. So to be
# sure that we won't wait for that key binding to match, but instead execute
# Ctrl-Q immediately, we can pass eager=True. (Don't make a habbit of adding
예제 #22
0
def create_key_bindings(editor):
    """
    Create custom key bindings.

    This starts with the key bindings, defined by `prompt-toolkit`, but adds
    the ones which are specific for the editor.
    """
    # Create new Key binding manager.
    registry = load_key_bindings(
        enable_search=True,
        enable_extra_page_navigation=True,
        enable_system_bindings=True)

    # Filters.
    vi_buffer_focussed = Condition(lambda cli: cli.current_buffer_name.startswith('buffer-'))

    in_insert_mode = ViInsertMode() & vi_buffer_focussed
    in_navigation_mode = ViNavigationMode() & vi_buffer_focussed

    handle = registry.add_binding

    @handle(Keys.ControlT)
    def _(event):
        """
        Override default behaviour of prompt-toolkit.
        (Control-T will swap the last two characters before the cursor, because
        that's what readline does.)
        """
        pass

    @handle(Keys.ControlT, filter=in_insert_mode)
    def indent_line(event):
        """
        Indent current line.
        """
        b = event.cli.current_buffer

        # Move to start of line.
        pos = b.document.get_start_of_line_position(after_whitespace=True)
        b.cursor_position += pos

        # Insert tab.
        if editor.expand_tab:
            b.insert_text('    ')
        else:
            b.insert_text('\t')

        # Restore cursor.
        b.cursor_position -= pos

    @handle(Keys.ControlR, filter=in_navigation_mode, save_before=(lambda e: False))
    def redo(event):
        """
        Redo.
        """
        event.cli.current_buffer.redo()

    @handle(':', filter=in_navigation_mode)
    def enter_command_mode(event):
        """
        Entering command mode.
        """
        editor.enter_command_mode()

    @handle(Keys.Tab, filter=ViInsertMode() &
            ~HasFocus(COMMAND_BUFFER) & WhitespaceBeforeCursorOnLine())
    def autocomplete_or_indent(event):
        """
        When the 'tab' key is pressed with only whitespace character before the
        cursor, do autocompletion. Otherwise, insert indentation.
        """
        b = event.cli.current_buffer
        if editor.expand_tab:
            b.insert_text('    ')
        else:
            b.insert_text('\t')

    @handle(Keys.Escape, filter=HasFocus(COMMAND_BUFFER))
    @handle(Keys.ControlC, filter=HasFocus(COMMAND_BUFFER))
    @handle(
        Keys.Backspace,
        filter=HasFocus(COMMAND_BUFFER) & Condition(lambda cli: cli.buffers[COMMAND_BUFFER].text == ''))
    def leave_command_mode(event):
        """
        Leaving command mode.
        """
        editor.leave_command_mode()

    @handle(Keys.ControlW, Keys.ControlW, filter=in_navigation_mode)
    def focus_next_window(event):
        editor.window_arrangement.cycle_focus()
        editor.sync_with_prompt_toolkit()

    @handle(Keys.ControlW, 'n', filter=in_navigation_mode)
    def horizontal_split(event):
        """
        Split horizontally.
        """
        editor.window_arrangement.hsplit(None)
        editor.sync_with_prompt_toolkit()

    @handle(Keys.ControlW, 'v', filter=in_navigation_mode)
    def vertical_split(event):
        """
        Split vertically.
        """
        editor.window_arrangement.vsplit(None)
        editor.sync_with_prompt_toolkit()

    @handle('g', 't', filter=in_navigation_mode)
    def focus_next_tab(event):
        editor.window_arrangement.go_to_next_tab()
        editor.sync_with_prompt_toolkit()

    @handle('g', 'T', filter=in_navigation_mode)
    def focus_previous_tab(event):
        editor.window_arrangement.go_to_previous_tab()
        editor.sync_with_prompt_toolkit()

    @handle(Keys.ControlJ, filter=in_navigation_mode)
    def goto_line_beginning_or_open_file(event):
        """
        Enter in navigation mode should move to the start of the next line.
        Enter in directory mode should open the directory or file under the cursor.
        """
        if editor.file_explorer:
            b = event.current_buffer
            i0 = b.cursor_position + b.document.get_start_of_line_position()
            i1 = b.cursor_position + b.document.get_end_of_line_position()
            name_under_cursor = b.text[i0:i1]
            editor.file_explorer = os.path.normpath(os.path.join(editor.file_explorer, name_under_cursor))
            editor.window_arrangement.open_buffer(editor.file_explorer, show_in_current_window=True)
            editor.sync_with_prompt_toolkit()
        else:
            b = event.current_buffer
            b.cursor_down(count=event.arg)
            b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True)

    @handle(Keys.F1)
    def show_help(event):
        editor.show_help()

    return registry
예제 #23
0
def show_dialog(questions, title, confirm, cancel):

    handlers = []

    for q in questions:
        handler = get_handlers_registry().get_handler(q,
                                                      questions,
                                                      None,
                                                      mode=Mode.DIALOG)
        handlers.append(handler)

    def ok_handler():
        result = dict()
        for handler in handlers:
            result.update(handler.get_answer())
        get_app().exit(result=result)

    dialog = Dialog(title=title,
                    body=HSplit([h.get_layout() for h in handlers], padding=1),
                    buttons=[
                        Button(text=confirm, handler=ok_handler),
                        Button(text=cancel, handler=lambda: get_app().exit()),
                    ],
                    with_background=True)

    # Key bindings.
    bindings = KeyBindings()
    bindings.add('tab')(focus_next)
    bindings.add('s-tab')(focus_previous)

    app = Application(layout=Layout(dialog),
                      key_bindings=merge_key_bindings([
                          load_key_bindings(),
                          bindings,
                      ]),
                      mouse_support=True,
                      style=get_theme_manager().get_current_style(),
                      full_screen=True)

    size = app.renderer.output.get_size()
    container = app.layout.container
    height = container.preferred_height(size.columns, size.rows).preferred
    if height > size.rows:
        message_dialog(title='Too many questions',
                       text='Cannot render a {} rows dialog in a '
                       '{} rows screen: too many questions!'.format(
                           height, size.rows),
                       ok_text='Got it!')
        return

    while True:
        validation_errors = []
        answers = app.run()
        if answers is None:
            return
        for handler in handlers:
            for msg in handler.apply_validators():
                validation_errors.append('{}: {}'.format(
                    handler.get_variable_name(), msg))
        if not validation_errors:
            return answers

        show_error_dialog(validation_errors)
예제 #24
0
def create_key_bindings(pager):
    registry = load_key_bindings(enable_search=True,
                                 enable_extra_page_navigation=True,
                                 enable_system_bindings=True)
    handle = registry.add_binding

    @Condition
    def has_colon(cli):
        return pager.in_colon_mode

    @Condition
    def default_focus(cli):
        return (cli.current_buffer_name.startswith('source')
                and not pager.in_colon_mode)

    @Condition
    def displaying_help(cli):
        return pager.displaying_help

    for c in '01234556789':

        @handle(c, filter=default_focus)
        def _(event, c=c):
            event.append_to_arg_count(c)

    @handle('q', filter=default_focus | has_colon)
    @handle('Q', filter=default_focus | has_colon)
    @handle('Z', 'Z', filter=default_focus)
    def _(event):
        " Quit. "
        if pager.displaying_help:
            pager.quit_help()
        else:
            event.cli.set_return_value(None)

    @handle(' ', filter=default_focus)
    @handle('f', filter=default_focus)
    @handle(Keys.ControlF, filter=default_focus)
    @handle(Keys.ControlV, filter=default_focus)
    def _(event):
        " Page down."
        scroll_page_down(event)

    @handle('b', filter=default_focus)
    @handle(Keys.ControlB, filter=default_focus)
    @handle(Keys.Escape, 'v', filter=default_focus)
    def _(event):
        " Page up."
        scroll_page_up(event)

    @handle('d', filter=default_focus)
    @handle(Keys.ControlD, filter=default_focus)
    def _(event):
        " Half page down."
        scroll_half_page_down(event)

    @handle('u', filter=default_focus)
    @handle(Keys.ControlU, filter=default_focus)
    def _(event):
        " Half page up."
        scroll_half_page_up(event)

    @handle('e', filter=default_focus)
    @handle('j', filter=default_focus)
    @handle(Keys.ControlE, filter=default_focus)
    @handle(Keys.ControlN, filter=default_focus)
    @handle(Keys.ControlJ, filter=default_focus)
    @handle(Keys.ControlM, filter=default_focus)
    @handle(Keys.Down, filter=default_focus)
    def _(event):
        " Scoll one line down."
        if event.arg > 1:
            # When an argument is given, go this amount of lines down.
            event.current_buffer.auto_down(count=event.arg)
        else:
            scroll_one_line_down(event)

    @handle('y', filter=default_focus)
    @handle('k', filter=default_focus)
    @handle(Keys.ControlY, filter=default_focus)
    @handle(Keys.ControlK, filter=default_focus)
    @handle(Keys.ControlP, filter=default_focus)
    @handle(Keys.Up, filter=default_focus)
    def _(event):
        " Scoll one line up."
        if event.arg > 1:
            event.current_buffer.auto_up(count=event.arg)
        else:
            scroll_one_line_up(event)

    @handle('/', filter=default_focus)
    def _(event):
        " Start searching forward. "
        event.cli.search_state.direction = IncrementalSearchDirection.FORWARD
        event.cli.vi_state.input_mode = InputMode.INSERT
        event.cli.push_focus(SEARCH_BUFFER)

    @handle('?', filter=default_focus)
    def _(event):
        " Start searching backwards. "
        event.cli.search_state.direction = IncrementalSearchDirection.BACKWARD
        event.cli.vi_state.input_mode = InputMode.INSERT
        event.cli.push_focus(SEARCH_BUFFER)

    @handle('n', filter=default_focus)
    def _(event):
        " Search next. "
        event.current_buffer.apply_search(event.cli.search_state,
                                          include_current_position=False,
                                          count=event.arg)

    @handle('N', filter=default_focus)
    def _(event):
        " Search previous. "
        event.current_buffer.apply_search(~event.cli.search_state,
                                          include_current_position=False,
                                          count=event.arg)

    @handle(Keys.Escape, 'u')
    def _(event):
        " Toggle search highlighting. "
        pager.highlight_search = not pager.highlight_search

    @handle('=', filter=default_focus)
    @handle(Keys.ControlG, filter=default_focus)
    @handle('f', filter=has_colon)
    def _(event):
        " Print the current file name. "
        pager.message = ' {} '.format(pager.source.get_name())

    @handle('h', filter=default_focus & ~displaying_help)
    @handle('H', filter=default_focus & ~displaying_help)
    def _(event):
        " Display Help. "
        pager.display_help()

    @handle('g', filter=default_focus)
    @handle('<', filter=default_focus)
    @handle(Keys.Escape, '<', filter=default_focus)
    def _(event):
        " Go to the first line of the file. "
        event.current_buffer.cursor_position = 0

    @handle('G', filter=default_focus)
    @handle('>', filter=default_focus)
    @handle(Keys.Escape, '>', filter=default_focus)
    def _(event):
        " Go to the last line of the file. "
        b = event.current_buffer
        b.cursor_position = len(b.text)

    @handle('m', Keys.Any, filter=default_focus)
    def _(event):
        " Mark current position. "
        pager.marks[event.data] = (event.current_buffer.cursor_position,
                                   pager.layout.buffer_window.vertical_scroll)

    @handle("'", Keys.Any, filter=default_focus)
    def _(event):
        " Go to a previously marked position. "
        go_to_mark(event, event.data)

    @handle(Keys.ControlX, Keys.ControlX, filter=default_focus)
    def _(event):
        " Same as '. "
        go_to_mark(event, '.')

    def go_to_mark(event, mark):
        b = event.current_buffer
        try:
            if mark == '^':  # Start of file.
                cursor_pos, vertical_scroll = 0, 0
            elif mark == '$':  # End of file - mark.
                cursor_pos, vertical_scroll = len(b.text), 0
            else:  # Custom mark.
                cursor_pos, vertical_scroll = pager.marks[mark]
        except KeyError:
            pass  # TODO: show warning.
        else:
            b.cursor_position = cursor_pos
            pager.layout.buffer_window.vertical_scroll = vertical_scroll

    @handle('F', filter=default_focus)
    def _(event):
        " Forward forever, like 'tail -f'. "
        pager.forward_forever = True

    @handle(Keys.ControlR, filter=default_focus)
    @handle('r', filter=default_focus)
    @handle('R', filter=default_focus)
    def _(event):
        event.cli.renderer.clear()

    def search_buffer_is_empty(cli):
        " Returns True when the search buffer is empty. "
        return cli.buffers[SEARCH_BUFFER].text == ''

    @handle(Keys.Backspace,
            filter=HasFocus(SEARCH_BUFFER) & Condition(search_buffer_is_empty))
    def _(event):
        " Cancel search when backspace is pressed. "
        event.cli.vi_state.input_mode = InputMode.NAVIGATION
        event.cli.pop_focus()
        event.cli.buffers[SEARCH_BUFFER].reset()

    @handle(Keys.Left, filter=default_focus)
    @handle(Keys.Escape, '(', filter=default_focus)
    def _(event):
        " Scroll half page to the left. "
        w = find_window_for_buffer_name(event.cli,
                                        event.cli.current_buffer_name)
        b = event.cli.current_buffer

        if w and w.render_info:
            info = w.render_info
            amount = info.window_width // 2

            # Move cursor horizontally.
            value = b.cursor_position - min(
                amount, len(b.document.current_line_before_cursor))
            b.cursor_position = value

            # Scroll.
            w.horizontal_scroll = max(0, w.horizontal_scroll - amount)

    @handle(Keys.Right, filter=default_focus)
    @handle(Keys.Escape, ')', filter=default_focus)
    def _(event):
        " Scroll half page to the right. "
        w = find_window_for_buffer_name(event.cli,
                                        event.cli.current_buffer_name)
        b = event.cli.current_buffer

        if w and w.render_info:
            info = w.render_info
            amount = info.window_width // 2

            # Move the cursor first to a visible line that is long enough to
            # have the cursor visible after scrolling. (Otherwise, the Window
            # will scroll back.)
            xpos = w.horizontal_scroll + amount

            for line in info.displayed_lines:
                if len(b.document.lines[line]) >= xpos:
                    b.cursor_position = b.document.translate_row_col_to_index(
                        line, xpos)
                    break

            # Scroll.
            w.horizontal_scroll = max(0, w.horizontal_scroll + amount)

    @handle(':', filter=default_focus & ~displaying_help)
    def _(event):
        pager.in_colon_mode = True

    @handle('n', filter=has_colon)
    def _(event):
        " Go to next file. "
        pager.focus_next_source()

    @handle('p', filter=has_colon)
    def _(event):
        " Go to previous file. "
        pager.focus_previous_source()

    @handle('e', filter=has_colon)
    @handle(Keys.ControlX, Keys.ControlV, filter=default_focus)
    def _(event):
        pager.buffers.focus(event.cli, 'EXAMINE')
        pager.in_colon_mode = False

    @handle('d', filter=has_colon)
    def _(event):
        pager.remove_current_source()

    @handle(Keys.Any, filter=has_colon)
    @handle(Keys.Backspace, filter=has_colon)
    def _(event):
        pager.in_colon_mode = False
        pager.message = 'No command.'

    @handle(Keys.ControlC, filter=HasFocus('EXAMINE'))
    @handle(Keys.ControlG, filter=HasFocus('EXAMINE'))
    def _(event):
        " Cancel 'Examine' input. "
        pager.buffers.focus(event.cli,
                            pager.source_info[pager.source].buffer_name)

    @handle(Keys.ControlZ,
            filter=Condition(lambda cli: suspend_to_background_supported()))
    def _(event):
        " Suspend to bakground. "
        event.cli.suspend_to_background()

    return registry
예제 #25
0
    def __init__(
        self,
        layout: Optional[Layout] = None,
        style: Optional[BaseStyle] = None,
        include_default_pygments_style: FilterOrBool = True,
        style_transformation: Optional[StyleTransformation] = None,
        key_bindings: Optional[KeyBindingsBase] = None,
        clipboard: Optional[Clipboard] = None,
        full_screen: bool = False,
        color_depth: Union[ColorDepth, Callable[[], Union[ColorDepth, None]],
                           None] = None,
        mouse_support: FilterOrBool = False,
        enable_page_navigation_bindings: Optional[
            FilterOrBool] = None,  # Can be None, True or False.
        paste_mode: FilterOrBool = False,
        editing_mode: EditingMode = EditingMode.EMACS,
        erase_when_done: bool = False,
        reverse_vi_search_direction: FilterOrBool = False,
        min_redraw_interval: Union[float, int, None] = None,
        max_render_postpone_time: Union[float, int, None] = 0.01,
        refresh_interval: Optional[float] = None,
        on_reset: Optional[ApplicationEventHandler] = None,
        on_invalidate: Optional[ApplicationEventHandler] = None,
        before_render: Optional[ApplicationEventHandler] = None,
        after_render: Optional[ApplicationEventHandler] = None,
        # I/O.
        input: Optional[Input] = None,
        output: Optional[Output] = None,
    ):

        # If `enable_page_navigation_bindings` is not specified, enable it in
        # case of full screen applications only. This can be overridden by the user.
        if enable_page_navigation_bindings is None:
            enable_page_navigation_bindings = Condition(
                lambda: self.full_screen)

        paste_mode = to_filter(paste_mode)
        mouse_support = to_filter(mouse_support)
        reverse_vi_search_direction = to_filter(reverse_vi_search_direction)
        enable_page_navigation_bindings = to_filter(
            enable_page_navigation_bindings)
        include_default_pygments_style = to_filter(
            include_default_pygments_style)

        if layout is None:
            layout = create_dummy_layout()

        if style_transformation is None:
            style_transformation = DummyStyleTransformation()

        self.style = style
        self.style_transformation = style_transformation

        # Key bindings.
        self.key_bindings = key_bindings
        self._default_bindings = load_key_bindings()
        self._page_navigation_bindings = load_page_navigation_bindings()

        self.layout = layout
        self.clipboard = clipboard or InMemoryClipboard()
        self.full_screen: bool = full_screen
        self._color_depth = color_depth
        self.mouse_support = mouse_support

        self.paste_mode = paste_mode
        self.editing_mode = editing_mode
        self.erase_when_done = erase_when_done
        self.reverse_vi_search_direction = reverse_vi_search_direction
        self.enable_page_navigation_bindings = enable_page_navigation_bindings
        self.min_redraw_interval = min_redraw_interval
        self.max_render_postpone_time = max_render_postpone_time
        self.refresh_interval = refresh_interval

        # Events.
        self.on_invalidate = Event(self, on_invalidate)
        self.on_reset = Event(self, on_reset)
        self.before_render = Event(self, before_render)
        self.after_render = Event(self, after_render)

        # I/O.
        session = get_app_session()
        self.output = output or session.output
        self.input = input or session.input

        # List of 'extra' functions to execute before a Application.run.
        self.pre_run_callables: List[Callable[[], None]] = []

        self._is_running = False
        self.future: Optional[Future[_AppResult]] = None
        self.loop: Optional[AbstractEventLoop] = None
        self.context: Optional[contextvars.Context] = None

        #: Quoted insert. This flag is set if we go into quoted insert mode.
        self.quoted_insert = False

        #: Vi state. (For Vi key bindings.)
        self.vi_state = ViState()
        self.emacs_state = EmacsState()

        #: When to flush the input (For flushing escape keys.) This is important
        #: on terminals that use vt100 input. We can't distinguish the escape
        #: key from for instance the left-arrow key, if we don't know what follows
        #: after "\x1b". This little timer will consider "\x1b" to be escape if
        #: nothing did follow in this time span.
        #: This seems to work like the `ttimeoutlen` option in Vim.
        self.ttimeoutlen = 0.5  # Seconds.

        #: Like Vim's `timeoutlen` option. This can be `None` or a float.  For
        #: instance, suppose that we have a key binding AB and a second key
        #: binding A. If the uses presses A and then waits, we don't handle
        #: this binding yet (unless it was marked 'eager'), because we don't
        #: know what will follow. This timeout is the maximum amount of time
        #: that we wait until we call the handlers anyway. Pass `None` to
        #: disable this timeout.
        self.timeoutlen = 1.0

        #: The `Renderer` instance.
        # Make sure that the same stdout is used, when a custom renderer has been passed.
        self._merged_style = self._create_merged_style(
            include_default_pygments_style)

        self.renderer = Renderer(
            self._merged_style,
            self.output,
            self.input,
            full_screen=full_screen,
            mouse_support=mouse_support,
            cpr_not_supported_callback=self.cpr_not_supported_callback,
        )

        #: Render counter. This one is increased every time the UI is rendered.
        #: It can be used as a key for caching certain information during one
        #: rendering.
        self.render_counter = 0

        # Invalidate flag. When 'True', a repaint has been scheduled.
        self._invalidated = False
        self._invalidate_events: List[Event[object]] = [
        ]  # Collection of 'invalidate' Event objects.
        self._last_redraw_time = 0.0  # Unix timestamp of last redraw. Used when
        # `min_redraw_interval` is given.

        #: The `InputProcessor` instance.
        self.key_processor = KeyProcessor(_CombinedRegistry(self))

        # If `run_in_terminal` was called. This will point to a `Future` what will be
        # set at the point when the previous run finishes.
        self._running_in_terminal = False
        self._running_in_terminal_f: Optional[Future[None]] = None

        # Trigger initialize callback.
        self.reset()
예제 #26
0
def interrogatio(questions, theme='default'):
    """
    Prompts user for inputs as defined in the questions parameter and returns
    a dictionary with the answers.

    :param questions: a list of questions.
    :type questions: list
    :param theme: the name of the theme to use.
    :type theme: string

    :return: a dictionary with the answers.
    :rtype: dict

    :raise InvalidQuestionError: if there is an error in the question
                                 definition.
    :raise ThemeNotFoundError: if the specified theme does not exists.

    Usage:

    .. code-block:: python

        from interrogatio import interrogatio
        questions = [
            {
                'name': 'name',
                'type': 'input',
                'message': 'What is your name'
            },
            {
                'name': 'favorite_pet',
                'type': 'input',
                'message': 'What is your favorite pet'
            }
        ]
        answers = interrogatio(questions, theme='purple')
    """
    set_theme(theme)
    answers = {}
    validate_questions(questions)
    for q in questions:
        handler = get_instance(q)
        handler.set_context(answers)
        layout = handler.get_layout()
        layout.align = HorizontalAlign.LEFT

        bindings = [load_key_bindings()]

        handler_bindings = handler.get_keybindings()

        if handler_bindings:  # pragma: no branch
            bindings.append(handler_bindings)

        app = Application(
            layout=Layout(layout),
            key_bindings=merge_key_bindings(bindings),
            style=for_prompt(),
        )

        while True:
            result = app.run()
            if not result:
                return
            if handler.is_valid(answers):
                answers.update(handler.get_answer())
                break
            else:
                print_formatted_text(
                    FormattedText([('class:error', handler.errors[0])]),
                    style=for_prompt(),
                )
    return answers
예제 #27
0
    def __init__(self):
        self.command_parser = BrewPiCommandParser(self)

        self.buffers = {
            DEFAULT_BUFFER:
            Buffer(completer=command_completer,
                   enable_history_search=True,
                   history=InMemoryHistory(),
                   accept_action=AcceptAction(self.command_parser.parse)),
            'MESSAGES':
            Buffer(),
            'RESULT':
            Buffer(),
            'STATE':
            Buffer(),
        }

        self.registry = load_key_bindings()
        self.registry.add_binding(Keys.ControlC,
                                  eager=True)(self._on_request_shutdown)
        self.registry.add_binding(Keys.ControlQ,
                                  eager=True)(self._on_request_shutdown)

        self.layout = HSplit([
            # One window that holds the BufferControl with the default buffer on the
            # left.
            VSplit([
                HSplit([
                    Window(content=TokenListControl(get_tokens=lambda cli: [(
                        Token.Title, 'Command Result')]),
                           height=D.exact(1)),
                    Window(content=BufferControl(buffer_name='RESULT'),
                           wrap_lines=True,
                           left_margins=[ScrollbarMargin()]),
                ]),
                Window(width=D.exact(1),
                       content=FillControl('|', token=Token.Line)),
                HSplit([
                    Window(content=TokenListControl(get_tokens=lambda cli: [(
                        Token.Title, 'Raw Protocol Messages')]),
                           height=D.exact(1)),
                    Window(
                        content=BufferControl(buffer_name='MESSAGES',
                                              lexer=PygmentsLexer(JsonLexer)),
                        wrap_lines=True,
                        left_margins=[NumberredMargin()],
                        right_margins=[ScrollbarMargin()])
                ])
            ]),
            VSplit([
                Window(content=TokenListControl(
                    get_tokens=self.get_prompt_tokens),
                       height=D.exact(1),
                       dont_extend_width=True),
                Window(content=BufferControl(buffer_name=DEFAULT_BUFFER),
                       height=D.exact(1),
                       dont_extend_height=True),
            ]),
            Window(content=BufferControl(buffer_name='STATE'),
                   height=D.exact(1),
                   dont_extend_height=True)
        ])

        super().__init__(
            layout=self.layout,
            buffers=self.buffers,
            key_bindings_registry=self.registry,
            mouse_support=True,
            style=style_from_pygments(
                get_style_by_name('emacs'),
                style_dict={
                    Token.Toolbar:
                    '#ffffff bg:#333333',
                    Token.Title:
                    '#ffffff bg:#000088',
                    # User input.
                    Token:
                    '#ff0066',

                    # Prompt.
                    Token.Name:
                    '#884444 italic',
                    Token.At:
                    '#00aa00',
                    Token.Colon:
                    '#00aa00',
                    Token.Pound:
                    '#00aa00',
                    Token.Host:
                    '#000088 bg:#aaaaff',
                    Token.Path:
                    '#884444 underline',
                    # Make a selection reverse/underlined.
                    # (Use Control-Space to select.)
                    Token.SelectedText:
                    'reverse underline',
                }),
            use_alternate_screen=True)

        # BrewPi Stuff
        self.controller_manager = BrewPiControllerManager()
        self.msg_decoder = RawMessageDecoder()

        self.controller = None
예제 #28
0
    def __init__(self, project=None, extra_locals=None):
        """
        Launch the Brownie console.

        Arguments
        ---------
        project : `Project`, optional
            Active Brownie project to include in the console's local namespace.
        extra_locals: dict, optional
            Additional variables to add to the console namespace.
        """
        console_settings = CONFIG.settings["console"]

        locals_dict = dict((i, getattr(brownie, i)) for i in brownie.__all__)
        locals_dict.update(_dir=dir,
                           dir=self._dir,
                           exit=_Quitter("exit"),
                           quit=_Quitter("quit"),
                           _console=self)

        if project:
            project._update_and_register(locals_dict)

        # only make GUI available if Tkinter is installed
        try:
            Gui = importlib.import_module("brownie._gui").Gui
            locals_dict["Gui"] = Gui
        except ModuleNotFoundError:
            pass

        if extra_locals:
            locals_dict.update(extra_locals)

        # create prompt session object
        history_file = str(_get_data_folder().joinpath(".history").absolute())
        kwargs = {}
        if console_settings["show_colors"]:
            kwargs.update(
                lexer=PygmentsLexer(PythonLexer),
                style=style_from_pygments_cls(
                    get_style_by_name(console_settings["color_style"])),
                include_default_pygments_style=False,
            )
        if console_settings["auto_suggest"]:
            kwargs["auto_suggest"] = ConsoleAutoSuggest(self, locals_dict)
        if console_settings["completions"]:
            kwargs["completer"] = ConsoleCompleter(self, locals_dict)

        self.compile_mode = "single"
        self.prompt_session = PromptSession(
            history=SanitizedFileHistory(history_file, locals_dict),
            input=self.prompt_input,
            key_bindings=KeyBindings(),
            **kwargs,
        )

        # add custom bindings
        key_bindings = self.prompt_session.key_bindings
        key_bindings.add(Keys.BracketedPaste)(self.paste_event)

        key_bindings.add("c-i")(self.tab_event)
        key_bindings.get_bindings_for_keys(
            ("c-i", ))[-1].filter = lambda: not self.tab_filter()

        # modify default bindings
        key_bindings = load_key_bindings()
        key_bindings.get_bindings_for_keys(
            ("c-i", ))[-1].filter = self.tab_filter

        if console_settings["auto_suggest"]:
            # remove the builtin binding for auto-suggest acceptance
            key_bindings = self.prompt_session.app.key_bindings
            accept_binding = key_bindings.get_bindings_for_keys(("right", ))[0]
            key_bindings._bindings2.remove(accept_binding.handler)

        # this is required because of a pytest conflict when using the debugging console
        if sys.platform == "win32":
            import colorama

            colorama.init()

        super().__init__(locals_dict)
예제 #29
0
def show_dialog(questions, title, confirm, cancel):

    handlers = []
    layouts = []
    for q in questions:
        handler = get_instance(q)
        l = handler.get_layout()
        l.align = HorizontalAlign.JUSTIFY
        layouts.append(l)
        handlers.append(handler)

    def ok_handler():
        result = dict()
        for handler in handlers:
            result.update(handler.get_answer())
        get_app().exit(result=result)

    dialog = Dialog(title=title,
                    body=HSplit(layouts, padding=1),
                    buttons=[
                        Button(text=confirm, handler=ok_handler),
                        Button(text=cancel, handler=lambda: get_app().exit()),
                    ],
                    with_background=True)

    # Key bindings.
    bindings = KeyBindings()

    app = Application(layout=Layout(dialog),
                      key_bindings=merge_key_bindings([
                          load_key_bindings(),
                          bindings,
                      ]),
                      mouse_support=True,
                      style=for_dialog(),
                      full_screen=True)

    size = app.renderer.output.get_size()
    container = app.layout.container
    height = container.preferred_height(size.columns, size.rows).preferred
    if height > size.rows:
        message_dialog(title='Too many questions',
                       text='Cannot render a {} rows dialog in a '
                       '{} rows screen: too many questions!'.format(
                           height, size.rows),
                       ok_text='Got it!')
        return

    while True:
        validation_errors = []
        answers = app.run()
        if answers is None:
            return
        for handler in handlers:
            if not handler.is_valid():
                for msg in handler.errors:
                    validation_errors.append('{}: {}'.format(
                        handler.get_variable_name(), msg))
        if not validation_errors:
            return answers

        show_error_dialog(validation_errors)
예제 #30
0
    def __init__(self, layout=None,
                 style=None, include_default_pygments_style=True,
                 key_bindings=None, clipboard=None,
                 full_screen=False, color_depth=None,
                 mouse_support=False,

                 enable_page_navigation_bindings=None,  # Can be None, True or False.

                 paste_mode=False,
                 editing_mode=EditingMode.EMACS,
                 erase_when_done=False,
                 reverse_vi_search_direction=False,
                 min_redraw_interval=None,
                 max_render_postpone_time=0,

                 on_reset=None, on_invalidate=None,
                 before_render=None, after_render=None,

                 # I/O.
                 input=None, output=None):

        # If `enable_page_navigation_bindings` is not specified, enable it in
        # case of full screen applications only. This can be overridden by the user.
        if enable_page_navigation_bindings is None:
            enable_page_navigation_bindings = Condition(lambda: self.full_screen)

        paste_mode = to_filter(paste_mode)
        mouse_support = to_filter(mouse_support)
        reverse_vi_search_direction = to_filter(reverse_vi_search_direction)
        enable_page_navigation_bindings = to_filter(enable_page_navigation_bindings)
        include_default_pygments_style = to_filter(include_default_pygments_style)

        assert layout is None or isinstance(layout, Layout), 'Got layout: %r' % (layout, )
        assert key_bindings is None or isinstance(key_bindings, KeyBindingsBase)
        assert clipboard is None or isinstance(clipboard, Clipboard)
        assert isinstance(full_screen, bool)
        assert (color_depth is None or callable(color_depth) or
                color_depth in ColorDepth._ALL), 'Got color_depth: %r' % (color_depth, )
        assert isinstance(editing_mode, six.string_types)
        assert style is None or isinstance(style, BaseStyle)
        assert isinstance(erase_when_done, bool)
        assert min_redraw_interval is None or isinstance(min_redraw_interval, (float, int))
        assert max_render_postpone_time is None or isinstance(max_render_postpone_time, (float, int))

        assert on_reset is None or callable(on_reset)
        assert on_invalidate is None or callable(on_invalidate)
        assert before_render is None or callable(before_render)
        assert after_render is None or callable(after_render)

        assert output is None or isinstance(output, Output)
        assert input is None or isinstance(input, Input)

        self.style = style

        if layout is None:
            layout = create_dummy_layout()

        # Key bindings.
        self.key_bindings = key_bindings
        self._default_bindings = load_key_bindings()
        self._page_navigation_bindings = load_page_navigation_bindings()

        self.layout = layout
        self.clipboard = clipboard or InMemoryClipboard()
        self.full_screen = full_screen
        self._color_depth = color_depth
        self.mouse_support = mouse_support

        self.paste_mode = paste_mode
        self.editing_mode = editing_mode
        self.erase_when_done = erase_when_done
        self.reverse_vi_search_direction = reverse_vi_search_direction
        self.enable_page_navigation_bindings = enable_page_navigation_bindings
        self.min_redraw_interval = min_redraw_interval
        self.max_render_postpone_time = max_render_postpone_time

        # Events.
        self.on_invalidate = Event(self, on_invalidate)
        self.on_reset = Event(self, on_reset)
        self.before_render = Event(self, before_render)
        self.after_render = Event(self, after_render)

        # I/O.
        self.output = output or get_default_output()
        self.input = input or get_default_input()

        # List of 'extra' functions to execute before a Application.run.
        self.pre_run_callables = []

        self._is_running = False
        self.future = None

        #: Quoted insert. This flag is set if we go into quoted insert mode.
        self.quoted_insert = False

        #: Vi state. (For Vi key bindings.)
        self.vi_state = ViState()
        self.emacs_state = EmacsState()

        #: When to flush the input (For flushing escape keys.) This is important
        #: on terminals that use vt100 input. We can't distinguish the escape
        #: key from for instance the left-arrow key, if we don't know what follows
        #: after "\x1b". This little timer will consider "\x1b" to be escape if
        #: nothing did follow in this time span.
        #: This seems to work like the `ttimeoutlen` option in Vim.
        self.ttimeoutlen = .5  # Seconds.

        #: Like Vim's `timeoutlen` option. This can be `None` or a float.  For
        #: instance, suppose that we have a key binding AB and a second key
        #: binding A. If the uses presses A and then waits, we don't handle
        #: this binding yet (unless it was marked 'eager'), because we don't
        #: know what will follow. This timeout is the maximum amount of time
        #: that we wait until we call the handlers anyway. Pass `None` to
        #: disable this timeout.
        self.timeoutlen = 1.0

        #: The `Renderer` instance.
        # Make sure that the same stdout is used, when a custom renderer has been passed.
        self._merged_style = self._create_merged_style(include_default_pygments_style)

        self.renderer = Renderer(
            self._merged_style,
            self.output,
            full_screen=full_screen,
            mouse_support=mouse_support,
            cpr_not_supported_callback=self.cpr_not_supported_callback)

        #: Render counter. This one is increased every time the UI is rendered.
        #: It can be used as a key for caching certain information during one
        #: rendering.
        self.render_counter = 0

        # Invalidate flag. When 'True', a repaint has been scheduled.
        self._invalidated = False
        self._invalidate_events = []  # Collection of 'invalidate' Event objects.
        self._last_redraw_time = 0  # Unix timestamp of last redraw. Used when
                                    # `min_redraw_interval` is given.

        #: The `InputProcessor` instance.
        self.key_processor = KeyProcessor(_CombinedRegistry(self))

        # If `run_in_terminal` was called. This will point to a `Future` what will be
        # set at the point when the previous run finishes.
        self._running_in_terminal = False
        self._running_in_terminal_f = None

        # Trigger initialize callback.
        self.reset()
예제 #31
0
from new_radio_list import NewRadioList

library = 'jqueryui'
resp = requests.get(
    'https://api.cdnjs.com/libraries/{0}?fields=assets'.format(library))
if resp.ok:
    data = json.loads(resp.text)
    if isinstance(data, dict) and 'assets' in data:
        assets = data['assets']
        versions = list(map(lambda item: item['version'], assets))
        print(versions)
        values = list(map(lambda item: (item, item), versions))
        rdo = NewRadioList(values)

        def do_exit(event):
            # get_app().exit()
            event.app.exit(result=rdo.current_value)

        def do_up_down(event):
            print(event)
            pass

        bindings = KeyBindings()
        bindings.add('enter')(do_exit)
        app_bindings = merge_key_bindings([load_key_bindings(), bindings])

        selected = Application(layout=Layout(rdo),
                               key_bindings=app_bindings).run()
        print('your choice is:', end=' ')
        # refer: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/examples/print-text/ansi.py
        print_formatted_text(ANSI('\x1b[91m{0}'.format(selected)))