From ba241b12e05071f26da09f0d28a6f840a79122f0 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 20 Dec 2021 20:09:29 +0100 Subject: [PATCH] use cache to store char-to-column mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is faster by O(n) to O(n²) compared to the previous algorithm that would re-compute the column for each call. --- highlight_selection.py | 5 ++++- line.py | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/highlight_selection.py b/highlight_selection.py index cd4b5c4..9f0b6d5 100644 --- a/highlight_selection.py +++ b/highlight_selection.py @@ -45,7 +45,10 @@ class HighlightSelection(Highlight): start_column = line.char_to_column(start_char) end_column = line.char_to_column(end_char) - length_in_columns = end_column - start_column + if end_column >= 0: + length_in_columns = end_column - start_column + else: + length_in_columns = 4096 return [HighlightedRange(start_column, length_in_columns, brush=QBrush(QColor(156, 215, 255, 192)), pen=Qt.PenStyle.NoPen)] diff --git a/line.py b/line.py index a738970..f2f4e64 100644 --- a/line.py +++ b/line.py @@ -1,3 +1,5 @@ +from typing import Dict + import constants @@ -6,6 +8,7 @@ class Line: self._byte_offset = byte_offset self._byte_end = byte_end self._line = line + self._char_to_column_cache = self._cache_char_to_column() def byte_offset(self) -> int: return self._byte_offset @@ -63,17 +66,25 @@ class Line: return result - # todo this method is slow def char_to_column(self, char_in_line: int) -> int: + if not char_in_line in self._char_to_column_cache: + # print("%d in %s" % (char_in_line, self._char_to_column_cache)) + return -1 + return self._char_to_column_cache[char_in_line] + + def _cache_char_to_column(self) -> Dict[int, int]: + char_to_column_cache = {} result = 0 i = 0 - while i < char_in_line: + char_to_column_cache[0] = 0 + while i < len(self._line): if i < len(self._line) and self._line[i] == "\t": result = result + constants.tab_width - result % constants.tab_width else: result = result + 1 i = i + 1 - return result + char_to_column_cache[i] = result + return char_to_column_cache def includes_byte(self, byte: int) -> bool: return self._byte_offset <= byte <= self._byte_end