Files
krowlog/src/ui/bigtext/highlight_regex.py
Andreas Huber ee514dc305 add support for regex groups
If a filter regex contains groups, then we only highlight the group matches.
2023-01-29 09:26:04 +01:00

102 lines
3.7 KiB
Python

from typing import Optional
from src.ui.bigtext.highlight import Highlight
from src.ui.bigtext.highlighted_range import HighlightedRange
from src.ui.bigtext.line import Line
from PySide6.QtGui import QBrush, QColor
from typing import List
import re
class HighlightRegex(Highlight):
def __init__(self, query: str, ignore_case: bool, is_regex: bool, hit_background_color: str = "None",
line_background_color: str = "None", active: bool = True):
self.active = active
self.query = query
self.ignore_case = ignore_case
self.is_regex = is_regex
self.regex = self._get_regex()
self.hit_background_color = hit_background_color
self.line_background_color = line_background_color
self._brush_hit = self.brush(self.hit_background_color)
self._brush_line = self.brush(self.line_background_color)
def _get_regex(self):
flags = re.IGNORECASE if self.ignore_case else 0
if self.is_regex:
return re.compile(self.query, flags=flags)
else:
return re.compile(re.escape(self.query), flags=flags)
def is_active(self) -> bool:
return self.active
def set_active(self, active: bool):
self.active = active
def set_query(self, query: str) -> None:
self.query = query
self.regex = self._get_regex()
def set_hit_background_color(self, color: str):
self.hit_background_color = color
def set_line_background_color(self, color: str):
self.line_background_color = color
def set_is_regex(self, is_regex: bool):
self.is_regex = is_regex
def set_is_ignore_case(self, ignore_case: bool):
self.ignore_case = ignore_case
def compute_highlight(self, line: Line) -> Optional[List[HighlightedRange]]:
result = []
if len(self.query) == 0:
# query is empty - this would result in many hits and is quite expensive
# This happens with the highlighter we use for the selected text and maybe for the current filter query.
return result
# print("execute regex: %s in %s" % (self.regex, line.line()))
match_iter = re.finditer(self.regex, line.line())
for match in match_iter:
# print("%s" % match)
# if the regex has groups then skip the first, it represents the whole match,
# but we only want to highlight the groups
first_group = 1 if len(match.groups()) > 0 else 0
for i in range(first_group, len(match.groups()) + 1):
start_column = line.char_to_column(match.start(i))
end_column = line.char_to_column(match.end(i))
# print(f"highlight: {start_column}:{end_column} - {match.group(i)}")
result.append(HighlightedRange(
start_column,
end_column - start_column,
highlight_full_line=True,
brush=self._brush_hit,
brush_full_line=self._brush_line
))
return result
def hit_background_brush(self):
return self.brush(self.hit_background_color)
@staticmethod
def brush(color: str) -> QBrush:
if re.match("^[0-9a-f]{6}$", color, flags=re.IGNORECASE):
red = int(color[0:2], 16)
green = int(color[2:4], 16)
blue = int(color[4:6], 16)
return QBrush(QColor(red, green, blue))
if re.match("^[0-9a-f]{8}$", color, flags=re.IGNORECASE):
red = int(color[0:2], 16)
green = int(color[2:4], 16)
blue = int(color[4:6], 16)
alpha = int(color[6:8], 16)
return QBrush(QColor(red, green, blue, alpha))
return QBrush()