def _get_positions_to_highlight(self, document): """ Return a list of (row, col) tuples that need to be highlighted. """ # Try for the character under the cursor. if document.current_char and document.current_char in self.chars: pos = document.find_matching_bracket_position( start_pos=document.cursor_position - self.max_cursor_distance, end_pos=document.cursor_position + self.max_cursor_distance) # Try for the character before the cursor. elif (document.char_before_cursor and document.char_before_cursor in self._closing_braces and document.char_before_cursor in self.chars): document = Document(document.text, document.cursor_position - 1) pos = document.find_matching_bracket_position( start_pos=document.cursor_position - self.max_cursor_distance, end_pos=document.cursor_position + self.max_cursor_distance) else: pos = None # Return a list of (row, col) tuples that need to be highlighted. if pos: pos += document.cursor_position # pos is relative. row, col = document.translate_index_to_position(pos) return [(row, col), (document.cursor_position_row, document.cursor_position_col)] else: return []
def run_sync(): with self._auto_refresh_context(): try: self.default_buffer.reset(Document(self.default)) return self.app.run(inputhook=self.inputhook) finally: restore()
def validate(self, document): # Parse input document. # We use `match`, not `match_prefix`, because for validation, we want # the actual, unambiguous interpretation of the input. m = self.compiled_grammar.match(document.text) if m: for v in m.variables(): validator = self.validators.get(v.varname) if validator: # Unescape text. unwrapped_text = self.compiled_grammar.unescape(v.varname, v.value) # Create a document, for the completions API (text/cursor_position) inner_document = Document(unwrapped_text, len(unwrapped_text)) try: validator.validate(inner_document) except ValidationError as e: raise ValidationError( cursor_position=v.start + e.cursor_position, message=e.message) else: raise ValidationError(cursor_position=len(document.text), message='Invalid command')
def _get_completions_for_match(self, match, complete_event): """ Yield all the possible completions for this input string. (The completer assumes that the cursor position was at the end of the input string.) """ for match_variable in match.end_nodes(): varname = match_variable.varname start = match_variable.start completer = self.completers.get(varname) if completer: text = match_variable.value # Unwrap text. unwrapped_text = self.compiled_grammar.unescape(varname, text) # Create a document, for the completions API (text/cursor_position) document = Document(unwrapped_text, len(unwrapped_text)) # Call completer for completion in completer.get_completions( document, complete_event): new_text = unwrapped_text[:len(text) + completion. start_position] + completion.text # Wrap again. yield Completion(text=self.compiled_grammar.escape( varname, new_text), start_position=start - len(match.string), display=completion.display, display_meta=completion.display_meta)
def run_async(): with self._auto_refresh_context(): try: self.default_buffer.reset(Document(self.default)) result = yield From(self.app.run_async()) raise Return(result) finally: restore()
def insert_comment(event): """ Without numeric argument, comment all lines. With numeric argument, uncomment all lines. In any case accept the input. """ buff = event.current_buffer # Transform all lines. if event.arg != 1: def change(line): return line[1:] if line.startswith('#') else line else: def change(line): return '#' + line buff.document = Document( text='\n'.join(map(change, buff.text.splitlines())), cursor_position=0) # Accept input. buff.validate_and_handle()
def _get_text_fragments(self, text): m = self.compiled_grammar.match_prefix(text) if m: characters = [[self.default_style, c] for c in text] for v in m.variables(): # If we have a `Lexer` instance for this part of the input. # Tokenize recursively and apply tokens. lexer = self.lexers.get(v.varname) if lexer: document = Document(text[v.start:v.stop]) lexer_tokens_for_line = lexer.lex_document(document) text_fragments = [] for i in range(len(document.lines)): text_fragments.extend(lexer_tokens_for_line(i)) text_fragments.append(('', '\n')) if text_fragments: text_fragments.pop() i = v.start for t, s in text_fragments: for c in s: if characters[i][0] == self.default_style: characters[i][0] = t i += 1 # Highlight trailing input. trailing_input = m.trailing_input() if trailing_input: for i in range(trailing_input.start, trailing_input.stop): characters[i][0] = 'class:trailing-input' return characters else: return [('', text)]
def __init__(self, text='', multiline=True, password=False, lexer=None, completer=None, accept_handler=None, focusable=True, wrap_lines=True, read_only=False, width=None, height=None, dont_extend_height=False, dont_extend_width=False, line_numbers=False, scrollbar=False, style='', search_field=None, preview_search=True, prompt=''): assert isinstance(text, six.text_type) assert search_field is None or isinstance(search_field, SearchToolbar) if search_field is None: search_control = None elif isinstance(search_field, SearchToolbar): search_control = search_field.control self.buffer = Buffer( document=Document(text, 0), multiline=multiline, read_only=read_only, completer=completer, complete_while_typing=True, accept_handler=lambda buff: accept_handler and accept_handler()) self.control = BufferControl( buffer=self.buffer, lexer=lexer, input_processors=[ ConditionalProcessor(processor=PasswordProcessor(), filter=to_filter(password)), BeforeInput(prompt, style='class:text-area.prompt'), ], search_buffer_control=search_control, preview_search=preview_search, focusable=focusable) if multiline: if scrollbar: right_margins = [ScrollbarMargin(display_arrows=True)] else: right_margins = [] if line_numbers: left_margins = [NumberedMargin()] else: left_margins = [] else: wrap_lines = False # Never wrap for single line input. height = D.exact(1) left_margins = [] right_margins = [] style = 'class:text-area ' + style self.window = Window(height=height, width=width, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, content=self.control, style=style, wrap_lines=wrap_lines, left_margins=left_margins, right_margins=right_margins)
def text(self, value): self.buffer.document = Document(value, 0)