widgets.remote: retain focus when showing remote messages
[git-cola.git] / cola / widgets / highlighter.py
blob0744838fa10ae619ee66e1b7a6d35b5b4b7ec9e6
1 from qtpy import QtCore
2 from qtpy import QtGui
3 from qtpy import QtWidgets
5 have_pygments = True
6 try:
7 from pygments.styles import get_style_by_name
8 from pygments import lex
9 from pygments.util import ClassNotFound
10 from pygments.lexers import get_lexer_for_filename
11 except ImportError:
12 have_pygments = False
15 def highlight_document(edit, filename):
16 if not have_pygments:
17 return
18 doc = edit.document()
19 try:
20 lexer = get_lexer_for_filename(filename, stripnl=False)
21 except ClassNotFound:
22 return
24 style = get_style_by_name('default')
26 font = doc.defaultFont()
27 base_format = QtGui.QTextCharFormat()
28 base_format.setFont(font)
29 token_formats = {}
31 window = edit.window()
32 if hasattr(window, 'processEvents'):
33 processEvents = window.processEvents
34 else:
35 processEvents = QtCore.QCoreApplication.processEvents
37 def get_token_format(token):
38 if token in token_formats:
39 return token_formats[token]
41 if token.parent:
42 parent_format = get_token_format(token.parent)
43 else:
44 parent_format = base_format
46 fmt = QtGui.QTextCharFormat(parent_format)
47 font = fmt.font()
48 if style.styles_token(token):
49 tstyle = style.style_for_token(token)
50 if tstyle['color']:
51 fmt.setForeground(QtGui.QColor('#' + tstyle['color']))
52 if tstyle['bold']:
53 font.setWeight(QtGui.QFont.Bold)
54 if tstyle['italic']:
55 font.setItalic(True)
56 if tstyle['underline']:
57 fmt.setFontUnderline(True)
58 if tstyle['bgcolor']:
59 fmt.setBackground(QtGui.QColor('#' + tstyle['bgcolor']))
60 token_formats[token] = fmt
61 return fmt
63 text = doc.toPlainText()
65 block_count = 0
66 block = doc.firstBlock()
67 assert isinstance(block, QtGui.QTextBlock)
68 block_pos = 0
69 block_len = block.length()
70 block_formats = []
72 for token, ttext in lex(text, lexer):
73 format_len = len(ttext)
74 fmt = get_token_format(token)
75 while format_len > 0:
76 format_range = QtGui.QTextLayout.FormatRange()
77 format_range.start = block_pos
78 format_range.length = min(format_len, block_len)
79 format_range.format = fmt
80 block_formats.append(format_range)
81 block_len -= format_range.length
82 format_len -= format_range.length
83 block_pos += format_range.length
84 if block_len == 0:
85 block.layout().setAdditionalFormats(block_formats)
86 doc.markContentsDirty(block.position(), block.length())
87 block = block.next()
88 block_pos = 0
89 block_len = block.length()
90 block_formats = []
92 block_count += 1
93 if block_count % 100 == 0:
94 processEvents()
97 if __name__ == '__main__':
98 app = QtWidgets.QApplication([])
100 python = QtWidgets.QPlainTextEdit()
101 with open(__file__, encoding='utf-8') as f:
102 python.setPlainText(f.read())
104 python.setWindowTitle('python')
105 python.show()
106 highlight_document(python, __file__)
108 app.exec_()