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
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)
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.
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))
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__
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, )
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__
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)
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)
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
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))
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
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)
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)
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))
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
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
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
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)
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()
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(), ), })
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
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 }
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
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))
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)
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))
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
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)
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 == ''
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
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')
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
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)
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