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

YamlHighlighter(document, theme: str = 'dark')
65    def __init__(self, document, theme: str = 'dark'):
66        super().__init__(document)
67        self._rules: list[tuple] = []
68        self.set_theme(theme)
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)
staticMetaObject = PySide6.QtCore.QMetaObject("YamlHighlighter" inherits "QSyntaxHighlighter": )