gui.utils.yaml_highlighter
1# Copyright (C) 2026 David Vaquero <pepesan@gmail.com> 2# 3# This program is free software: you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation, either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16from PySide6.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont 17from PySide6.QtCore import QRegularExpression 18 19 20def _fmt(color: str, bold: bool = False, italic: bool = False) -> QTextCharFormat: 21 f = QTextCharFormat() 22 f.setForeground(QColor(color)) 23 if bold: 24 f.setFontWeight(QFont.Weight.Bold) 25 if italic: 26 f.setFontItalic(True) 27 return f 28 29 30_PALETTES = { 31 'dark': { 32 'key': ('#7dd3fc', True, False), 33 'string': ('#86efac', False, False), 34 'number': ('#fb923c', False, False), 35 'bool': ('#c084fc', False, False), 36 'comment': ('#6b7280', False, True), 37 'dash': ('#fbbf24', False, False), 38 'anchor': ('#f9a8d4', False, False), 39 }, 40 'light': { 41 'key': ('#0369a1', True, False), 42 'string': ('#166534', False, False), 43 'number': ('#c2410c', False, False), 44 'bool': ('#7e22ce', False, False), 45 'comment': ('#6b7280', False, True), 46 'dash': ('#b45309', False, False), 47 'anchor': ('#be185d', False, False), 48 }, 49} 50 51_RULES_DEFS = [ 52 ('key', r'(?:^|(?<=[\s\-]))([A-Za-z_][\w\-]*)(?=\s*:)', 1), 53 ('string', r'"[^"\\]*(?:\\.[^"\\]*)*"', 0), 54 ('string', r"'[^']*'", 0), 55 ('number', r'(?<![:\w])-?\b\d+(?:\.\d+)?\b', 0), 56 ('bool', r'\b(?:true|false|yes|no|null|True|False|Yes|No|Null|~)\b', 0), 57 ('dash', r'^\s*-(?=\s|$)', 0), 58 ('anchor', r'[&*][A-Za-z_][\w\-]*', 0), 59 ('comment', r'#.*$', 0), 60] 61 62 63class YamlHighlighter(QSyntaxHighlighter): 64 def __init__(self, document, theme: str = 'dark'): 65 super().__init__(document) 66 self._rules: list[tuple] = [] 67 self.set_theme(theme) 68 69 def set_theme(self, theme: str) -> None: 70 palette = _PALETTES.get(theme, _PALETTES['dark']) 71 self._rules = [] 72 for role, pattern, group in _RULES_DEFS: 73 color, bold, italic = palette[role] 74 self._rules.append(( 75 QRegularExpression(pattern, QRegularExpression.PatternOption.MultilineOption), 76 _fmt(color, bold, italic), 77 group, 78 )) 79 self.rehighlight() 80 81 def highlightBlock(self, text: str) -> None: 82 for pattern, fmt, group in self._rules: 83 it = pattern.globalMatch(text) 84 while it.hasNext(): 85 m = it.next() 86 start = m.capturedStart(group) 87 length = m.capturedLength(group) 88 if start >= 0 and length > 0: 89 self.setFormat(start, length, fmt)
class
YamlHighlighter(PySide6.QtGui.QSyntaxHighlighter):
64class YamlHighlighter(QSyntaxHighlighter): 65 def __init__(self, document, theme: str = 'dark'): 66 super().__init__(document) 67 self._rules: list[tuple] = [] 68 self.set_theme(theme) 69 70 def set_theme(self, theme: str) -> None: 71 palette = _PALETTES.get(theme, _PALETTES['dark']) 72 self._rules = [] 73 for role, pattern, group in _RULES_DEFS: 74 color, bold, italic = palette[role] 75 self._rules.append(( 76 QRegularExpression(pattern, QRegularExpression.PatternOption.MultilineOption), 77 _fmt(color, bold, italic), 78 group, 79 )) 80 self.rehighlight() 81 82 def highlightBlock(self, text: str) -> None: 83 for pattern, fmt, group in self._rules: 84 it = pattern.globalMatch(text) 85 while it.hasNext(): 86 m = it.next() 87 start = m.capturedStart(group) 88 length = m.capturedLength(group) 89 if start >= 0 and length > 0: 90 self.setFormat(start, length, fmt)
QSyntaxHighlighter(self, parent: PySide6.QtGui.QTextDocument, /) -> None QSyntaxHighlighter(self, parent: PySide6.QtCore.QObject, /) -> None
def
set_theme(self, theme: str) -> None:
70 def set_theme(self, theme: str) -> None: 71 palette = _PALETTES.get(theme, _PALETTES['dark']) 72 self._rules = [] 73 for role, pattern, group in _RULES_DEFS: 74 color, bold, italic = palette[role] 75 self._rules.append(( 76 QRegularExpression(pattern, QRegularExpression.PatternOption.MultilineOption), 77 _fmt(color, bold, italic), 78 group, 79 )) 80 self.rehighlight()
def
highlightBlock(self, text: str) -> None:
82 def highlightBlock(self, text: str) -> None: 83 for pattern, fmt, group in self._rules: 84 it = pattern.globalMatch(text) 85 while it.hasNext(): 86 m = it.next() 87 start = m.capturedStart(group) 88 length = m.capturedLength(group) 89 if start >= 0 and length > 0: 90 self.setFormat(start, length, fmt)