handle tabs correctly when highlighting text

With the old solution I replaced tabs with four spaces and then did
some calculations to get the correct byte positions for a coordinate.
With the new solution (using FontMetric.horizontalAdvance) this is not
necessary anymore and we can use tha native tab.
But I cannot change the tab width. It is always 8 characters.
You can set tabStopDistance on horizontalAdvance(), but not on
elided_text() and I did not find a way to use it while rendering text.
This commit is contained in:
2025-05-06 20:45:19 +02:00
parent bfd8ce841f
commit d9c362419b
2 changed files with 4 additions and 17 deletions

View File

@@ -15,7 +15,7 @@ class Line:
self._cache_char_to_column()
def get_width_in_px(self, font_metric: QFontMetrics):
return font_metric.horizontalAdvance(self._line)
return font_metric.horizontalAdvance(self.line_prepared_for_display())
def byte_offset(self) -> int:
return self._byte_offset
@@ -43,7 +43,8 @@ class Line:
return len(prefix_chars)
def line_prepared_for_display(self) -> str:
line = self._line_tabs_replaced()
# line = self._line_tabs_replaced()
line = self._line
line = self._replace_control_chars_with_pictures(line)
return line
@@ -108,7 +109,7 @@ class Line:
if not result in self._column_to_char_cache:
self._column_to_char_cache[result] = i
current_char = self._line[i]
if current_char == "\t":
if False and current_char == "\t":
result = result + constants.tab_width - result % constants.tab_width
else:
result = result + 1

View File

@@ -78,20 +78,6 @@ class MyTestCase(unittest.TestCase):
self.assertEqual(2, line.char_to_column(4)) # z̈
self.assertEqual(2, line.char_to_column(5)) # z̈
def test_line_tabs_replaced(self):
byte_offset = 123
text = "\ta\tb" # will be rendered as: ....abc where . represents a whitespace column
expected = " a b"
line = Line(byte_offset=byte_offset, byte_end=byte_offset + len(text.encode("utf8")), line=text)
self.assertEqual(expected, line.line_prepared_for_display())
def test_line_tabs_replaced_performance(self):
byte_offset = 123
text = "a\t" * 10000
expected = "a " * 10000
line = Line(byte_offset=byte_offset, byte_end=byte_offset + len(text.encode("utf8")), line=text)
self.assertEqual(expected, line.line_prepared_for_display())
def test_byte_index_to_char_index(self):
byte_offset = 123
text = "x\u0308y\u0308z\u0308\t\u0308a"