Beispiel #1
0
def ctx():
    """Context in which the ptk multiline functionality will be tested."""
    builtins.__xonsh_env__ = DummyEnv()
    builtins.__xonsh_env__['INDENT'] = '    '
    from xonsh.ptk.key_bindings import carriage_return
    ptk_buffer = Buffer()
    ptk_buffer.accept_action = MagicMock(name='accept', spec=AcceptAction)
    cli = MagicMock(name='cli', spec=CommandLineInterface)
    yield Context(indent='    ',
                  buffer=ptk_buffer,
                  accept=ptk_buffer.accept_action,
                  cli=cli,
                  cr=carriage_return)
    del builtins.__xonsh_env__
def on_text_changed(buf: Buffer, state=state):
    filename = buf.text.rstrip().rsplit("\n", 1)[-1].strip()
    if filename == "":
        return
    if state["filename"] != filename:
        # state["filename"] = current_display.text = filename
        try:
            with open(filename) as rf:
                state["content"] = content_display.text = rf.read()
            buf.validation_state = ValidationState.VALID
            buf.validation_error = None
        except FileNotFoundError as e:
            buf.validation_error = ValidationError(message=repr(e))
            buf.validation_state = ValidationState.INVALID
Beispiel #3
0
    def __init__(self, process):
        assert isinstance(process, Process)

        self.process = process
        self.chosen_name = None

        # Displayed the clock instead of this pane content.
        self.clock_mode = False

        # Give unique ID.
        Pane._pane_counter += 1
        self.pane_id = Pane._pane_counter

        # Prompt_toolkit buffer, for displaying scrollable text.
        # (In copy mode, or help mode.)
        # Note: Because the scroll_buffer can only contain text, we also use the
        #       copy_token_list, that contains a token list with color information.
        self.scroll_buffer = Buffer(read_only=True)
        self.copy_token_list = []
        self.display_scroll_buffer = False
        self.scroll_buffer_title = ''

        # Search buffer, for use in copy mode. (Each pane gets its own search buffer.)
        self.search_buffer = Buffer()
        self.is_searching = False
        self.search_state = SearchState(ignore_case=False)
Beispiel #4
0
    def current_buffer(self):
        """
        The currently focused :class:`~.Buffer`.

        (This returns a dummy :class:`.Buffer` when none of the actual buffers
        has the focus. In this case, it's really not practical to check for
        `None` values or catch exceptions every time.)
        """
        return self.layout.current_buffer or Buffer(
            name='dummy-buffer')  # Dummy buffer.
Beispiel #5
0
 def __init__(self, commands: List[Command] = []):
     self.commands = commands
     wc = WordCompleter(sum([c.names for c in commands], []))
     self.buf = Buffer(completer=wc, complete_while_typing=True)
     self.buf.text = ''
     self.window = Window(content=BufferControl(
         buffer=self.buf, input_processors=[BeforeInput(':')]),
                          height=1)
     super(CommandLinePrompt, self).__init__(content=self.window,
                                             filter=has_focus(self.window))
Beispiel #6
0
def test_vsplit(tab_page):
    # Create new buffer.
    b = Buffer()
    eb = EditorBuffer(b, 'b1')

    # Insert in tab, by splitting.
    tab_page.vsplit(eb)

    assert isinstance(tab_page.root, VSplit)
    assert len(tab_page.root) == 2
    def __init__(self, python_input, original_document):
        """
        Create an `Application` for the history screen.
        This has to be run as a sub application of `python_input`.

        When this application runs and returns, it retuns the selected lines.
        """
        self.python_input = python_input

        history_mapping = HistoryMapping(self, python_input.history,
                                         original_document)
        self.history_mapping = history_mapping

        document = Document(history_mapping.concatenated_history)
        document = Document(document.text,
                            cursor_position=document.cursor_position +
                            document.get_start_of_line_position())

        self.history_buffer = Buffer(
            document=document,
            on_cursor_position_changed=self._history_buffer_pos_changed,
            accept_handler=(
                lambda buff: get_app().exit(result=self.default_buffer.text)),
            read_only=True)

        self.default_buffer = Buffer(
            name=DEFAULT_BUFFER,
            document=history_mapping.get_new_document(),
            on_cursor_position_changed=self._default_buffer_pos_changed,
            read_only=True)

        self.help_buffer = Buffer(document=Document(HELP_TEXT, 0),
                                  read_only=True)

        self.history_layout = HistoryLayout(self)

        self.app = Application(
            layout=self.history_layout.layout,
            full_screen=True,
            style=python_input._current_style,
            mouse_support=Condition(lambda: python_input.enable_mouse_support),
            key_bindings=create_key_bindings(self, python_input,
                                             history_mapping))
def ctx():
    """Context in which the ptk multiline functionality will be tested."""
    builtins.__xonsh__ = XonshSession()
    builtins.__xonsh__.env = DummyEnv()
    builtins.__xonsh__.env["INDENT"] = "    "
    from xonsh.ptk2.key_bindings import carriage_return

    ptk_buffer = Buffer()
    ptk_buffer.accept_action = MagicMock(name="accept")
    cli = MagicMock(name="cli", spec=Application)
    yield Context(
        indent="    ",
        buffer=ptk_buffer,
        accept=ptk_buffer.accept_action,
        cli=cli,
        cr=carriage_return,
    )
    del builtins.__xonsh__.env
    del builtins.__xonsh__
Beispiel #9
0
 def _create_buffer(self):
     self._create_completer()
     self.buffer = Buffer(
         history=FileHistory(os.path.expanduser('./network-history')),
         auto_suggest=AutoSuggestFromHistory(),
         enable_history_search=True,
         completer=self.completer,
         complete_while_typing=Always(),
         accept_action=AcceptAction.RETURN_DOCUMENT,
     )
Beispiel #10
0
def ctx():
    """Context in which the ptk multiline functionality will be tested."""
    builtins.__xonsh__ = XonshSession()
    builtins.__xonsh__.env = DummyEnv()
    builtins.__xonsh__.env["INDENT"] = "    "
    from xonsh.ptk_shell.key_bindings import carriage_return

    ptk_buffer = Buffer()
    ptk_buffer.accept_action = MagicMock(name="accept")
    cli = MagicMock(name="cli", spec=Application)
    yield Context(
        indent="    ",
        buffer=ptk_buffer,
        accept=ptk_buffer.accept_action,
        cli=cli,
        cr=carriage_return,
    )
    del builtins.__xonsh__.env
    del builtins.__xonsh__
Beispiel #11
0
    def _create_cli(self):
        """Creates the prompt_toolkit's CommandLineInterface.

        Args:
            * None.

        Returns:
            None.
        """
        history = FileHistory(os.path.expanduser('~/.saws-history'))
        toolbar = Toolbar(self.get_color,
                          self.get_fuzzy_match,
                          self.get_shortcut_match)
        layout = create_default_layout(
            message='saws> ',
            reserve_space_for_menu=8,
            lexer=CommandLexer,
            get_bottom_toolbar_tokens=toolbar.handler,
            extra_input_processors=[
                ConditionalProcessor(
                    processor=HighlightMatchingBracketProcessor(
                        chars='[](){}'),
                    filter=HasFocus(DEFAULT_BUFFER) & ~IsDone())
            ]
        )
        cli_buffer = Buffer(
            history=history,
            auto_suggest=AutoSuggestFromHistory(),
            enable_history_search=True,
            completer=self.completer,
            complete_while_typing=Always(),
            accept_action=AcceptAction.RETURN_DOCUMENT)
        self.key_manager = KeyManager(
            self.set_color,
            self.get_color,
            self.set_fuzzy_match,
            self.get_fuzzy_match,
            self.set_shortcut_match,
            self.get_shortcut_match,
            self.refresh_resources_and_options,
            self.handle_docs)
        style_factory = StyleFactory(self.theme)
        application = Application(
            mouse_support=False,
            style=style_factory.style,
            layout=layout,
            buffer=cli_buffer,
            key_bindings_registry=self.key_manager.manager.registry,
            on_exit=AbortAction.RAISE_EXCEPTION,
            on_abort=AbortAction.RETRY,
            ignore_case=True)
        eventloop = create_eventloop()
        self.aws_cli = CommandLineInterface(
            application=application,
            eventloop=eventloop)
Beispiel #12
0
    def pager(self, html, end="\n"):
        """
        Construct pager using prompt_toolkit
        """

        my_buffer = Buffer()
        my_window = Window(
            BufferControl(
                buffer=my_buffer,
                focusable=True,
                preview_search=True,
                input_processors=[FormatText()],
            ))

        my_buffer.text = html
        my_buffer.read_only = to_filter(True)

        root_container = HSplit([
            my_window,
        ])

        bindings = KeyBindings()

        @bindings.add("c-c")
        @bindings.add("q")
        def _(event):
            "Quit."
            event.app.exit()

        application = Application(
            layout=Layout(
                root_container,
                focused_element=my_window,
            ),
            key_bindings=bindings,
            enable_page_navigation_bindings=True,
            mouse_support=True,
            full_screen=True,
        )

        application.run()
        super().msg(html=html, end=end)
Beispiel #13
0
def setup():
    global indent_
    global buffer
    global bufaccept
    global cli
    global carriage_return
    global builtins

    import builtins

    builtins.__xonsh_env__ = Env()
    builtins.__xonsh_env__['INDENT'] = '    '

    from xonsh.ptk.key_bindings import carriage_return

    indent_ = '    '
    buffer = Buffer()
    bufaccept = MagicMock(name='accept', spec=AcceptAction)
    cli = MagicMock(name='cli', spec=CommandLineInterface)
    buffer.accept_action = bufaccept
Beispiel #14
0
 def __init__(self, lexer_name='yaml'):
     self.buf = Buffer()
     self.buf.text = ''
     self.lexer = PygmentsLexer(find_lexer_class_by_name(lexer_name))
     self.window = HSplit([
         HorizontalLine(),
         Window(content=BufferControl(buffer=self.buf, lexer=self.lexer))
     ],
                          height=Dimension(min=5, max=20, weight=1))
     super(InfoWindow, self).__init__(content=self.window,
                                      filter=has_focus(self))
Beispiel #15
0
    def _build_cli(self):
        eventloop = create_eventloop()

        history = FileHistory(
            os.path.join(
                os.path.expanduser("~"),
                ".{}_history".format(self._ctx.binary_name),
            ))

        layout = create_prompt_layout(
            lexer=PygmentsLexer(NubiaLexer),
            reserve_space_for_menu=5,
            get_prompt_tokens=self.get_prompt_tokens,
            get_rprompt_tokens=self._status_bar.get_rprompt_tokens,
            get_bottom_toolbar_tokens=self._status_bar.get_tokens,
            display_completions_in_columns=False,
            multiline=True,
            extra_input_processors=[
                ConditionalProcessor(
                    processor=HighlightMatchingBracketProcessor(
                        chars="[](){}"),
                    filter=HasFocus(DEFAULT_BUFFER) & ~IsDone(),
                )
            ],
        )

        buf = Buffer(
            completer=self._completer,
            history=history,
            auto_suggest=self._suggestor,
            complete_while_typing=Always(),
            accept_action=AcceptAction.RETURN_DOCUMENT,
        )

        # If EDITOR does not exist, take EMACS
        # if it does, try fit the EMACS/VI pattern using upper
        editor = getattr(EditingMode,
                         os.environ.get("EDITOR", EditingMode.EMACS).upper(),
                         EditingMode.EMACS)

        application = Application(
            style=shell_style,
            buffer=buf,
            editing_mode=editor,
            key_bindings_registry=self._registry,
            layout=layout,
            on_exit=AbortAction.RAISE_EXCEPTION,
            on_abort=AbortAction.RETRY,
            ignore_case=True,
        )

        cli = CommandLineInterface(application=application,
                                   eventloop=eventloop)
        return cli
Beispiel #16
0
def create_cli(eventloop, message='',
               multiline=False,
               is_password=False,
               vi_mode=False,
               lexer=None,
               enable_system_prompt=False,
               enable_open_in_editor=False,
               validator=None,
               completer=None,
               style=None,
               history=None,
               get_prompt_tokens=None,
               get_bottom_toolbar_tokens=None,
               extra_input_processors=None,
               key_bindings_registry=None,
               output=None,
               on_abort=AbortAction.RAISE_EXCEPTION,
               on_exit=AbortAction.RAISE_EXCEPTION,
               on_accept=AcceptAction.RETURN_DOCUMENT):
    """
    Create a `CommandLineInterface` instance.
    """
    assert isinstance(eventloop, EventLoop)

    # Create history instance.
    if history is None:
        history = History()

    # Use default registry from KeyBindingManager if none was given.
    if key_bindings_registry is None:
        key_bindings_registry = KeyBindingManager(
            enable_vi_mode=vi_mode,
            enable_system_prompt=enable_system_prompt,
            enable_open_in_editor=enable_open_in_editor).registry

    # Create interface.
    return CommandLineInterface(
        eventloop=eventloop,
        layout=create_default_layout(message=message, lexer=lexer, is_password=is_password,
                                     reserve_space_for_menu=(completer is not None),
                                     get_prompt_tokens=get_prompt_tokens,
                                     get_bottom_toolbar_tokens=get_bottom_toolbar_tokens,
                                     extra_input_processors=extra_input_processors),
        buffer=Buffer(
            is_multiline=(Always() if multiline else Never()),
            history=history,
            validator=validator,
            completer=completer,
        ),
        key_bindings_registry=key_bindings_registry,
        style=style,
        output=output,
        on_abort=on_abort,
        on_exit=on_exit)
Beispiel #17
0
def setup():
    global indent_
    global buffer
    global bufaccept
    global cli
    global carriage_return
    global builtins
    
    import builtins

    builtins.__xonsh_env__ = Env()
    builtins.__xonsh_env__['INDENT'] = '    '

    from xonsh.ptk.key_bindings import carriage_return

    indent_ = '    '
    buffer = Buffer()
    bufaccept = MagicMock(name='accept', spec=AcceptAction)
    cli = MagicMock(name='cli', spec=CommandLineInterface)
    buffer.accept_action = bufaccept
Beispiel #18
0
 def create_cmd_buffer(self, command):
     completer = PathCompleter()
     # if command == 'open' or command == 'inspect':
     # completer=PathCompleter()
     # else:
     # completer=None
     accept_handler = getattr(self, 'do_' + command)
     return Buffer(completer=completer,
                   name='cmd_buffer_' + command,
                   accept_handler=accept_handler,
                   multiline=False)
Beispiel #19
0
    def __init__(self, prompt='Shell command: '):
        self.prompt = prompt
        self.system_buffer = Buffer(name=SYSTEM_BUFFER)

        self._global_bindings = self._build_global_key_bindings()
        self._bindings = self._build_key_bindings()

        self.buffer_control = BufferControl(
            buffer=self.system_buffer,
            lexer=SimpleLexer(style='class:system-toolbar.text'),
            input_processor=BeforeInput(
                lambda: self.prompt, style='class:system-toolbar'),
            key_bindings=self._bindings)

        self.window = Window(
            self.buffer_control, height=1,
            style='class:system-toolbar')

        self.container = ConditionalContainer(
            content=self.window,
            filter=has_focus(self.system_buffer))
Beispiel #20
0
    def get_or_append_buffer(self, buf_name, document_text):
        for i, b in enumerate(self._buffers):
            if b.name == buf_name:
                self._current_buffer_index = i
                return b

        buf = Buffer(name=buf_name,
                     read_only=True,
                     document=Document(document_text))
        self._buffers.append(buf)
        self._current_buffer_index += 1
        return buf
Beispiel #21
0
    def expand(self, buffer: Buffer) -> bool:
        """expand the given abbr text. Return true if cursor position changed."""
        if not abbrevs:
            return False
        document = buffer.document
        word = document.get_word_before_cursor(WORD=True)
        if word in abbrevs.keys():
            partial = document.text[:document.cursor_position]
            startix, endix, quote = check_for_partial_string(partial)
            if startix is not None and endix is None:
                return False
            text = get_abbreviated(word, buffer)

            buffer.delete_before_cursor(count=len(word))
            buffer.insert_text(text)

            self.last_expanded = _LastExpanded(word, text)
            if EDIT_SYMBOL in text:
                set_cursor_position(buffer, text)
                return True
        return False
    def __init__(self,
                 buffer=None,
                 input_processors=None,
                 include_default_input_processors=True,
                 lexer=None,
                 preview_search=False,
                 focusable=True,
                 search_buffer_control=None,
                 menu_position=None,
                 focus_on_click=False,
                 key_bindings=None):
        from prompt_toolkit.key_binding.key_bindings import KeyBindingsBase
        assert buffer is None or isinstance(buffer, Buffer)
        assert input_processors is None or isinstance(input_processors, list)
        assert isinstance(include_default_input_processors, bool)
        assert menu_position is None or callable(menu_position)
        assert lexer is None or isinstance(lexer, Lexer)
        assert (search_buffer_control is None
                or callable(search_buffer_control)
                or isinstance(search_buffer_control, SearchBufferControl))
        assert key_bindings is None or isinstance(key_bindings,
                                                  KeyBindingsBase)

        self.input_processors = input_processors
        self.include_default_input_processors = include_default_input_processors

        self.default_input_processors = [
            HighlightSearchProcessor(),
            HighlightIncrementalSearchProcessor(),
            HighlightSelectionProcessor(),
            DisplayMultipleCursors(),
        ]

        self.preview_search = to_filter(preview_search)
        self.focusable = to_filter(focusable)
        self.focus_on_click = to_filter(focus_on_click)

        self.buffer = buffer or Buffer()
        self.menu_position = menu_position
        self.lexer = lexer or SimpleLexer()
        self.key_bindings = key_bindings
        self._search_buffer_control = search_buffer_control

        #: Cache for the lexer.
        #: Often, due to cursor movement, undo/redo and window resizing
        #: operations, it happens that a short time, the same document has to be
        #: lexed. This is a fairly easy way to cache such an expensive operation.
        self._fragment_cache = SimpleCache(maxsize=8)

        self._xy_to_cursor_position = None
        self._last_click_timestamp = None
        self._last_get_processed_line = None
Beispiel #23
0
    def __init__(self):
        self.buffer = Buffer(is_multiline=True, read_only=True)
        self.buffer_name = self._generate_buffer_name()

        # List of lines. (Each line is a list of (token, text) tuples itself.)
        self.line_tokens = [[]]

        # Marks. (Mapping from mark name to (cursor position, scroll_offset).)
        self.marks = {}

        # `Pager` sets this flag when he starts reading the generator of this
        # source in a coroutine.
        self.waiting_for_input_stream = False
Beispiel #24
0
    def test_undo_capitalize(self):
        buffer = Buffer()

        text = u'Selec'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual(u'Selec', buffer.text)

        text = buffer.text + 't'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual(u'SELECT', buffer.text)

        text = buffer.text + 'i'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual(u'Selecti', buffer.text)

        text = buffer.text + 'on'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual(u'Selection', buffer.text)
Beispiel #25
0
    def __init__(
        self,
        state,
    ):
        self.state = state
        self.kb = KeyBindings()

        # layout components
        self.header_bar = FormattedTextControl(focusable=False, )
        self.input_buffer = Buffer(multiline=False, )
        self.input_buffer.on_text_changed += self.update_results
        self.results_control = SelectableList(text="")
        self.preview_bar = FormattedTextControl(focusable=False, )
        self.preview_buffer = BufferControl(
            input_processors=[TabsProcessor(tabstop=4, char1="", char2="")],
            focusable=False,
        )
        self.status_bar = FormattedTextControl()
        self.layout = Layout(
            HSplit([
                Window(self.header_bar, height=1, style="reverse"),
                Window(
                    BufferControl(self.input_buffer),
                    height=1,
                ),
                Window(self.results_control,
                       height=Dimension(**RESULTS_DIMENSION_DICT)),
                Window(self.preview_bar, height=1, style="reverse"),
                Window(
                    self.preview_buffer,
                    wrap_lines=True,
                    height=Dimension(**PREVIEW_DIMENSION_DICT),
                ),
                Window(self.status_bar, height=1, style="reverse"),
            ]), )
        self.reset_view()

        @self.kb.add("up")
        def _(event):
            self.results_control.index -= 1
            self.update_preview()

        @self.kb.add("down")
        def _(event):
            self.results_control.index += 1
            self.update_preview()

        @self.kb.add("enter")
        def _(event):
            self.select_collection()
            self.reset_view()
Beispiel #26
0
    def __init__(self, pymux):
        self.pymux = pymux

        def _handle_command(cli, buffer):
            " When text is accepted in the command line. "
            text = buffer.text

            # First leave command mode. We want to make sure that the working
            # pane is focussed again before executing the command handers.
            pymux.leave_command_mode(cli, append_to_history=True)

            # Execute command.
            pymux.handle_command(cli, text)

        def _handle_prompt_command(cli, buffer):
            " When a command-prompt command is accepted. "
            text = buffer.text
            client_state = pymux.get_client_state(cli)
            prompt_command = client_state.prompt_command

            # Leave command mode and handle command.
            pymux.leave_command_mode(cli, append_to_history=True)
            pymux.handle_command(cli, prompt_command.replace('%%', text))

        super(_BufferMapping, self).__init__({
            COMMAND:
            Buffer(
                complete_while_typing=True,
                completer=create_command_completer(pymux),
                accept_action=AcceptAction(handler=_handle_command),
                auto_suggest=AutoSuggestFromHistory(),
            ),
            PROMPT:
            Buffer(
                accept_action=AcceptAction(handler=_handle_prompt_command),
                auto_suggest=AutoSuggestFromHistory(),
            ),
        })
Beispiel #27
0
    def create_cli(self):
        ## KeyBindings configuration
        key_binding = KeyBindingManager(enable_search=True,
                                        enable_abort_and_exit_bindings=True,
                                        enable_system_bindings=True,
                                        enable_auto_suggest_bindings=True,
                                        enable_open_in_editor=False)

        ## Buffer configuration
        default_buffer = Buffer(history=self.file_history,
                                auto_suggest=AutoSuggestFromHistory(),
                                enable_history_search=True,
                                completer=self.completer,
                                complete_while_typing=Always(),
                                accept_action=AcceptAction.RETURN_DOCUMENT)

        ## Style configuration
        try:
            style = get_style_by_name(self._config.highlighter_style)
        except ClassNotFound:
            style = get_style_by_name('native')

        styles = {}
        styles.update(style.styles)
        styles.update(default_style_extensions)
        styles.update({
            Token.Menu.Completions.Completion: 'bg:#003fff #ffffff',
            Token.Menu.Completions.Completion.Current: 'bg:#5ab300 #000000',
            Token.Menu.Completions.Meta.Current: 'bg:#5ab300 #ffffff',
            Token.Menu.Completions.Meta: 'bg:#ffffff #000000',
            Token.Scrollbar: 'bg:#003fff',
            Token.Scrollbar.Button: 'bg:#003333',
        })
        prompt_style = style_from_dict(styles)

        ## Application
        application = Application(
            layout=self.create_cli_layout(),
            mouse_support=False,
            style=prompt_style,
            buffer=default_buffer,
            on_abort=AbortAction.RETRY,
            on_exit=AbortAction.RAISE_EXCEPTION,
            on_input_timeout=self.on_input_timeout,
            key_bindings_registry=key_binding.registry,
        )

        cli = CommandLineInterface(application=application,
                                   eventloop=create_eventloop())
        return cli
Beispiel #28
0
    def __init__(self):
        history = InMemoryHistory()
        os_commandhelper = OSCommandHelper()
        resource = Resource()
        os_completer = OSCompleter(os_commandhelper, resource)

        self.main_buffer = Buffer(
            accept_action=AcceptAction.RETURN_DOCUMENT,
            history=history,
            auto_suggest=AutoSuggestFromHistory(),
            completer=os_completer,
            complete_while_typing=True)

        self.help_buffer = Buffer(
            is_multiline=True)
        self.help_buffer.text = "HELP"

        os_completer.help_buffer = self.help_buffer

        self.buffers = {
            DEFAULT_BUFFER: self.main_buffer,
            'HELP': self.help_buffer
        }
Beispiel #29
0
    def _create_python_buffer(self):
        def is_buffer_multiline():
            return (self.settings.paste_mode
                    or document_is_multiline_python(b.document))

        b = Buffer(is_multiline=Condition(is_buffer_multiline),
                   complete_while_typing=Condition(
                       lambda: self.settings.complete_while_typing),
                   enable_history_search=Always(),
                   tempfile_suffix='.py',
                   history=self.history,
                   completer=self.completer,
                   validator=self.validator)
        return b
Beispiel #30
0
    def create_application(self, full_layout=True):
        """ makes the application object and the buffers """
        layout_manager = LayoutManager(self)
        if full_layout:
            layout = layout_manager.create_layout(ExampleLexer, ToolbarLexer)
        else:
            layout = layout_manager.create_tutorial_layout()

        buffers = {
            DEFAULT_BUFFER: Buffer(is_multiline=True),
            'description': Buffer(is_multiline=True, read_only=True),
            'parameter': Buffer(is_multiline=True, read_only=True),
            'examples': Buffer(is_multiline=True, read_only=True),
            'bottom_toolbar': Buffer(is_multiline=True),
            'example_line': Buffer(is_multiline=True),
            'default_values': Buffer(),
            'symbols': Buffer(),
            'progress': Buffer(is_multiline=False)
        }

        writing_buffer = Buffer(
            history=self.history,
            auto_suggest=AutoSuggestFromHistory(),
            enable_history_search=True,
            completer=self.completer,
            complete_while_typing=Always()
        )

        return Application(
            mouse_support=False,
            style=self.style,
            buffer=writing_buffer,
            on_input_timeout=self.on_input_timeout,
            key_bindings_registry=InteractiveKeyBindings(self).registry,
            layout=layout,
            buffers=buffers,
        )
    def __init__(self, prompt: AnyFormattedText = 'Shell command: ',
                 enable_global_bindings: FilterOrBool = True) -> None:

        self.prompt = prompt
        self.enable_global_bindings = to_filter(enable_global_bindings)

        self.system_buffer = Buffer(name=SYSTEM_BUFFER)

        self._bindings = self._build_key_bindings()

        self.buffer_control = BufferControl(
            buffer=self.system_buffer,
            lexer=SimpleLexer(style='class:system-toolbar.text'),
            input_processors=[BeforeInput(
                lambda: self.prompt, style='class:system-toolbar')],
            key_bindings=self._bindings)

        self.window = Window(
            self.buffer_control, height=1,
            style='class:system-toolbar')

        self.container = ConditionalContainer(
            content=self.window,
            filter=has_focus(self.system_buffer))
Beispiel #32
0
    def test_undo_capitalize(self):
        buffer = Buffer()

        text = 'Selec'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('Selec', buffer.text)

        text = buffer.text + 't'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('SELECT', buffer.text)

        text = buffer.text + 'i'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('Selecti', buffer.text)

        text = buffer.text + 'on'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('Selection', buffer.text)
Beispiel #33
0
    def __init__(self, view):
        super(SearchToolbar, self).__init__(view)

        self._find_idx = 0
        self._last_search_str = None

        self.control = BufferControl(
            focus_on_click=True,
            key_bindings=self._get_kb(),
            include_default_input_processors=False,
            input_processors=[
                BeforeInput("Search: ", style="bold bg:#3200ff"),
                # AfterInput("Regex: [ ]", style="bold bg:#3200ff"),
                ShowLeadingWhiteSpaceProcessor(),
                ShowTrailingWhiteSpaceProcessor()
            ],
            buffer=Buffer(multiline=False, accept_handler=self.handler))
Beispiel #34
0
    def __init__(
        self,
        buffer: Optional[Buffer] = None,
        input_processors: Optional[List[Processor]] = None,
        include_default_input_processors: bool = True,
        lexer: Optional[Lexer] = None,
        preview_search: FilterOrBool = False,
        focusable: FilterOrBool = True,
        search_buffer_control: Union[None, "SearchBufferControl",
                                     Callable[[],
                                              "SearchBufferControl"]] = None,
        menu_position: Optional[Callable] = None,
        focus_on_click: FilterOrBool = False,
        key_bindings: Optional["KeyBindingsBase"] = None,
    ):

        self.input_processors = input_processors
        self.include_default_input_processors = include_default_input_processors

        self.default_input_processors = [
            HighlightSearchProcessor(),
            HighlightIncrementalSearchProcessor(),
            HighlightSelectionProcessor(),
            DisplayMultipleCursors(),
        ]

        self.preview_search = to_filter(preview_search)
        self.focusable = to_filter(focusable)
        self.focus_on_click = to_filter(focus_on_click)

        self.buffer = buffer or Buffer()
        self.menu_position = menu_position
        self.lexer = lexer or SimpleLexer()
        self.key_bindings = key_bindings
        self._search_buffer_control = search_buffer_control

        #: Cache for the lexer.
        #: Often, due to cursor movement, undo/redo and window resizing
        #: operations, it happens that a short time, the same document has to be
        #: lexed. This is a fairly easy way to cache such an expensive operation.
        self._fragment_cache: SimpleCache[Hashable, Callable[
            [int], StyleAndTextTuples]] = SimpleCache(maxsize=8)

        self._last_click_timestamp: Optional[float] = None
        self._last_get_processed_line: Optional[Callable[
            [int], _ProcessedLine]] = None
Beispiel #35
0
    def _body_windows(self, formatted_columns):
        rows = list(itertools.zip_longest(*formatted_columns, fillvalue=""))
        if rows:
            rows_string = [self._sep.join(row) for row in rows]
            table_body = "\n".join(rows_string)

            document = Document(table_body, 0)
            _buffer = Buffer(document=document, read_only=True)
            self._body_control = BufferControl(_buffer)
            body_windows = [
                Window(
                    self._body_control,
                    right_margins=[ScrollbarMargin(display_arrows=True)],
                )
            ]
        else:
            body_windows = []
        return body_windows
def main(database):
    connection = sqlite3.connect(database)
    layout = Layout(before_input=DefaultPrompt('> '),
                    lexer=SqlLexer,
                    menus=[CompletionsMenu()])
    buffer = Buffer(completer=SqlCompleter())
    cli = CommandLineInterface(style=DocumentStyle,
                               layout=layout,
                               buffer=buffer)
    try:
        while True:
            document = cli.read_input(on_exit=AbortAction.RAISE_EXCEPTION)
            with connection:
                messages = connection.execute(document.text)
                for message in messages:
                    print(message)
    except Exit:
        print('GoodBye!')
    def __init__(self, prompt='Shell command: ', enable_global_bindings=True):
        self.prompt = prompt
        self.enable_global_bindings = to_filter(enable_global_bindings)

        self.system_buffer = Buffer(name=SYSTEM_BUFFER)

        self._bindings = self._build_key_bindings()

        self.buffer_control = BufferControl(
            buffer=self.system_buffer,
            lexer=SimpleLexer(style='class:system-toolbar.text'),
            input_processors=[BeforeInput(
                lambda: self.prompt, style='class:system-toolbar')],
            key_bindings=self._bindings)

        self.window = Window(
            self.buffer_control, height=1,
            style='class:system-toolbar')

        self.container = ConditionalContainer(
            content=self.window,
            filter=has_focus(self.system_buffer))
def test_repeated_search_with_wraparound(_history):
    buff = Buffer(history=_history)
    buff.yank_last_arg()
    buff.yank_last_arg()
    buff.yank_last_arg()
    assert buff.document.current_line == 'four'
    def __init__(self,
                 get_globals=None, get_locals=None, history_filename=None,
                 vi_mode=False,

                 input=None,
                 output=None,
                 color_depth=None,

                 # For internal use.
                 extra_key_bindings=None,
                 _completer=None, _validator=None,
                 _lexer=None, _extra_buffer_processors=None,
                 _extra_layout_body=None, _extra_toolbars=None,
                 _input_buffer_height=None):

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

        self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals)
        self._validator = _validator or PythonValidator(self.get_compiler_flags)
        self._lexer = _lexer or PygmentsLexer(PythonLexer)

        if history_filename:
            self.history = ThreadedHistory(FileHistory(history_filename))
        else:
            self.history = InMemoryHistory()

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        self.extra_key_bindings = extra_key_bindings or KeyBindings()

        # Settings.
        self.show_signature = False
        self.show_docstring = False
        self.show_meta_enter_message = True
        self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.completion_menu_scroll_offset = 1

        self.show_line_numbers = False
        self.show_status_bar = True
        self.wrap_lines = True
        self.complete_while_typing = True
        self.paste_mode = False  # When True, don't insert whitespace after newline.
        self.confirm_exit = True  # Ask for confirmation when Control-D is pressed.
        self.accept_input_on_enter = 2  # Accept when pressing Enter 'n' times.
                                        # 'None' means that meta-enter is always required.
        self.enable_open_in_editor = True
        self.enable_system_bindings = True
        self.enable_input_validation = True
        self.enable_auto_suggest = False
        self.enable_mouse_support = False
        self.enable_history_search = False  # When True, like readline, going
                                            # back in history will filter the
                                            # history on the records starting
                                            # with the current input.

        self.enable_syntax_highlighting = True
        self.swap_light_and_dark = False
        self.highlight_matching_parenthesis = False
        self.show_sidebar = False  # Currently show the sidebar.
        self.show_sidebar_help = True # When the sidebar is visible, also show the help text.
        self.show_exit_confirmation = False  # Currently show 'Do you really want to exit?'
        self.terminal_title = None  # The title to be displayed in the terminal. (None or string.)
        self.exit_message = 'Do you really want to exit?'
        self.insert_blank_line_after_output = True  # (For the REPL.)

        # The buffers.
        self.default_buffer = self._create_buffer()
        self.search_buffer = Buffer()
        self.docstring_buffer = Buffer(read_only=True)

        # Tokens to be shown at the prompt.
        self.prompt_style = 'classic'  # The currently active style.

        self.all_prompt_styles = {  # Styles selectable from the menu.
            'ipython': IPythonPrompt(self),
            'classic': ClassicPrompt(),
        }

        self.get_input_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].in_prompt()

        self.get_output_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].out_prompt()

        #: Load styles.
        self.code_styles = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name = 'default'
        self._current_ui_style_name = 'default'

        if is_windows():
            self._current_code_style_name = 'win32'

        self._current_style = self._generate_style()
        self.color_depth = color_depth or ColorDepth.default()

        self.max_brightness = 1.0
        self.min_brightness = 0.0

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index = 0

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

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures = []

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running = False

        self.output = output or create_output()
        self.input = input or create_input(sys.stdin)

        self.style_transformation = merge_style_transformations([
            ConditionalStyleTransformation(
                SwapLightAndDarkStyleTransformation(),
                filter=Condition(lambda: self.swap_light_and_dark)),
            AdjustBrightnessStyleTransformation(
                lambda: self.min_brightness,
                lambda: self.max_brightness),
        ])
        self.ptpython_layout = PtPythonLayout(
            self,
            lexer=DynamicLexer(
                lambda: self._lexer if self.enable_syntax_highlighting else SimpleLexer()),
            input_buffer_height=self._input_buffer_height,
            extra_buffer_processors=self._extra_buffer_processors,
            extra_body=self._extra_layout_body,
            extra_toolbars=self._extra_toolbars)

        self.app = self._create_application()

        if vi_mode:
            self.app.editing_mode = EditingMode.VI
class PythonInput(object):
    """
    Prompt for reading Python input.

    ::

        python_input = PythonInput(...)
        python_code = python_input.app.run()
    """
    def __init__(self,
                 get_globals=None, get_locals=None, history_filename=None,
                 vi_mode=False,

                 input=None,
                 output=None,
                 color_depth=None,

                 # For internal use.
                 extra_key_bindings=None,
                 _completer=None, _validator=None,
                 _lexer=None, _extra_buffer_processors=None,
                 _extra_layout_body=None, _extra_toolbars=None,
                 _input_buffer_height=None):

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

        self._completer = _completer or PythonCompleter(self.get_globals, self.get_locals)
        self._validator = _validator or PythonValidator(self.get_compiler_flags)
        self._lexer = _lexer or PygmentsLexer(PythonLexer)

        if history_filename:
            self.history = ThreadedHistory(FileHistory(history_filename))
        else:
            self.history = InMemoryHistory()

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        self.extra_key_bindings = extra_key_bindings or KeyBindings()

        # Settings.
        self.show_signature = False
        self.show_docstring = False
        self.show_meta_enter_message = True
        self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.completion_menu_scroll_offset = 1

        self.show_line_numbers = False
        self.show_status_bar = True
        self.wrap_lines = True
        self.complete_while_typing = True
        self.paste_mode = False  # When True, don't insert whitespace after newline.
        self.confirm_exit = True  # Ask for confirmation when Control-D is pressed.
        self.accept_input_on_enter = 2  # Accept when pressing Enter 'n' times.
                                        # 'None' means that meta-enter is always required.
        self.enable_open_in_editor = True
        self.enable_system_bindings = True
        self.enable_input_validation = True
        self.enable_auto_suggest = False
        self.enable_mouse_support = False
        self.enable_history_search = False  # When True, like readline, going
                                            # back in history will filter the
                                            # history on the records starting
                                            # with the current input.

        self.enable_syntax_highlighting = True
        self.swap_light_and_dark = False
        self.highlight_matching_parenthesis = False
        self.show_sidebar = False  # Currently show the sidebar.
        self.show_sidebar_help = True # When the sidebar is visible, also show the help text.
        self.show_exit_confirmation = False  # Currently show 'Do you really want to exit?'
        self.terminal_title = None  # The title to be displayed in the terminal. (None or string.)
        self.exit_message = 'Do you really want to exit?'
        self.insert_blank_line_after_output = True  # (For the REPL.)

        # The buffers.
        self.default_buffer = self._create_buffer()
        self.search_buffer = Buffer()
        self.docstring_buffer = Buffer(read_only=True)

        # Tokens to be shown at the prompt.
        self.prompt_style = 'classic'  # The currently active style.

        self.all_prompt_styles = {  # Styles selectable from the menu.
            'ipython': IPythonPrompt(self),
            'classic': ClassicPrompt(),
        }

        self.get_input_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].in_prompt()

        self.get_output_prompt = lambda: \
            self.all_prompt_styles[self.prompt_style].out_prompt()

        #: Load styles.
        self.code_styles = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name = 'default'
        self._current_ui_style_name = 'default'

        if is_windows():
            self._current_code_style_name = 'win32'

        self._current_style = self._generate_style()
        self.color_depth = color_depth or ColorDepth.default()

        self.max_brightness = 1.0
        self.min_brightness = 0.0

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index = 0

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

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures = []

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running = False

        self.output = output or create_output()
        self.input = input or create_input(sys.stdin)

        self.style_transformation = merge_style_transformations([
            ConditionalStyleTransformation(
                SwapLightAndDarkStyleTransformation(),
                filter=Condition(lambda: self.swap_light_and_dark)),
            AdjustBrightnessStyleTransformation(
                lambda: self.min_brightness,
                lambda: self.max_brightness),
        ])
        self.ptpython_layout = PtPythonLayout(
            self,
            lexer=DynamicLexer(
                lambda: self._lexer if self.enable_syntax_highlighting else SimpleLexer()),
            input_buffer_height=self._input_buffer_height,
            extra_buffer_processors=self._extra_buffer_processors,
            extra_body=self._extra_layout_body,
            extra_toolbars=self._extra_toolbars)

        self.app = self._create_application()

        if vi_mode:
            self.app.editing_mode = EditingMode.VI

    def _accept_handler(self, buff):
        app = get_app()
        app.exit(result=buff.text)
        app.pre_run_callables.append(buff.reset)
        return True  # Keep text, we call 'reset' later on.

    @property
    def option_count(self):
        " Return the total amount of options. (In all categories together.) "
        return sum(len(category.options) for category in self.options)

    @property
    def selected_option(self):
        " Return the currently selected option. "
        i = 0
        for category in self.options:
            for o in category.options:
                if i == self.selected_option_index:
                    return o
                else:
                    i += 1

    def get_compiler_flags(self):
        """
        Give the current compiler flags by looking for _Feature instances
        in the globals.
        """
        flags = 0

        for value in self.get_globals().values():
            if isinstance(value, __future__._Feature):
                flags |= value.compiler_flag

        return flags

    @property
    def add_key_binding(self):
        """
        Shortcut for adding new key bindings.
        (Mostly useful for a .ptpython/config.py file, that receives
        a PythonInput/Repl instance as input.)

        ::

            @python_input.add_key_binding(Keys.ControlX, filter=...)
            def handler(event):
                ...
        """
        def add_binding_decorator(*k, **kw):
            return self.extra_key_bindings.add(*k, **kw)
        return add_binding_decorator

    def install_code_colorscheme(self, name, style_dict):
        """
        Install a new code color scheme.
        """
        assert isinstance(name, six.text_type)
        assert isinstance(style_dict, dict)

        self.code_styles[name] = style_dict

    def use_code_colorscheme(self, name):
        """
        Apply new colorscheme. (By name.)
        """
        assert name in self.code_styles

        self._current_code_style_name = name
        self._current_style = self._generate_style()

    def install_ui_colorscheme(self, name, style_dict):
        """
        Install a new UI color scheme.
        """
        assert isinstance(name, six.text_type)
        assert isinstance(style_dict, dict)

        self.ui_styles[name] = style_dict

    def use_ui_colorscheme(self, name):
        """
        Apply new colorscheme. (By name.)
        """
        assert name in self.ui_styles

        self._current_ui_style_name = name
        self._current_style = self._generate_style()

    def _use_color_depth(self, depth):
        self.color_depth = depth

    def _set_min_brightness(self, value):
        self.min_brightness = value
        self.max_brightness = max(self.max_brightness, value)

    def _set_max_brightness(self, value):
        self.max_brightness = value
        self.min_brightness = min(self.min_brightness, value)

    def _generate_style(self):
        """
        Create new Style instance.
        (We don't want to do this on every key press, because each time the
        renderer receives a new style class, he will redraw everything.)
        """
        return generate_style(self.code_styles[self._current_code_style_name],
                              self.ui_styles[self._current_ui_style_name])

    def _create_options(self):
        """
        Create a list of `Option` instances for the options sidebar.
        """
        def enable(attribute, value=True):
            setattr(self, attribute, value)

            # Return `True`, to be able to chain this in the lambdas below.
            return True

        def disable(attribute):
            setattr(self, attribute, False)
            return True

        def simple_option(title, description, field_name, values=None):
            " Create Simple on/of option. "
            values = values or ['off', 'on']

            def get_current_value():
                return values[bool(getattr(self, field_name))]

            def get_values():
                return {
                    values[1]: lambda: enable(field_name),
                    values[0]: lambda: disable(field_name),
                }

            return Option(title=title, description=description,
                          get_values=get_values,
                          get_current_value=get_current_value)

        brightness_values = [1.0 / 20 * value for value in range(0, 21)]

        return [
            OptionCategory('Input', [
                simple_option(title='Editing mode',
                              description='Vi or emacs key bindings.',
                              field_name='vi_mode',
                              values=[EditingMode.EMACS, EditingMode.VI]),
                simple_option(title='Paste mode',
                              description="When enabled, don't indent automatically.",
                              field_name='paste_mode'),
                Option(title='Complete while typing',
                       description="Generate autocompletions automatically while typing. "
                                   'Don\'t require pressing TAB. (Not compatible with "History search".)',
                       get_current_value=lambda: ['off', 'on'][self.complete_while_typing],
                       get_values=lambda: {
                           'on': lambda: enable('complete_while_typing') and disable('enable_history_search'),
                           'off': lambda: disable('complete_while_typing'),
                       }),
                Option(title='History search',
                       description='When pressing the up-arrow, filter the history on input starting '
                                   'with the current text. (Not compatible with "Complete while typing".)',
                       get_current_value=lambda: ['off', 'on'][self.enable_history_search],
                       get_values=lambda: {
                           'on': lambda: enable('enable_history_search') and disable('complete_while_typing'),
                           'off': lambda: disable('enable_history_search'),
                       }),
                simple_option(title='Mouse support',
                              description='Respond to mouse clicks and scrolling for positioning the cursor, '
                                          'selecting text and scrolling through windows.',
                              field_name='enable_mouse_support'),
                simple_option(title='Confirm on exit',
                              description='Require confirmation when exiting.',
                              field_name='confirm_exit'),
                simple_option(title='Input validation',
                              description='In case of syntax errors, move the cursor to the error '
                                          'instead of showing a traceback of a SyntaxError.',
                              field_name='enable_input_validation'),
                simple_option(title='Auto suggestion',
                              description='Auto suggest inputs by looking at the history. '
                                          'Pressing right arrow or Ctrl-E will complete the entry.',
                              field_name='enable_auto_suggest'),
                Option(title='Accept input on enter',
                       description='Amount of ENTER presses required to execute input when the cursor '
                                   'is at the end of the input. (Note that META+ENTER will always execute.)',
                       get_current_value=lambda: str(self.accept_input_on_enter or 'meta-enter'),
                       get_values=lambda: {
                           '2': lambda: enable('accept_input_on_enter', 2),
                           '3': lambda: enable('accept_input_on_enter', 3),
                           '4': lambda: enable('accept_input_on_enter', 4),
                           'meta-enter': lambda: enable('accept_input_on_enter', None),
                       }),
            ]),
            OptionCategory('Display', [
                Option(title='Completions',
                       description='Visualisation to use for displaying the completions. (Multiple columns, one column, a toolbar or nothing.)',
                       get_current_value=lambda: self.completion_visualisation,
                       get_values=lambda: {
                           CompletionVisualisation.NONE: lambda: enable('completion_visualisation', CompletionVisualisation.NONE),
                           CompletionVisualisation.POP_UP: lambda: enable('completion_visualisation', CompletionVisualisation.POP_UP),
                           CompletionVisualisation.MULTI_COLUMN: lambda: enable('completion_visualisation', CompletionVisualisation.MULTI_COLUMN),
                           CompletionVisualisation.TOOLBAR: lambda: enable('completion_visualisation', CompletionVisualisation.TOOLBAR),
                       }),
                Option(title='Prompt',
                       description="Visualisation of the prompt. ('>>>' or 'In [1]:')",
                       get_current_value=lambda: self.prompt_style,
                       get_values=lambda: dict((s, partial(enable, 'prompt_style', s)) for s in self.all_prompt_styles)),
                simple_option(title='Blank line after output',
                              description='Insert a blank line after the output.',
                              field_name='insert_blank_line_after_output'),
                simple_option(title='Show signature',
                              description='Display function signatures.',
                              field_name='show_signature'),
                simple_option(title='Show docstring',
                              description='Display function docstrings.',
                              field_name='show_docstring'),
                simple_option(title='Show line numbers',
                              description='Show line numbers when the input consists of multiple lines.',
                              field_name='show_line_numbers'),
                simple_option(title='Show Meta+Enter message',
                              description='Show the [Meta+Enter] message when this key combination is required to execute commands. ' +
                                  '(This is the case when a simple [Enter] key press will insert a newline.',
                              field_name='show_meta_enter_message'),
                simple_option(title='Wrap lines',
                              description='Wrap lines instead of scrolling horizontally.',
                              field_name='wrap_lines'),
                simple_option(title='Show status bar',
                              description='Show the status bar at the bottom of the terminal.',
                              field_name='show_status_bar'),
                simple_option(title='Show sidebar help',
                              description='When the sidebar is visible, also show this help text.',
                              field_name='show_sidebar_help'),
                simple_option(title='Highlight parenthesis',
                              description='Highlight matching parenthesis, when the cursor is on or right after one.',
                              field_name='highlight_matching_parenthesis'),
            ]),
            OptionCategory('Colors', [
                simple_option(title='Syntax highlighting',
                              description='Use colors for syntax highligthing',
                              field_name='enable_syntax_highlighting'),
                simple_option(title='Swap light/dark colors',
                              description='Swap light and dark colors.',
                              field_name='swap_light_and_dark'),
                Option(title='Code',
                       description='Color scheme to use for the Python code.',
                       get_current_value=lambda: self._current_code_style_name,
                       get_values=lambda: dict(
                            (name, partial(self.use_code_colorscheme, name)) for name in self.code_styles)
                       ),
                Option(title='User interface',
                       description='Color scheme to use for the user interface.',
                       get_current_value=lambda: self._current_ui_style_name,
                       get_values=lambda: dict(
                            (name, partial(self.use_ui_colorscheme, name)) for name in self.ui_styles)
                       ),
                Option(title='Color depth',
                       description='Monochrome (1 bit), 16 ANSI colors (4 bit),\n256 colors (8 bit), or 24 bit.',
                       get_current_value=lambda: COLOR_DEPTHS[self.color_depth],
                       get_values=lambda: dict(
                           (name, partial(self._use_color_depth, depth)) for depth, name in COLOR_DEPTHS.items())
                       ),
                Option(title='Min brightness',
                       description='Minimum brightness for the color scheme (default=0.0).',
                       get_current_value=lambda: '%.2f' % self.min_brightness,
                       get_values=lambda: dict(
                           ('%.2f' % value, partial(self._set_min_brightness, value))
                            for value in brightness_values)
                       ),
                Option(title='Max brightness',
                       description='Maximum brightness for the color scheme (default=1.0).',
                       get_current_value=lambda: '%.2f' % self.max_brightness,
                       get_values=lambda: dict(
                           ('%.2f' % value, partial(self._set_max_brightness, value))
                            for value in brightness_values)
                       ),
            ]),
        ]

    def _create_application(self):
        """
        Create an `Application` instance.
        """
        return Application(
            input=self.input,
            output=self.output,
            layout=self.ptpython_layout.layout,
            key_bindings=merge_key_bindings([
                load_python_bindings(self),
                load_auto_suggest_bindings(),
                load_sidebar_bindings(self),
                load_confirm_exit_bindings(self),
                ConditionalKeyBindings(
                    load_open_in_editor_bindings(),
                    Condition(lambda: self.enable_open_in_editor)),
                # Extra key bindings should not be active when the sidebar is visible.
                ConditionalKeyBindings(
                    self.extra_key_bindings,
                    Condition(lambda: not self.show_sidebar))
            ]),
            color_depth=lambda: self.color_depth,
            paste_mode=Condition(lambda: self.paste_mode),
            mouse_support=Condition(lambda: self.enable_mouse_support),
            style=DynamicStyle(lambda: self._current_style),
            style_transformation=self.style_transformation,
            include_default_pygments_style=False,
            reverse_vi_search_direction=True)

    def _create_buffer(self):
        """
        Create the `Buffer` for the Python input.
        """
        python_buffer = Buffer(
            name=DEFAULT_BUFFER,
            complete_while_typing=Condition(lambda: self.complete_while_typing),
            enable_history_search=Condition(lambda: self.enable_history_search),
            tempfile_suffix='.py',
            history=self.history,
            completer=ThreadedCompleter(self._completer),
            validator=ConditionalValidator(
                self._validator,
                Condition(lambda: self.enable_input_validation)),
            auto_suggest=ConditionalAutoSuggest(
                ThreadedAutoSuggest(AutoSuggestFromHistory()),
                Condition(lambda: self.enable_auto_suggest)),
            accept_handler=self._accept_handler,
            on_text_changed=self._on_input_timeout)

        return python_buffer

    @property
    def editing_mode(self):
        return self.app.editing_mode

    @editing_mode.setter
    def editing_mode(self, value):
        self.app.editing_mode = value

    @property
    def vi_mode(self):
        return self.editing_mode == EditingMode.VI

    @vi_mode.setter
    def vi_mode(self, value):
        if value:
            self.editing_mode = EditingMode.VI
        else:
            self.editing_mode = EditingMode.EMACS

    def _on_input_timeout(self, buff):
        """
        When there is no input activity,
        in another thread, get the signature of the current code.
        """
        assert isinstance(buff, Buffer)
        app = self.app

        # Never run multiple get-signature threads.
        if self._get_signatures_thread_running:
            return
        self._get_signatures_thread_running = True

        document = buff.document

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

            # Show signatures in help text.
            if script:
                try:
                    signatures = script.call_signatures()
                except ValueError:
                    # e.g. in case of an invalid \\x escape.
                    signatures = []
                except Exception:
                    # Sometimes we still get an exception (TypeError), because
                    # of probably bugs in jedi. We can silence them.
                    # See: https://github.com/davidhalter/jedi/issues/492
                    signatures = []
                else:
                    # Try to access the params attribute just once. For Jedi
                    # signatures containing the keyword-only argument star,
                    # this will crash when retrieving it the first time with
                    # AttributeError. Every following time it works.
                    # See: https://github.com/jonathanslenders/ptpython/issues/47
                    #      https://github.com/davidhalter/jedi/issues/598
                    try:
                        if signatures:
                            signatures[0].params
                    except AttributeError:
                        pass
            else:
                signatures = []

            self._get_signatures_thread_running = False

            # Set signatures and redraw if the text didn't change in the
            # meantime. Otherwise request new signatures.
            if buff.text == document.text:
                self.signatures = signatures

                # Set docstring in docstring buffer.
                if signatures:
                    string = signatures[0].docstring()
                    if not isinstance(string, six.text_type):
                        string = string.decode('utf-8')
                    self.docstring_buffer.reset(
                        document=Document(string, cursor_position=0))
                else:
                    self.docstring_buffer.reset()

                app.invalidate()
            else:
                self._on_input_timeout(buff)

        get_event_loop().run_in_executor(run)

    def on_reset(self):
        self.signatures = []

    def enter_history(self):
        """
        Display the history.
        """
        app = get_app()
        app.vi_state.input_mode = InputMode.NAVIGATION

        def done(f):
            result = f.result()
            if result is not None:
                self.default_buffer.text = result

            app.vi_state.input_mode = InputMode.INSERT

        history = History(self, self.default_buffer.document)

        future = run_coroutine_in_terminal(history.app.run_async)
        future.add_done_callback(done)
Beispiel #41
0
    def test_capitalize(self):
        buffer = Buffer()

        text = 'selec'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('selec', buffer.text)

        text = 'select'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('SELECT', buffer.text)

        text = 'CREATE TABLE "select'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('CREATE TABLE "select', buffer.text)

        text = 'CREATE TABLE \'select\''
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('CREATE TABLE \'select\'', buffer.text)

        text = 'create table test (x int)'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('CREATE TABLE test (x INT)', buffer.text)

        text = 'create table test (a boolean, b string, c integer)'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('CREATE TABLE test (a BOOLEAN, b STRING, c INTEGER)', buffer.text)

        text = 'create table test\n(a boolean, b string, c integer)'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('CREATE TABLE test\n(a BOOLEAN, b STRING, c INTEGER)', buffer.text)

        text = '\\select dynamic'
        buffer.set_document(Document(text, len(text)))
        self.capitalizer.apply_capitalization(buffer)
        self.assertEqual('\\select dynamic', buffer.text)
def test_empty_history():
    buf = Buffer()
    buf.yank_last_arg()
    assert buf.document.current_line == ''
Beispiel #43
0
class Editor(object):
    """
    The main class. Containing the whole editor.

    :param config_directory: Place where configuration is stored.
    :param input: (Optionally) `prompt_toolkit.input.Input` object.
    :param output: (Optionally) `prompt_toolkit.output.Output` object.
    """
    def __init__(self, config_directory='~/.pyvim', input=None, output=None):
        self.input = input
        self.output = output

        # Vi options.
        self.show_line_numbers = True
        self.highlight_search = True
        self.paste_mode = False
        self.show_ruler = True
        self.show_wildmenu = True
        self.expand_tab = True  # Insect spaces instead of tab characters.
        self.tabstop = 4  # Number of spaces that a tab character represents.
        self.incsearch = True  # Show matches while typing search string.
        self.ignore_case = False  # Ignore case while searching.
        self.enable_mouse_support = True
        self.display_unprintable_characters = True  # ':set list'
        self.enable_jedi = True  # ':set jedi', for Python Jedi completion.
        self.scroll_offset = 0  # ':set scrolloff'
        self.relative_number = False  # ':set relativenumber'
        self.wrap_lines = True  # ':set wrap'
        self.break_indent = False  # ':set breakindent'
        self.cursorline = False  # ':set cursorline'
        self.cursorcolumn = False  # ':set cursorcolumn'
        self.colorcolumn = []  # ':set colorcolumn'. List of integers.

        # Ensure config directory exists.
        self.config_directory = os.path.abspath(os.path.expanduser(config_directory))
        if not os.path.exists(self.config_directory):
            os.mkdir(self.config_directory)

        self.window_arrangement = WindowArrangement(self)
        self.message = None

        # Load styles. (Mapping from name to Style class.)
        self.styles = generate_built_in_styles()
        self.current_style = get_editor_style_by_name('vim')

        # I/O backends.
        self.io_backends = [
            DirectoryIO(),
            HttpIO(),
            GZipFileIO(),  # Should come before FileIO.
            FileIO(),
        ]

        # Create history and search buffers.
        def handle_action(buff):
            ' When enter is pressed in the Vi command line. '
            text = buff.text  # Remember: leave_command_mode resets the buffer.

            # First leave command mode. We want to make sure that the working
            # pane is focussed again before executing the command handlers.
            self.leave_command_mode(append_to_history=True)

            # Execute command.
            handle_command(self, text)

        commands_history = FileHistory(os.path.join(self.config_directory, 'commands_history'))
        self.command_buffer = Buffer(
            accept_handler=handle_action,
            enable_history_search=True,
            completer=create_command_completer(self),
            history=commands_history,
            multiline=False)

        search_buffer_history = FileHistory(os.path.join(self.config_directory, 'search_history'))
        self.search_buffer = Buffer(
            history=search_buffer_history,
            enable_history_search=True,
            multiline=False)

        # Create key bindings registry.
        self.key_bindings = create_key_bindings(self)

        # Create layout and CommandLineInterface instance.
        self.editor_layout = EditorLayout(self, self.window_arrangement)
        self.application = self._create_application()

        # Hide message when a key is pressed.
        def key_pressed(_):
            self.message = None
        self.application.key_processor.before_key_press += key_pressed

        # Command line previewer.
        self.previewer = CommandPreviewer(self)

    def load_initial_files(self, locations, in_tab_pages=False, hsplit=False, vsplit=False):
        """
        Load a list of files.
        """
        assert in_tab_pages + hsplit + vsplit <= 1  # Max one of these options.

        # When no files were given, open at least one empty buffer.
        locations2 = locations or [None]

        # First file
        self.window_arrangement.open_buffer(locations2[0])

        for f in locations2[1:]:
            if in_tab_pages:
                self.window_arrangement.create_tab(f)
            elif hsplit:
                self.window_arrangement.hsplit(location=f)
            elif vsplit:
                self.window_arrangement.vsplit(location=f)
            else:
                self.window_arrangement.open_buffer(f)

        self.window_arrangement.active_tab_index = 0

        if locations and len(locations) > 1:
            self.show_message('%i files loaded.' % len(locations))

    def _create_application(self):
        """
        Create CommandLineInterface instance.
        """
        # Create Application.
        application = Application(
            input=self.input,
            output=self.output,
            editing_mode=EditingMode.VI,
            layout=self.editor_layout.layout,
            key_bindings=self.key_bindings,
#            get_title=lambda: get_terminal_title(self),
            style=DynamicStyle(lambda: self.current_style),
            paste_mode=Condition(lambda: self.paste_mode),
#            ignore_case=Condition(lambda: self.ignore_case),  # TODO
            include_default_pygments_style=False,
            mouse_support=Condition(lambda: self.enable_mouse_support),
            full_screen=True,
            enable_page_navigation_bindings=True)

        # Handle command line previews.
        # (e.g. when typing ':colorscheme blue', it should already show the
        # preview before pressing enter.)
        def preview(_):
            if self.application.layout.has_focus(self.command_buffer):
                self.previewer.preview(self.command_buffer.text)
        self.command_buffer.on_text_changed += preview

        return application

    @property
    def current_editor_buffer(self):
        """
        Return the `EditorBuffer` that is currently active.
        """
        current_buffer = self.application.current_buffer

        # Find/return the EditorBuffer with this name.
        for b in self.window_arrangement.editor_buffers:
            if b.buffer == current_buffer:
                return b

    @property
    def add_key_binding(self):
        """
        Shortcut for adding new key bindings.
        (Mostly useful for a pyvimrc file, that receives this Editor instance
        as input.)
        """
        return self.key_bindings.add

    def show_message(self, message):
        """
        Set a warning message. The layout will render it as a "pop-up" at the
        bottom.
        """
        self.message = message

    def use_colorscheme(self, name='default'):
        """
        Apply new colorscheme. (By name.)
        """
        try:
            self.current_style = get_editor_style_by_name(name)
        except pygments.util.ClassNotFound:
            pass

    def sync_with_prompt_toolkit(self):
        """
        Update the prompt-toolkit Layout and FocusStack.
        """
        # After executing a command, make sure that the layout of
        # prompt-toolkit matches our WindowArrangement.
        self.editor_layout.update()

        # Make sure that the focus stack of prompt-toolkit has the current
        # page.
        window = self.window_arrangement.active_pt_window
        if window:
            self.application.layout.focus(window)

    def show_help(self):
        """
        Show help in new window.
        """
        self.window_arrangement.hsplit(text=HELP_TEXT)
        self.sync_with_prompt_toolkit()  # Show new window.

    def run(self):
        """
        Run the event loop for the interface.
        This starts the interaction.
        """
        # Make sure everything is in sync, before starting.
        self.sync_with_prompt_toolkit()

        def pre_run():
            # Start in navigation mode.
            self.application.vi_state.input_mode = InputMode.NAVIGATION

        # Run eventloop of prompt_toolkit.
        self.application.run(pre_run=pre_run)

    def enter_command_mode(self):
        """
        Go into command mode.
        """
        self.application.layout.focus(self.command_buffer)
        self.application.vi_state.input_mode = InputMode.INSERT

        self.previewer.save()

    def leave_command_mode(self, append_to_history=False):
        """
        Leave command mode. Focus document window again.
        """
        self.previewer.restore()

        self.application.layout.focus_last()
        self.application.vi_state.input_mode = InputMode.NAVIGATION

        self.command_buffer.reset(append_to_history=append_to_history)
 def setUp(self):
     self.buffer = Buffer()
class SystemToolbar(object):
    """
    Toolbar for a system prompt.

    :param prompt: Prompt to be displayed to the user.
    """
    def __init__(self, prompt='Shell command: ', enable_global_bindings=True):
        self.prompt = prompt
        self.enable_global_bindings = to_filter(enable_global_bindings)

        self.system_buffer = Buffer(name=SYSTEM_BUFFER)

        self._bindings = self._build_key_bindings()

        self.buffer_control = BufferControl(
            buffer=self.system_buffer,
            lexer=SimpleLexer(style='class:system-toolbar.text'),
            input_processors=[BeforeInput(
                lambda: self.prompt, style='class:system-toolbar')],
            key_bindings=self._bindings)

        self.window = Window(
            self.buffer_control, height=1,
            style='class:system-toolbar')

        self.container = ConditionalContainer(
            content=self.window,
            filter=has_focus(self.system_buffer))

    def _get_display_before_text(self):
        return [
            ('class:system-toolbar', 'Shell command: '),
            ('class:system-toolbar.text', self.system_buffer.text),
            ('', '\n'),
        ]

    def _build_key_bindings(self):
        focused = has_focus(self.system_buffer)

        # Emacs
        emacs_bindings = KeyBindings()
        handle = emacs_bindings.add

        @handle('escape', filter=focused)
        @handle('c-g', filter=focused)
        @handle('c-c', filter=focused)
        def _(event):
            " Hide system prompt. "
            self.system_buffer.reset()
            event.app.layout.focus_last()

        @handle('enter', filter=focused)
        def _(event):
            " Run system command. "
            event.app.run_system_command(
                self.system_buffer.text,
                display_before_text=self._get_display_before_text())
            self.system_buffer.reset(append_to_history=True)
            event.app.layout.focus_last()

        # Vi.
        vi_bindings = KeyBindings()
        handle = vi_bindings.add

        @handle('escape', filter=focused)
        @handle('c-c', filter=focused)
        def _(event):
            " Hide system prompt. "
            event.app.vi_state.input_mode = InputMode.NAVIGATION
            self.system_buffer.reset()
            event.app.layout.focus_last()

        @handle('enter', filter=focused)
        def _(event):
            " Run system command. "
            event.app.vi_state.input_mode = InputMode.NAVIGATION
            event.app.run_system_command(
                self.system_buffer.text,
                display_before_text=self._get_display_before_text())
            self.system_buffer.reset(append_to_history=True)
            event.app.layout.focus_last()

        # Global bindings. (Listen to these bindings, even when this widget is
        # not focussed.)
        global_bindings = KeyBindings()
        handle = global_bindings.add

        @handle(Keys.Escape, '!', filter= ~focused & emacs_mode, is_global=True)
        def _(event):
            " M-'!' will focus this user control. "
            event.app.layout.focus(self.window)

        @handle('!', filter=~focused & vi_mode & vi_navigation_mode, is_global=True)
        def _(event):
            " Focus. "
            event.app.vi_state.input_mode = InputMode.INSERT
            event.app.layout.focus(self.window)

        return merge_key_bindings([
            ConditionalKeyBindings(emacs_bindings, emacs_mode),
            ConditionalKeyBindings(vi_bindings, vi_mode),
            ConditionalKeyBindings(global_bindings, self.enable_global_bindings),
        ])

    def __pt_container__(self):
        return self.container
Beispiel #46
0
    def __init__(self, config_directory='~/.pyvim', input=None, output=None):
        self.input = input
        self.output = output

        # Vi options.
        self.show_line_numbers = True
        self.highlight_search = True
        self.paste_mode = False
        self.show_ruler = True
        self.show_wildmenu = True
        self.expand_tab = True  # Insect spaces instead of tab characters.
        self.tabstop = 4  # Number of spaces that a tab character represents.
        self.incsearch = True  # Show matches while typing search string.
        self.ignore_case = False  # Ignore case while searching.
        self.enable_mouse_support = True
        self.display_unprintable_characters = True  # ':set list'
        self.enable_jedi = True  # ':set jedi', for Python Jedi completion.
        self.scroll_offset = 0  # ':set scrolloff'
        self.relative_number = False  # ':set relativenumber'
        self.wrap_lines = True  # ':set wrap'
        self.break_indent = False  # ':set breakindent'
        self.cursorline = False  # ':set cursorline'
        self.cursorcolumn = False  # ':set cursorcolumn'
        self.colorcolumn = []  # ':set colorcolumn'. List of integers.

        # Ensure config directory exists.
        self.config_directory = os.path.abspath(os.path.expanduser(config_directory))
        if not os.path.exists(self.config_directory):
            os.mkdir(self.config_directory)

        self.window_arrangement = WindowArrangement(self)
        self.message = None

        # Load styles. (Mapping from name to Style class.)
        self.styles = generate_built_in_styles()
        self.current_style = get_editor_style_by_name('vim')

        # I/O backends.
        self.io_backends = [
            DirectoryIO(),
            HttpIO(),
            GZipFileIO(),  # Should come before FileIO.
            FileIO(),
        ]

        # Create history and search buffers.
        def handle_action(buff):
            ' When enter is pressed in the Vi command line. '
            text = buff.text  # Remember: leave_command_mode resets the buffer.

            # First leave command mode. We want to make sure that the working
            # pane is focussed again before executing the command handlers.
            self.leave_command_mode(append_to_history=True)

            # Execute command.
            handle_command(self, text)

        commands_history = FileHistory(os.path.join(self.config_directory, 'commands_history'))
        self.command_buffer = Buffer(
            accept_handler=handle_action,
            enable_history_search=True,
            completer=create_command_completer(self),
            history=commands_history,
            multiline=False)

        search_buffer_history = FileHistory(os.path.join(self.config_directory, 'search_history'))
        self.search_buffer = Buffer(
            history=search_buffer_history,
            enable_history_search=True,
            multiline=False)

        # Create key bindings registry.
        self.key_bindings = create_key_bindings(self)

        # Create layout and CommandLineInterface instance.
        self.editor_layout = EditorLayout(self, self.window_arrangement)
        self.application = self._create_application()

        # Hide message when a key is pressed.
        def key_pressed(_):
            self.message = None
        self.application.key_processor.before_key_press += key_pressed

        # Command line previewer.
        self.previewer = CommandPreviewer(self)
def test_repeated_search(_history):
    buff = Buffer(history=_history)
    buff.yank_last_arg()
    buff.yank_last_arg()
    assert buff.document.current_line == 'delta'
def test_simple_search_with_arg_out_of_bounds(_history):
    buff = Buffer(history=_history)
    buff.yank_last_arg(n=8)
    assert buff.document.current_line == ''
def test_simple_search_with_arg(_history):
    buff = Buffer(history=_history)
    buff.yank_last_arg(n=2)
    assert buff.document.current_line == 'three'
def test_simple_search_with_quotes(_history):
    _history.append_string("""one two "three 'x' four"\n""")
    buff = Buffer(history=_history)
    buff.yank_last_arg()
    assert buff.document.current_line == '''"three 'x' four"'''
def test_simple_search(_history):
    buff = Buffer(history=_history)
    buff.yank_last_arg()
    assert buff.document.current_line == 'four'
    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)
def test_repeated_yank_nth_arg(_history):
    buff = Buffer(history=_history)
    buff.yank_nth_arg()
    buff.yank_nth_arg()
    assert buff.document.current_line == 'beta'
Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Maecenas
quis interdum enim. Nam viverra, mauris et blandit malesuada, ante est bibendum
mauris, ac dignissim dui tellus quis ligula. Aenean condimentum leo at
dignissim placerat. In vel dictum ex, vulputate accumsan mi. Donec ut quam
placerat massa tempor elementum. Sed tristique mauris ac suscipit euismod. Ut
tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue
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."""

# Create text buffers. Cursorcolumn/cursorline are mostly combined with an
# (editable) text buffers, where the user can move the cursor.

buff = Buffer()
buff.text = LIPSUM

# 1. The layout
body = HSplit([
    Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'),
    Window(BufferControl(buffer=buff), cursorcolumn=True, cursorline=True),
])


# 2. Key bindings
kb = KeyBindings()


@kb.add('q')
def _(event):
def test_yank_nth_arg_with_arg(_history):
    buff = Buffer(history=_history)
    buff.yank_nth_arg(n=2)
    assert buff.document.current_line == 'three'
class BufferTest(unittest.TestCase):
    def setUp(self):
        self.buffer = Buffer()

    def test_initial(self):
        self.assertEqual(self.buffer.text, '')
        self.assertEqual(self.buffer.cursor_position, 0)

    def test_insert_text(self):
        self.buffer.insert_text('some_text')
        self.assertEqual(self.buffer.text, 'some_text')
        self.assertEqual(self.buffer.cursor_position, len('some_text'))

    def test_cursor_movement(self):
        self.buffer.insert_text('some_text')
        self.buffer.cursor_left()
        self.buffer.cursor_left()
        self.buffer.cursor_left()
        self.buffer.cursor_right()
        self.buffer.insert_text('A')

        self.assertEqual(self.buffer.text, 'some_teAxt')
        self.assertEqual(self.buffer.cursor_position, len('some_teA'))

    def test_backspace(self):
        self.buffer.insert_text('some_text')
        self.buffer.cursor_left()
        self.buffer.cursor_left()
        self.buffer.delete_before_cursor()

        self.assertEqual(self.buffer.text, 'some_txt')
        self.assertEqual(self.buffer.cursor_position, len('some_t'))

    def test_cursor_up(self):
        # Cursor up to a line thats longer.
        self.buffer.insert_text('long line1\nline2')
        self.buffer.cursor_up()

        self.assertEqual(self.buffer.document.cursor_position, 5)

        # Going up when already at the top.
        self.buffer.cursor_up()
        self.assertEqual(self.buffer.document.cursor_position, 5)

        # Going up to a line that's shorter.
        self.buffer.reset()
        self.buffer.insert_text('line1\nlong line2')

        self.buffer.cursor_up()
        self.assertEqual(self.buffer.document.cursor_position, 5)

    def test_cursor_down(self):
        self.buffer.insert_text('line1\nline2')
        self.buffer.cursor_position = 3

        # Normally going down
        self.buffer.cursor_down()
        self.assertEqual(self.buffer.document.cursor_position, len('line1\nlin'))

        # Going down to a line that's storter.
        self.buffer.reset()
        self.buffer.insert_text('long line1\na\nb')
        self.buffer.cursor_position = 3

        self.buffer.cursor_down()
        self.assertEqual(self.buffer.document.cursor_position, len('long line1\na'))

    def test_join_next_line(self):
        self.buffer.insert_text('line1\nline2\nline3')
        self.buffer.cursor_up()
        self.buffer.join_next_line()

        self.assertEqual(self.buffer.text, 'line1\nline2 line3')

        # Test when there is no '\n' in the text
        self.buffer.reset()
        self.buffer.insert_text('line1')
        self.buffer.cursor_position = 0
        self.buffer.join_next_line()

        self.assertEqual(self.buffer.text, 'line1')

    def test_newline(self):
        self.buffer.insert_text('hello world')
        self.buffer.newline()

        self.assertEqual(self.buffer.text, 'hello world\n')

    def test_swap_characters_before_cursor(self):
        self.buffer.insert_text('hello world')
        self.buffer.cursor_left()
        self.buffer.cursor_left()
        self.buffer.swap_characters_before_cursor()

        self.assertEqual(self.buffer.text, 'hello wrold')
Beispiel #57
0
class TextArea(object):
    """
    A simple input field.

    This is a higher level abstraction on top of several other classes with
    sane defaults.

    This widget does have the most common options, but it does not intend to
    cover every single use case. For more configurations options, you can
    always build a text area manually, using a
    :class:`~prompt_toolkit.buffer.Buffer`,
    :class:`~prompt_toolkit.layout.BufferControl` and
    :class:`~prompt_toolkit.layout.Window`.

    Buffer attributes:

    :param text: The initial text.
    :param multiline: If True, allow multiline input.
    :param completer: :class:`~prompt_toolkit.completion.Completer` instance
        for auto completion.
    :param complete_while_typing: Boolean.
    :param accept_handler: Called when `Enter` is pressed (This should be a
        callable that takes a buffer as input).
    :param history: :class:`~prompt_toolkit.history.History` instance.
    :param auto_suggest: :class:`~prompt_toolkit.auto_suggest.AutoSuggest`
        instance for input suggestions.

    BufferControl attributes:

    :param password: When `True`, display using asterisks.
    :param focusable: When `True`, allow this widget to receive the focus.
    :param focus_on_click: When `True`, focus after mouse click.
    :param input_processors: `None` or a list of
        :class:`~prompt_toolkit.layout.Processor` objects.

    Window attributes:

    :param lexer: :class:`~prompt_toolkit.lexers.Lexer` instance for syntax
        highlighting.
    :param wrap_lines: When `True`, don't scroll horizontally, but wrap lines.
    :param width: Window width. (:class:`~prompt_toolkit.layout.Dimension` object.)
    :param height: Window height. (:class:`~prompt_toolkit.layout.Dimension` object.)
    :param scrollbar: When `True`, display a scroll bar.
    :param style: A style string.
    :param dont_extend_width: When `True`, don't take up more width then the
                              preferred width reported by the control.
    :param dont_extend_height: When `True`, don't take up more width then the
                               preferred height reported by the control.
    :param get_line_prefix: None or a callable that returns formatted text to
        be inserted before a line. It takes a line number (int) and a
        wrap_count and returns formatted text. This can be used for
        implementation of line continuations, things like Vim "breakindent" and
        so on.

    Other attributes:

    :param search_field: An optional `SearchToolbar` object.
    """
    def __init__(self, text='', multiline=True, password=False,
                 lexer=None, auto_suggest=None, completer=None,
                 complete_while_typing=True, accept_handler=None, history=None,
                 focusable=True, focus_on_click=False, wrap_lines=True,
                 read_only=False, width=None, height=None,
                 dont_extend_height=False, dont_extend_width=False,
                 line_numbers=False, get_line_prefix=None, scrollbar=False,
                 style='', search_field=None, preview_search=True, prompt='',
                 input_processors=None):
       # assert isinstance(text, six.text_type)

        if search_field is None:
            search_control = None

        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)

    @property
    def text(self):
        """
        The `Buffer` text.
        """
        return self.buffer.text

    @text.setter
    def text(self, value):
        self.buffer.set_document(Document(value, 0), bypass_readonly=True)

    @property
    def document(self):
        """
        The `Buffer` document (text + cursor position).
        """
        return self.buffer.document

    @document.setter
    def document(self, value):
        self.buffer.document = value

    @property
    def accept_handler(self):
        """
        The accept handler. Called when the user accepts the input.
        """
        return self.buffer.accept_handler

    @accept_handler.setter
    def accept_handler(self, value):
        self.buffer.accept_handler = value

    def __pt_container__(self):
        return self.window
Beispiel #58
0
    def __init__(self, text='', multiline=True, password=False,
                 lexer=None, auto_suggest=None, completer=None,
                 complete_while_typing=True, accept_handler=None, history=None,
                 focusable=True, focus_on_click=False, wrap_lines=True,
                 read_only=False, width=None, height=None,
                 dont_extend_height=False, dont_extend_width=False,
                 line_numbers=False, get_line_prefix=None, scrollbar=False,
                 style='', search_field=None, preview_search=True, prompt='',
                 input_processors=None):
       # assert isinstance(text, six.text_type)

        if search_field is None:
            search_control = None

        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)
Beispiel #59
0
class Pane(object):
    """
    One pane, containing one process and a search buffer for going into copy
    mode or displaying the help.
    """
    _pane_counter = 1000  # Start at 1000, to be sure to not confuse this with pane indexes.

    def __init__(self, process):
        assert isinstance(process, Process)

        self.process = process
        self.chosen_name = None

        # Displayed the clock instead of this pane content.
        self.clock_mode = False

        # Give unique ID.
        Pane._pane_counter += 1
        self.pane_id = Pane._pane_counter

        # Prompt_toolkit buffer, for displaying scrollable text.
        # (In copy mode, or help mode.)
        # Note: Because the scroll_buffer can only contain text, we also use the
        #       copy_token_list, that contains a token list with color information.
        self.scroll_buffer = Buffer(read_only=True)
        self.copy_token_list = []
        self.display_scroll_buffer = False
        self.scroll_buffer_title = ''

        # Search buffer, for use in copy mode. (Each pane gets its own search buffer.)
        self.search_buffer = Buffer()
        self.is_searching = False
        self.search_state = SearchState(ignore_case=False)

    @property
    def name(self):
        """
        The name for the window as displayed in the title bar and status bar.
        """
        # Name, explicitely set for the pane.
        if self.chosen_name:
            return self.chosen_name
        else:
            # Name from the process running inside the pane.
            name = self.process.get_name()
            if name:
                return os.path.basename(name)

        return ''

    def enter_copy_mode(self):
        """
        Suspend the process, and copy the screen content to the `scroll_buffer`.
        That way the user can search through the history and copy/paste.
        """
        document, token_list = self.process.create_copy_document()
        self._enter_scroll_buffer('Copy', document, token_list)

    def display_text(self, text, title=''):
        """
        Display the given text in the scroll buffer.
        """
        self._enter_scroll_buffer(
            title,
            document=Document(text, 0),
            token_list=[(Token, text)])

    def _enter_scroll_buffer(self, title, document, token_list):
        # Suspend child process.
        self.process.suspend()

        self.scroll_buffer.set_document(document, bypass_readonly=True)
        self.copy_token_list = token_list
        self.display_scroll_buffer = True
        self.scroll_buffer_title = title

        # Reset search state.
        self.search_state = SearchState(ignore_case=False)

    def exit_scroll_buffer(self):
        """
        Exit scroll buffer. (Exits help or copy mode.)
        """
        self.process.resume()
        self.display_scroll_buffer = False