# HG changeset patch
# User Peter Demcak <
majs...@gmail.com>
# Date 1772737276 -3600
# Thu Mar 05 20:01:16 2026 +0100
# Node ID 851dc4bb18fcfb43622489de1bdfa8c4b3e75939
# Parent 6162e5e90a503ff93d5e5bddc798324a2634c124
lexers: add theme-driven syntax highlighting for QScintilla lexers
Add _applyThemeSyntaxColors() to apply a consistent
dark-theme palette across lexer styles (default, comments, keywords, strings,
numbers, operators, classes, and functions).
Also update diff lexer colors in dark mode (default text, hunk headers,
added/removed lines, and EOF note)
diff -r 6162e5e90a50 -r 851dc4bb18fc tortoisehg/hgqt/lexers.py
--- a/tortoisehg/hgqt/lexers.py Thu Mar 05 20:00:58 2026 +0100
+++ b/tortoisehg/hgqt/lexers.py Thu Mar 05 20:01:16 2026 +0100
@@ -25,6 +25,8 @@
hglib,
)
+from .theme import THEME
+
if hasattr(QtGui.QColor, 'getHslF'):
def _fixdarkcolors(lexer):
"""Invert lightness of low-contrast colors on dark theme"""
@@ -42,6 +44,61 @@
def _fixdarkcolors(lexer):
pass
+def _applyThemeSyntaxColors(lexer):
+ """Apply theme syntax colors to a lexer (generic implementation for all languages)
+ """
+ if not THEME.enabled:
+ return
+
+ # Only indices that are consistent across virtually all QScintilla lexers.
+ style_map = {
+ 0: THEME.syntax_default, # Default (always 0)
+ 1: THEME.syntax_comment, # Comment (always 1 for most lexers)
+ }
+
+ for style_idx, color in style_map.items():
+ try:
+ lexer.setColor(color, style_idx)
+ except:
+ pass
+
+ # Named style attributes - mapped to correct numeric values per lexer
+ named_styles = {
+ 'Default': THEME.syntax_default,
+ 'Identifier': THEME.syntax_identifier,
+ 'Comment': THEME.syntax_comment,
+ 'CommentLine': THEME.syntax_comment,
+ 'CommentBlock': THEME.syntax_comment,
+ 'CommentDoc': THEME.syntax_comment,
+ 'CommentLineDoc': THEME.syntax_comment,
+ 'Keyword': THEME.syntax_keyword,
+ 'KeywordSet2': THEME.syntax_keyword,
+ 'PreProcessor': THEME.syntax_keyword,
+ 'Number': THEME.syntax_number,
+ 'Operator': THEME.syntax_operator,
+ 'SingleQuotedString': THEME.syntax_string,
+ 'DoubleQuotedString': THEME.syntax_string,
+ 'RawString': THEME.syntax_string,
+ 'UnclosedString': THEME.syntax_string,
+ 'VerbatimString': THEME.syntax_string,
+ 'TripleSingleQuotedString': THEME.syntax_string,
+ 'TripleDoubleQuotedString': THEME.syntax_string,
+ 'HereDocument': THEME.syntax_string,
+ 'ClassName': THEME.syntax_class,
+ 'GlobalClass': THEME.syntax_class,
+ 'FunctionMethodName': THEME.syntax_function,
+ }
+
+ for style_name, color in named_styles.items():
+ try:
+ style_attr = getattr(lexer.__class__, style_name, None)
+ if style_attr is not None:
+ lexer.setColor(color, style_attr)
+ except:
+ pass
+
+ return
+
class _LexerSelector:
_lexer = None
def match(self, filename, filedata):
@@ -56,7 +113,11 @@
def cfg_lexer(self, lexer):
font = qtlib.getfont('fontlog').font()
lexer.setFont(font, -1)
- _fixdarkcolors(lexer)
+
+ if THEME.enabled:
+ _applyThemeSyntaxColors(lexer)
+ else:
+ _fixdarkcolors(lexer)
return lexer
class _FilenameLexerSelector(_LexerSelector):
@@ -228,16 +289,29 @@
_lexer = Qsci.QsciLexerDiff
regex = re.compile(br'^@@ [-]\d+,\d+ [+]\d+,\d+ @@$')
def cfg_lexer(self, lexer):
- for label, i in (('diff.inserted', Qsci.QsciLexerDiff.LineAdded),
- ('diff.deleted', Qsci.QsciLexerDiff.LineRemoved),
- ('diff.hunk', Qsci.QsciLexerDiff.Position)):
- effect = qtlib.geteffect(label)
- for e in effect.split(';'):
- if e.startswith('color:'):
- lexer.setColor(QtGui.QColor(e[7:]), i)
- if e.startswith('background-color:'):
- lexer.setEolFill(True, i)
- lexer.setPaper(QtGui.QColor(e[18:]), i)
+
+ if THEME.enabled:
+ lexer.setColor(THEME.diff_text, Qsci.QsciLexerDiff.Default) # normal / untouched text
+ lexer.setColor(THEME.diff_start, Qsci.QsciLexerDiff.Position) # @@ hunk header
+ lexer.setColor(THEME.diff_added, Qsci.QsciLexerDiff.LineAdded) # + added lines
+ lexer.setColor(THEME.diff_removed, Qsci.QsciLexerDiff.LineRemoved) # - removed lines
+ #lexer.setColor(THEME.diff_start, Qsci.QsciLexerDiff.FileHeader) # --- / +++ file header (optional)
+
+ # Fix "No newline at end of file"
+ lexer.setColor(THEME.text_margin, Qsci.QsciLexerDiff.Comment)
+
+ else:
+ for label, i in (('diff.inserted', Qsci.QsciLexerDiff.LineAdded),
+ ('diff.deleted', Qsci.QsciLexerDiff.LineRemoved),
+ ('diff.hunk', Qsci.QsciLexerDiff.Position)):
+ effect = qtlib.geteffect(label)
+ for e in effect.split(';'):
+ if e.startswith('color:'):
+ lexer.setColor(QtGui.QColor(e[7:]), i)
+ if e.startswith('background-color:'):
+ lexer.setEolFill(True, i)
+ lexer.setPaper(QtGui.QColor(e[18:]), i)
+
font = qtlib.getfont('fontdiff').font()
lexer.setFont(font, -1)
_fixdarkcolors(lexer)