source: greatly improve location reporting for multi-line source extracts
This commit is contained in:
parent
fc9b6b30c6
commit
820fa1760d
1 changed files with 29 additions and 12 deletions
|
|
@ -1,8 +1,11 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from beartype import beartype
|
from beartype import beartype
|
||||||
from beartype.typing import Optional
|
from beartype.typing import Optional
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
@beartype
|
@beartype
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -44,21 +47,35 @@ class SourceLocation:
|
||||||
source_lines[-1] = source_lines[-1][:self.end.character]
|
source_lines[-1] = source_lines[-1][:self.end.character]
|
||||||
return "\n".join(source_lines)
|
return "\n".join(source_lines)
|
||||||
|
|
||||||
def show_in_source(self) -> str:
|
@staticmethod
|
||||||
source = self.source.splitlines(keepends=False)
|
def underline(string: str, begin: int, end: int) -> str:
|
||||||
source_line = source[self.begin.line]
|
assert begin <= end
|
||||||
result = [source_line]
|
result = [string]
|
||||||
if self.begin.line != self.end.line:
|
line = " " * begin
|
||||||
return "\n".join(result)
|
line += "^" + "~" * max(0, (end - begin - 1))
|
||||||
|
line += " " * (len(string) - len(line))
|
||||||
line = " " * self.begin.character
|
|
||||||
line += "^" + "-" * max(0, (self.end.character - self.begin.character - 1))
|
|
||||||
line += " " * (len(source_line) - len(line))
|
|
||||||
|
|
||||||
result += [line]
|
result += [line]
|
||||||
|
|
||||||
return "\n".join(result)
|
return "\n".join(result)
|
||||||
|
|
||||||
|
def show_in_source(self) -> str:
|
||||||
|
source = self.source.splitlines(keepends=False)
|
||||||
|
line_number_maxlen = int(math.log10(len(source)) + 1)
|
||||||
|
lines = source[self.begin.line:self.end.line + 1]
|
||||||
|
result = []
|
||||||
|
begin_char = self.begin.character
|
||||||
|
while len(lines) > 0:
|
||||||
|
line = lines.pop(0)
|
||||||
|
end_char = self.end.character if len(lines) == 0 else len(line)
|
||||||
|
result += [SourceLocation.underline(line, begin_char, end_char)]
|
||||||
|
begin_char = 0
|
||||||
|
|
||||||
|
for i, source_line in enumerate(result):
|
||||||
|
line_prefix = f"Line {self.begin.line + i:0>{line_number_maxlen}}: "
|
||||||
|
lines = source_line.splitlines(keepends=False)
|
||||||
|
lines[0] = line_prefix + lines[0]
|
||||||
|
lines[1] = " " * len(line_prefix) + lines[1]
|
||||||
|
result[i] = "\n".join(lines)
|
||||||
|
|
||||||
|
return "\n".join(result)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue