Files
krowlog/line.py
Andreas Huber ffea831e2d fix the way tabs are used
The previous code just assumed a tab was 4 spaces wide.
This is not true, because a tab can be between 1 and 4 spaces wide.
2021-12-21 08:15:44 +01:00

96 lines
2.9 KiB
Python

import constants
class Line:
def __init__(self, byte_offset: int, byte_end: int, line: str):
self._byte_offset = byte_offset
self._byte_end = byte_end
self._line = line
def byte_offset(self) -> int:
return self._byte_offset
def byte_end(self) -> int:
return self._byte_end
def line(self) -> str:
return self._line
def length_in_charaters(self) -> int:
return len(self._line)
def length_in_columns(self) -> int:
return self.char_to_column(len(self._line))
def char_index_to_byte(self, char_in_line: int) -> int:
return len(self.prefix(char_in_line).encode("utf8"))
def byte_index_to_char_index(self, byte_index: int) -> int:
prefix_bytes = self._line.encode("utf8")[:byte_index]
prefix_chars = prefix_bytes.decode("utf8", errors="ignore")
return len(prefix_chars)
def line_tabs_replaced(self):
line = self._line;
i = 0
offset = 0
result = ""
length = len(line)
while True:
tab_index = line.find("\t", offset)
if tab_index < 0:
break
result = result + line[offset:tab_index]
result = result + " " * (constants.tab_width - len(result) % constants.tab_width)
offset = tab_index + 1
result = result + line[offset:]
return result
def column_to_char(self, column_in_line: int) -> int:
i = 0
result = 0
while i < column_in_line:
char = self._line[result]
if char == "\t":
i = i + constants.tab_width - i % constants.tab_width # jump the additional columns to complete the tab
if i > column_in_line:
break;
else:
i = i + 1
result = result + 1
return result
# todo this method is slow
def char_to_column(self, char_in_line: int) -> int:
result = 0
i = 0
while i < char_in_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
def includes_byte(self, byte: int) -> bool:
return self._byte_offset <= byte <= self._byte_end
def intersects(self, start_byte: int, end_byte: int):
result = start_byte < self._byte_end and end_byte > self._byte_offset
# print("%d,%d in %d,%d" % (start_byte, end_byte, self._byte_offset, self._byte_end))
return result
def prefix(self, index: int) -> str:
return self._line[0:index]
def substr(self, offset: int, length: int) -> str:
return self._line[offset:offset+length]
def suffix(self, index: int) -> str:
return self._line[index:]
def __str__(self):
return "%s (%d->%d)" % (self._line, self._byte_offset, self._byte_end)