weblate/weblate/checks/utils.py
Michal Čihař 0013acbae4 chore: use itemgetter instead of lambdas
This is easier to read code and performs better.
2023-11-04 06:18:20 +01:00

77 lines
2.5 KiB
Python

# Copyright © Michal Čihař <michal@weblate.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later
from operator import itemgetter
from pygments.lexers.markup import RstLexer
from pygments.token import Token
from weblate.checks.models import CHECKS
def highlight_pygments(source: str, unit):
"""
Highlight syntax characters using pygments.
This is not really a full syntax highlighting, we're only interested in
non-translatable strings.
"""
if "rst-text" in unit.all_flags:
lexer = RstLexer(stripnl=False)
start = 0
for token, text in lexer.get_tokens(source):
if token == Token.Literal.String:
if text[0] == "`" and text != "`_":
yield ((start, start + 1, "`"))
else:
yield ((start, start + len(text), text))
elif token == Token.Literal.String.Interpol:
yield ((start, start + len(text), text))
elif token == Token.Generic.Strong:
end = start + len(text)
yield (start, start + 2, "**")
yield (end - 2, end, "**")
elif token == Token.Generic.Emph:
end = start + len(text)
yield (start, start + 1, "*")
yield (end - 1, end, "*")
start += len(text)
def highlight_string(source: str, unit, hightlight_syntax: bool = False):
"""Return highlights for a string."""
if unit is None:
return []
highlights = []
for check in CHECKS:
if not CHECKS[check].target:
continue
highlights.extend(CHECKS[check].check_highlight(source, unit))
if hightlight_syntax:
highlights.extend(highlight_pygments(source, unit))
# Remove empty strings
highlights = [highlight for highlight in highlights if highlight[2]]
# Sort by order in string
highlights.sort(key=itemgetter(0))
# Remove overlapping ones
for hl_idx in range(len(highlights)):
if hl_idx >= len(highlights):
break
elref = highlights[hl_idx]
for hl_idx_next in range(hl_idx + 1, len(highlights)):
if hl_idx_next >= len(highlights):
break
eltest = highlights[hl_idx_next]
if eltest[0] >= elref[0] and eltest[0] < elref[1]:
# Elements overlap, remove inner one
highlights.pop(hl_idx_next)
elif eltest[0] > elref[1]:
# This is not an overlapping element
break
return highlights