Source code for mau.text_buffer

[docs]class EOLError(ValueError): """ Signals that the buffer is reading after the end of a line."""
[docs]class EOFError(ValueError): """ Signals that the buffer is reading after the end of the text."""
[docs]class TextBuffer: def __init__(self, text=None): self.lines = [] self.reset() if text is not None: self.load(text)
[docs] def reset(self): self.line = 0 self.column = 0
[docs] def load(self, text): self.lines = text.split("\n") if text is not None else [] self.reset()
@property def current_line(self): """ Returns the current line. This property returns the current line without advancing the index. If the buffer is reading after the last line it raises EOFError. """ try: return self.lines[self.line] except IndexError: raise EOFError("EOF reading line {}".format(self.line)) @property def current_char(self): """ Returns the current character. This property returns the current character without advancing the index. If the buffer is reading after the last character of the line it raises EOLError. """ try: return self.current_line[self.column] except IndexError: raise EOLError( "EOL reading column {} at line {}".format(self.column, self.line) ) @property def peek_char(self): """ Returns the next character. This property returns the next character without advancing the index. If the buffer is reading after the last character of the line it raises EOLError. """ try: return self.current_line[self.column + 1] except IndexError: raise EOLError( "EOL reading column {} at line {}".format(self.column, self.line) ) @property def tail(self): """ Returns the remaining part of the line. This property returns a string with the last part of the current line from the current character to the end. """ return self.current_line[self.column :] @property def position(self): """ Returns a tuple with the current position. """ return (self.line, self.column) @position.setter def position(self, position): """ Sets the current position. """ self.line, self.column = position
[docs] def nextline(self): """ Moves the index to the beginning of the next line """ self.line += 1 self.column = 0
[docs] def skip(self, chars=1): """ Skips the given number of characters (default 1). Can silently go over the end of the line. """ self.column += chars
[docs] def goto(self, line, column=0): self.line, self.column = line, column
[docs] def context(self, line_number, column_number): text_line = self.lines[line_number] prefix = f"{line_number}: " suffix = "" HALF_SIZE = 32 min_column = max(0, column_number - HALF_SIZE) max_column = min(len(text_line), column_number + HALF_SIZE + 1) if min_column > 0: prefix = f"{prefix}[...]" if max_column < len(text_line): suffix = "[...]" text_line = text_line[min_column:max_column] # Create the caret line caret_line = " " * (column_number - min_column + len(prefix)) + "^" return { "text": [f"{prefix}{text_line}{suffix}", caret_line], "line": line_number, "column": column_number, }
[docs] def insert(self, text): """ Inserts the given text in the buffer. """ # Split the new text removing the trailing newline splittext = text.strip().split("\n") if text is not None else [] # Insert the new text lines into the current buffer newlines = self.lines[: self.line] + splittext + self.lines[self.line :] self.lines = newlines